Commit 7164aaaa authored by Jehonathan Thomas's avatar Jehonathan Thomas Committed by GitHub

Revert "Stable"

parent bf310af0
...@@ -5,7 +5,7 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -5,7 +5,7 @@ namespace Titanium.Web.Proxy.Examples.Basic
{ {
public class Program public class Program
{ {
private static readonly ProxyTestController controller = new ProxyTestController(); private static readonly ProxyTestController Controller = new ProxyTestController();
public static void Main(string[] args) public static void Main(string[] args)
{ {
...@@ -15,13 +15,13 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -15,13 +15,13 @@ namespace Titanium.Web.Proxy.Examples.Basic
//Start proxy controller //Start proxy controller
controller.StartProxy(); Controller.StartProxy();
Console.WriteLine("Hit any key to exit.."); Console.WriteLine("Hit any key to exit..");
Console.WriteLine(); Console.WriteLine();
Console.Read(); Console.Read();
controller.Stop(); Controller.Stop();
} }
...@@ -30,7 +30,7 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -30,7 +30,7 @@ namespace Titanium.Web.Proxy.Examples.Basic
if (eventType != 2) return false; if (eventType != 2) return false;
try try
{ {
controller.Stop(); Controller.Stop();
} }
catch catch
{ {
......
...@@ -9,23 +9,16 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -9,23 +9,16 @@ namespace Titanium.Web.Proxy.Examples.Basic
{ {
public class ProxyTestController public class ProxyTestController
{ {
private readonly ProxyServer proxyServer; private ProxyServer proxyServer;
//share requestBody outside handlers //share requestBody outside handlers
private readonly Dictionary<Guid, string> requestBodyHistory = new Dictionary<Guid, string>(); private Dictionary<Guid, string> requestBodyHistory;
public ProxyTestController() public ProxyTestController()
{ {
proxyServer = new ProxyServer(); proxyServer = new ProxyServer();
proxyServer.ExceptionFunc = exception => Console.WriteLine(exception.Message);
proxyServer.TrustRootCertificate = true; proxyServer.TrustRootCertificate = true;
requestBodyHistory = new Dictionary<Guid, string>();
//optionally set the Certificate Engine
//Under Mono only BouncyCastle will be supported
//proxyServer.CertificateEngine = Network.CertificateEngine.BouncyCastle;
//optionally set the Root Certificate
//proxyServer.RootCertificate = new X509Certificate2("myCert.pfx", string.Empty, X509KeyStorageFlags.Exportable);
} }
public void StartProxy() public void StartProxy()
...@@ -35,32 +28,21 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -35,32 +28,21 @@ namespace Titanium.Web.Proxy.Examples.Basic
proxyServer.ServerCertificateValidationCallback += OnCertificateValidation; proxyServer.ServerCertificateValidationCallback += OnCertificateValidation;
proxyServer.ClientCertificateSelectionCallback += OnCertificateSelection; proxyServer.ClientCertificateSelectionCallback += OnCertificateSelection;
//Exclude Https addresses you don't want to proxy
//Usefull for clients that use certificate pinning
//for example dropbox.com
var explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, 8000, true) var explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, 8000, true)
{ {
//Exclude Https addresses you don't want to proxy
//Useful for clients that use certificate pinning
//for example google.com and dropbox.com
// ExcludedHttpsHostNameRegex = new List<string>() { "google.com", "dropbox.com" } // ExcludedHttpsHostNameRegex = new List<string>() { "google.com", "dropbox.com" }
//Include Https addresses you want to proxy (others will be excluded)
//for example github.com
// IncludedHttpsHostNameRegex = new List<string>() { "github.com" }
//You can set only one of the ExcludedHttpsHostNameRegex and IncludedHttpsHostNameRegex properties, otherwise ArgumentException will be thrown
//Use self-issued generic certificate on all https requests
//Optimizes performance by not creating a certificate for each https-enabled domain
//Useful when certificate trust is not required by proxy clients
// GenericCertificate = new X509Certificate2(Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "genericcert.pfx"), "password")
}; };
//An explicit endpoint is where the client knows about the existence of a proxy //An explicit endpoint is where the client knows about the existance of a proxy
//So client sends request in a proxy friendly manner //So client sends request in a proxy friendly manner
proxyServer.AddEndPoint(explicitEndPoint); proxyServer.AddEndPoint(explicitEndPoint);
proxyServer.Start(); proxyServer.Start();
//Transparent endpoint is useful for reverse proxying (client is not aware of the existence of proxy) //Transparent endpoint is usefull for reverse proxying (client is not aware of the existance of proxy)
//A transparent endpoint usually requires a network router port forwarding HTTP(S) packets to this endpoint //A transparent endpoint usually requires a network router port forwarding HTTP(S) packets to this endpoint
//Currently do not support Server Name Indication (It is not currently supported by SslStream class) //Currently do not support Server Name Indication (It is not currently supported by SslStream class)
//That means that the transparent endpoint will always provide the same Generic Certificate to all HTTPS requests //That means that the transparent endpoint will always provide the same Generic Certificate to all HTTPS requests
...@@ -94,12 +76,12 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -94,12 +76,12 @@ namespace Titanium.Web.Proxy.Examples.Basic
proxyServer.Stop(); proxyServer.Stop();
} }
//intecept & cancel redirect or update requests //intecept & cancel, redirect or update requests
public async Task OnRequest(object sender, SessionEventArgs e) public async Task OnRequest(object sender, SessionEventArgs e)
{ {
Console.WriteLine(e.WebSession.Request.Url); Console.WriteLine(e.WebSession.Request.Url);
//read request headers ////read request headers
var requestHeaders = e.WebSession.Request.RequestHeaders; var requestHeaders = e.WebSession.Request.RequestHeaders;
var method = e.WebSession.Request.Method.ToUpper(); var method = e.WebSession.Request.Method.ToUpper();
...@@ -128,7 +110,6 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -128,7 +110,6 @@ namespace Titanium.Web.Proxy.Examples.Basic
"</body>" + "</body>" +
"</html>"); "</html>");
} }
//Redirect example //Redirect example
if (e.WebSession.Request.RequestUri.AbsoluteUri.Contains("wikipedia.org")) if (e.WebSession.Request.RequestUri.AbsoluteUri.Contains("wikipedia.org"))
{ {
...@@ -144,7 +125,6 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -144,7 +125,6 @@ namespace Titanium.Web.Proxy.Examples.Basic
//access request body by looking up the shared dictionary using requestId //access request body by looking up the shared dictionary using requestId
var requestBody = requestBodyHistory[e.Id]; var requestBody = requestBodyHistory[e.Id];
} }
//read response headers //read response headers
var responseHeaders = e.WebSession.Response.ResponseHeaders; var responseHeaders = e.WebSession.Response.ResponseHeaders;
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
<Prefer32Bit>false</Prefer32Bit> <Prefer32Bit>false</Prefer32Bit>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType> <DebugType>pdbonly</DebugType>
<Optimize>true</Optimize> <Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath> <OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE;NET45</DefineConstants> <DefineConstants>TRACE;NET45</DefineConstants>
...@@ -33,7 +33,6 @@ ...@@ -33,7 +33,6 @@
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion> <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<Prefer32Bit>false</Prefer32Bit> <Prefer32Bit>false</Prefer32Bit>
<DebugSymbols>false</DebugSymbols>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<StartupObject /> <StartupObject />
......
Doneness: Doneness:
- [ ] Build is okay - I made sure that this change is building successfully. - [ ] Build is okay - I made sure that this change is building successfully.
- [ ] No Bugs - I made sure that this change is working properly as expected. It doesn't have any bugs that you are aware of. - [ ] No Bugs - I made sure that this change is working properly as expected. It does'nt have any bugs that you are aware of.
- [ ] Branching - If this is not a hotfix, I am making this request against develop branch - [ ] Branching - If this is not a hotfix, I am making this request against develop branch
This diff is collapsed.
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Titanium.Web.Proxy.IntegrationTests")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Titanium.Web.Proxy.IntegrationTests")]
[assembly: AssemblyCopyright("Copyright © 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("32231301-b0fb-4f9e-98df-b3e8a88f4c16")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Net;
using System.Threading.Tasks;
using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Models;
using System.Net.Http;
using System.Diagnostics;
namespace Titanium.Web.Proxy.IntegrationTests
{
[TestClass]
public class SslTests
{
[TestMethod]
public void TestSsl()
{
//expand this to stress test to find
//why in long run proxy becomes unresponsive as per issue #184
var testUrl = "https://google.com";
int proxyPort = 8086;
var proxy = new ProxyTestController();
proxy.StartProxy(proxyPort);
using (var client = CreateHttpClient(testUrl, proxyPort))
{
var response = client.GetAsync(new Uri(testUrl)).Result;
}
}
private HttpClient CreateHttpClient(string url, int localProxyPort)
{
var handler = new HttpClientHandler
{
Proxy = new WebProxy($"http://localhost:{localProxyPort}", false),
UseProxy = true,
};
var client = new HttpClient(handler);
return client;
}
}
public class ProxyTestController
{
private readonly ProxyServer proxyServer;
public ProxyTestController()
{
proxyServer = new ProxyServer();
proxyServer.TrustRootCertificate = true;
}
public void StartProxy(int proxyPort)
{
proxyServer.BeforeRequest += OnRequest;
proxyServer.BeforeResponse += OnResponse;
proxyServer.ServerCertificateValidationCallback += OnCertificateValidation;
proxyServer.ClientCertificateSelectionCallback += OnCertificateSelection;
var explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, proxyPort, true);
//An explicit endpoint is where the client knows about the existance of a proxy
//So client sends request in a proxy friendly manner
proxyServer.AddEndPoint(explicitEndPoint);
proxyServer.Start();
foreach (var endPoint in proxyServer.ProxyEndPoints)
Console.WriteLine("Listening on '{0}' endpoint at Ip {1} and port: {2} ",
endPoint.GetType().Name, endPoint.IpAddress, endPoint.Port);
}
public void Stop()
{
proxyServer.BeforeRequest -= OnRequest;
proxyServer.BeforeResponse -= OnResponse;
proxyServer.ServerCertificateValidationCallback -= OnCertificateValidation;
proxyServer.ClientCertificateSelectionCallback -= OnCertificateSelection;
proxyServer.Stop();
}
//intecept & cancel, redirect or update requests
public async Task OnRequest(object sender, SessionEventArgs e)
{
Debug.WriteLine(e.WebSession.Request.Url);
await Task.FromResult(0);
}
//Modify response
public async Task OnResponse(object sender, SessionEventArgs e)
{
await Task.FromResult(0);
}
/// <summary>
/// Allows overriding default certificate validation logic
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public Task OnCertificateValidation(object sender, CertificateValidationEventArgs e)
{
//set IsValid to true/false based on Certificate Errors
if (e.SslPolicyErrors == System.Net.Security.SslPolicyErrors.None)
{
e.IsValid = true;
}
return Task.FromResult(0);
}
/// <summary>
/// Allows overriding default client certificate selection logic during mutual authentication
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public Task OnCertificateSelection(object sender, CertificateSelectionEventArgs e)
{
//set e.clientCertificate to override
return Task.FromResult(0);
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{32231301-B0FB-4F9E-98DF-B3E8A88F4C16}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Titanium.Web.Proxy.IntegrationTests</RootNamespace>
<AssemblyName>Titanium.Web.Proxy.IntegrationTests</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
<ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath>
<IsCodedUITest>False</IsCodedUITest>
<TestProjectType>UnitTest</TestProjectType>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Net.Http" />
</ItemGroup>
<Choose>
<When Condition="('$(VisualStudioVersion)' == '10.0' or '$(VisualStudioVersion)' == '') and '$(TargetFrameworkVersion)' == 'v3.5'">
<ItemGroup>
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
</ItemGroup>
</When>
<Otherwise>
<ItemGroup>
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework" />
</ItemGroup>
</Otherwise>
</Choose>
<ItemGroup>
<Compile Include="SslTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Titanium.Web.Proxy\Titanium.Web.Proxy.csproj">
<Project>{8d73a1be-868c-42d2-9ece-f32cc1a02906}</Project>
<Name>Titanium.Web.Proxy</Name>
</ProjectReference>
</ItemGroup>
<Choose>
<When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">
<ItemGroup>
<Reference Include="Microsoft.VisualStudio.QualityTools.CodedUITestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.VisualStudio.TestTools.UITest.Common, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.VisualStudio.TestTools.UITest.Extension, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.VisualStudio.TestTools.UITesting, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<Private>False</Private>
</Reference>
</ItemGroup>
</When>
</Choose>
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
\ No newline at end of file
...@@ -9,7 +9,7 @@ namespace Titanium.Web.Proxy.UnitTests ...@@ -9,7 +9,7 @@ namespace Titanium.Web.Proxy.UnitTests
[TestClass] [TestClass]
public class CertificateManagerTests public class CertificateManagerTests
{ {
private static readonly string[] hostNames private readonly static string[] hostNames
= new string[] { "facebook.com", "youtube.com", "google.com", = new string[] { "facebook.com", "youtube.com", "google.com",
"bing.com", "yahoo.com"}; "bing.com", "yahoo.com"};
...@@ -20,7 +20,8 @@ namespace Titanium.Web.Proxy.UnitTests ...@@ -20,7 +20,8 @@ namespace Titanium.Web.Proxy.UnitTests
{ {
var tasks = new List<Task>(); var tasks = new List<Task>();
var mgr = new CertificateManager(new Lazy<Action<Exception>>(() => (e => { })).Value); var mgr = new CertificateManager("Titanium", "Titanium Root Certificate Authority",
new Lazy<Action<Exception>>(() => (e => { })).Value);
mgr.ClearIdleCertificates(1); mgr.ClearIdleCertificates(1);
......
using System.Reflection; using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following // General Information about an assembly is controlled through the following
......
...@@ -34,12 +34,6 @@ ...@@ -34,12 +34,6 @@
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<PropertyGroup>
<SignAssembly>true</SignAssembly>
</PropertyGroup>
<PropertyGroup>
<AssemblyOriginatorKeyFile>StrongNameKey.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="System" /> <Reference Include="System" />
</ItemGroup> </ItemGroup>
...@@ -66,9 +60,6 @@ ...@@ -66,9 +60,6 @@
<Name>Titanium.Web.Proxy</Name> <Name>Titanium.Web.Proxy</Name>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup>
<None Include="StrongNameKey.snk" />
</ItemGroup>
<Choose> <Choose>
<When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'"> <When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">
<ItemGroup> <ItemGroup>
......
 
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14 # Visual Studio 14
VisualStudioVersion = 14.0.25420.1 VisualStudioVersion = 14.0.25123.0
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{B6DBABDC-C985-4872-9C38-B4E5079CBC4B}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{B6DBABDC-C985-4872-9C38-B4E5079CBC4B}"
EndProject EndProject
...@@ -33,8 +33,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{BC1E0789 ...@@ -33,8 +33,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{BC1E0789
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Titanium.Web.Proxy.UnitTests", "Tests\Titanium.Web.Proxy.UnitTests\Titanium.Web.Proxy.UnitTests.csproj", "{B517E3D0-D03B-436F-AB03-34BA0D5321AF}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Titanium.Web.Proxy.UnitTests", "Tests\Titanium.Web.Proxy.UnitTests\Titanium.Web.Proxy.UnitTests.csproj", "{B517E3D0-D03B-436F-AB03-34BA0D5321AF}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Titanium.Web.Proxy.IntegrationTests", "Tests\Titanium.Web.Proxy.IntegrationTests\Titanium.Web.Proxy.IntegrationTests.csproj", "{32231301-B0FB-4F9E-98DF-B3E8A88F4C16}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
...@@ -53,10 +51,6 @@ Global ...@@ -53,10 +51,6 @@ Global
{B517E3D0-D03B-436F-AB03-34BA0D5321AF}.Debug|Any CPU.Build.0 = Debug|Any CPU {B517E3D0-D03B-436F-AB03-34BA0D5321AF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B517E3D0-D03B-436F-AB03-34BA0D5321AF}.Release|Any CPU.ActiveCfg = Release|Any CPU {B517E3D0-D03B-436F-AB03-34BA0D5321AF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B517E3D0-D03B-436F-AB03-34BA0D5321AF}.Release|Any CPU.Build.0 = Release|Any CPU {B517E3D0-D03B-436F-AB03-34BA0D5321AF}.Release|Any CPU.Build.0 = Release|Any CPU
{32231301-B0FB-4F9E-98DF-B3E8A88F4C16}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{32231301-B0FB-4F9E-98DF-B3E8A88F4C16}.Debug|Any CPU.Build.0 = Debug|Any CPU
{32231301-B0FB-4F9E-98DF-B3E8A88F4C16}.Release|Any CPU.ActiveCfg = Release|Any CPU
{32231301-B0FB-4F9E-98DF-B3E8A88F4C16}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
...@@ -64,7 +58,6 @@ Global ...@@ -64,7 +58,6 @@ Global
GlobalSection(NestedProjects) = preSolution GlobalSection(NestedProjects) = preSolution
{F3B7E553-1904-4E80-BDC7-212342B5C952} = {B6DBABDC-C985-4872-9C38-B4E5079CBC4B} {F3B7E553-1904-4E80-BDC7-212342B5C952} = {B6DBABDC-C985-4872-9C38-B4E5079CBC4B}
{B517E3D0-D03B-436F-AB03-34BA0D5321AF} = {BC1E0789-D348-49CF-8B67-5E99D50EDF64} {B517E3D0-D03B-436F-AB03-34BA0D5321AF} = {BC1E0789-D348-49CF-8B67-5E99D50EDF64}
{32231301-B0FB-4F9E-98DF-B3E8A88F4C16} = {BC1E0789-D348-49CF-8B67-5E99D50EDF64}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
EnterpriseLibraryConfigurationToolBinariesPath = .1.505.2\lib\NET35 EnterpriseLibraryConfigurationToolBinariesPath = .1.505.2\lib\NET35
......
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/LINE_FEED_AT_FILE_END/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=BC/@EntryIndexedValue">BC</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateConstants/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateInstanceFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticReadonly/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=dda2ffa1_002D435c_002D4111_002D88eb_002D1a7c93c382f0/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Static, Instance" AccessRightKinds="Private" Description="Property (private)"&gt;&lt;ElementKinds&gt;&lt;Kind Name="PROPERTY" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;&lt;/Policy&gt;</s:String></wpf:ResourceDictionary>
\ No newline at end of file
using System; using System;
using System.Linq;
using System.Net.Security; using System.Net.Security;
using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks; using System.Threading.Tasks;
...@@ -16,7 +17,7 @@ namespace Titanium.Web.Proxy ...@@ -16,7 +17,7 @@ namespace Titanium.Web.Proxy
/// <param name="chain"></param> /// <param name="chain"></param>
/// <param name="sslPolicyErrors"></param> /// <param name="sslPolicyErrors"></param>
/// <returns></returns> /// <returns></returns>
private bool ValidateServerCertificate( internal bool ValidateServerCertificate(
object sender, object sender,
X509Certificate certificate, X509Certificate certificate,
X509Chain chain, X509Chain chain,
...@@ -25,12 +26,11 @@ namespace Titanium.Web.Proxy ...@@ -25,12 +26,11 @@ namespace Titanium.Web.Proxy
//if user callback is registered then do it //if user callback is registered then do it
if (ServerCertificateValidationCallback != null) if (ServerCertificateValidationCallback != null)
{ {
var args = new CertificateValidationEventArgs var args = new CertificateValidationEventArgs();
{
Certificate = certificate, args.Certificate = certificate;
Chain = chain, args.Chain = chain;
SslPolicyErrors = sslPolicyErrors args.SslPolicyErrors = sslPolicyErrors;
};
Delegate[] invocationList = ServerCertificateValidationCallback.GetInvocationList(); Delegate[] invocationList = ServerCertificateValidationCallback.GetInvocationList();
...@@ -38,7 +38,7 @@ namespace Titanium.Web.Proxy ...@@ -38,7 +38,7 @@ namespace Titanium.Web.Proxy
for (int i = 0; i < invocationList.Length; i++) for (int i = 0; i < invocationList.Length; i++)
{ {
handlerTasks[i] = ((Func<object, CertificateValidationEventArgs, Task>) invocationList[i])(null, args); handlerTasks[i] = ((Func<object, CertificateValidationEventArgs, Task>)invocationList[i])(null, args);
} }
Task.WhenAll(handlerTasks).Wait(); Task.WhenAll(handlerTasks).Wait();
...@@ -65,7 +65,7 @@ namespace Titanium.Web.Proxy ...@@ -65,7 +65,7 @@ namespace Titanium.Web.Proxy
/// <param name="remoteCertificate"></param> /// <param name="remoteCertificate"></param>
/// <param name="acceptableIssuers"></param> /// <param name="acceptableIssuers"></param>
/// <returns></returns> /// <returns></returns>
private X509Certificate SelectClientCertificate( internal X509Certificate SelectClientCertificate(
object sender, object sender,
string targetHost, string targetHost,
X509CertificateCollection localCertificates, X509CertificateCollection localCertificates,
...@@ -73,6 +73,7 @@ namespace Titanium.Web.Proxy ...@@ -73,6 +73,7 @@ namespace Titanium.Web.Proxy
string[] acceptableIssuers) string[] acceptableIssuers)
{ {
X509Certificate clientCertificate = null; X509Certificate clientCertificate = null;
var customSslStream = sender as SslStream;
if (acceptableIssuers != null && if (acceptableIssuers != null &&
acceptableIssuers.Length > 0 && acceptableIssuers.Length > 0 &&
...@@ -99,22 +100,20 @@ namespace Titanium.Web.Proxy ...@@ -99,22 +100,20 @@ namespace Titanium.Web.Proxy
//If user call back is registered //If user call back is registered
if (ClientCertificateSelectionCallback != null) if (ClientCertificateSelectionCallback != null)
{ {
var args = new CertificateSelectionEventArgs var args = new CertificateSelectionEventArgs();
{
TargetHost = targetHost,
LocalCertificates = localCertificates,
RemoteCertificate = remoteCertificate,
AcceptableIssuers = acceptableIssuers,
ClientCertificate = clientCertificate
};
args.TargetHost = targetHost;
args.LocalCertificates = localCertificates;
args.RemoteCertificate = remoteCertificate;
args.AcceptableIssuers = acceptableIssuers;
args.ClientCertificate = clientCertificate;
Delegate[] invocationList = ClientCertificateSelectionCallback.GetInvocationList(); Delegate[] invocationList = ClientCertificateSelectionCallback.GetInvocationList();
Task[] handlerTasks = new Task[invocationList.Length]; Task[] handlerTasks = new Task[invocationList.Length];
for (int i = 0; i < invocationList.Length; i++) for (int i = 0; i < invocationList.Length; i++)
{ {
handlerTasks[i] = ((Func<object, CertificateSelectionEventArgs, Task>) invocationList[i])(null, args); handlerTasks[i] = ((Func<object, CertificateSelectionEventArgs, Task>)invocationList[i])(null, args);
} }
Task.WhenAll(handlerTasks).Wait(); Task.WhenAll(handlerTasks).Wait();
......
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
return new GZipCompression(); return new GZipCompression();
case "deflate": case "deflate":
return new DeflateCompression(); return new DeflateCompression();
case "zlib":
return new ZlibCompression();
default: default:
return null; return null;
} }
......
using System.IO; using Ionic.Zlib;
using System.IO.Compression; using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Titanium.Web.Proxy.Compression namespace Titanium.Web.Proxy.Compression
......
using Ionic.Zlib;
using System.IO;
using System.Threading.Tasks;
namespace Titanium.Web.Proxy.Compression
{
/// <summary>
/// concrete implementation of zlib compression
/// </summary>
internal class ZlibCompression : ICompression
{
public async Task<byte[]> Compress(byte[] responseBody)
{
using (var ms = new MemoryStream())
{
using (var zip = new ZlibStream(ms, CompressionMode.Compress, true))
{
await zip.WriteAsync(responseBody, 0, responseBody.Length);
}
return ms.ToArray();
}
}
}
}
...@@ -7,12 +7,14 @@ ...@@ -7,12 +7,14 @@
{ {
internal IDecompression Create(string type) internal IDecompression Create(string type)
{ {
switch (type) switch(type)
{ {
case "gzip": case "gzip":
return new GZipDecompression(); return new GZipDecompression();
case "deflate": case "deflate":
return new DeflateDecompression(); return new DeflateDecompression();
case "zlib":
return new ZlibDecompression();
default: default:
return new DefaultDecompression(); return new DefaultDecompression();
} }
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
namespace Titanium.Web.Proxy.Decompression namespace Titanium.Web.Proxy.Decompression
{ {
/// <summary> /// <summary>
/// When no compression is specified just return the byte array /// When no compression is specified just return the byte array
/// </summary> /// </summary>
......
using System.IO; using Ionic.Zlib;
using System.IO.Compression; using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
using Titanium.Web.Proxy.Shared;
namespace Titanium.Web.Proxy.Decompression namespace Titanium.Web.Proxy.Decompression
{ {
...@@ -11,7 +12,8 @@ namespace Titanium.Web.Proxy.Decompression ...@@ -11,7 +12,8 @@ namespace Titanium.Web.Proxy.Decompression
{ {
public async Task<byte[]> Decompress(byte[] compressedArray, int bufferSize) public async Task<byte[]> Decompress(byte[] compressedArray, int bufferSize)
{ {
using (var stream = new MemoryStream(compressedArray)) var stream = new MemoryStream(compressedArray);
using (var decompressor = new DeflateStream(stream, CompressionMode.Decompress)) using (var decompressor = new DeflateStream(stream, CompressionMode.Decompress))
{ {
var buffer = new byte[bufferSize]; var buffer = new byte[bufferSize];
...@@ -21,7 +23,7 @@ namespace Titanium.Web.Proxy.Decompression ...@@ -21,7 +23,7 @@ namespace Titanium.Web.Proxy.Decompression
int read; int read;
while ((read = await decompressor.ReadAsync(buffer, 0, buffer.Length)) > 0) while ((read = await decompressor.ReadAsync(buffer, 0, buffer.Length)) > 0)
{ {
output.Write(buffer, 0, read); await output.WriteAsync(buffer, 0, read);
} }
return output.ToArray(); return output.ToArray();
......
using System.IO; using System.IO;
using System.IO.Compression; using System.IO.Compression;
using System.Threading.Tasks; using System.Threading.Tasks;
using Titanium.Web.Proxy.Shared;
namespace Titanium.Web.Proxy.Decompression namespace Titanium.Web.Proxy.Decompression
{ {
...@@ -19,9 +20,8 @@ namespace Titanium.Web.Proxy.Decompression ...@@ -19,9 +20,8 @@ namespace Titanium.Web.Proxy.Decompression
int read; int read;
while ((read = await decompressor.ReadAsync(buffer, 0, buffer.Length)) > 0) while ((read = await decompressor.ReadAsync(buffer, 0, buffer.Length)) > 0)
{ {
output.Write(buffer, 0, read); await output.WriteAsync(buffer, 0, read);
} }
return output.ToArray(); return output.ToArray();
} }
} }
......
using Ionic.Zlib;
using System.IO;
using System.Threading.Tasks;
using Titanium.Web.Proxy.Shared;
namespace Titanium.Web.Proxy.Decompression
{
/// <summary>
/// concrete implemetation of zlib de-compression
/// </summary>
internal class ZlibDecompression : IDecompression
{
public async Task<byte[]> Decompress(byte[] compressedArray, int bufferSize)
{
var memoryStream = new MemoryStream(compressedArray);
using (var decompressor = new ZlibStream(memoryStream, CompressionMode.Decompress))
{
var buffer = new byte[bufferSize];
using (var output = new MemoryStream())
{
int read;
while ((read = await decompressor.ReadAsync(buffer, 0, buffer.Length)) > 0)
{
await output.WriteAsync(buffer, 0, read);
}
return output.ToArray();
}
}
}
}
}
...@@ -8,34 +8,13 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -8,34 +8,13 @@ namespace Titanium.Web.Proxy.EventArguments
/// </summary> /// </summary>
public class CertificateSelectionEventArgs : EventArgs public class CertificateSelectionEventArgs : EventArgs
{ {
/// <summary>
/// Sender object.
/// </summary>
public object Sender { get; internal set; } public object Sender { get; internal set; }
/// <summary>
/// Target host.
/// </summary>
public string TargetHost { get; internal set; } public string TargetHost { get; internal set; }
/// <summary>
/// Local certificates.
/// </summary>
public X509CertificateCollection LocalCertificates { get; internal set; } public X509CertificateCollection LocalCertificates { get; internal set; }
/// <summary>
/// Remote certificate.
/// </summary>
public X509Certificate RemoteCertificate { get; internal set; } public X509Certificate RemoteCertificate { get; internal set; }
/// <summary>
/// Acceptable issuers.
/// </summary>
public string[] AcceptableIssuers { get; internal set; } public string[] AcceptableIssuers { get; internal set; }
/// <summary>
/// Client Certificate.
/// </summary>
public X509Certificate ClientCertificate { get; set; } public X509Certificate ClientCertificate { get; set; }
} }
} }
...@@ -7,26 +7,17 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -7,26 +7,17 @@ namespace Titanium.Web.Proxy.EventArguments
/// <summary> /// <summary>
/// An argument passed on to the user for validating the server certificate during SSL authentication /// An argument passed on to the user for validating the server certificate during SSL authentication
/// </summary> /// </summary>
public class CertificateValidationEventArgs : EventArgs public class CertificateValidationEventArgs : EventArgs, IDisposable
{ {
/// <summary>
/// Certificate
/// </summary>
public X509Certificate Certificate { get; internal set; } public X509Certificate Certificate { get; internal set; }
/// <summary>
/// Certificate chain
/// </summary>
public X509Chain Chain { get; internal set; } public X509Chain Chain { get; internal set; }
/// <summary>
/// SSL policy errors.
/// </summary>
public SslPolicyErrors SslPolicyErrors { get; internal set; } public SslPolicyErrors SslPolicyErrors { get; internal set; }
/// <summary>
/// is a valid certificate?
/// </summary>
public bool IsValid { get; set; } public bool IsValid { get; set; }
public void Dispose()
{
}
} }
} }
...@@ -22,6 +22,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -22,6 +22,7 @@ namespace Titanium.Web.Proxy.EventArguments
/// </summary> /// </summary>
public class SessionEventArgs : EventArgs, IDisposable public class SessionEventArgs : EventArgs, IDisposable
{ {
/// <summary> /// <summary>
/// Size of Buffers used by this object /// Size of Buffers used by this object
/// </summary> /// </summary>
...@@ -43,20 +44,20 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -43,20 +44,20 @@ namespace Titanium.Web.Proxy.EventArguments
/// </summary> /// </summary>
public Guid Id => WebSession.RequestId; public Guid Id => WebSession.RequestId;
/// <summary> //Should we send a rerequest
/// Should we send a rerequest public bool ReRequest
/// </summary> {
public bool ReRequest { get; set; } get;
set;
}
/// <summary> /// <summary>
/// Does this session uses SSL /// Does this session uses SSL
/// </summary> /// </summary>
public bool IsHttps => WebSession.Request.RequestUri.Scheme == Uri.UriSchemeHttps; public bool IsHttps => WebSession.Request.RequestUri.Scheme == Uri.UriSchemeHttps;
/// <summary>
/// Client End Point. public IPEndPoint ClientEndPoint => (IPEndPoint)ProxyClient.TcpClient.Client.RemoteEndPoint;
/// </summary>
public IPEndPoint ClientEndPoint => (IPEndPoint) ProxyClient.TcpClient.Client.RemoteEndPoint;
/// <summary> /// <summary>
/// A web session corresponding to a single request/response sequence /// A web session corresponding to a single request/response sequence
...@@ -64,14 +65,8 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -64,14 +65,8 @@ namespace Titanium.Web.Proxy.EventArguments
/// </summary> /// </summary>
public HttpWebClient WebSession { get; set; } public HttpWebClient WebSession { get; set; }
/// <summary>
/// Are we using a custom upstream HTTP proxy?
/// </summary>
public ExternalProxy CustomUpStreamHttpProxyUsed { get; set; } public ExternalProxy CustomUpStreamHttpProxyUsed { get; set; }
/// <summary>
/// Are we using a custom upstream HTTPS proxy?
/// </summary>
public ExternalProxy CustomUpStreamHttpsProxyUsed { get; set; } public ExternalProxy CustomUpStreamHttpsProxyUsed { get; set; }
/// <summary> /// <summary>
...@@ -103,13 +98,14 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -103,13 +98,14 @@ namespace Titanium.Web.Proxy.EventArguments
//Caching check //Caching check
if (WebSession.Request.RequestBody == null) if (WebSession.Request.RequestBody == null)
{ {
//If chunked then its easy just read the whole body with the content length mentioned in the request header //If chunked then its easy just read the whole body with the content length mentioned in the request header
using (var requestBodyStream = new MemoryStream()) using (var requestBodyStream = new MemoryStream())
{ {
//For chunked request we need to read data as they arrive, until we reach a chunk end symbol //For chunked request we need to read data as they arrive, until we reach a chunk end symbol
if (WebSession.Request.IsChunked) if (WebSession.Request.IsChunked)
{ {
await ProxyClient.ClientStreamReader.CopyBytesToStreamChunked(requestBodyStream); await this.ProxyClient.ClientStreamReader.CopyBytesToStreamChunked(bufferSize, requestBodyStream);
} }
else else
{ {
...@@ -117,8 +113,9 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -117,8 +113,9 @@ namespace Titanium.Web.Proxy.EventArguments
if (WebSession.Request.ContentLength > 0) if (WebSession.Request.ContentLength > 0)
{ {
//If not chunked then its easy just read the amount of bytes mentioned in content length header of response //If not chunked then its easy just read the amount of bytes mentioned in content length header of response
await ProxyClient.ClientStreamReader.CopyBytesToStream(bufferSize, requestBodyStream, await this.ProxyClient.ClientStreamReader.CopyBytesToStream(bufferSize, requestBodyStream,
WebSession.Request.ContentLength); WebSession.Request.ContentLength);
} }
else if (WebSession.Request.HttpVersion.Major == 1 && WebSession.Request.HttpVersion.Minor == 0) else if (WebSession.Request.HttpVersion.Major == 1 && WebSession.Request.HttpVersion.Minor == 0)
{ {
...@@ -133,6 +130,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -133,6 +130,7 @@ namespace Titanium.Web.Proxy.EventArguments
//So that next time we can deliver body from cache //So that next time we can deliver body from cache
WebSession.Request.RequestBodyRead = true; WebSession.Request.RequestBodyRead = true;
} }
} }
/// <summary> /// <summary>
...@@ -148,7 +146,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -148,7 +146,7 @@ namespace Titanium.Web.Proxy.EventArguments
//If chuncked the read chunk by chunk until we hit chunk end symbol //If chuncked the read chunk by chunk until we hit chunk end symbol
if (WebSession.Response.IsChunked) if (WebSession.Response.IsChunked)
{ {
await WebSession.ServerConnection.StreamReader.CopyBytesToStreamChunked(responseBodyStream); await WebSession.ServerConnection.StreamReader.CopyBytesToStreamChunked(bufferSize, responseBodyStream);
} }
else else
{ {
...@@ -157,6 +155,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -157,6 +155,7 @@ namespace Titanium.Web.Proxy.EventArguments
//If not chunked then its easy just read the amount of bytes mentioned in content length header of response //If not chunked then its easy just read the amount of bytes mentioned in content length header of response
await WebSession.ServerConnection.StreamReader.CopyBytesToStream(bufferSize, responseBodyStream, await WebSession.ServerConnection.StreamReader.CopyBytesToStream(bufferSize, responseBodyStream,
WebSession.Response.ContentLength); WebSession.Response.ContentLength);
} }
else if ((WebSession.Response.HttpVersion.Major == 1 && WebSession.Response.HttpVersion.Minor == 0) || WebSession.Response.ContentLength == -1) else if ((WebSession.Response.HttpVersion.Major == 1 && WebSession.Response.HttpVersion.Minor == 0) || WebSession.Response.ContentLength == -1)
{ {
...@@ -166,6 +165,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -166,6 +165,7 @@ namespace Titanium.Web.Proxy.EventArguments
WebSession.Response.ResponseBody = await GetDecompressedResponseBody(WebSession.Response.ContentEncoding, WebSession.Response.ResponseBody = await GetDecompressedResponseBody(WebSession.Response.ContentEncoding,
responseBodyStream.ToArray()); responseBodyStream.ToArray());
} }
//set this to true for caching //set this to true for caching
WebSession.Response.ResponseBodyRead = true; WebSession.Response.ResponseBodyRead = true;
...@@ -189,7 +189,6 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -189,7 +189,6 @@ namespace Titanium.Web.Proxy.EventArguments
} }
return WebSession.Request.RequestBody; return WebSession.Request.RequestBody;
} }
/// <summary> /// <summary>
/// Gets the request body as string /// Gets the request body as string
/// </summary> /// </summary>
...@@ -256,6 +255,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -256,6 +255,7 @@ namespace Titanium.Web.Proxy.EventArguments
} }
await SetRequestBody(WebSession.Request.Encoding.GetBytes(body)); await SetRequestBody(WebSession.Request.Encoding.GetBytes(body));
} }
/// <summary> /// <summary>
...@@ -406,7 +406,6 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -406,7 +406,6 @@ namespace Titanium.Web.Proxy.EventArguments
public async Task Ok(byte[] result, Dictionary<string, HttpHeader> headers) public async Task Ok(byte[] result, Dictionary<string, HttpHeader> headers)
{ {
var response = new OkResponse(); var response = new OkResponse();
if (headers != null && headers.Count > 0) if (headers != null && headers.Count > 0)
{ {
response.ResponseHeaders = headers; response.ResponseHeaders = headers;
...@@ -419,83 +418,12 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -419,83 +418,12 @@ namespace Titanium.Web.Proxy.EventArguments
WebSession.Request.CancelRequest = true; WebSession.Request.CancelRequest = true;
} }
/// <summary>
/// Before request is made to server 
/// Respond with the specified HTML string to client
/// and ignore the request 
/// </summary>
/// <param name="html"></param>
/// <param name="status"></param>
public async Task GenericResponse(string html, HttpStatusCode status)
{
await GenericResponse(html, null, status);
}
/// <summary>
/// Before request is made to server 
/// Respond with the specified HTML string to client
/// and the specified status
/// and ignore the request 
/// </summary>
/// <param name="html"></param>
/// <param name="headers"></param>
/// <param name="status"></param>
public async Task GenericResponse(string html, Dictionary<string, HttpHeader> headers, HttpStatusCode status)
{
if (WebSession.Request.RequestLocked)
{
throw new Exception("You cannot call this function after request is made to server.");
}
if (html == null)
{
html = string.Empty;
}
var result = Encoding.Default.GetBytes(html);
await GenericResponse(result, headers, status);
}
/// <summary>
/// Before request is made to server
/// Respond with the specified byte[] to client
/// and the specified status
/// and ignore the request
/// </summary>
/// <param name="result"></param>
/// <param name="headers"></param>
/// <param name="status"></param>
/// <returns></returns>
public async Task GenericResponse(byte[] result, Dictionary<string, HttpHeader> headers, HttpStatusCode status)
{
var response = new GenericResponse(status);
if (headers != null && headers.Count > 0)
{
response.ResponseHeaders = headers;
}
response.HttpVersion = WebSession.Request.HttpVersion;
response.ResponseBody = result;
await Respond(response);
WebSession.Request.CancelRequest = true;
}
/// <summary>
/// Redirect to URL.
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
public async Task Redirect(string url) public async Task Redirect(string url)
{ {
var response = new RedirectResponse(); var response = new RedirectResponse();
response.HttpVersion = WebSession.Request.HttpVersion; response.HttpVersion = WebSession.Request.HttpVersion;
response.ResponseHeaders.Add("Location", new HttpHeader("Location", url)); response.ResponseHeaders.Add("Location", new Models.HttpHeader("Location", url));
response.ResponseBody = Encoding.ASCII.GetBytes(string.Empty); response.ResponseBody = Encoding.ASCII.GetBytes(string.Empty);
await Respond(response); await Respond(response);
...@@ -521,6 +449,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -521,6 +449,7 @@ namespace Titanium.Web.Proxy.EventArguments
/// </summary> /// </summary>
public void Dispose() public void Dispose()
{ {
} }
} }
} }
\ No newline at end of file
namespace Titanium.Web.Proxy.Exceptions using System;
namespace Titanium.Web.Proxy.Exceptions
{ {
/// <summary> /// <summary>
/// An expception thrown when body is unexpectedly empty /// An expception thrown when body is unexpectedly empty
/// </summary> /// </summary>
public class BodyNotFoundException : ProxyException public class BodyNotFoundException : ProxyException
{ {
/// <summary>
/// Constructor.
/// </summary>
/// <param name="message"></param>
public BodyNotFoundException(string message) public BodyNotFoundException(string message)
: base(message) : base(message)
{ {
......
...@@ -2,10 +2,7 @@ ...@@ -2,10 +2,7 @@
namespace Titanium.Web.Proxy.Extensions namespace Titanium.Web.Proxy.Extensions
{ {
/// <summary> public static class ByteArrayExtensions
/// Extension methods for Byte Arrays.
/// </summary>
internal static class ByteArrayExtensions
{ {
/// <summary> /// <summary>
/// Get the sub array from byte of data /// Get the sub array from byte of data
...@@ -15,11 +12,12 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -15,11 +12,12 @@ namespace Titanium.Web.Proxy.Extensions
/// <param name="index"></param> /// <param name="index"></param>
/// <param name="length"></param> /// <param name="length"></param>
/// <returns></returns> /// <returns></returns>
internal static T[] SubArray<T>(this T[] data, int index, int length) public static T[] SubArray<T>(this T[] data, int index, int length)
{ {
var result = new T[length]; T[] result = new T[length];
Array.Copy(data, index, result, 0, length); Array.Copy(data, index, result, 0, length);
return result; return result;
} }
} }
} }
using System; using System.Text;
using System.Text;
using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Shared; using Titanium.Web.Proxy.Shared;
...@@ -30,7 +29,7 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -30,7 +29,7 @@ namespace Titanium.Web.Proxy.Extensions
foreach (var contentType in contentTypes) foreach (var contentType in contentTypes)
{ {
var encodingSplit = contentType.Split('='); var encodingSplit = contentType.Split('=');
if (encodingSplit.Length == 2 && encodingSplit[0].Trim().Equals("charset", StringComparison.CurrentCultureIgnoreCase)) if (encodingSplit.Length == 2 && encodingSplit[0].ToLower().Trim() == "charset")
{ {
return Encoding.GetEncoding(encodingSplit[1]); return Encoding.GetEncoding(encodingSplit[1]);
} }
......
using System; using System.Text;
using System.Text;
using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Shared; using Titanium.Web.Proxy.Shared;
...@@ -27,7 +26,7 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -27,7 +26,7 @@ namespace Titanium.Web.Proxy.Extensions
foreach (var contentType in contentTypes) foreach (var contentType in contentTypes)
{ {
var encodingSplit = contentType.Split('='); var encodingSplit = contentType.Split('=');
if (encodingSplit.Length == 2 && encodingSplit[0].Trim().Equals("charset", StringComparison.CurrentCultureIgnoreCase)) if (encodingSplit.Length == 2 && encodingSplit[0].ToLower().Trim() == "charset")
{ {
return Encoding.GetEncoding(encodingSplit[1]); return Encoding.GetEncoding(encodingSplit[1]);
} }
......
...@@ -46,7 +46,7 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -46,7 +46,7 @@ namespace Titanium.Web.Proxy.Extensions
while (totalbytesRead < totalBytesToRead) while (totalbytesRead < totalBytesToRead)
{ {
var buffer = await streamReader.ReadBytesAsync(bytesToRead); var buffer = await streamReader.ReadBytesAsync(bufferSize, bytesToRead);
if (buffer.Length == 0) if (buffer.Length == 0)
{ {
...@@ -69,9 +69,10 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -69,9 +69,10 @@ namespace Titanium.Web.Proxy.Extensions
/// Copies the stream chunked /// Copies the stream chunked
/// </summary> /// </summary>
/// <param name="clientStreamReader"></param> /// <param name="clientStreamReader"></param>
/// <param name="bufferSize"></param>
/// <param name="stream"></param> /// <param name="stream"></param>
/// <returns></returns> /// <returns></returns>
internal static async Task CopyBytesToStreamChunked(this CustomBinaryReader clientStreamReader, Stream stream) internal static async Task CopyBytesToStreamChunked(this CustomBinaryReader clientStreamReader, int bufferSize, Stream stream)
{ {
while (true) while (true)
{ {
...@@ -80,7 +81,7 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -80,7 +81,7 @@ namespace Titanium.Web.Proxy.Extensions
if (chunkSize != 0) if (chunkSize != 0)
{ {
var buffer = await clientStreamReader.ReadBytesAsync(chunkSize); var buffer = await clientStreamReader.ReadBytesAsync(bufferSize, chunkSize);
await stream.WriteAsync(buffer, 0, buffer.Length); await stream.WriteAsync(buffer, 0, buffer.Length);
//chunk trail //chunk trail
await clientStreamReader.ReadLineAsync(); await clientStreamReader.ReadLineAsync();
...@@ -92,7 +93,6 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -92,7 +93,6 @@ namespace Titanium.Web.Proxy.Extensions
} }
} }
} }
/// <summary> /// <summary>
/// Writes the byte array body to the given stream; optionally chunked /// Writes the byte array body to the given stream; optionally chunked
/// </summary> /// </summary>
...@@ -136,7 +136,7 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -136,7 +136,7 @@ namespace Titanium.Web.Proxy.Extensions
if (contentLength < bufferSize) if (contentLength < bufferSize)
{ {
bytesToRead = (int) contentLength; bytesToRead = (int)contentLength;
} }
var buffer = new byte[bufferSize]; var buffer = new byte[bufferSize];
...@@ -154,12 +154,12 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -154,12 +154,12 @@ namespace Titanium.Web.Proxy.Extensions
bytesRead = 0; bytesRead = 0;
var remainingBytes = (contentLength - totalBytesRead); var remainingBytes = (contentLength - totalBytesRead);
bytesToRead = remainingBytes > (long) bufferSize ? bufferSize : (int) remainingBytes; bytesToRead = remainingBytes > (long)bufferSize ? bufferSize : (int)remainingBytes;
} }
} }
else else
{ {
await WriteResponseBodyChunked(inStreamReader, outStream); await WriteResponseBodyChunked(inStreamReader, bufferSize, outStream);
} }
} }
...@@ -167,9 +167,10 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -167,9 +167,10 @@ namespace Titanium.Web.Proxy.Extensions
/// Copies the streams chunked /// Copies the streams chunked
/// </summary> /// </summary>
/// <param name="inStreamReader"></param> /// <param name="inStreamReader"></param>
/// <param name="bufferSize"></param>
/// <param name="outStream"></param> /// <param name="outStream"></param>
/// <returns></returns> /// <returns></returns>
internal static async Task WriteResponseBodyChunked(this CustomBinaryReader inStreamReader, Stream outStream) internal static async Task WriteResponseBodyChunked(this CustomBinaryReader inStreamReader, int bufferSize, Stream outStream)
{ {
while (true) while (true)
{ {
...@@ -178,7 +179,7 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -178,7 +179,7 @@ namespace Titanium.Web.Proxy.Extensions
if (chunkSize != 0) if (chunkSize != 0)
{ {
var buffer = await inStreamReader.ReadBytesAsync(chunkSize); var buffer = await inStreamReader.ReadBytesAsync(bufferSize, chunkSize);
var chunkHeadBytes = Encoding.ASCII.GetBytes(chunkSize.ToString("x2")); var chunkHeadBytes = Encoding.ASCII.GetBytes(chunkSize.ToString("x2"));
...@@ -198,7 +199,6 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -198,7 +199,6 @@ namespace Titanium.Web.Proxy.Extensions
} }
} }
} }
/// <summary> /// <summary>
/// Copies the given input bytes to output stream chunked /// Copies the given input bytes to output stream chunked
/// </summary> /// </summary>
...@@ -216,5 +216,6 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -216,5 +216,6 @@ namespace Titanium.Web.Proxy.Extensions
await outStream.WriteAsync(ProxyConstants.ChunkEnd, 0, ProxyConstants.ChunkEnd.Length); await outStream.WriteAsync(ProxyConstants.ChunkEnd, 0, ProxyConstants.ChunkEnd.Length);
} }
} }
} }
\ No newline at end of file
using System.Globalization;
namespace Titanium.Web.Proxy.Extensions
{
internal static class StringExtensions
{
internal static bool ContainsIgnoreCase(this string str, string value)
{
return CultureInfo.CurrentCulture.CompareInfo.IndexOf(str, value, CompareOptions.IgnoreCase) >= 0;
}
}
}
...@@ -12,11 +12,11 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -12,11 +12,11 @@ namespace Titanium.Web.Proxy.Extensions
internal static bool IsConnected(this Socket client) internal static bool IsConnected(this Socket client)
{ {
// This is how you can determine whether a socket is still connected. // This is how you can determine whether a socket is still connected.
var blockingState = client.Blocking; bool blockingState = client.Blocking;
try try
{ {
var tmp = new byte[1]; byte[] tmp = new byte[1];
client.Blocking = false; client.Blocking = false;
client.Send(tmp, 0, 0); client.Send(tmp, 0, 0);
...@@ -25,7 +25,14 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -25,7 +25,14 @@ namespace Titanium.Web.Proxy.Extensions
catch (SocketException e) catch (SocketException e)
{ {
// 10035 == WSAEWOULDBLOCK // 10035 == WSAEWOULDBLOCK
return e.NativeErrorCode.Equals(10035); if (e.NativeErrorCode.Equals(10035))
{
return true;
}
else
{
return false;
}
} }
finally finally
{ {
...@@ -33,4 +40,5 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -33,4 +40,5 @@ namespace Titanium.Web.Proxy.Extensions
} }
} }
} }
} }
...@@ -3,9 +3,12 @@ using System.Collections.Generic; ...@@ -3,9 +3,12 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Shared;
namespace Titanium.Web.Proxy.Helpers namespace Titanium.Web.Proxy.Helpers
{ {
/// <summary> /// <summary>
/// A custom binary reader that would allo us to read string line by line /// A custom binary reader that would allo us to read string line by line
/// using the specified encoding /// using the specified encoding
...@@ -13,33 +16,15 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -13,33 +16,15 @@ namespace Titanium.Web.Proxy.Helpers
/// </summary> /// </summary>
internal class CustomBinaryReader : IDisposable internal class CustomBinaryReader : IDisposable
{ {
private readonly CustomBufferedStream stream; private Stream stream;
private readonly int bufferSize; private Encoding encoding;
private readonly Encoding encoding;
[ThreadStatic]
private static byte[] staticBufferField;
private byte[] staticBuffer internal CustomBinaryReader(Stream stream)
{
get
{
if (staticBufferField == null || staticBufferField.Length != bufferSize)
{
staticBufferField = new byte[bufferSize];
}
return staticBufferField;
}
}
internal CustomBinaryReader(CustomBufferedStream stream, int bufferSize)
{ {
this.stream = stream; this.stream = stream;
this.bufferSize = bufferSize;
//default to UTF-8 //default to UTF-8
encoding = Encoding.UTF8; this.encoding = Encoding.UTF8;
} }
internal Stream BaseStream => stream; internal Stream BaseStream => stream;
...@@ -50,41 +35,33 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -50,41 +35,33 @@ namespace Titanium.Web.Proxy.Helpers
/// <returns></returns> /// <returns></returns>
internal async Task<string> ReadLineAsync() internal async Task<string> ReadLineAsync()
{ {
var lastChar = default(byte); using (var readBuffer = new MemoryStream())
int bufferDataLength = 0;
// try to use the thread static buffer, usually it is enough
var buffer = staticBuffer;
while (stream.DataAvailable || await stream.FillBufferAsync())
{ {
var newChar = stream.ReadByteFromBuffer(); var lastChar = default(char);
buffer[bufferDataLength] = newChar; var buffer = new byte[1];
while ((await this.stream.ReadAsync(buffer, 0, 1)) > 0)
{
//if new line //if new line
if (lastChar == '\r' && newChar == '\n') if (lastChar == '\r' && buffer[0] == '\n')
{ {
return encoding.GetString(buffer, 0, bufferDataLength - 1); var result = readBuffer.ToArray();
return encoding.GetString(result.SubArray(0, result.Length - 1));
} }
//end of stream //end of stream
if (newChar == '\0') if (buffer[0] == '\0')
{ {
return encoding.GetString(buffer, 0, bufferDataLength); return encoding.GetString(readBuffer.ToArray());
} }
bufferDataLength++; await readBuffer.WriteAsync(buffer,0,1);
//store last char for new line comparison //store last char for new line comparison
lastChar = newChar; lastChar = (char)buffer[0];
if (bufferDataLength == buffer.Length)
{
ResizeBuffer(ref buffer, bufferDataLength * 2);
}
} }
return encoding.GetString(buffer, 0, bufferDataLength); return encoding.GetString(readBuffer.ToArray());
}
} }
/// <summary> /// <summary>
...@@ -102,69 +79,46 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -102,69 +79,46 @@ namespace Titanium.Web.Proxy.Helpers
return requestLines; return requestLines;
} }
/// <summary>
/// Read until the last new line, ignores the result
/// </summary>
/// <returns></returns>
internal async Task ReadAndIgnoreAllLinesAsync()
{
while (!string.IsNullOrEmpty(await ReadLineAsync()))
{
}
}
/// <summary> /// <summary>
/// Read the specified number of raw bytes from the base stream /// Read the specified number of raw bytes from the base stream
/// </summary> /// </summary>
/// <param name="totalBytesToRead"></param> /// <param name="totalBytesToRead"></param>
/// <returns></returns> /// <returns></returns>
internal async Task<byte[]> ReadBytesAsync(long totalBytesToRead) internal async Task<byte[]> ReadBytesAsync(int bufferSize, long totalBytesToRead)
{ {
int bytesToRead = bufferSize; int bytesToRead = bufferSize;
if (totalBytesToRead < bufferSize) if (totalBytesToRead < bufferSize)
bytesToRead = (int) totalBytesToRead; bytesToRead = (int)totalBytesToRead;
var buffer = staticBuffer; var buffer = new byte[bufferSize];
int bytesRead;
var bytesRead = 0;
var totalBytesRead = 0; var totalBytesRead = 0;
while ((bytesRead = await stream.ReadAsync(buffer, totalBytesRead, bytesToRead)) > 0) using (var outStream = new MemoryStream())
{
while ((bytesRead += await this.stream.ReadAsync(buffer, 0, bytesToRead)) > 0)
{ {
await outStream.WriteAsync(buffer, 0, bytesRead);
totalBytesRead += bytesRead; totalBytesRead += bytesRead;
if (totalBytesRead == totalBytesToRead) if (totalBytesRead == totalBytesToRead)
break; break;
var remainingBytes = totalBytesToRead - totalBytesRead; bytesRead = 0;
bytesToRead = Math.Min(bufferSize, (int) remainingBytes); var remainingBytes = (totalBytesToRead - totalBytesRead);
bytesToRead = remainingBytes > (long)bufferSize ? bufferSize : (int)remainingBytes;
if (totalBytesRead + bytesToRead > buffer.Length)
{
ResizeBuffer(ref buffer, Math.Min(totalBytesToRead, buffer.Length * 2));
}
} }
if (totalBytesRead != buffer.Length) return outStream.ToArray();
{
//Normally this should not happen. Resize the buffer anyway
var newBuffer = new byte[totalBytesRead];
Buffer.BlockCopy(buffer, 0, newBuffer, 0, totalBytesRead);
buffer = newBuffer;
} }
return buffer;
} }
public void Dispose() public void Dispose()
{ {
}
private void ResizeBuffer(ref byte[] buffer, long size)
{
var newBuffer = new byte[size];
Buffer.BlockCopy(buffer, 0, newBuffer, 0, buffer.Length);
buffer = newBuffer;
} }
} }
} }
\ No newline at end of file
This diff is collapsed.
...@@ -6,12 +6,9 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -6,12 +6,9 @@ namespace Titanium.Web.Proxy.Helpers
/// <summary> /// <summary>
/// A helper class to set proxy settings for firefox /// A helper class to set proxy settings for firefox
/// </summary> /// </summary>
internal class FireFoxProxySettingsManager public class FireFoxProxySettingsManager
{ {
/// <summary> public void AddFirefox()
/// Add Firefox settings.
/// </summary>
internal void AddFirefox()
{ {
try try
{ {
...@@ -19,28 +16,29 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -19,28 +16,29 @@ namespace Titanium.Web.Proxy.Helpers
new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) +
"\\Mozilla\\Firefox\\Profiles\\").GetDirectories("*.default"); "\\Mozilla\\Firefox\\Profiles\\").GetDirectories("*.default");
var myFfPrefFile = myProfileDirectory[0].FullName + "\\prefs.js"; var myFfPrefFile = myProfileDirectory[0].FullName + "\\prefs.js";
if (!File.Exists(myFfPrefFile)) return; if (File.Exists(myFfPrefFile))
{
// We have a pref file so let''s make sure it has the proxy setting // We have a pref file so let''s make sure it has the proxy setting
var myReader = new StreamReader(myFfPrefFile); var myReader = new StreamReader(myFfPrefFile);
var myPrefContents = myReader.ReadToEnd(); var myPrefContents = myReader.ReadToEnd();
myReader.Close(); myReader.Close();
if (!myPrefContents.Contains("user_pref(\"network.proxy.type\", 0);")) return; if (myPrefContents.Contains("user_pref(\"network.proxy.type\", 0);"))
{
// Add the proxy enable line and write it back to the file // Add the proxy enable line and write it back to the file
myPrefContents = myPrefContents.Replace("user_pref(\"network.proxy.type\", 0);", ""); myPrefContents = myPrefContents.Replace("user_pref(\"network.proxy.type\", 0);", "");
File.Delete(myFfPrefFile); File.Delete(myFfPrefFile);
File.WriteAllText(myFfPrefFile, myPrefContents); File.WriteAllText(myFfPrefFile, myPrefContents);
} }
}
}
catch (Exception) catch (Exception)
{ {
// Only exception should be a read/write error because the user opened up FireFox so they can be ignored. // Only exception should be a read/write error because the user opened up FireFox so they can be ignored.
} }
} }
/// <summary> public void RemoveFirefox()
/// Remove firefox settings.
/// </summary>
internal void RemoveFirefox()
{ {
try try
{ {
...@@ -48,7 +46,8 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -48,7 +46,8 @@ namespace Titanium.Web.Proxy.Helpers
new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) +
"\\Mozilla\\Firefox\\Profiles\\").GetDirectories("*.default"); "\\Mozilla\\Firefox\\Profiles\\").GetDirectories("*.default");
var myFfPrefFile = myProfileDirectory[0].FullName + "\\prefs.js"; var myFfPrefFile = myProfileDirectory[0].FullName + "\\prefs.js";
if (!File.Exists(myFfPrefFile)) return; if (File.Exists(myFfPrefFile))
{
// We have a pref file so let''s make sure it has the proxy setting // We have a pref file so let''s make sure it has the proxy setting
var myReader = new StreamReader(myFfPrefFile); var myReader = new StreamReader(myFfPrefFile);
var myPrefContents = myReader.ReadToEnd(); var myPrefContents = myReader.ReadToEnd();
...@@ -62,6 +61,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -62,6 +61,7 @@ namespace Titanium.Web.Proxy.Helpers
File.WriteAllText(myFfPrefFile, myPrefContents); File.WriteAllText(myFfPrefFile, myPrefContents);
} }
} }
}
catch (Exception) catch (Exception)
{ {
// Only exception should be a read/write error because the user opened up FireFox so they can be ignored. // Only exception should be a read/write error because the user opened up FireFox so they can be ignored.
......
using System.Linq; using System;
using System.Collections.Generic;
using System.Linq;
using System.Net; using System.Net;
using System.Net.Sockets; using System.Text;
using System.Threading.Tasks;
namespace Titanium.Web.Proxy.Helpers namespace Titanium.Web.Proxy.Helpers
{ {
...@@ -30,50 +33,28 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -30,50 +33,28 @@ namespace Titanium.Web.Proxy.Helpers
/// Adapated from below link /// Adapated from below link
/// http://stackoverflow.com/questions/11834091/how-to-check-if-localhost /// http://stackoverflow.com/questions/11834091/how-to-check-if-localhost
/// </summary> /// </summary>
/// <param name="address"></param> /// <param name="address></param>
/// <returns></returns> /// <returns></returns>
internal static bool IsLocalIpAddress(IPAddress address) internal static bool IsLocalIpAddress(IPAddress address)
{
try
{ {
// get local IP addresses // get local IP addresses
var localIPs = Dns.GetHostAddresses(Dns.GetHostName()); IPAddress[] localIPs = Dns.GetHostAddresses(Dns.GetHostName());
// test if any host IP equals to any local IP or to localhost
return IPAddress.IsLoopback(address) || localIPs.Contains(address);
}
internal static bool IsLocalIpAddress(string hostName) // test if any host IP equals to any local IP or to localhost
{
bool isLocalhost = false;
IPHostEntry localhost = Dns.GetHostEntry("127.0.0.1"); // is localhost
if (hostName == localhost.HostName) if (IPAddress.IsLoopback(address)) return true;
// is local address
foreach (IPAddress localIP in localIPs)
{ {
IPHostEntry hostEntry = Dns.GetHostEntry(hostName); if (address.Equals(localIP)) return true;
isLocalhost = hostEntry.AddressList.Any(IPAddress.IsLoopback);
} }
if (!isLocalhost)
{
localhost = Dns.GetHostEntry(Dns.GetHostName());
IPAddress ipAddress;
if (IPAddress.TryParse(hostName, out ipAddress))
isLocalhost = localhost.AddressList.Any(x => x.Equals(ipAddress));
if (!isLocalhost)
{
try
{
var hostEntry = Dns.GetHostEntry(hostName);
isLocalhost = localhost.AddressList.Any(x => hostEntry.AddressList.Any(x.Equals));
} }
catch (SocketException) catch { }
{ return false;
}
}
}
return isLocalhost;
} }
} }
} }
using System;
namespace Titanium.Web.Proxy.Helpers
{
/// <summary>
/// Run time helpers
/// </summary>
internal class RunTime
{
/// <summary>
/// Checks if current run time is Mono
/// </summary>
/// <returns></returns>
internal static bool IsRunningOnMono()
{
return Type.GetType("Mono.Runtime") != null;
}
}
}
...@@ -4,8 +4,11 @@ using Microsoft.Win32; ...@@ -4,8 +4,11 @@ using Microsoft.Win32;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net.Sockets;
// Helper classes for setting system proxy settings /// <summary>
/// Helper classes for setting system proxy settings
/// </summary>
namespace Titanium.Web.Proxy.Helpers namespace Titanium.Web.Proxy.Helpers
{ {
internal enum ProxyProtocolType internal enum ProxyProtocolType
...@@ -125,7 +128,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -125,7 +128,7 @@ namespace Titanium.Web.Proxy.Helpers
} }
/// <summary> /// <summary>
/// Removes all types of proxy settings (both http and https) /// Removes all types of proxy settings (both http & https)
/// </summary> /// </summary>
internal void DisableAllProxy() internal void DisableAllProxy()
{ {
...@@ -181,7 +184,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -181,7 +184,7 @@ namespace Titanium.Web.Proxy.Helpers
if (tmp.StartsWith("http=") || tmp.StartsWith("https=")) if (tmp.StartsWith("http=") || tmp.StartsWith("https="))
{ {
var endPoint = tmp.Substring(5); var endPoint = tmp.Substring(5);
return new HttpSystemProxyValue return new HttpSystemProxyValue()
{ {
HostName = endPoint.Split(':')[0], HostName = endPoint.Split(':')[0],
Port = int.Parse(endPoint.Split(':')[1]), Port = int.Parse(endPoint.Split(':')[1]),
...@@ -190,8 +193,8 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -190,8 +193,8 @@ namespace Titanium.Web.Proxy.Helpers
} }
return null; return null;
}
}
/// <summary> /// <summary>
/// Prepares the proxy server registry (create empty values if they don't exist) /// Prepares the proxy server registry (create empty values if they don't exist)
/// </summary> /// </summary>
...@@ -207,6 +210,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -207,6 +210,7 @@ namespace Titanium.Web.Proxy.Helpers
{ {
reg.SetValue("ProxyServer", string.Empty); reg.SetValue("ProxyServer", string.Empty);
} }
} }
/// <summary> /// <summary>
......
...@@ -42,7 +42,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -42,7 +42,7 @@ namespace Titanium.Web.Proxy.Helpers
} }
/// <summary> /// <summary>
/// <see href="http://msdn2.microsoft.com/en-us/library/aa366921.aspx"/> /// <see cref="http://msdn2.microsoft.com/en-us/library/aa366921.aspx"/>
/// </summary> /// </summary>
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
internal struct TcpTable internal struct TcpTable
...@@ -52,7 +52,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -52,7 +52,7 @@ namespace Titanium.Web.Proxy.Helpers
} }
/// <summary> /// <summary>
/// <see href="http://msdn2.microsoft.com/en-us/library/aa366913.aspx"/> /// <see cref="http://msdn2.microsoft.com/en-us/library/aa366913.aspx"/>
/// </summary> /// </summary>
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
internal struct TcpRow internal struct TcpRow
...@@ -72,7 +72,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -72,7 +72,7 @@ namespace Titanium.Web.Proxy.Helpers
} }
/// <summary> /// <summary>
/// <see href="http://msdn2.microsoft.com/en-us/library/aa365928.aspx"/> /// <see cref="http://msdn2.microsoft.com/en-us/library/aa365928.aspx"/>
/// </summary> /// </summary>
[DllImport("iphlpapi.dll", SetLastError = true)] [DllImport("iphlpapi.dll", SetLastError = true)]
internal static extern uint GetExtendedTcpTable(IntPtr tcpTable, ref int size, bool sort, int ipVersion, int tableClass, int reserved); internal static extern uint GetExtendedTcpTable(IntPtr tcpTable, ref int size, bool sort, int ipVersion, int tableClass, int reserved);
...@@ -93,21 +93,21 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -93,21 +93,21 @@ namespace Titanium.Web.Proxy.Helpers
var ipVersionValue = ipVersion == IpVersion.Ipv4 ? NativeMethods.AfInet : NativeMethods.AfInet6; var ipVersionValue = ipVersion == IpVersion.Ipv4 ? NativeMethods.AfInet : NativeMethods.AfInet6;
if (NativeMethods.GetExtendedTcpTable(tcpTable, ref tcpTableLength, false, ipVersionValue, (int) NativeMethods.TcpTableType.OwnerPidAll, 0) != 0) if (NativeMethods.GetExtendedTcpTable(tcpTable, ref tcpTableLength, false, ipVersionValue, (int)NativeMethods.TcpTableType.OwnerPidAll, 0) != 0)
{ {
try try
{ {
tcpTable = Marshal.AllocHGlobal(tcpTableLength); tcpTable = Marshal.AllocHGlobal(tcpTableLength);
if (NativeMethods.GetExtendedTcpTable(tcpTable, ref tcpTableLength, true, ipVersionValue, (int) NativeMethods.TcpTableType.OwnerPidAll, 0) == 0) if (NativeMethods.GetExtendedTcpTable(tcpTable, ref tcpTableLength, true, ipVersionValue, (int)NativeMethods.TcpTableType.OwnerPidAll, 0) == 0)
{ {
NativeMethods.TcpTable table = (NativeMethods.TcpTable) Marshal.PtrToStructure(tcpTable, typeof(NativeMethods.TcpTable)); NativeMethods.TcpTable table = (NativeMethods.TcpTable)Marshal.PtrToStructure(tcpTable, typeof(NativeMethods.TcpTable));
IntPtr rowPtr = (IntPtr) ((long) tcpTable + Marshal.SizeOf(table.length)); IntPtr rowPtr = (IntPtr)((long)tcpTable + Marshal.SizeOf(table.length));
for (int i = 0; i < table.length; ++i) for (int i = 0; i < table.length; ++i)
{ {
tcpRows.Add(new TcpRow((NativeMethods.TcpRow) Marshal.PtrToStructure(rowPtr, typeof(NativeMethods.TcpRow)))); tcpRows.Add(new TcpRow((NativeMethods.TcpRow)Marshal.PtrToStructure(rowPtr, typeof(NativeMethods.TcpRow))));
rowPtr = (IntPtr) ((long) rowPtr + Marshal.SizeOf(typeof(NativeMethods.TcpRow))); rowPtr = (IntPtr)((long)rowPtr + Marshal.SizeOf(typeof(NativeMethods.TcpRow)));
} }
} }
} }
...@@ -124,7 +124,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -124,7 +124,7 @@ namespace Titanium.Web.Proxy.Helpers
} }
/// <summary> /// <summary>
/// relays the input clientStream to the server at the specified host name and port with the given httpCmd and headers as prefix /// relays the input clientStream to the server at the specified host name & port with the given httpCmd & headers as prefix
/// Usefull for websocket requests /// Usefull for websocket requests
/// </summary> /// </summary>
/// <param name="bufferSize"></param> /// <param name="bufferSize"></param>
...@@ -140,7 +140,6 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -140,7 +140,6 @@ namespace Titanium.Web.Proxy.Helpers
/// <param name="localCertificateSelectionCallback"></param> /// <param name="localCertificateSelectionCallback"></param>
/// <param name="clientStream"></param> /// <param name="clientStream"></param>
/// <param name="tcpConnectionFactory"></param> /// <param name="tcpConnectionFactory"></param>
/// <param name="upStreamEndPoint"></param>
/// <returns></returns> /// <returns></returns>
internal static async Task SendRaw(int bufferSize, int connectionTimeOutSeconds, internal static async Task SendRaw(int bufferSize, int connectionTimeOutSeconds,
string remoteHostName, int remotePort, string httpCmd, Version httpVersion, Dictionary<string, HttpHeader> requestHeaders, string remoteHostName, int remotePort, string httpCmd, Version httpVersion, Dictionary<string, HttpHeader> requestHeaders,
......
This diff is collapsed.
...@@ -34,7 +34,12 @@ namespace Titanium.Web.Proxy.Http ...@@ -34,7 +34,12 @@ namespace Titanium.Web.Proxy.Http
get get
{ {
var hasHeader = RequestHeaders.ContainsKey("host"); var hasHeader = RequestHeaders.ContainsKey("host");
return hasHeader ? RequestHeaders["host"].Value : null; if (hasHeader)
{
return RequestHeaders["host"].Value;
}
return null;
} }
set set
{ {
...@@ -47,6 +52,7 @@ namespace Titanium.Web.Proxy.Http ...@@ -47,6 +52,7 @@ namespace Titanium.Web.Proxy.Http
{ {
RequestHeaders.Add("Host", new HttpHeader("Host", value)); RequestHeaders.Add("Host", new HttpHeader("Host", value));
} }
} }
} }
...@@ -118,7 +124,9 @@ namespace Titanium.Web.Proxy.Http ...@@ -118,7 +124,9 @@ namespace Titanium.Web.Proxy.Http
{ {
RequestHeaders.Remove("content-length"); RequestHeaders.Remove("content-length");
} }
} }
} }
} }
...@@ -146,13 +154,14 @@ namespace Titanium.Web.Proxy.Http ...@@ -146,13 +154,14 @@ namespace Titanium.Web.Proxy.Http
if (hasHeader) if (hasHeader)
{ {
var header = RequestHeaders["content-type"]; var header = RequestHeaders["content-type"];
header.Value = value; header.Value = value.ToString();
} }
else else
{ {
RequestHeaders.Add("content-type", new HttpHeader("content-type", value)); RequestHeaders.Add("content-type", new HttpHeader("content-type", value.ToString()));
} }
} }
} }
/// <summary> /// <summary>
...@@ -168,7 +177,7 @@ namespace Titanium.Web.Proxy.Http ...@@ -168,7 +177,7 @@ namespace Titanium.Web.Proxy.Http
{ {
var header = RequestHeaders["transfer-encoding"]; var header = RequestHeaders["transfer-encoding"];
return header.Value.ContainsIgnoreCase("chunked"); return header.Value.ToLower().Contains("chunked");
} }
return false; return false;
...@@ -210,11 +219,15 @@ namespace Titanium.Web.Proxy.Http ...@@ -210,11 +219,15 @@ namespace Titanium.Web.Proxy.Http
{ {
var hasHeader = RequestHeaders.ContainsKey("expect"); var hasHeader = RequestHeaders.ContainsKey("expect");
if (!hasHeader) return false; if (hasHeader)
{
var header = RequestHeaders["expect"]; var header = RequestHeaders["expect"];
return header.Value.Equals("100-continue"); return header.Value.Equals("100-continue");
} }
return false;
}
} }
/// <summary> /// <summary>
...@@ -262,7 +275,13 @@ namespace Titanium.Web.Proxy.Http ...@@ -262,7 +275,13 @@ namespace Titanium.Web.Proxy.Http
var header = RequestHeaders["upgrade"]; var header = RequestHeaders["upgrade"];
return header.Value.Equals("websocket", StringComparison.CurrentCultureIgnoreCase); if (header.Value.ToLower() == "websocket")
{
return true;
}
return false;
} }
} }
...@@ -286,13 +305,11 @@ namespace Titanium.Web.Proxy.Http ...@@ -286,13 +305,11 @@ namespace Titanium.Web.Proxy.Http
/// </summary> /// </summary>
public bool ExpectationFailed { get; internal set; } public bool ExpectationFailed { get; internal set; }
/// <summary>
/// Constructor.
/// </summary>
public Request() public Request()
{ {
RequestHeaders = new Dictionary<string, HttpHeader>(StringComparer.OrdinalIgnoreCase); RequestHeaders = new Dictionary<string, HttpHeader>(StringComparer.OrdinalIgnoreCase);
NonUniqueRequestHeaders = new Dictionary<string, List<HttpHeader>>(StringComparer.OrdinalIgnoreCase); NonUniqueRequestHeaders = new Dictionary<string, List<HttpHeader>>(StringComparer.OrdinalIgnoreCase);
} }
} }
} }
...@@ -12,14 +12,7 @@ namespace Titanium.Web.Proxy.Http ...@@ -12,14 +12,7 @@ namespace Titanium.Web.Proxy.Http
/// </summary> /// </summary>
public class Response public class Response
{ {
/// <summary>
/// Response Status Code.
/// </summary>
public string ResponseStatusCode { get; set; } public string ResponseStatusCode { get; set; }
/// <summary>
/// Response Status description.
/// </summary>
public string ResponseStatusDescription { get; set; } public string ResponseStatusDescription { get; set; }
internal Encoding Encoding => this.GetResponseCharacterEncoding(); internal Encoding Encoding => this.GetResponseCharacterEncoding();
...@@ -33,11 +26,15 @@ namespace Titanium.Web.Proxy.Http ...@@ -33,11 +26,15 @@ namespace Titanium.Web.Proxy.Http
{ {
var hasHeader = ResponseHeaders.ContainsKey("content-encoding"); var hasHeader = ResponseHeaders.ContainsKey("content-encoding");
if (!hasHeader) return null; if (hasHeader)
{
var header = ResponseHeaders["content-encoding"]; var header = ResponseHeaders["content-encoding"];
return header.Value.Trim(); return header.Value.Trim();
} }
return null;
}
} }
internal Version HttpVersion { get; set; } internal Version HttpVersion { get; set; }
...@@ -55,13 +52,14 @@ namespace Titanium.Web.Proxy.Http ...@@ -55,13 +52,14 @@ namespace Titanium.Web.Proxy.Http
{ {
var header = ResponseHeaders["connection"]; var header = ResponseHeaders["connection"];
if (header.Value.ContainsIgnoreCase("close")) if (header.Value.ToLower().Contains("close"))
{ {
return false; return false;
} }
} }
return true; return true;
} }
} }
...@@ -82,6 +80,7 @@ namespace Titanium.Web.Proxy.Http ...@@ -82,6 +80,7 @@ namespace Titanium.Web.Proxy.Http
} }
return null; return null;
} }
} }
...@@ -109,6 +108,7 @@ namespace Titanium.Web.Proxy.Http ...@@ -109,6 +108,7 @@ namespace Titanium.Web.Proxy.Http
} }
return -1; return -1;
} }
set set
{ {
...@@ -151,13 +151,14 @@ namespace Titanium.Web.Proxy.Http ...@@ -151,13 +151,14 @@ namespace Titanium.Web.Proxy.Http
{ {
var header = ResponseHeaders["transfer-encoding"]; var header = ResponseHeaders["transfer-encoding"];
if (header.Value.ContainsIgnoreCase("chunked")) if (header.Value.ToLower().Contains("chunked"))
{ {
return true; return true;
} }
} }
return false; return false;
} }
set set
{ {
...@@ -183,7 +184,9 @@ namespace Titanium.Web.Proxy.Http ...@@ -183,7 +184,9 @@ namespace Titanium.Web.Proxy.Http
{ {
ResponseHeaders.Remove("transfer-encoding"); ResponseHeaders.Remove("transfer-encoding");
} }
} }
} }
} }
...@@ -226,13 +229,11 @@ namespace Titanium.Web.Proxy.Http ...@@ -226,13 +229,11 @@ namespace Titanium.Web.Proxy.Http
/// </summary> /// </summary>
public bool ExpectationFailed { get; internal set; } public bool ExpectationFailed { get; internal set; }
/// <summary>
/// Constructor.
/// </summary>
public Response() public Response()
{ {
ResponseHeaders = new Dictionary<string, HttpHeader>(StringComparer.OrdinalIgnoreCase); this.ResponseHeaders = new Dictionary<string, HttpHeader>(StringComparer.OrdinalIgnoreCase);
NonUniqueResponseHeaders = new Dictionary<string, List<HttpHeader>>(StringComparer.OrdinalIgnoreCase); this.NonUniqueResponseHeaders = new Dictionary<string, List<HttpHeader>>(StringComparer.OrdinalIgnoreCase);
} }
} }
} }
using System.Net;
namespace Titanium.Web.Proxy.Http.Responses
{
/// <summary>
/// Anything other than a 200 or 302 response
/// </summary>
public class GenericResponse : Response
{
/// <summary>
/// Constructor.
/// </summary>
/// <param name="status"></param>
public GenericResponse(HttpStatusCode status)
{
ResponseStatusCode = ((int) status).ToString();
ResponseStatusDescription = status.ToString();
}
/// <summary>
/// Constructor.
/// </summary>
/// <param name="statusCode"></param>
/// <param name="statusDescription"></param>
public GenericResponse(string statusCode, string statusDescription)
{
ResponseStatusCode = statusCode;
ResponseStatusDescription = statusDescription;
}
}
}
...@@ -5,9 +5,6 @@ ...@@ -5,9 +5,6 @@
/// </summary> /// </summary>
public sealed class OkResponse : Response public sealed class OkResponse : Response
{ {
/// <summary>
/// Constructor.
/// </summary>
public OkResponse() public OkResponse()
{ {
ResponseStatusCode = "200"; ResponseStatusCode = "200";
......
...@@ -5,9 +5,6 @@ ...@@ -5,9 +5,6 @@
/// </summary> /// </summary>
public sealed class RedirectResponse : Response public sealed class RedirectResponse : Response
{ {
/// <summary>
/// Constructor.
/// </summary>
public RedirectResponse() public RedirectResponse()
{ {
ResponseStatusCode = "302"; ResponseStatusCode = "302";
......
using System; using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using System.Net; using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
using System.Security.Cryptography.X509Certificates;
using System.Text.RegularExpressions;
namespace Titanium.Web.Proxy.Models namespace Titanium.Web.Proxy.Models
{ {
...@@ -13,42 +9,22 @@ namespace Titanium.Web.Proxy.Models ...@@ -13,42 +9,22 @@ namespace Titanium.Web.Proxy.Models
/// </summary> /// </summary>
public abstract class ProxyEndPoint public abstract class ProxyEndPoint
{ {
/// <summary> public ProxyEndPoint(IPAddress IpAddress, int Port, bool EnableSsl)
/// Constructor.
/// </summary>
/// <param name="ipAddress"></param>
/// <param name="port"></param>
/// <param name="enableSsl"></param>
protected ProxyEndPoint(IPAddress ipAddress, int port, bool enableSsl)
{ {
IpAddress = ipAddress; this.IpAddress = IpAddress;
Port = port; this.Port = Port;
EnableSsl = enableSsl; this.EnableSsl = EnableSsl;
} }
/// <summary>
/// Ip Address.
/// </summary>
public IPAddress IpAddress { get; internal set; } public IPAddress IpAddress { get; internal set; }
/// <summary>
/// Port.
/// </summary>
public int Port { get; internal set; } public int Port { get; internal set; }
/// <summary>
/// Enable SSL?
/// </summary>
public bool EnableSsl { get; internal set; } public bool EnableSsl { get; internal set; }
/// <summary> public bool IpV6Enabled => IpAddress == IPAddress.IPv6Any
/// Is IPv6 enabled? || IpAddress == IPAddress.IPv6Loopback
/// </summary> || IpAddress == IPAddress.IPv6None;
public bool IpV6Enabled => Equals(IpAddress, IPAddress.IPv6Any)
|| Equals(IpAddress, IPAddress.IPv6Loopback)
|| Equals(IpAddress, IPAddress.IPv6None);
internal TcpListener Listener { get; set; } internal TcpListener listener { get; set; }
} }
/// <summary> /// <summary>
...@@ -57,61 +33,15 @@ namespace Titanium.Web.Proxy.Models ...@@ -57,61 +33,15 @@ namespace Titanium.Web.Proxy.Models
/// </summary> /// </summary>
public class ExplicitProxyEndPoint : ProxyEndPoint public class ExplicitProxyEndPoint : ProxyEndPoint
{ {
internal List<Regex> ExcludedHttpsHostNameRegexList;
internal List<Regex> IncludedHttpsHostNameRegexList;
internal bool IsSystemHttpProxy { get; set; } internal bool IsSystemHttpProxy { get; set; }
internal bool IsSystemHttpsProxy { get; set; } internal bool IsSystemHttpsProxy { get; set; }
/// <summary> public List<string> ExcludedHttpsHostNameRegex { get; set; }
/// List of host names to exclude using Regular Expressions.
/// </summary>
public IEnumerable<string> ExcludedHttpsHostNameRegex
{
get { return ExcludedHttpsHostNameRegexList?.Select(x => x.ToString()).ToList(); }
set
{
if (IncludedHttpsHostNameRegex != null)
{
throw new ArgumentException("Cannot set excluded when included is set");
}
ExcludedHttpsHostNameRegexList = value?.Select(x => new Regex(x, RegexOptions.Compiled)).ToList();
}
}
/// <summary> public ExplicitProxyEndPoint(IPAddress IpAddress, int Port, bool EnableSsl)
/// List of host names to exclude using Regular Expressions. : base(IpAddress, Port, EnableSsl)
/// </summary>
public IEnumerable<string> IncludedHttpsHostNameRegex
{ {
get { return IncludedHttpsHostNameRegexList?.Select(x => x.ToString()).ToList(); }
set
{
if (ExcludedHttpsHostNameRegex != null)
{
throw new ArgumentException("Cannot set included when excluded is set");
}
IncludedHttpsHostNameRegexList = value?.Select(x => new Regex(x, RegexOptions.Compiled)).ToList();
}
}
/// <summary>
/// Generic certificate to use for SSL decryption.
/// </summary>
public X509Certificate2 GenericCertificate { get; set; }
/// <summary>
/// Constructor.
/// </summary>
/// <param name="ipAddress"></param>
/// <param name="port"></param>
/// <param name="enableSsl"></param>
public ExplicitProxyEndPoint(IPAddress ipAddress, int port, bool enableSsl)
: base(ipAddress, port, enableSsl)
{
} }
} }
...@@ -121,22 +51,18 @@ namespace Titanium.Web.Proxy.Models ...@@ -121,22 +51,18 @@ namespace Titanium.Web.Proxy.Models
/// </summary> /// </summary>
public class TransparentProxyEndPoint : ProxyEndPoint public class TransparentProxyEndPoint : ProxyEndPoint
{ {
/// <summary> //Name of the Certificate need to be sent (same as the hostname we want to proxy)
/// Name of the Certificate need to be sent (same as the hostname we want to proxy) //This is valid only when UseServerNameIndication is set to false
/// This is valid only when UseServerNameIndication is set to false
/// </summary>
public string GenericCertificateName { get; set; } public string GenericCertificateName { get; set; }
/// <summary>
/// Constructor. // public bool UseServerNameIndication { get; set; }
/// </summary>
/// <param name="ipAddress"></param> public TransparentProxyEndPoint(IPAddress IpAddress, int Port, bool EnableSsl)
/// <param name="port"></param> : base(IpAddress, Port, EnableSsl)
/// <param name="enableSsl"></param>
public TransparentProxyEndPoint(IPAddress ipAddress, int port, bool enableSsl)
: base(ipAddress, port, enableSsl)
{ {
GenericCertificateName = "localhost"; this.GenericCertificateName = "localhost";
} }
} }
} }
...@@ -8,63 +8,41 @@ namespace Titanium.Web.Proxy.Models ...@@ -8,63 +8,41 @@ namespace Titanium.Web.Proxy.Models
/// </summary> /// </summary>
public class ExternalProxy public class ExternalProxy
{ {
private static readonly Lazy<NetworkCredential> defaultCredentials = new Lazy<NetworkCredential>(() => CredentialCache.DefaultNetworkCredentials); private static readonly Lazy<NetworkCredential> DefaultCredentials = new Lazy<NetworkCredential>(() => CredentialCache.DefaultNetworkCredentials);
private string userName; private string userName;
private string password; private string password;
/// <summary>
/// Use default windows credentials?
/// </summary>
public bool UseDefaultCredentials { get; set; } public bool UseDefaultCredentials { get; set; }
/// <summary> public string UserName {
/// Bypass this proxy for connections to localhost? get { return UseDefaultCredentials ? DefaultCredentials.Value.UserName : userName; }
/// </summary>
public bool BypassForLocalhost { get; set; }
/// <summary>
/// Username.
/// </summary>
public string UserName
{
get { return UseDefaultCredentials ? defaultCredentials.Value.UserName : userName; }
set set
{ {
userName = value; userName = value;
if (defaultCredentials.Value.UserName != userName) if (DefaultCredentials.Value.UserName != userName)
{ {
UseDefaultCredentials = false; UseDefaultCredentials = false;
} }
} }
} }
/// <summary>
/// Password.
/// </summary>
public string Password public string Password
{ {
get { return UseDefaultCredentials ? defaultCredentials.Value.Password : password; } get { return UseDefaultCredentials ? DefaultCredentials.Value.Password : password; }
set set
{ {
password = value; password = value;
if (defaultCredentials.Value.Password != password) if (DefaultCredentials.Value.Password != password)
{ {
UseDefaultCredentials = false; UseDefaultCredentials = false;
} }
} }
} }
/// <summary>
/// Host name.
/// </summary>
public string HostName { get; set; } public string HostName { get; set; }
/// <summary>
/// Port.
/// </summary>
public int Port { get; set; } public int Port { get; set; }
} }
} }
using System; using System;
using System.IO;
using System.Threading.Tasks;
namespace Titanium.Web.Proxy.Models namespace Titanium.Web.Proxy.Models
{ {
...@@ -9,12 +7,6 @@ namespace Titanium.Web.Proxy.Models ...@@ -9,12 +7,6 @@ namespace Titanium.Web.Proxy.Models
/// </summary> /// </summary>
public class HttpHeader public class HttpHeader
{ {
/// <summary>
/// Constructor.
/// </summary>
/// <param name="name"></param>
/// <param name="value"></param>
/// <exception cref="Exception"></exception>
public HttpHeader(string name, string value) public HttpHeader(string name, string value)
{ {
if (string.IsNullOrEmpty(name)) if (string.IsNullOrEmpty(name))
...@@ -26,14 +18,7 @@ namespace Titanium.Web.Proxy.Models ...@@ -26,14 +18,7 @@ namespace Titanium.Web.Proxy.Models
Value = value.Trim(); Value = value.Trim();
} }
/// <summary>
/// Header Name.
/// </summary>
public string Name { get; set; } public string Name { get; set; }
/// <summary>
/// Header Value.
/// </summary>
public string Value { get; set; } public string Value { get; set; }
/// <summary> /// <summary>
...@@ -42,14 +27,7 @@ namespace Titanium.Web.Proxy.Models ...@@ -42,14 +27,7 @@ namespace Titanium.Web.Proxy.Models
/// <returns></returns> /// <returns></returns>
public override string ToString() public override string ToString()
{ {
return $"{Name}: {Value}"; return string.Format("{0}: {1}", Name, Value);
}
internal async Task WriteToStream(StreamWriter writer)
{
await writer.WriteAsync(Name);
await writer.WriteAsync(": ");
await writer.WriteLineAsync(Value);
} }
} }
} }
\ No newline at end of file
...@@ -20,5 +20,6 @@ namespace Titanium.Web.Proxy.Network ...@@ -20,5 +20,6 @@ namespace Titanium.Web.Proxy.Network
{ {
LastAccess = DateTime.Now; LastAccess = DateTime.Now;
} }
} }
} }
using System;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Operators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Prng;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.X509;
namespace Titanium.Web.Proxy.Network.Certificate
{
/// <summary>
/// Implements certificate generation operations.
/// </summary>
internal class BCCertificateMaker : ICertificateMaker
{
private const int certificateValidDays = 1825;
private const int certificateGraceDays = 366;
/// <summary>
/// Makes the certificate.
/// </summary>
/// <param name="sSubjectCn">The s subject cn.</param>
/// <param name="isRoot">if set to <c>true</c> [is root].</param>
/// <param name="signingCert">The signing cert.</param>
/// <returns>X509Certificate2 instance.</returns>
public X509Certificate2 MakeCertificate(string sSubjectCn, bool isRoot, X509Certificate2 signingCert = null)
{
return MakeCertificateInternal(sSubjectCn, isRoot, true, signingCert);
}
/// <summary>
/// Generates the certificate.
/// </summary>
/// <param name="subjectName">Name of the subject.</param>
/// <param name="issuerName">Name of the issuer.</param>
/// <param name="validFrom">The valid from.</param>
/// <param name="validTo">The valid to.</param>
/// <param name="keyStrength">The key strength.</param>
/// <param name="signatureAlgorithm">The signature algorithm.</param>
/// <param name="issuerPrivateKey">The issuer private key.</param>
/// <param name="hostName">The host name</param>
/// <returns>X509Certificate2 instance.</returns>
/// <exception cref="PemException">Malformed sequence in RSA private key</exception>
private static X509Certificate2 GenerateCertificate(string hostName,
string subjectName,
string issuerName, DateTime validFrom,
DateTime validTo, int keyStrength = 2048,
string signatureAlgorithm = "SHA256WithRSA",
AsymmetricKeyParameter issuerPrivateKey = null)
{
// Generating Random Numbers
var randomGenerator = new CryptoApiRandomGenerator();
var secureRandom = new SecureRandom(randomGenerator);
// The Certificate Generator
var certificateGenerator = new X509V3CertificateGenerator();
// Serial Number
var serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(long.MaxValue), secureRandom);
certificateGenerator.SetSerialNumber(serialNumber);
// Issuer and Subject Name
var subjectDn = new X509Name(subjectName);
var issuerDn = new X509Name(issuerName);
certificateGenerator.SetIssuerDN(issuerDn);
certificateGenerator.SetSubjectDN(subjectDn);
certificateGenerator.SetNotBefore(validFrom);
certificateGenerator.SetNotAfter(validTo);
if (hostName != null)
{
//add subject alternative names
var subjectAlternativeNames = new Asn1Encodable[]
{
new GeneralName(GeneralName.DnsName, hostName),
};
var subjectAlternativeNamesExtension = new DerSequence(subjectAlternativeNames);
certificateGenerator.AddExtension(
X509Extensions.SubjectAlternativeName.Id, false, subjectAlternativeNamesExtension);
}
// Subject Public Key
var keyGenerationParameters = new KeyGenerationParameters(secureRandom, keyStrength);
var keyPairGenerator = new RsaKeyPairGenerator();
keyPairGenerator.Init(keyGenerationParameters);
var subjectKeyPair = keyPairGenerator.GenerateKeyPair();
certificateGenerator.SetPublicKey(subjectKeyPair.Public);
// Set certificate intended purposes to only Server Authentication
certificateGenerator.AddExtension(X509Extensions.ExtendedKeyUsage.Id, false, new ExtendedKeyUsage(KeyPurposeID.IdKPServerAuth));
var signatureFactory = new Asn1SignatureFactory(signatureAlgorithm, issuerPrivateKey ?? subjectKeyPair.Private, secureRandom);
// Self-sign the certificate
var certificate = certificateGenerator.Generate(signatureFactory);
var x509Certificate = new X509Certificate2(certificate.GetEncoded());
// Corresponding private key
var privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(subjectKeyPair.Private);
var seq = (Asn1Sequence) Asn1Object.FromByteArray(privateKeyInfo.ParsePrivateKey().GetDerEncoded());
if (seq.Count != 9)
{
throw new PemException("Malformed sequence in RSA private key");
}
var rsa = RsaPrivateKeyStructure.GetInstance(seq);
var rsaparams = new RsaPrivateCrtKeyParameters(rsa.Modulus, rsa.PublicExponent, rsa.PrivateExponent, rsa.Prime1, rsa.Prime2, rsa.Exponent1, rsa.Exponent2, rsa.Coefficient);
// Set private key onto certificate instance
x509Certificate.PrivateKey = DotNetUtilities.ToRSA(rsaparams);
x509Certificate.FriendlyName = subjectName;
return x509Certificate;
}
/// <summary>
/// Makes the certificate internal.
/// </summary>
/// <param name="isRoot">if set to <c>true</c> [is root].</param>
/// <param name="hostName">hostname for certificate</param>
/// <param name="subjectName">The full subject.</param>
/// <param name="validFrom">The valid from.</param>
/// <param name="validTo">The valid to.</param>
/// <param name="signingCertificate">The signing certificate.</param>
/// <returns>X509Certificate2 instance.</returns>
/// <exception cref="System.ArgumentException">You must specify a Signing Certificate if and only if you are not creating a root.</exception>
private X509Certificate2 MakeCertificateInternal(bool isRoot,
string hostName, string subjectName,
DateTime validFrom, DateTime validTo, X509Certificate2 signingCertificate)
{
if (isRoot != (null == signingCertificate))
{
throw new ArgumentException("You must specify a Signing Certificate if and only if you are not creating a root.", nameof(signingCertificate));
}
return isRoot
? GenerateCertificate(null, subjectName, subjectName, validFrom, validTo)
: GenerateCertificate(hostName, subjectName, signingCertificate.Subject, validFrom, validTo, issuerPrivateKey: DotNetUtilities.GetKeyPair(signingCertificate.PrivateKey).Private);
}
/// <summary>
/// Makes the certificate internal.
/// </summary>
/// <param name="subject">The s subject cn.</param>
/// <param name="isRoot">if set to <c>true</c> [is root].</param>
/// <param name="switchToMtaIfNeeded">if set to <c>true</c> [switch to MTA if needed].</param>
/// <param name="signingCert">The signing cert.</param>
/// <param name="cancellationToken">Task cancellation token</param>
/// <returns>X509Certificate2.</returns>
private X509Certificate2 MakeCertificateInternal(string subject, bool isRoot,
bool switchToMtaIfNeeded, X509Certificate2 signingCert = null,
CancellationToken cancellationToken = default(CancellationToken))
{
X509Certificate2 certificate = null;
if (switchToMtaIfNeeded && Thread.CurrentThread.GetApartmentState() != ApartmentState.MTA)
{
using (var manualResetEvent = new ManualResetEventSlim(false))
{
ThreadPool.QueueUserWorkItem(o =>
{
certificate = MakeCertificateInternal(subject, isRoot, false, signingCert);
if (!cancellationToken.IsCancellationRequested)
{
manualResetEvent?.Set();
}
});
manualResetEvent.Wait(TimeSpan.FromMinutes(1), cancellationToken);
}
return certificate;
}
return MakeCertificateInternal(isRoot, subject, $"CN={subject}", DateTime.UtcNow.AddDays(-certificateGraceDays), DateTime.UtcNow.AddDays(certificateValidDays), isRoot ? null : signingCert);
}
}
}
using System.Security.Cryptography.X509Certificates;
namespace Titanium.Web.Proxy.Network.Certificate
{
/// <summary>
/// Abstract interface for different Certificate Maker Engines
/// </summary>
internal interface ICertificateMaker
{
X509Certificate2 MakeCertificate(string sSubjectCn, bool isRoot, X509Certificate2 signingCert);
}
}
This diff is collapsed.
...@@ -7,7 +7,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -7,7 +7,7 @@ namespace Titanium.Web.Proxy.Network
/// <summary> /// <summary>
/// This class wraps Tcp connection to client /// This class wraps Tcp connection to client
/// </summary> /// </summary>
internal class ProxyClient public class ProxyClient
{ {
/// <summary> /// <summary>
/// TcpClient used to communicate with client /// TcpClient used to communicate with client
...@@ -28,5 +28,6 @@ namespace Titanium.Web.Proxy.Network ...@@ -28,5 +28,6 @@ namespace Titanium.Web.Proxy.Network
/// used to write line by line to client /// used to write line by line to client
/// </summary> /// </summary>
internal StreamWriter ClientStreamWriter { get; set; } internal StreamWriter ClientStreamWriter { get; set; }
} }
} }
...@@ -7,16 +7,15 @@ using Titanium.Web.Proxy.Models; ...@@ -7,16 +7,15 @@ using Titanium.Web.Proxy.Models;
namespace Titanium.Web.Proxy.Network.Tcp namespace Titanium.Web.Proxy.Network.Tcp
{ {
/// <summary> /// <summary>
/// An object that holds TcpConnection to a particular server and port /// An object that holds TcpConnection to a particular server & port
/// </summary> /// </summary>
internal class TcpConnection : IDisposable public class TcpConnection : IDisposable
{ {
internal ExternalProxy UpStreamHttpProxy { get; set; } internal ExternalProxy UpStreamHttpProxy { get; set; }
internal ExternalProxy UpStreamHttpsProxy { get; set; } internal ExternalProxy UpStreamHttpsProxy { get; set; }
internal string HostName { get; set; } internal string HostName { get; set; }
internal int Port { get; set; } internal int Port { get; set; }
internal bool IsHttps { get; set; } internal bool IsHttps { get; set; }
...@@ -48,17 +47,18 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -48,17 +47,18 @@ namespace Titanium.Web.Proxy.Network.Tcp
LastAccess = DateTime.Now; LastAccess = DateTime.Now;
} }
/// <summary>
/// Dispose.
/// </summary>
public void Dispose() public void Dispose()
{ {
Stream?.Close(); Stream.Close();
Stream?.Dispose(); Stream.Dispose();
StreamReader?.Dispose();
TcpClient.LingerState = new LingerOption(true, 0); TcpClient.LingerState = new LingerOption(true, 0);
TcpClient.Client.Shutdown(SocketShutdown.Both);
TcpClient.Client.Close();
TcpClient.Client.Dispose();
TcpClient.Close(); TcpClient.Close();
} }
} }
} }
...@@ -8,7 +8,6 @@ using Titanium.Web.Proxy.Helpers; ...@@ -8,7 +8,6 @@ using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Models; using Titanium.Web.Proxy.Models;
using System.Security.Authentication; using System.Security.Authentication;
using System.Linq; using System.Linq;
using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Shared; using Titanium.Web.Proxy.Shared;
namespace Titanium.Web.Proxy.Network.Tcp namespace Titanium.Web.Proxy.Network.Tcp
...@@ -20,12 +19,14 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -20,12 +19,14 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// </summary> /// </summary>
internal class TcpConnectionFactory internal class TcpConnectionFactory
{ {
/// <summary> /// <summary>
/// Creates a TCP connection to server /// Creates a TCP connection to server
/// </summary> /// </summary>
/// <param name="bufferSize"></param> /// <param name="bufferSize"></param>
/// <param name="connectionTimeOutSeconds"></param> /// <param name="connectionTimeOutSeconds"></param>
/// <param name="remoteHostName"></param> /// <param name="remoteHostName"></param>
/// <param name="httpCmd"></param>
/// <param name="httpVersion"></param> /// <param name="httpVersion"></param>
/// <param name="isHttps"></param> /// <param name="isHttps"></param>
/// <param name="remotePort"></param> /// <param name="remotePort"></param>
...@@ -42,28 +43,24 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -42,28 +43,24 @@ namespace Titanium.Web.Proxy.Network.Tcp
bool isHttps, SslProtocols supportedSslProtocols, bool isHttps, SslProtocols supportedSslProtocols,
RemoteCertificateValidationCallback remoteCertificateValidationCallback, LocalCertificateSelectionCallback localCertificateSelectionCallback, RemoteCertificateValidationCallback remoteCertificateValidationCallback, LocalCertificateSelectionCallback localCertificateSelectionCallback,
ExternalProxy externalHttpProxy, ExternalProxy externalHttpsProxy, ExternalProxy externalHttpProxy, ExternalProxy externalHttpsProxy,
Stream clientStream, IPEndPoint upStreamEndPoint) Stream clientStream, EndPoint upStreamEndPoint)
{ {
TcpClient client; TcpClient client;
CustomBufferedStream stream; Stream stream;
bool isLocalhost = (externalHttpsProxy == null && externalHttpProxy == null) ? false : NetworkHelper.IsLocalIpAddress(remoteHostName);
bool useHttpsProxy = externalHttpsProxy != null && externalHttpsProxy.HostName != remoteHostName && (externalHttpsProxy.BypassForLocalhost && !isLocalhost);
bool useHttpProxy = externalHttpProxy != null && externalHttpProxy.HostName != remoteHostName && (externalHttpProxy.BypassForLocalhost && !isLocalhost);
if (isHttps) if (isHttps)
{ {
SslStream sslStream = null; SslStream sslStream = null;
//If this proxy uses another external proxy then create a tunnel request for HTTPS connections //If this proxy uses another external proxy then create a tunnel request for HTTPS connections
if (useHttpsProxy) if (externalHttpsProxy != null && externalHttpsProxy.HostName != remoteHostName)
{ {
client = new TcpClient(upStreamEndPoint); client = new TcpClient();
await client.ConnectAsync(externalHttpsProxy.HostName, externalHttpsProxy.Port); client.Client.Bind(upStreamEndPoint);
stream = new CustomBufferedStream(client.GetStream(), bufferSize); client.Client.Connect(externalHttpsProxy.HostName, externalHttpsProxy.Port);
stream = client.GetStream();
using (var writer = new StreamWriter(stream, Encoding.ASCII, bufferSize, true) {NewLine = ProxyConstants.NewLine}) using (var writer = new StreamWriter(stream, Encoding.ASCII, bufferSize, true) { NewLine = ProxyConstants.NewLine })
{ {
await writer.WriteLineAsync($"CONNECT {remoteHostName}:{remotePort} HTTP/{httpVersion}"); await writer.WriteLineAsync($"CONNECT {remoteHostName}:{remotePort} HTTP/{httpVersion}");
await writer.WriteLineAsync($"Host: {remoteHostName}:{remotePort}"); await writer.WriteLineAsync($"Host: {remoteHostName}:{remotePort}");
...@@ -72,30 +69,32 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -72,30 +69,32 @@ namespace Titanium.Web.Proxy.Network.Tcp
if (!string.IsNullOrEmpty(externalHttpsProxy.UserName) && externalHttpsProxy.Password != null) if (!string.IsNullOrEmpty(externalHttpsProxy.UserName) && externalHttpsProxy.Password != null)
{ {
await writer.WriteLineAsync("Proxy-Connection: keep-alive"); await writer.WriteLineAsync("Proxy-Connection: keep-alive");
await writer.WriteLineAsync("Proxy-Authorization" + ": Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes(externalHttpsProxy.UserName + ":" + externalHttpsProxy.Password))); await writer.WriteLineAsync("Proxy-Authorization" + ": Basic " + Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(externalHttpsProxy.UserName + ":" + externalHttpsProxy.Password)));
} }
await writer.WriteLineAsync(); await writer.WriteLineAsync();
await writer.FlushAsync(); await writer.FlushAsync();
writer.Close(); writer.Close();
} }
using (var reader = new CustomBinaryReader(stream, bufferSize)) using (var reader = new CustomBinaryReader(stream))
{ {
var result = await reader.ReadLineAsync(); var result = await reader.ReadLineAsync();
if (!new[] {"200 OK", "connection established"}.Any(s => result.ContainsIgnoreCase(s)))
if (!new string[] { "200 OK", "connection established" }.Any(s => result.ToLower().Contains(s.ToLower())))
{ {
throw new Exception("Upstream proxy failed to create a secure tunnel"); throw new Exception("Upstream proxy failed to create a secure tunnel");
} }
await reader.ReadAndIgnoreAllLinesAsync(); await reader.ReadAllLinesAsync();
} }
} }
else else
{ {
client = new TcpClient(upStreamEndPoint); client = new TcpClient();
await client.ConnectAsync(remoteHostName, remotePort); client.Client.Bind(upStreamEndPoint);
stream = new CustomBufferedStream(client.GetStream(), bufferSize); client.Client.Connect(remoteHostName, remotePort);
stream = client.GetStream();
} }
try try
...@@ -105,7 +104,7 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -105,7 +104,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
await sslStream.AuthenticateAsClientAsync(remoteHostName, null, supportedSslProtocols, false); await sslStream.AuthenticateAsClientAsync(remoteHostName, null, supportedSslProtocols, false);
stream = new CustomBufferedStream(sslStream, bufferSize); stream = sslStream;
} }
catch catch
{ {
...@@ -116,17 +115,19 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -116,17 +115,19 @@ namespace Titanium.Web.Proxy.Network.Tcp
} }
else else
{ {
if (useHttpProxy) if (externalHttpProxy != null && externalHttpProxy.HostName != remoteHostName)
{ {
client = new TcpClient(upStreamEndPoint); client = new TcpClient();
await client.ConnectAsync(externalHttpProxy.HostName, externalHttpProxy.Port); client.Client.Bind(upStreamEndPoint);
stream = new CustomBufferedStream(client.GetStream(), bufferSize); client.Client.Connect(externalHttpProxy.HostName, externalHttpProxy.Port);
stream = client.GetStream();
} }
else else
{ {
client = new TcpClient(upStreamEndPoint); client = new TcpClient();
await client.ConnectAsync(remoteHostName, remotePort); client.Client.Bind(upStreamEndPoint);
stream = new CustomBufferedStream(client.GetStream(), bufferSize); client.Client.Connect(remoteHostName, remotePort);
stream = client.GetStream();
} }
} }
...@@ -137,7 +138,7 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -137,7 +138,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
stream.WriteTimeout = connectionTimeOutSeconds * 1000; stream.WriteTimeout = connectionTimeOutSeconds * 1000;
return new TcpConnection return new TcpConnection()
{ {
UpStreamHttpProxy = externalHttpProxy, UpStreamHttpProxy = externalHttpProxy,
UpStreamHttpsProxy = externalHttpsProxy, UpStreamHttpsProxy = externalHttpsProxy,
...@@ -145,7 +146,7 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -145,7 +146,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
Port = remotePort, Port = remotePort,
IsHttps = isHttps, IsHttps = isHttps,
TcpClient = client, TcpClient = client,
StreamReader = new CustomBinaryReader(stream, bufferSize), StreamReader = new CustomBinaryReader(stream),
Stream = stream, Stream = stream,
Version = httpVersion Version = httpVersion
}; };
......
...@@ -5,7 +5,7 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -5,7 +5,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
{ {
/// <summary> /// <summary>
/// Represents a managed interface of IP Helper API TcpRow struct /// Represents a managed interface of IP Helper API TcpRow struct
/// <see href="http://msdn2.microsoft.com/en-us/library/aa366913.aspx"/> /// <see cref="http://msdn2.microsoft.com/en-us/library/aa366913.aspx"/>
/// </summary> /// </summary>
internal class TcpRow internal class TcpRow
{ {
...@@ -13,7 +13,7 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -13,7 +13,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// Initializes a new instance of the <see cref="TcpRow"/> class. /// Initializes a new instance of the <see cref="TcpRow"/> class.
/// </summary> /// </summary>
/// <param name="tcpRow">TcpRow struct.</param> /// <param name="tcpRow">TcpRow struct.</param>
internal TcpRow(NativeMethods.TcpRow tcpRow) public TcpRow(NativeMethods.TcpRow tcpRow)
{ {
ProcessId = tcpRow.owningPid; ProcessId = tcpRow.owningPid;
...@@ -29,16 +29,16 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -29,16 +29,16 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// <summary> /// <summary>
/// Gets the local end point. /// Gets the local end point.
/// </summary> /// </summary>
internal IPEndPoint LocalEndPoint { get; } public IPEndPoint LocalEndPoint { get; private set; }
/// <summary> /// <summary>
/// Gets the remote end point. /// Gets the remote end point.
/// </summary> /// </summary>
internal IPEndPoint RemoteEndPoint { get; } public IPEndPoint RemoteEndPoint { get; private set; }
/// <summary> /// <summary>
/// Gets the process identifier. /// Gets the process identifier.
/// </summary> /// </summary>
internal int ProcessId { get; } public int ProcessId { get; private set; }
} }
} }
\ No newline at end of file
...@@ -6,9 +6,7 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -6,9 +6,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// <summary> /// <summary>
/// Represents collection of TcpRows /// Represents collection of TcpRows
/// </summary> /// </summary>
/// <seealso> /// <seealso cref="System.Collections.Generic.IEnumerable{Proxy.Tcp.TcpRow}" />
/// <cref>System.Collections.Generic.IEnumerable{Proxy.Tcp.TcpRow}</cref>
/// </seealso>
internal class TcpTable : IEnumerable<TcpRow> internal class TcpTable : IEnumerable<TcpRow>
{ {
private readonly IEnumerable<TcpRow> tcpRows; private readonly IEnumerable<TcpRow> tcpRows;
...@@ -17,7 +15,7 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -17,7 +15,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// Initializes a new instance of the <see cref="TcpTable"/> class. /// Initializes a new instance of the <see cref="TcpTable"/> class.
/// </summary> /// </summary>
/// <param name="tcpRows">TcpRow collection to initialize with.</param> /// <param name="tcpRows">TcpRow collection to initialize with.</param>
internal TcpTable(IEnumerable<TcpRow> tcpRows) public TcpTable(IEnumerable<TcpRow> tcpRows)
{ {
this.tcpRows = tcpRows; this.tcpRows = tcpRows;
} }
...@@ -25,7 +23,7 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -25,7 +23,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// <summary> /// <summary>
/// Gets the TCP rows. /// Gets the TCP rows.
/// </summary> /// </summary>
internal IEnumerable<TcpRow> TcpRows => tcpRows; public IEnumerable<TcpRow> TcpRows => tcpRows;
/// <summary> /// <summary>
/// Returns an enumerator that iterates through the collection. /// Returns an enumerator that iterates through the collection.
......
...@@ -14,12 +14,7 @@ using System.Runtime.InteropServices; ...@@ -14,12 +14,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCopyright("Copyright © 2015")] [assembly: AssemblyCopyright("Copyright © 2015")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
[assembly: InternalsVisibleTo("Titanium.Web.Proxy.UnitTests, PublicKey=" + [assembly: InternalsVisibleTo("Titanium.Web.Proxy.UnitTests")]
"0024000004800000940000000602000000240000525341310004000001000100e7368e0ccc717e" +
"eb4d57d35ad6a8305cbbed14faa222e13869405e92c83856266d400887d857005f1393ffca2b92" +
"de7f3ba0bdad35ec2d6057ee1846091b34be2abc3f97dc7e72c16fd4958c15126b12923df76964" +
"7d84922c3f4f3b80ee0ae8e4cb40bc1973b782afb90bb00519fd16adf960f217e23696e7c31654" +
"01d0acd6")]
// Setting ComVisible to false makes the types in this assembly not visible // Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from // to COM components. If you need to access a type in this assembly from
......
...@@ -12,56 +12,44 @@ namespace Titanium.Web.Proxy ...@@ -12,56 +12,44 @@ namespace Titanium.Web.Proxy
{ {
public partial class ProxyServer public partial class ProxyServer
{ {
private async Task<bool> CheckAuthorization(StreamWriter clientStreamWriter, IEnumerable<HttpHeader> headers)
private async Task<bool> CheckAuthorization(StreamWriter clientStreamWriter, IEnumerable<HttpHeader> Headers)
{ {
if (AuthenticateUserFunc == null) if (AuthenticateUserFunc == null)
{ {
return true; return true;
} }
var httpHeaders = headers as HttpHeader[] ?? headers.ToArray(); var httpHeaders = Headers as HttpHeader[] ?? Headers.ToArray();
try try
{ {
if (httpHeaders.All(t => t.Name != "Proxy-Authorization")) if (!httpHeaders.Where(t => t.Name == "Proxy-Authorization").Any())
{ {
await WriteResponseStatus(new Version(1, 1), "407", await WriteResponseStatus(new Version(1, 1), "407",
"Proxy Authentication Required", clientStreamWriter); "Proxy Authentication Required", clientStreamWriter);
var response = new Response var response = new Response();
{ response.ResponseHeaders = new Dictionary<string, HttpHeader>();
ResponseHeaders = new Dictionary<string, HttpHeader> response.ResponseHeaders.Add("Proxy-Authenticate", new HttpHeader("Proxy-Authenticate", "Basic realm=\"TitaniumProxy\""));
{ response.ResponseHeaders.Add("Proxy-Connection", new HttpHeader("Proxy-Connection", "close"));
{
"Proxy-Authenticate",
new HttpHeader("Proxy-Authenticate", "Basic realm=\"TitaniumProxy\"")
},
{"Proxy-Connection", new HttpHeader("Proxy-Connection", "close")}
}
};
await WriteResponseHeaders(clientStreamWriter, response); await WriteResponseHeaders(clientStreamWriter, response);
await clientStreamWriter.WriteLineAsync(); await clientStreamWriter.WriteLineAsync();
return false; return false;
} }
var header = httpHeaders.FirstOrDefault(t => t.Name == "Proxy-Authorization"); else
if (null == header) throw new NullReferenceException(); {
var headerValue = header.Value.Trim(); var headerValue = httpHeaders.Where(t => t.Name == "Proxy-Authorization").FirstOrDefault().Value.Trim();
if (!headerValue.StartsWith("basic", StringComparison.CurrentCultureIgnoreCase)) if (!headerValue.ToLower().StartsWith("basic"))
{ {
//Return not authorized //Return not authorized
await WriteResponseStatus(new Version(1, 1), "407", await WriteResponseStatus(new Version(1, 1), "407",
"Proxy Authentication Invalid", clientStreamWriter); "Proxy Authentication Invalid", clientStreamWriter);
var response = new Response var response = new Response();
{ response.ResponseHeaders = new Dictionary<string, HttpHeader>();
ResponseHeaders = new Dictionary<string, HttpHeader> response.ResponseHeaders.Add("Proxy-Authenticate", new HttpHeader("Proxy-Authenticate", "Basic realm=\"TitaniumProxy\""));
{ response.ResponseHeaders.Add("Proxy-Connection", new HttpHeader("Proxy-Connection", "close"));
{
"Proxy-Authenticate",
new HttpHeader("Proxy-Authenticate", "Basic realm=\"TitaniumProxy\"")
},
{"Proxy-Connection", new HttpHeader("Proxy-Connection", "close")}
}
};
await WriteResponseHeaders(clientStreamWriter, response); await WriteResponseHeaders(clientStreamWriter, response);
await clientStreamWriter.WriteLineAsync(); await clientStreamWriter.WriteLineAsync();
...@@ -75,17 +63,10 @@ namespace Titanium.Web.Proxy ...@@ -75,17 +63,10 @@ namespace Titanium.Web.Proxy
//Return not authorized //Return not authorized
await WriteResponseStatus(new Version(1, 1), "407", await WriteResponseStatus(new Version(1, 1), "407",
"Proxy Authentication Invalid", clientStreamWriter); "Proxy Authentication Invalid", clientStreamWriter);
var response = new Response var response = new Response();
{ response.ResponseHeaders = new Dictionary<string, HttpHeader>();
ResponseHeaders = new Dictionary<string, HttpHeader> response.ResponseHeaders.Add("Proxy-Authenticate", new HttpHeader("Proxy-Authenticate", "Basic realm=\"TitaniumProxy\""));
{ response.ResponseHeaders.Add("Proxy-Connection", new HttpHeader("Proxy-Connection", "close"));
{
"Proxy-Authenticate",
new HttpHeader("Proxy-Authenticate", "Basic realm=\"TitaniumProxy\"")
},
{"Proxy-Connection", new HttpHeader("Proxy-Connection", "close")}
}
};
await WriteResponseHeaders(clientStreamWriter, response); await WriteResponseHeaders(clientStreamWriter, response);
await clientStreamWriter.WriteLineAsync(); await clientStreamWriter.WriteLineAsync();
...@@ -93,7 +74,8 @@ namespace Titanium.Web.Proxy ...@@ -93,7 +74,8 @@ namespace Titanium.Web.Proxy
} }
var username = decoded.Substring(0, decoded.IndexOf(':')); var username = decoded.Substring(0, decoded.IndexOf(':'));
var password = decoded.Substring(decoded.IndexOf(':') + 1); var password = decoded.Substring(decoded.IndexOf(':') + 1);
return await AuthenticateUserFunc(username, password); return await AuthenticateUserFunc(username, password).ConfigureAwait(false);
}
} }
catch (Exception e) catch (Exception e)
{ {
...@@ -101,19 +83,16 @@ namespace Titanium.Web.Proxy ...@@ -101,19 +83,16 @@ namespace Titanium.Web.Proxy
//Return not authorized //Return not authorized
await WriteResponseStatus(new Version(1, 1), "407", await WriteResponseStatus(new Version(1, 1), "407",
"Proxy Authentication Invalid", clientStreamWriter); "Proxy Authentication Invalid", clientStreamWriter);
var response = new Response var response = new Response();
{ response.ResponseHeaders = new Dictionary<string, HttpHeader>();
ResponseHeaders = new Dictionary<string, HttpHeader> response.ResponseHeaders.Add("Proxy-Authenticate", new HttpHeader("Proxy-Authenticate", "Basic realm=\"TitaniumProxy\""));
{ response.ResponseHeaders.Add("Proxy-Connection", new HttpHeader("Proxy-Connection", "close"));
{"Proxy-Authenticate", new HttpHeader("Proxy-Authenticate", "Basic realm=\"TitaniumProxy\"")},
{"Proxy-Connection", new HttpHeader("Proxy-Connection", "close")}
}
};
await WriteResponseHeaders(clientStreamWriter, response); await WriteResponseHeaders(clientStreamWriter, response);
await clientStreamWriter.WriteLineAsync(); await clientStreamWriter.WriteLineAsync();
return false; return false;
} }
} }
} }
} }
This diff is collapsed.
This diff is collapsed.
...@@ -17,12 +17,8 @@ namespace Titanium.Web.Proxy ...@@ -17,12 +17,8 @@ namespace Titanium.Web.Proxy
/// </summary> /// </summary>
partial class ProxyServer partial class ProxyServer
{ {
/// <summary> //Called asynchronously when a request was successfully and we received the response
/// Called asynchronously when a request was successfully and we received the response public async Task HandleHttpSessionResponse(SessionEventArgs args)
/// </summary>
/// <param name="args"></param>
/// <returns></returns>
private async Task HandleHttpSessionResponse(SessionEventArgs args)
{ {
//read response & headers from server //read response & headers from server
await args.WebSession.ReceiveResponse(); await args.WebSession.ReceiveResponse();
...@@ -44,15 +40,15 @@ namespace Titanium.Web.Proxy ...@@ -44,15 +40,15 @@ namespace Titanium.Web.Proxy
for (int i = 0; i < invocationList.Length; i++) for (int i = 0; i < invocationList.Length; i++)
{ {
handlerTasks[i] = ((Func<object, SessionEventArgs, Task>) invocationList[i])(this, args); handlerTasks[i] = ((Func<object, SessionEventArgs, Task>)invocationList[i])(this, args);
} }
await Task.WhenAll(handlerTasks); await Task.WhenAll(handlerTasks);
} }
if (args.ReRequest) if(args.ReRequest)
{ {
await HandleHttpSessionRequestInternal(null, args, null, null, true); await HandleHttpSessionRequestInternal(null, args, null, null, true).ConfigureAwait(false);
return; return;
} }
...@@ -108,7 +104,7 @@ namespace Titanium.Web.Proxy ...@@ -108,7 +104,7 @@ namespace Titanium.Web.Proxy
|| !args.WebSession.Response.ResponseKeepAlive) || !args.WebSession.Response.ResponseKeepAlive)
{ {
await args.WebSession.ServerConnection.StreamReader await args.WebSession.ServerConnection.StreamReader
.WriteResponseBody(BufferSize, args.ProxyClient.ClientStream, args.WebSession.Response.IsChunked, .WriteResponseBody(BUFFER_SIZE, args.ProxyClient.ClientStream, args.WebSession.Response.IsChunked,
args.WebSession.Response.ContentLength); args.WebSession.Response.ContentLength);
} }
//write response if connection:keep-alive header exist and when version is http/1.0 //write response if connection:keep-alive header exist and when version is http/1.0
...@@ -116,14 +112,15 @@ namespace Titanium.Web.Proxy ...@@ -116,14 +112,15 @@ namespace Titanium.Web.Proxy
else if (args.WebSession.Response.ResponseKeepAlive && args.WebSession.Response.HttpVersion.Minor == 0) else if (args.WebSession.Response.ResponseKeepAlive && args.WebSession.Response.HttpVersion.Minor == 0)
{ {
await args.WebSession.ServerConnection.StreamReader await args.WebSession.ServerConnection.StreamReader
.WriteResponseBody(BufferSize, args.ProxyClient.ClientStream, args.WebSession.Response.IsChunked, .WriteResponseBody(BUFFER_SIZE, args.ProxyClient.ClientStream, args.WebSession.Response.IsChunked,
args.WebSession.Response.ContentLength); args.WebSession.Response.ContentLength);
} }
} }
await args.ProxyClient.ClientStream.FlushAsync(); await args.ProxyClient.ClientStream.FlushAsync();
} }
catch (Exception e) catch(Exception e)
{ {
ExceptionFunc(new ProxyHttpException("Error occured wilst handling session response", e, args)); ExceptionFunc(new ProxyHttpException("Error occured wilst handling session response", e, args));
Dispose(args.ProxyClient.ClientStream, args.ProxyClient.ClientStreamReader, Dispose(args.ProxyClient.ClientStream, args.ProxyClient.ClientStreamReader,
...@@ -159,14 +156,14 @@ namespace Titanium.Web.Proxy ...@@ -159,14 +156,14 @@ namespace Titanium.Web.Proxy
private async Task WriteResponseStatus(Version version, string code, string description, private async Task WriteResponseStatus(Version version, string code, string description,
StreamWriter responseWriter) StreamWriter responseWriter)
{ {
await responseWriter.WriteLineAsync($"HTTP/{version.Major}.{version.Minor} {code} {description}"); await responseWriter.WriteLineAsync(string.Format("HTTP/{0}.{1} {2} {3}", version.Major, version.Minor, code, description));
} }
/// <summary> /// <summary>
/// Write response headers to client /// Write response headers to client
/// </summary> /// </summary>
/// <param name="responseWriter"></param> /// <param name="responseWriter"></param>
/// <param name="response"></param> /// <param name="headers"></param>
/// <returns></returns> /// <returns></returns>
private async Task WriteResponseHeaders(StreamWriter responseWriter, Response response) private async Task WriteResponseHeaders(StreamWriter responseWriter, Response response)
{ {
...@@ -174,7 +171,7 @@ namespace Titanium.Web.Proxy ...@@ -174,7 +171,7 @@ namespace Titanium.Web.Proxy
foreach (var header in response.ResponseHeaders) foreach (var header in response.ResponseHeaders)
{ {
await header.Value.WriteToStream(responseWriter); await responseWriter.WriteLineAsync(header.Value.ToString());
} }
//write non unique request headers //write non unique request headers
...@@ -183,10 +180,11 @@ namespace Titanium.Web.Proxy ...@@ -183,10 +180,11 @@ namespace Titanium.Web.Proxy
var headers = headerItem.Value; var headers = headerItem.Value;
foreach (var header in headers) foreach (var header in headers)
{ {
await header.WriteToStream(responseWriter); await responseWriter.WriteLineAsync(header.ToString());
} }
} }
await responseWriter.WriteLineAsync(); await responseWriter.WriteLineAsync();
await responseWriter.FlushAsync(); await responseWriter.FlushAsync();
} }
...@@ -216,11 +214,13 @@ namespace Titanium.Web.Proxy ...@@ -216,11 +214,13 @@ namespace Titanium.Web.Proxy
headers.Remove("proxy-connection"); headers.Remove("proxy-connection");
} }
} }
/// <summary> /// <summary>
/// Handle dispose of a client/server session /// Handle dispose of a client/server session
/// </summary> /// </summary>
/// <param name="tcpClient"></param>
/// <param name="clientStream"></param> /// <param name="clientStream"></param>
/// <param name="clientStreamReader"></param> /// <param name="clientStreamReader"></param>
/// <param name="clientStreamWriter"></param> /// <param name="clientStreamWriter"></param>
...@@ -228,15 +228,28 @@ namespace Titanium.Web.Proxy ...@@ -228,15 +228,28 @@ namespace Titanium.Web.Proxy
private void Dispose(Stream clientStream, CustomBinaryReader clientStreamReader, private void Dispose(Stream clientStream, CustomBinaryReader clientStreamReader,
StreamWriter clientStreamWriter, IDisposable args) StreamWriter clientStreamWriter, IDisposable args)
{ {
clientStream?.Close();
clientStream?.Dispose();
clientStreamReader?.Dispose(); if (clientStream != null)
{
clientStream.Close();
clientStream.Dispose();
}
if (args != null)
{
args.Dispose();
}
clientStreamWriter?.Close(); if (clientStreamReader != null)
clientStreamWriter?.Dispose(); {
clientStreamReader.Dispose();
}
args?.Dispose(); if (clientStreamWriter != null)
{
clientStreamWriter.Close();
clientStreamWriter.Dispose();
}
} }
} }
} }
\ No newline at end of file
using System.Text; using System;
using System.Text;
namespace Titanium.Web.Proxy.Shared namespace Titanium.Web.Proxy.Shared
{ {
...@@ -7,9 +8,9 @@ namespace Titanium.Web.Proxy.Shared ...@@ -7,9 +8,9 @@ namespace Titanium.Web.Proxy.Shared
/// </summary> /// </summary>
internal class ProxyConstants internal class ProxyConstants
{ {
internal static readonly char[] SpaceSplit = {' '}; internal static readonly char[] SpaceSplit = { ' ' };
internal static readonly char[] ColonSplit = {':'}; internal static readonly char[] ColonSplit = { ':' };
internal static readonly char[] SemiColonSplit = {';'}; internal static readonly char[] SemiColonSplit = { ';' };
internal static readonly byte[] NewLineBytes = Encoding.ASCII.GetBytes(NewLine); internal static readonly byte[] NewLineBytes = Encoding.ASCII.GetBytes(NewLine);
......
...@@ -26,7 +26,6 @@ ...@@ -26,7 +26,6 @@
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion> <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<Prefer32Bit>false</Prefer32Bit> <Prefer32Bit>false</Prefer32Bit>
<DocumentationFile>bin\Debug\Titanium.Web.Proxy.XML</DocumentationFile> <DocumentationFile>bin\Debug\Titanium.Web.Proxy.XML</DocumentationFile>
<LangVersion>6</LangVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
<PlatformTarget>AnyCPU</PlatformTarget> <PlatformTarget>AnyCPU</PlatformTarget>
...@@ -35,18 +34,10 @@ ...@@ -35,18 +34,10 @@
<DefineConstants>NET45</DefineConstants> <DefineConstants>NET45</DefineConstants>
<Prefer32Bit>false</Prefer32Bit> <Prefer32Bit>false</Prefer32Bit>
<DocumentationFile>bin\Release\Titanium.Web.Proxy.XML</DocumentationFile> <DocumentationFile>bin\Release\Titanium.Web.Proxy.XML</DocumentationFile>
<DebugType>none</DebugType>
<DebugSymbols>false</DebugSymbols>
</PropertyGroup>
<PropertyGroup>
<SignAssembly>true</SignAssembly>
</PropertyGroup>
<PropertyGroup>
<AssemblyOriginatorKeyFile>StrongNameKey.snk</AssemblyOriginatorKeyFile>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="BouncyCastle.Crypto, Version=1.8.1.0, Culture=neutral, PublicKeyToken=0e99375e54769942"> <Reference Include="Ionic.Zip, Version=1.9.8.0, Culture=neutral, PublicKeyToken=6583c7c814667745, processorArchitecture=MSIL">
<HintPath>..\packages\BouncyCastle.1.8.1\lib\BouncyCastle.Crypto.dll</HintPath> <HintPath>..\packages\DotNetZip.1.9.8\lib\net20\Ionic.Zip.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="System" /> <Reference Include="System" />
...@@ -65,23 +56,19 @@ ...@@ -65,23 +56,19 @@
<Compile Include="Compression\DeflateCompression.cs" /> <Compile Include="Compression\DeflateCompression.cs" />
<Compile Include="Compression\GZipCompression.cs" /> <Compile Include="Compression\GZipCompression.cs" />
<Compile Include="Compression\ICompression.cs" /> <Compile Include="Compression\ICompression.cs" />
<Compile Include="Compression\ZlibCompression.cs" />
<Compile Include="Decompression\DecompressionFactory.cs" /> <Compile Include="Decompression\DecompressionFactory.cs" />
<Compile Include="Decompression\DefaultDecompression.cs" /> <Compile Include="Decompression\DefaultDecompression.cs" />
<Compile Include="Decompression\DeflateDecompression.cs" /> <Compile Include="Decompression\DeflateDecompression.cs" />
<Compile Include="Decompression\GZipDecompression.cs" /> <Compile Include="Decompression\GZipDecompression.cs" />
<Compile Include="Decompression\IDecompression.cs" /> <Compile Include="Decompression\IDecompression.cs" />
<Compile Include="Decompression\ZlibDecompression.cs" />
<Compile Include="EventArguments\CertificateSelectionEventArgs.cs" /> <Compile Include="EventArguments\CertificateSelectionEventArgs.cs" />
<Compile Include="EventArguments\CertificateValidationEventArgs.cs" /> <Compile Include="EventArguments\CertificateValidationEventArgs.cs" />
<Compile Include="Extensions\ByteArrayExtensions.cs" /> <Compile Include="Extensions\ByteArrayExtensions.cs" />
<Compile Include="Extensions\StringExtensions.cs" />
<Compile Include="Helpers\CustomBufferedStream.cs" />
<Compile Include="Helpers\Network.cs" /> <Compile Include="Helpers\Network.cs" />
<Compile Include="Helpers\RunTime.cs" />
<Compile Include="Http\Responses\GenericResponse.cs" />
<Compile Include="Network\CachedCertificate.cs" /> <Compile Include="Network\CachedCertificate.cs" />
<Compile Include="Network\Certificate\WinCertificateMaker.cs" /> <Compile Include="Network\CertificateMaker.cs" />
<Compile Include="Network\Certificate\BCCertificateMaker.cs" />
<Compile Include="Network\Certificate\ICertificateMaker.cs" />
<Compile Include="Network\ProxyClient.cs" /> <Compile Include="Network\ProxyClient.cs" />
<Compile Include="Exceptions\BodyNotFoundException.cs" /> <Compile Include="Exceptions\BodyNotFoundException.cs" />
<Compile Include="Exceptions\ProxyAuthorizationException.cs" /> <Compile Include="Exceptions\ProxyAuthorizationException.cs" />
...@@ -130,7 +117,6 @@ ...@@ -130,7 +117,6 @@
<ItemGroup> <ItemGroup>
<None Include="app.config" /> <None Include="app.config" />
<None Include="packages.config" /> <None Include="packages.config" />
<None Include="StrongNameKey.snk" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" /> <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
<copyright>Copyright &#x00A9; Titanium. All rights reserved.</copyright> <copyright>Copyright &#x00A9; Titanium. All rights reserved.</copyright>
<tags></tags> <tags></tags>
<dependencies> <dependencies>
<dependency id="BouncyCastle" version="1.8.1" /> <dependency id="DotNetZip" version="1.9.8" />
</dependencies> </dependencies>
</metadata> </metadata>
<files> <files>
......
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<configuration> <configuration>
<runtime> <runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
...@@ -12,7 +12,4 @@ ...@@ -12,7 +12,4 @@
</dependentAssembly> </dependentAssembly>
</assemblyBinding> </assemblyBinding>
</runtime> </runtime>
<startup> <startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/></startup></configuration>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/>
</startup>
</configuration>
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="BouncyCastle" version="1.8.1" targetFramework="net45" /> <package id="DotNetZip" version="1.9.8" targetFramework="net45" />
</packages> </packages>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment