Commit 990b7412 authored by justcoding121's avatar justcoding121 Committed by justcoding121

cleanup

parent 6b42b1b4
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<configuration> <configuration>
<solution> <solution>
<add key="disableSourceControlIntegration" value="true" /> <add key="disableSourceControlIntegration" value="true" />
......
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<configuration> <configuration>
<startup> <startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0,Profile=Client" /> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0,Profile=Client" />
</startup> </startup>
</configuration> </configuration>
\ No newline at end of file
using System; using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using Titanium.Web.Proxy.Helpers;
namespace Titanium.Web.Proxy.Test namespace Titanium.Web.Proxy.Test
{ {
public class Program public class Program
{ {
static ProxyTestController controller = new ProxyTestController(); private static readonly ProxyTestController Controller = new ProxyTestController();
public static void Main(string[] args) public static void Main(string[] args)
{ {
//On Console exit make sure we also exit the proxy //On Console exit make sure we also exit the proxy
NativeMethods.handler = new NativeMethods.ConsoleEventDelegate(ConsoleEventCallback); NativeMethods.Handler = ConsoleEventCallback;
NativeMethods.SetConsoleCtrlHandler(NativeMethods.handler, true); NativeMethods.SetConsoleCtrlHandler(NativeMethods.Handler, true);
Console.Write("Do you want to monitor HTTPS? (Y/N):"); Console.Write("Do you want to monitor HTTPS? (Y/N):");
if (Console.ReadLine().Trim().ToLower() == "y") var readLine = Console.ReadLine();
if (readLine != null && readLine.Trim().ToLower() == "y")
{ {
controller.EnableSSL = true; Controller.EnableSsl = true;
} }
Console.Write("Do you want to set this as a System Proxy? (Y/N):"); Console.Write("Do you want to set this as a System Proxy? (Y/N):");
if (Console.ReadLine().Trim().ToLower() == "y") var line = Console.ReadLine();
if (line != null && line.Trim().ToLower() == "y")
{ {
controller.SetAsSystemProxy = true; Controller.SetAsSystemProxy = true;
} }
//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();
} }
static bool ConsoleEventCallback(int eventType) private static bool ConsoleEventCallback(int eventType)
{ {
if (eventType == 2) if (eventType == 2)
{ {
try try
{ {
controller.Stop(); Controller.Stop();
}
catch
{
// ignored
} }
catch { }
} }
return false; return false;
} }
} }
internal static class NativeMethods internal static class NativeMethods
{ {
// Keeps it from getting garbage collected
internal static ConsoleEventDelegate Handler;
[DllImport("kernel32.dll", SetLastError = true)] [DllImport("kernel32.dll", SetLastError = true)]
internal static extern bool SetConsoleCtrlHandler(ConsoleEventDelegate callback, bool add); internal static extern bool SetConsoleCtrlHandler(ConsoleEventDelegate callback, bool add);
// Pinvoke // Pinvoke
internal delegate bool ConsoleEventDelegate(int eventType); internal delegate bool ConsoleEventDelegate(int eventType);
// Keeps it from getting garbage collected
internal static ConsoleEventDelegate handler;
} }
}
} \ No newline at end of file
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
// set of attributes. Change these attribute values to modify the information // set of attributes. Change these attribute values to modify the information
// associated with an assembly. // associated with an assembly.
[assembly: AssemblyTitle("Demo")] [assembly: AssemblyTitle("Demo")]
[assembly: AssemblyDescription("")] [assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
...@@ -17,9 +17,11 @@ using System.Runtime.InteropServices; ...@@ -17,9 +17,11 @@ using System.Runtime.InteropServices;
// 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
// COM, set the ComVisible attribute to true on that type. // COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)] [assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM // The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("33a2109d-0312-4c94-aa51-fbb2a83e63ab")] [assembly: Guid("33a2109d-0312-4c94-aa51-fbb2a83e63ab")]
// Version information for an assembly consists of the following four values: // Version information for an assembly consists of the following four values:
...@@ -32,5 +34,6 @@ using System.Runtime.InteropServices; ...@@ -32,5 +34,6 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")]
\ No newline at end of file
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Text.RegularExpressions;
using System.DirectoryServices.AccountManagement;
using System.DirectoryServices.ActiveDirectory;
using Titanium.Web.Proxy.EventArguments; using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy;
using Titanium.Web.Proxy.Helpers;
namespace Titanium.Web.Proxy.Test namespace Titanium.Web.Proxy.Test
{ {
public partial class ProxyTestController public class ProxyTestController
{ {
public int ListeningPort { get; set; } public int ListeningPort { get; set; }
public bool EnableSSL { get; set; } public bool EnableSsl { get; set; }
public bool SetAsSystemProxy { get; set; } public bool SetAsSystemProxy { get; set; }
public void StartProxy() public void StartProxy()
{ {
ProxyServer.BeforeRequest += OnRequest; ProxyServer.BeforeRequest += OnRequest;
ProxyServer.BeforeResponse += OnResponse; ProxyServer.BeforeResponse += OnResponse;
ProxyServer.EnableSSL = EnableSSL; ProxyServer.EnableSsl = EnableSsl;
ProxyServer.SetAsSystemProxy = SetAsSystemProxy; ProxyServer.SetAsSystemProxy = SetAsSystemProxy;
...@@ -40,9 +27,9 @@ namespace Titanium.Web.Proxy.Test ...@@ -40,9 +27,9 @@ namespace Titanium.Web.Proxy.Test
ProxyServer.ListeningPort = ProxyServer.ListeningPort; ProxyServer.ListeningPort = ProxyServer.ListeningPort;
Console.WriteLine(String.Format("Proxy listening on local machine port: {0} ", ProxyServer.ListeningPort)); Console.WriteLine("Proxy listening on local machine port: {0} ", ProxyServer.ListeningPort);
} }
public void Stop() public void Stop()
{ {
ProxyServer.BeforeRequest -= OnRequest; ProxyServer.BeforeRequest -= OnRequest;
...@@ -52,13 +39,11 @@ namespace Titanium.Web.Proxy.Test ...@@ -52,13 +39,11 @@ namespace Titanium.Web.Proxy.Test
} }
//Test On Request, intecept requests //Test On Request, intecept requests
//Read browser URL send back to proxy by the injection script in OnResponse event //Read browser URL send back to proxy by the injection script in OnResponse event
public void OnRequest(object sender, SessionEventArgs e) public void OnRequest(object sender, SessionEventArgs e)
{ {
Console.WriteLine(e.RequestUrl);
Console.WriteLine(e.RequestURL);
////read request headers ////read request headers
//var requestHeaders = e.RequestHeaders; //var requestHeaders = e.RequestHeaders;
...@@ -82,7 +67,6 @@ namespace Titanium.Web.Proxy.Test ...@@ -82,7 +67,6 @@ namespace Titanium.Web.Proxy.Test
//{ //{
// e.Ok("<!DOCTYPE html><html><body><h1>Website Blocked</h1><p>Blocked by titanium web proxy.</p></body></html>"); // e.Ok("<!DOCTYPE html><html><body><h1>Website Blocked</h1><p>Blocked by titanium web proxy.</p></body></html>");
//} //}
} }
//Test script injection //Test script injection
...@@ -112,9 +96,6 @@ namespace Titanium.Web.Proxy.Test ...@@ -112,9 +96,6 @@ namespace Titanium.Web.Proxy.Test
// e.SetResponseBodyString(modified); // e.SetResponseBodyString(modified);
// } // }
//} //}
} }
} }
}
} \ No newline at end of file
using System; using System;
using System.Text; using System.Collections.Generic;
using System.Globalization;
using System.IO; using System.IO;
using System.Linq;
using System.Net; using System.Net;
using Titanium.Web.Proxy.Helpers;
using System.Net.Sockets; using System.Net.Sockets;
using System.Text;
using Titanium.Web.Proxy.Exceptions; using Titanium.Web.Proxy.Exceptions;
using System.Linq; using Titanium.Web.Proxy.Helpers;
using System.Collections.Generic;
using Titanium.Web.Proxy.Models; using Titanium.Web.Proxy.Models;
namespace Titanium.Web.Proxy.EventArguments namespace Titanium.Web.Proxy.EventArguments
{ {
public class SessionEventArgs : EventArgs, IDisposable public class SessionEventArgs : EventArgs, IDisposable
{ {
readonly int _bufferSize;
internal int BUFFER_SIZE; internal SessionEventArgs(int bufferSize)
{
_bufferSize = bufferSize;
}
internal TcpClient client { get; set; } internal TcpClient Client { get; set; }
internal Stream clientStream { get; set; } internal Stream ClientStream { get; set; }
internal CustomBinaryReader clientStreamReader { get; set; } internal CustomBinaryReader ClientStreamReader { get; set; }
internal StreamWriter clientStreamWriter { get; set; } internal StreamWriter ClientStreamWriter { get; set; }
internal bool isHttps { get; set; } public bool IsHttps { get; internal set; }
internal string requestURL { get; set; } public string RequestUrl { get; internal set; }
internal string requestHostname { get; set; } public string RequestHostname { get; internal set; }
internal int clientPort { get; set; } public int ClientPort { get; internal set; }
internal IPAddress clientIpAddress { get; set; } public IPAddress ClientIpAddress { get; internal set; }
internal Encoding requestEncoding { get; set; } internal Encoding RequestEncoding { get; set; }
internal Version requestHttpVersion { get; set; } internal Version RequestHttpVersion { get; set; }
internal bool requestIsAlive { get; set; } internal bool RequestIsAlive { get; set; }
internal bool cancelRequest { get; set; } internal bool CancelRequest { get; set; }
internal byte[] requestBody { get; set; } internal byte[] RequestBody { get; set; }
internal string requestBodyString { get; set; } internal string RequestBodyString { get; set; }
internal bool requestBodyRead { get; set; } internal bool RequestBodyRead { get; set; }
internal List<HttpHeader> requestHeaders { get; set; } public List<HttpHeader> RequestHeaders { get; internal set; }
internal bool RequestLocked { get; set; } internal bool RequestLocked { get; set; }
internal HttpWebRequest proxyRequest { get; set; } internal HttpWebRequest ProxyRequest { get; set; }
internal Encoding responseEncoding { get; set; } internal Encoding ResponseEncoding { get; set; }
internal Stream responseStream { get; set; } internal Stream ResponseStream { get; set; }
internal byte[] responseBody { get; set; } internal byte[] ResponseBody { get; set; }
internal string responseBodyString { get; set; } internal string ResponseBodyString { get; set; }
internal bool responseBodyRead { get; set; } internal bool ResponseBodyRead { get; set; }
internal List<HttpHeader> responseHeaders { get; set; } public List<HttpHeader> ResponseHeaders { get; internal set; }
internal bool ResponseLocked { get; set; } internal bool ResponseLocked { get; set; }
internal HttpWebResponse serverResponse { get; set; } internal HttpWebResponse ServerResponse { get; set; }
public int ClientPort { get { return this.clientPort; } }
public IPAddress ClientIpAddress { get { return this.clientIpAddress; } }
public bool IsHttps { get { return this.isHttps; } }
public string RequestURL { get { return this.requestURL; } }
public string RequestHostname { get { return this.requestHostname; } }
public List<HttpHeader> RequestHeaders { get { return this.requestHeaders; } }
public List<HttpHeader> ResponseHeaders { get { return this.responseHeaders; } }
public int RequestContentLength public int RequestContentLength
{ {
get get
{ {
if (this.requestHeaders.Any(x => x.Name.ToLower() == "content-length")) if (RequestHeaders.All(x => x.Name.ToLower() != "content-length")) return -1;
{ int contentLen;
int contentLen; int.TryParse(RequestHeaders.First(x => x.Name.ToLower() == "content-length").Value, out contentLen);
int.TryParse(this.requestHeaders.First(x => x.Name.ToLower() == "content-length").Value, out contentLen); if (contentLen != 0)
if (contentLen != 0) return contentLen;
return contentLen;
}
return -1; return -1;
} }
} }
public string RequestMethod { get { return this.proxyRequest.Method; } } public string RequestMethod
{
get { return ProxyRequest.Method; }
}
public HttpStatusCode ResponseStatusCode { get { return this.serverResponse.StatusCode; } } public HttpStatusCode ResponseStatusCode
public string ResponseContentType { get { return this.responseHeaders.Any(x => x.Name.ToLower() == "content-type") ? this.responseHeaders.First(x => x.Name.ToLower() == "content-type").Value : null; } } {
get { return ServerResponse.StatusCode; }
}
public string ResponseContentType
{
get
{
return ResponseHeaders.Any(x => x.Name.ToLower() == "content-type")
? ResponseHeaders.First(x => x.Name.ToLower() == "content-type").Value
: null;
}
}
internal SessionEventArgs(int bufferSize) public void Dispose()
{ {
BUFFER_SIZE = bufferSize; if (ProxyRequest != null)
ProxyRequest.Abort();
if (ResponseStream != null)
ResponseStream.Dispose();
if (ServerResponse != null)
ServerResponse.Close();
} }
private void readRequestBody() private void ReadRequestBody()
{ {
if ((proxyRequest.Method.ToUpper() != "POST" && proxyRequest.Method.ToUpper() != "PUT")) if ((ProxyRequest.Method.ToUpper() != "POST" && ProxyRequest.Method.ToUpper() != "PUT"))
{ {
throw new BodyNotFoundException("Request don't have a body." + throw new BodyNotFoundException("Request don't have a body." +
"Please verify that this request is a Http POST/PUT and request content length is greater than zero before accessing the body."); "Please verify that this request is a Http POST/PUT and request content length is greater than zero before accessing the body.");
} }
if (requestBody == null) if (RequestBody == null)
{ {
bool isChunked = false; var isChunked = false;
string requestContentEncoding = null; string requestContentEncoding = null;
if (requestHeaders.Any(x => x.Name.ToLower() == "content-encoding")) if (RequestHeaders.Any(x => x.Name.ToLower() == "content-encoding"))
{ {
requestContentEncoding = requestHeaders.First(x => x.Name.ToLower() == "content-encoding").Value; requestContentEncoding = RequestHeaders.First(x => x.Name.ToLower() == "content-encoding").Value;
} }
if (requestHeaders.Any(x => x.Name.ToLower() == "transfer-encoding")) if (RequestHeaders.Any(x => x.Name.ToLower() == "transfer-encoding"))
{ {
var transferEncoding = requestHeaders.First(x => x.Name.ToLower() == "transfer-encoding").Value.ToLower(); var transferEncoding =
RequestHeaders.First(x => x.Name.ToLower() == "transfer-encoding").Value.ToLower();
if (transferEncoding.Contains("chunked")) if (transferEncoding.Contains("chunked"))
{ {
isChunked = true; isChunked = true;
} }
} }
if (requestContentEncoding == null && !isChunked) if (requestContentEncoding == null && !isChunked)
requestBody = clientStreamReader.ReadBytes(RequestContentLength); RequestBody = ClientStreamReader.ReadBytes(RequestContentLength);
else else
{ {
using (var requestBodyStream = new MemoryStream()) using (var requestBodyStream = new MemoryStream())
...@@ -128,76 +140,72 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -128,76 +140,72 @@ namespace Titanium.Web.Proxy.EventArguments
{ {
while (true) while (true)
{ {
var chuchkHead = clientStreamReader.ReadLine(); var chuchkHead = ClientStreamReader.ReadLine();
var chunkSize = int.Parse(chuchkHead, System.Globalization.NumberStyles.HexNumber); var chunkSize = int.Parse(chuchkHead, NumberStyles.HexNumber);
if (chunkSize != 0) if (chunkSize != 0)
{ {
var buffer = clientStreamReader.ReadBytes(chunkSize); var buffer = ClientStreamReader.ReadBytes(chunkSize);
requestBodyStream.Write(buffer, 0, buffer.Length); requestBodyStream.Write(buffer, 0, buffer.Length);
//chunk trail
var chunkTrail = clientStreamReader.ReadLine(); ClientStreamReader.ReadLine();
} }
else else
{ {
clientStreamReader.ReadLine(); ClientStreamReader.ReadLine();
break; break;
} }
} }
} }
try try
{ {
switch (requestContentEncoding) switch (requestContentEncoding)
{ {
case "gzip": case "gzip":
requestBody = CompressionHelper.DecompressGzip(requestBodyStream); RequestBody = CompressionHelper.DecompressGzip(requestBodyStream);
break; break;
case "deflate": case "deflate":
requestBody = CompressionHelper.DecompressDeflate(requestBodyStream); RequestBody = CompressionHelper.DecompressDeflate(requestBodyStream);
break; break;
case "zlib": case "zlib":
requestBody = CompressionHelper.DecompressGzip(requestBodyStream); RequestBody = CompressionHelper.DecompressGzip(requestBodyStream);
break; break;
default: default:
requestBody = requestBodyStream.ToArray(); RequestBody = requestBodyStream.ToArray();
break; break;
} }
} }
catch { catch
requestBody = requestBodyStream.ToArray(); {
RequestBody = requestBodyStream.ToArray();
} }
} }
} }
} }
requestBodyRead = true; RequestBodyRead = true;
} }
private void readResponseBody()
private void ReadResponseBody()
{ {
if (responseBody == null) if (ResponseBody == null)
{ {
switch (ServerResponse.ContentEncoding)
switch (serverResponse.ContentEncoding)
{ {
case "gzip": case "gzip":
responseBody = CompressionHelper.DecompressGzip(responseStream); ResponseBody = CompressionHelper.DecompressGzip(ResponseStream);
break; break;
case "deflate": case "deflate":
responseBody = CompressionHelper.DecompressDeflate(responseStream); ResponseBody = CompressionHelper.DecompressDeflate(ResponseStream);
break; break;
case "zlib": case "zlib":
responseBody = CompressionHelper.DecompressZlib(responseStream); ResponseBody = CompressionHelper.DecompressZlib(ResponseStream);
break; break;
default: default:
responseBody = DecodeData(responseStream); ResponseBody = DecodeData(ResponseStream);
break; break;
} }
responseBodyRead = true; ResponseBodyRead = true;
} }
} }
...@@ -205,8 +213,8 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -205,8 +213,8 @@ namespace Titanium.Web.Proxy.EventArguments
//stream reader not recomended for images //stream reader not recomended for images
private byte[] DecodeData(Stream responseStream) private byte[] DecodeData(Stream responseStream)
{ {
byte[] buffer = new byte[BUFFER_SIZE]; var buffer = new byte[_bufferSize];
using (MemoryStream ms = new MemoryStream()) using (var ms = new MemoryStream())
{ {
int read; int read;
while ((read = responseStream.Read(buffer, 0, buffer.Length)) > 0) while ((read = responseStream.Read(buffer, 0, buffer.Length)) > 0)
...@@ -215,117 +223,105 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -215,117 +223,105 @@ namespace Titanium.Web.Proxy.EventArguments
} }
return ms.ToArray(); return ms.ToArray();
} }
} }
public Encoding GetRequestBodyEncoding() public Encoding GetRequestBodyEncoding()
{ {
if (RequestLocked) throw new Exception("You cannot call this function after request is made to server."); if (RequestLocked) throw new Exception("You cannot call this function after request is made to server.");
return requestEncoding; return RequestEncoding;
} }
public byte[] GetRequestBody() public byte[] GetRequestBody()
{ {
if (RequestLocked) throw new Exception("You cannot call this function after request is made to server."); if (RequestLocked) throw new Exception("You cannot call this function after request is made to server.");
readRequestBody(); ReadRequestBody();
return requestBody; return RequestBody;
} }
public string GetRequestBodyAsString() public string GetRequestBodyAsString()
{ {
if (RequestLocked) throw new Exception("You cannot call this function after request is made to server."); if (RequestLocked) throw new Exception("You cannot call this function after request is made to server.");
readRequestBody(); ReadRequestBody();
if (requestBodyString == null)
{
requestBodyString = requestEncoding.GetString(requestBody);
}
return requestBodyString;
return RequestBodyString ?? (RequestBodyString = RequestEncoding.GetString(RequestBody));
} }
public void SetRequestBody(byte[] body) public void SetRequestBody(byte[] body)
{ {
if (RequestLocked) throw new Exception("You cannot call this function after request is made to server."); if (RequestLocked) throw new Exception("You cannot call this function after request is made to server.");
if (!requestBodyRead) if (!RequestBodyRead)
{ {
readRequestBody(); ReadRequestBody();
} }
requestBody = body; RequestBody = body;
requestBodyRead = true; RequestBodyRead = true;
} }
public void SetRequestBodyString(string body) public void SetRequestBodyString(string body)
{ {
if (RequestLocked) throw new Exception("Youcannot call this function after request is made to server."); if (RequestLocked) throw new Exception("Youcannot call this function after request is made to server.");
if (!requestBodyRead) if (!RequestBodyRead)
{ {
readRequestBody(); ReadRequestBody();
} }
this.requestBody = requestEncoding.GetBytes(body); RequestBody = RequestEncoding.GetBytes(body);
requestBodyRead = true; RequestBodyRead = true;
} }
public Encoding GetResponseBodyEncoding() public Encoding GetResponseBodyEncoding()
{ {
if (!RequestLocked) throw new Exception("You cannot call this function before request is made to server."); if (!RequestLocked) throw new Exception("You cannot call this function before request is made to server.");
return responseEncoding; return ResponseEncoding;
} }
public byte[] GetResponseBody() public byte[] GetResponseBody()
{ {
if (!RequestLocked) throw new Exception("You cannot call this function before request is made to server."); if (!RequestLocked) throw new Exception("You cannot call this function before request is made to server.");
readResponseBody(); ReadResponseBody();
return responseBody; return ResponseBody;
} }
public string GetResponseBodyAsString() public string GetResponseBodyAsString()
{ {
if (!RequestLocked) throw new Exception("You cannot call this function before request is made to server."); if (!RequestLocked) throw new Exception("You cannot call this function before request is made to server.");
GetResponseBody(); GetResponseBody();
if (responseBodyString == null) return ResponseBodyString ?? (ResponseBodyString = ResponseEncoding.GetString(ResponseBody));
{
responseBodyString = responseEncoding.GetString(responseBody);
}
return responseBodyString;
} }
public void SetResponseBody(byte[] body) public void SetResponseBody(byte[] body)
{ {
if (!RequestLocked) throw new Exception("You cannot call this function before request is made to server."); if (!RequestLocked) throw new Exception("You cannot call this function before request is made to server.");
if (responseBody == null) if (ResponseBody == null)
{ {
GetResponseBody(); GetResponseBody();
} }
responseBody = body; ResponseBody = body;
} }
public void SetResponseBodyString(string body) public void SetResponseBodyString(string body)
{ {
if (!RequestLocked) throw new Exception("You cannot call this function before request is made to server."); if (!RequestLocked) throw new Exception("You cannot call this function before request is made to server.");
if (responseBody == null) if (ResponseBody == null)
{ {
GetResponseBody(); GetResponseBody();
} }
var bodyBytes = responseEncoding.GetBytes(body); var bodyBytes = ResponseEncoding.GetBytes(body);
SetResponseBody(bodyBytes); SetResponseBody(bodyBytes);
} }
...@@ -339,45 +335,24 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -339,45 +335,24 @@ namespace Titanium.Web.Proxy.EventArguments
var result = Encoding.Default.GetBytes(html); var result = Encoding.Default.GetBytes(html);
StreamWriter connectStreamWriter = new StreamWriter(clientStream); var connectStreamWriter = new StreamWriter(ClientStream);
var s = String.Format("HTTP/{0}.{1} {2} {3}", requestHttpVersion.Major, requestHttpVersion.Minor, 200, "Ok"); var s = string.Format("HTTP/{0}.{1} {2} {3}", RequestHttpVersion.Major, RequestHttpVersion.Minor, 200, "Ok");
connectStreamWriter.WriteLine(s); connectStreamWriter.WriteLine(s);
connectStreamWriter.WriteLine(String.Format("Timestamp: {0}", DateTime.Now.ToString())); connectStreamWriter.WriteLine("Timestamp: {0}", DateTime.Now);
connectStreamWriter.WriteLine("content-length: " + result.Length); connectStreamWriter.WriteLine("content-length: " + result.Length);
connectStreamWriter.WriteLine("Cache-Control: no-cache, no-store, must-revalidate"); connectStreamWriter.WriteLine("Cache-Control: no-cache, no-store, must-revalidate");
connectStreamWriter.WriteLine("Pragma: no-cache"); connectStreamWriter.WriteLine("Pragma: no-cache");
connectStreamWriter.WriteLine("Expires: 0"); connectStreamWriter.WriteLine("Expires: 0");
if (requestIsAlive) connectStreamWriter.WriteLine(RequestIsAlive ? "Connection: Keep-Alive" : "Connection: close");
{
connectStreamWriter.WriteLine("Connection: Keep-Alive");
}
else
connectStreamWriter.WriteLine("Connection: close");
connectStreamWriter.WriteLine(); connectStreamWriter.WriteLine();
connectStreamWriter.Flush(); connectStreamWriter.Flush();
clientStream.Write(result, 0, result.Length); ClientStream.Write(result, 0, result.Length);
cancelRequest = true; CancelRequest = true;
} }
public void Dispose()
{
if (this.proxyRequest != null)
this.proxyRequest.Abort();
if (this.responseStream != null)
this.responseStream.Dispose();
if (this.serverResponse != null)
this.serverResponse.Close();
}
} }
} }
\ No newline at end of file
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Titanium.Web.Proxy.Exceptions namespace Titanium.Web.Proxy.Exceptions
{ {
public class BodyNotFoundException : Exception public class BodyNotFoundException : Exception
{ {
public BodyNotFoundException(string message) public BodyNotFoundException(string message)
:base(message) : base(message)
{ {
} }
} }
} }
\ No newline at end of file
using System; using System.Net;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text; using System.Text;
namespace Titanium.Web.Proxy.Extensions namespace Titanium.Web.Proxy.Extensions
...@@ -24,9 +21,12 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -24,9 +21,12 @@ namespace Titanium.Web.Proxy.Extensions
} }
} }
} }
catch { } catch
{
// ignored
}
return Encoding.GetEncoding("ISO-8859-1"); return Encoding.GetEncoding("ISO-8859-1");
} }
} }
} }
\ No newline at end of file
using System; using System.Net;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text; using System.Text;
namespace Titanium.Web.Proxy.Extensions namespace Titanium.Web.Proxy.Extensions
...@@ -11,8 +8,7 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -11,8 +8,7 @@ namespace Titanium.Web.Proxy.Extensions
public static Encoding GetEncoding(this HttpWebResponse response) public static Encoding GetEncoding(this HttpWebResponse response)
{ {
if (string.IsNullOrEmpty(response.CharacterSet)) return Encoding.GetEncoding("ISO-8859-1"); if (string.IsNullOrEmpty(response.CharacterSet)) return Encoding.GetEncoding("ISO-8859-1");
else return Encoding.GetEncoding(response.CharacterSet);
return Encoding.GetEncoding(response.CharacterSet);
} }
} }
} }
\ No newline at end of file
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO; using System.IO;
using System.Text;
namespace Titanium.Web.Proxy.Extensions namespace Titanium.Web.Proxy.Extensions
{ {
public static class StreamHelper public static class StreamHelper
{ {
private const int DEFAULT_BUFFER_SIZE = 8192; // +32767
public static void CopyToAsync(this Stream input, string initialData, Stream output, int bufferSize) public static void CopyToAsync(this Stream input, string initialData, Stream output, int bufferSize)
{ {
var bytes = Encoding.ASCII.GetBytes(initialData); var bytes = Encoding.ASCII.GetBytes(initialData);
output.Write(bytes,0, bytes.Length); output.Write(bytes, 0, bytes.Length);
CopyToAsync(input, output, bufferSize); CopyToAsync(input, output, bufferSize);
} }
//http://stackoverflow.com/questions/1540658/net-asynchronous-stream-read-write //http://stackoverflow.com/questions/1540658/net-asynchronous-stream-read-write
...@@ -25,15 +21,14 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -25,15 +21,14 @@ namespace Titanium.Web.Proxy.Extensions
if (!input.CanRead) throw new InvalidOperationException("input must be open for reading"); if (!input.CanRead) throw new InvalidOperationException("input must be open for reading");
if (!output.CanWrite) throw new InvalidOperationException("output must be open for writing"); if (!output.CanWrite) throw new InvalidOperationException("output must be open for writing");
byte[][] buf = { new byte[bufferSize], new byte[bufferSize] }; byte[][] buf = {new byte[bufferSize], new byte[bufferSize]};
int[] bufl = { 0, 0 }; int[] bufl = {0, 0};
int bufno = 0; var bufno = 0;
IAsyncResult read = input.BeginRead(buf[bufno], 0, buf[bufno].Length, null, null); var read = input.BeginRead(buf[bufno], 0, buf[bufno].Length, null, null);
IAsyncResult write = null; IAsyncResult write = null;
while (true) while (true)
{ {
// wait for the read operation to complete // wait for the read operation to complete
read.AsyncWaitHandle.WaitOne(); read.AsyncWaitHandle.WaitOne();
bufl[bufno] = input.EndRead(read); bufl[bufno] = input.EndRead(read);
...@@ -62,7 +57,6 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -62,7 +57,6 @@ namespace Titanium.Web.Proxy.Extensions
// A little speedier than using a ternary expression. // A little speedier than using a ternary expression.
bufno ^= 1; // bufno = ( bufno == 0 ? 1 : 0 ) ; bufno ^= 1; // bufno = ( bufno == 0 ? 1 : 0 ) ;
read = input.BeginRead(buf[bufno], 0, buf[bufno].Length, null, null); read = input.BeginRead(buf[bufno], 0, buf[bufno].Length, null, null);
} }
// wait for the final in-flight write operation, if one exists, to complete // wait for the final in-flight write operation, if one exists, to complete
...@@ -75,9 +69,11 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -75,9 +69,11 @@ namespace Titanium.Web.Proxy.Extensions
output.Flush(); output.Flush();
} }
catch { } catch
{
// ignored
}
// return to the caller ; // return to the caller ;
return;
} }
} }
} }
\ No newline at end of file
...@@ -8,10 +8,10 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -8,10 +8,10 @@ namespace Titanium.Web.Proxy.Helpers
{ {
public class CertificateManager : IDisposable public class CertificateManager : IDisposable
{ {
private const string CERT_CREATE_FORMAT = private const string CertCreateFormat =
"-ss {0} -n \"CN={1}, O={2}\" -sky {3} -cy {4} -m 120 -a sha256 -eku 1.3.6.1.5.5.7.3.1 -b {5:MM/dd/yyyy} {6}"; "-ss {0} -n \"CN={1}, O={2}\" -sky {3} -cy {4} -m 120 -a sha256 -eku 1.3.6.1.5.5.7.3.1 -b {5:MM/dd/yyyy} {6}";
private readonly IDictionary<string, X509Certificate2> certificateCache; private readonly IDictionary<string, X509Certificate2> _certificateCache;
public string Issuer { get; private set; } public string Issuer { get; private set; }
public string RootCertificateName { get; private set; } public string RootCertificateName { get; private set; }
...@@ -27,7 +27,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -27,7 +27,7 @@ namespace Titanium.Web.Proxy.Helpers
MyStore = new X509Store(StoreName.My, StoreLocation.CurrentUser); MyStore = new X509Store(StoreName.My, StoreLocation.CurrentUser);
RootStore = new X509Store(StoreName.Root, StoreLocation.CurrentUser); RootStore = new X509Store(StoreName.Root, StoreLocation.CurrentUser);
certificateCache = new Dictionary<string, X509Certificate2>(); _certificateCache = new Dictionary<string, X509Certificate2>();
} }
/// <summary> /// <summary>
...@@ -69,8 +69,9 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -69,8 +69,9 @@ namespace Titanium.Web.Proxy.Helpers
} }
protected virtual X509Certificate2 CreateCertificate(X509Store store, string certificateName) protected virtual X509Certificate2 CreateCertificate(X509Store store, string certificateName)
{ {
if (certificateCache.ContainsKey(certificateName))
return certificateCache[certificateName]; if (_certificateCache.ContainsKey(certificateName))
return _certificateCache[certificateName];
lock (store) lock (store)
{ {
...@@ -80,7 +81,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -80,7 +81,7 @@ namespace Titanium.Web.Proxy.Helpers
store.Open(OpenFlags.ReadWrite); store.Open(OpenFlags.ReadWrite);
string certificateSubject = string.Format("CN={0}, O={1}", certificateName, Issuer); string certificateSubject = string.Format("CN={0}, O={1}", certificateName, Issuer);
X509Certificate2Collection certificates = var certificates =
FindCertificates(store, certificateSubject); FindCertificates(store, certificateSubject);
if (certificates != null) if (certificates != null)
...@@ -102,8 +103,8 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -102,8 +103,8 @@ namespace Titanium.Web.Proxy.Helpers
finally finally
{ {
store.Close(); store.Close();
if (certificate != null && !certificateCache.ContainsKey(certificateName)) if (certificate != null && !_certificateCache.ContainsKey(certificateName))
certificateCache.Add(certificateName, certificate); _certificateCache.Add(certificateName, certificate);
} }
} }
} }
...@@ -151,9 +152,9 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -151,9 +152,9 @@ namespace Titanium.Web.Proxy.Helpers
{ {
store.Close(); store.Close();
if (certificates == null && if (certificates == null &&
certificateCache.ContainsKey(certificateName)) _certificateCache.ContainsKey(certificateName))
{ {
certificateCache.Remove(certificateName); _certificateCache.Remove(certificateName);
} }
} }
} }
...@@ -164,7 +165,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -164,7 +165,7 @@ namespace Titanium.Web.Proxy.Helpers
bool isRootCertificate = bool isRootCertificate =
(certificateName == RootCertificateName); (certificateName == RootCertificateName);
string certCreatArgs = string.Format(CERT_CREATE_FORMAT, string certCreatArgs = string.Format(CertCreateFormat,
store.Name, certificateName, Issuer, store.Name, certificateName, Issuer,
isRootCertificate ? "signature" : "exchange", isRootCertificate ? "signature" : "exchange",
isRootCertificate ? "authority" : "end", DateTime.Now, isRootCertificate ? "authority" : "end", DateTime.Now,
......
using System; using System.Diagnostics.CodeAnalysis;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO; using System.IO;
using System.Diagnostics.CodeAnalysis; using Ionic.Zlib;
namespace Titanium.Web.Proxy.Helpers namespace Titanium.Web.Proxy.Helpers
{ {
public class CompressionHelper public class CompressionHelper
{ {
private static readonly int BUFFER_SIZE = 8192; private const int BufferSize = 8192;
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")] [SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")]
public static byte[] CompressZlib(byte[] bytes) public static byte[] CompressZlib(byte[] bytes)
{ {
using (var ms = new MemoryStream())
using (MemoryStream ms = new MemoryStream())
{ {
using (Ionic.Zlib.ZlibStream zip = new Ionic.Zlib.ZlibStream(ms, Ionic.Zlib.CompressionMode.Compress, true)) using (var zip = new ZlibStream(ms, CompressionMode.Compress, true))
{ {
zip.Write(bytes, 0, bytes.Length); zip.Write(bytes, 0, bytes.Length);
} }
...@@ -26,13 +22,12 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -26,13 +22,12 @@ namespace Titanium.Web.Proxy.Helpers
} }
} }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")] [SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")]
public static byte[] CompressDeflate(byte[] bytes) public static byte[] CompressDeflate(byte[] bytes)
{ {
using (var ms = new MemoryStream())
using (MemoryStream ms = new MemoryStream())
{ {
using (Ionic.Zlib.DeflateStream zip = new Ionic.Zlib.DeflateStream(ms, Ionic.Zlib.CompressionMode.Compress, true)) using (var zip = new DeflateStream(ms, CompressionMode.Compress, true))
{ {
zip.Write(bytes, 0, bytes.Length); zip.Write(bytes, 0, bytes.Length);
} }
...@@ -41,32 +36,31 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -41,32 +36,31 @@ namespace Titanium.Web.Proxy.Helpers
} }
} }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")] [SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")]
public static byte[] CompressGzip(byte[] bytes) public static byte[] CompressGzip(byte[] bytes)
{ {
using (var ms = new MemoryStream())
using (MemoryStream ms = new MemoryStream())
{ {
using (Ionic.Zlib.GZipStream zip = new Ionic.Zlib.GZipStream(ms, Ionic.Zlib.CompressionMode.Compress, true)) using (var zip = new GZipStream(ms, CompressionMode.Compress, true))
{ {
zip.Write(bytes, 0, bytes.Length); zip.Write(bytes, 0, bytes.Length);
} }
return ms.ToArray(); return ms.ToArray();
} }
} }
public static byte[] DecompressGzip(Stream input) public static byte[] DecompressGzip(Stream input)
{ {
using (var decompressor = new System.IO.Compression.GZipStream(input, System.IO.Compression.CompressionMode.Decompress)) using (
var decompressor = new System.IO.Compression.GZipStream(input,
System.IO.Compression.CompressionMode.Decompress))
{ {
var buffer = new byte[BufferSize];
int read = 0; using (var output = new MemoryStream())
var buffer = new byte[BUFFER_SIZE];
using (MemoryStream output = new MemoryStream())
{ {
int read;
while ((read = decompressor.Read(buffer, 0, buffer.Length)) > 0) while ((read = decompressor.Read(buffer, 0, buffer.Length)) > 0)
{ {
output.Write(buffer, 0, read); output.Write(buffer, 0, read);
...@@ -78,13 +72,13 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -78,13 +72,13 @@ namespace Titanium.Web.Proxy.Helpers
public static byte[] DecompressDeflate(Stream input) public static byte[] DecompressDeflate(Stream input)
{ {
using (Ionic.Zlib.DeflateStream decompressor = new Ionic.Zlib.DeflateStream(input, Ionic.Zlib.CompressionMode.Decompress)) using (var decompressor = new DeflateStream(input, CompressionMode.Decompress))
{ {
int read = 0; var buffer = new byte[BufferSize];
var buffer = new byte[BUFFER_SIZE];
using (MemoryStream output = new MemoryStream()) using (var output = new MemoryStream())
{ {
int read;
while ((read = decompressor.Read(buffer, 0, buffer.Length)) > 0) while ((read = decompressor.Read(buffer, 0, buffer.Length)) > 0)
{ {
output.Write(buffer, 0, read); output.Write(buffer, 0, read);
...@@ -93,15 +87,16 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -93,15 +87,16 @@ namespace Titanium.Web.Proxy.Helpers
} }
} }
} }
public static byte[] DecompressZlib(Stream input) public static byte[] DecompressZlib(Stream input)
{ {
using (Ionic.Zlib.ZlibStream decompressor = new Ionic.Zlib.ZlibStream(input, Ionic.Zlib.CompressionMode.Decompress)) using (var decompressor = new ZlibStream(input, CompressionMode.Decompress))
{ {
int read = 0; var buffer = new byte[BufferSize];
var buffer = new byte[BUFFER_SIZE];
using (MemoryStream output = new MemoryStream()) using (var output = new MemoryStream())
{ {
int read;
while ((read = decompressor.Read(buffer, 0, buffer.Length)) > 0) while ((read = decompressor.Read(buffer, 0, buffer.Length)) > 0)
{ {
output.Write(buffer, 0, read); output.Write(buffer, 0, read);
...@@ -111,4 +106,4 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -111,4 +106,4 @@ namespace Titanium.Web.Proxy.Helpers
} }
} }
} }
} }
\ No newline at end of file
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO; using System.IO;
using System.Diagnostics; using System.Text;
namespace Titanium.Web.Proxy.Helpers namespace Titanium.Web.Proxy.Helpers
{ {
internal class CustomBinaryReader : BinaryReader internal class CustomBinaryReader : BinaryReader
{ {
internal CustomBinaryReader(Stream stream, Encoding encoding) internal CustomBinaryReader(Stream stream, Encoding encoding)
: base(stream, encoding) : base(stream, encoding)
{ {
} }
internal string ReadLine() internal string ReadLine()
{ {
char[] buf = new char[1]; var buf = new char[1];
StringBuilder readBuffer = new StringBuilder(); var readBuffer = new StringBuilder();
try try
{ {
var charsRead = 0; var lastChar = new char();
char lastChar = new char();
while ((charsRead = base.Read(buf, 0, 1)) > 0) while ((Read(buf, 0, 1)) > 0)
{ {
if (lastChar == '\r' && buf[0] == '\n') if (lastChar == '\r' && buf[0] == '\n')
{ {
return readBuffer.Remove(readBuffer.Length - 1, 1).ToString(); return readBuffer.Remove(readBuffer.Length - 1, 1).ToString();
} }
else if (buf[0] == '\0')
if (buf[0] == '\0') {
{ return readBuffer.ToString();
return readBuffer.ToString(); }
} readBuffer.Append(buf[0]);
else
readBuffer.Append(buf[0]);
lastChar = buf[0]; lastChar = buf[0];
} }
return readBuffer.ToString(); return readBuffer.ToString();
} }
catch (IOException) catch (IOException)
{ {
return readBuffer.ToString(); return readBuffer.ToString();
} }
catch (Exception)
{
throw;
}
} }
internal List<string> ReadAllLines() internal List<string> ReadAllLines()
{ {
string tmpLine = null; string tmpLine;
List<string> requestLines = new List<string>(); var requestLines = new List<string>();
while (!String.IsNullOrEmpty(tmpLine = ReadLine())) while (!string.IsNullOrEmpty(tmpLine = ReadLine()))
{ {
requestLines.Add(tmpLine); requestLines.Add(tmpLine);
} }
return requestLines; return requestLines;
} }
} }
} }
\ No newline at end of file
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO; using System.IO;
namespace Titanium.Web.Proxy.Helpers namespace Titanium.Web.Proxy.Helpers
...@@ -12,21 +9,23 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -12,21 +9,23 @@ namespace Titanium.Web.Proxy.Helpers
{ {
try try
{ {
DirectoryInfo[] myProfileDirectory = new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\Mozilla\\Firefox\\Profiles\\").GetDirectories("*.default"); var myProfileDirectory =
string myFFPrefFile = myProfileDirectory[0].FullName + "\\prefs.js"; new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) +
if (File.Exists(myFFPrefFile)) "\\Mozilla\\Firefox\\Profiles\\").GetDirectories("*.default");
var myFfPrefFile = myProfileDirectory[0].FullName + "\\prefs.js";
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
StreamReader myReader = new StreamReader(myFFPrefFile); var myReader = new StreamReader(myFfPrefFile);
string myPrefContents = myReader.ReadToEnd(); var myPrefContents = myReader.ReadToEnd();
myReader.Close(); myReader.Close();
if (myPrefContents.Contains("user_pref(\"network.proxy.type\", 0);")) 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);
} }
} }
} }
...@@ -35,25 +34,28 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -35,25 +34,28 @@ namespace Titanium.Web.Proxy.Helpers
// 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.
} }
} }
public static void RemoveFirefox() public static void RemoveFirefox()
{ {
try try
{ {
DirectoryInfo[] myProfileDirectory = new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\Mozilla\\Firefox\\Profiles\\").GetDirectories("*.default"); var myProfileDirectory =
string myFFPrefFile = myProfileDirectory[0].FullName + "\\prefs.js"; new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) +
if (File.Exists(myFFPrefFile)) "\\Mozilla\\Firefox\\Profiles\\").GetDirectories("*.default");
var myFfPrefFile = myProfileDirectory[0].FullName + "\\prefs.js";
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
StreamReader myReader = new StreamReader(myFFPrefFile); var myReader = new StreamReader(myFfPrefFile);
string myPrefContents = myReader.ReadToEnd(); var myPrefContents = myReader.ReadToEnd();
myReader.Close(); myReader.Close();
if (!myPrefContents.Contains("user_pref(\"network.proxy.type\", 0);")) 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 + "\n\r" + "user_pref(\"network.proxy.type\", 0);"; myPrefContents = myPrefContents + "\n\r" + "user_pref(\"network.proxy.type\", 0);";
File.Delete(myFFPrefFile); File.Delete(myFfPrefFile);
File.WriteAllText(myFFPrefFile, myPrefContents); File.WriteAllText(myFfPrefFile, myPrefContents);
} }
} }
} }
...@@ -63,4 +65,4 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -63,4 +65,4 @@ namespace Titanium.Web.Proxy.Helpers
} }
} }
} }
} }
\ No newline at end of file
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Configuration; using System.Net.Configuration;
using System.Reflection; using System.Reflection;
using System.Text;
namespace Titanium.Web.Proxy.Helpers namespace Titanium.Web.Proxy.Helpers
{ {
...@@ -11,25 +8,24 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -11,25 +8,24 @@ namespace Titanium.Web.Proxy.Helpers
{ {
//Fix bug in .Net 4.0 HttpWebRequest (don't use this for 4.5 and above) //Fix bug in .Net 4.0 HttpWebRequest (don't use this for 4.5 and above)
//http://stackoverflow.com/questions/856885/httpwebrequest-to-url-with-dot-at-the-end //http://stackoverflow.com/questions/856885/httpwebrequest-to-url-with-dot-at-the-end
public static void URLPeriodFix() public static void UrlPeriodFix()
{ {
MethodInfo getSyntax = typeof(UriParser).GetMethod("GetSyntax", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic); var getSyntax = typeof (UriParser).GetMethod("GetSyntax", BindingFlags.Static | BindingFlags.NonPublic);
FieldInfo flagsField = typeof(UriParser).GetField("m_Flags", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); var flagsField = typeof (UriParser).GetField("m_Flags", BindingFlags.Instance | BindingFlags.NonPublic);
if (getSyntax != null && flagsField != null) if (getSyntax != null && flagsField != null)
{ {
foreach (string scheme in new[] { "http", "https" }) foreach (var scheme in new[] {"http", "https"})
{ {
UriParser parser = (UriParser)getSyntax.Invoke(null, new object[] { scheme }); var parser = (UriParser) getSyntax.Invoke(null, new object[] {scheme});
if (parser != null) if (parser != null)
{ {
int flagsValue = (int)flagsField.GetValue(parser); var flagsValue = (int) flagsField.GetValue(parser);
if ((flagsValue & 0x1000000) != 0) if ((flagsValue & 0x1000000) != 0)
flagsField.SetValue(parser, flagsValue & ~0x1000000); flagsField.SetValue(parser, flagsValue & ~0x1000000);
} }
} }
} }
} }
// Enable/disable useUnsafeHeaderParsing. // Enable/disable useUnsafeHeaderParsing.
...@@ -37,31 +33,32 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -37,31 +33,32 @@ namespace Titanium.Web.Proxy.Helpers
public static bool ToggleAllowUnsafeHeaderParsing(bool enable) public static bool ToggleAllowUnsafeHeaderParsing(bool enable)
{ {
//Get the assembly that contains the internal class //Get the assembly that contains the internal class
Assembly assembly = Assembly.GetAssembly(typeof(SettingsSection)); var assembly = Assembly.GetAssembly(typeof (SettingsSection));
if (assembly != null) if (assembly != null)
{ {
//Use the assembly in order to get the internal type for the internal class //Use the assembly in order to get the internal type for the internal class
Type settingsSectionType = assembly.GetType("System.Net.Configuration.SettingsSectionInternal"); var settingsSectionType = assembly.GetType("System.Net.Configuration.SettingsSectionInternal");
if (settingsSectionType != null) if (settingsSectionType != null)
{ {
//Use the internal static property to get an instance of the internal settings class. //Use the internal static property to get an instance of the internal settings class.
//If the static instance isn't created already invoking the property will create it for us. //If the static instance isn't created already invoking the property will create it for us.
object anInstance = settingsSectionType.InvokeMember("Section", var anInstance = settingsSectionType.InvokeMember("Section",
BindingFlags.Static | BindingFlags.GetProperty | BindingFlags.NonPublic, null, null, new object[] { }); BindingFlags.Static | BindingFlags.GetProperty | BindingFlags.NonPublic, null, null,
new object[] {});
if (anInstance != null) if (anInstance != null)
{ {
//Locate the private bool field that tells the framework if unsafe header parsing is allowed //Locate the private bool field that tells the framework if unsafe header parsing is allowed
FieldInfo aUseUnsafeHeaderParsing = settingsSectionType.GetField("useUnsafeHeaderParsing", BindingFlags.NonPublic | BindingFlags.Instance); var aUseUnsafeHeaderParsing = settingsSectionType.GetField("useUnsafeHeaderParsing",
BindingFlags.NonPublic | BindingFlags.Instance);
if (aUseUnsafeHeaderParsing != null) if (aUseUnsafeHeaderParsing != null)
{ {
aUseUnsafeHeaderParsing.SetValue(anInstance, enable); aUseUnsafeHeaderParsing.SetValue(anInstance, enable);
return true; return true;
} }
} }
} }
} }
return false; return false;
} }
} }
} }
\ No newline at end of file
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Win32;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using Microsoft.Win32;
namespace Titanium.Web.Proxy.Helpers namespace Titanium.Web.Proxy.Helpers
{ {
internal static class NativeMethods internal static class NativeMethods
{ {
[DllImport("wininet.dll")] [DllImport("wininet.dll")]
internal static extern bool InternetSetOption(IntPtr hInternet, int dwOption, IntPtr lpBuffer, int dwBufferLength); internal static extern bool InternetSetOption(IntPtr hInternet, int dwOption, IntPtr lpBuffer,
int dwBufferLength);
} }
public static class SystemProxyHelper public static class SystemProxyHelper
{ {
public const int InternetOptionSettingsChanged = 39;
public const int InternetOptionRefresh = 37;
private static object _prevProxyServer;
private static object _prevProxyEnable;
public const int INTERNET_OPTION_SETTINGS_CHANGED = 39; public static void EnableProxyHttp(string hostname, int port)
public const int INTERNET_OPTION_REFRESH = 37;
static bool settingsReturn, refreshReturn;
static object prevProxyServer;
static object prevProxyEnable;
public static void EnableProxyHTTP(string hostname, int port)
{ {
RegistryKey reg = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", true); var reg = Registry.CurrentUser.OpenSubKey(
prevProxyEnable = reg.GetValue("ProxyEnable"); "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", true);
prevProxyServer = reg.GetValue("ProxyServer"); if (reg != null)
reg.SetValue("ProxyEnable", 1); {
reg.SetValue("ProxyServer", "http=" + hostname + ":" + port + ";"); _prevProxyEnable = reg.GetValue("ProxyEnable");
refresh(); _prevProxyServer = reg.GetValue("ProxyServer");
reg.SetValue("ProxyEnable", 1);
reg.SetValue("ProxyServer", "http=" + hostname + ":" + port + ";");
}
Refresh();
} }
public static void EnableProxyHTTPS(string hostname, int port)
public static void EnableProxyHttps(string hostname, int port)
{ {
RegistryKey reg = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", true); var reg = Registry.CurrentUser.OpenSubKey(
reg.SetValue("ProxyEnable", 1); "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", true);
reg.SetValue("ProxyServer", "http=" + hostname + ":" + port + ";https=" + hostname + ":" + port); if (reg != null)
refresh(); {
reg.SetValue("ProxyEnable", 1);
reg.SetValue("ProxyServer", "http=" + hostname + ":" + port + ";https=" + hostname + ":" + port);
}
Refresh();
} }
public static void DisableAllProxy() public static void DisableAllProxy()
{ {
RegistryKey reg = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", true); var reg = Registry.CurrentUser.OpenSubKey(
reg.SetValue("ProxyEnable", prevProxyEnable); "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", true);
if (prevProxyServer != null) if (reg != null)
reg.SetValue("ProxyServer", prevProxyServer); {
refresh(); reg.SetValue("ProxyEnable", _prevProxyEnable);
if (_prevProxyServer != null)
reg.SetValue("ProxyServer", _prevProxyServer);
}
Refresh();
} }
private static void refresh()
private static void Refresh()
{ {
settingsReturn = NativeMethods.InternetSetOption(IntPtr.Zero, INTERNET_OPTION_SETTINGS_CHANGED, IntPtr.Zero, 0); NativeMethods.InternetSetOption(IntPtr.Zero, InternetOptionSettingsChanged, IntPtr.Zero,0);
refreshReturn = NativeMethods.InternetSetOption(IntPtr.Zero, INTERNET_OPTION_REFRESH, IntPtr.Zero, 0); NativeMethods.InternetSetOption(IntPtr.Zero, InternetOptionRefresh, IntPtr.Zero, 0);
} }
} }
} }
\ No newline at end of file
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using System.Text;
using System.Net.Security; using System.Net.Security;
using System.IO;
using System.Net;
using System.Threading.Tasks;
using System.Net.Sockets; using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using Titanium.Web.Proxy.Extensions; using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Models; using Titanium.Web.Proxy.Models;
...@@ -15,9 +14,9 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -15,9 +14,9 @@ namespace Titanium.Web.Proxy.Helpers
public class TcpHelper public class TcpHelper
{ {
private static readonly int BUFFER_SIZE = 8192; private static readonly int BUFFER_SIZE = 8192;
private static readonly String[] colonSpaceSplit = new string[] { ": " };
public static void SendRaw(Stream clientStream, string httpCmd, List<HttpHeader> requestHeaders, string hostName,
public static void SendRaw(Stream clientStream, string httpCmd, List<HttpHeader> requestHeaders, string hostName, int tunnelPort, bool isHttps) int tunnelPort, bool isHttps)
{ {
StringBuilder sb = null; StringBuilder sb = null;
if (httpCmd != null || requestHeaders != null) if (httpCmd != null || requestHeaders != null)
...@@ -29,23 +28,22 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -29,23 +28,22 @@ namespace Titanium.Web.Proxy.Helpers
sb.Append(Environment.NewLine); sb.Append(Environment.NewLine);
} }
if (requestHeaders != null) if (requestHeaders != null)
for (int i = 0; i < requestHeaders.Count; i++) foreach (var header in requestHeaders.Select(t => t.ToString()))
{ {
var header = requestHeaders[i].ToString(); sb.Append(header);
sb.Append(header); sb.Append(Environment.NewLine);
sb.Append(Environment.NewLine); }
}
sb.Append(Environment.NewLine); sb.Append(Environment.NewLine);
} }
System.Net.Sockets.TcpClient tunnelClient = null;
TcpClient tunnelClient = null;
Stream tunnelStream = null; Stream tunnelStream = null;
try try
{ {
tunnelClient = new System.Net.Sockets.TcpClient(hostName, tunnelPort); tunnelClient = new TcpClient(hostName, tunnelPort);
tunnelStream = tunnelClient.GetStream() as Stream; tunnelStream = tunnelClient.GetStream();
if (isHttps) if (isHttps)
{ {
...@@ -60,12 +58,15 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -60,12 +58,15 @@ namespace Titanium.Web.Proxy.Helpers
{ {
if (sslStream != null) if (sslStream != null)
sslStream.Dispose(); sslStream.Dispose();
throw;
} }
} }
var sendRelay = Task.Factory.StartNew(() => { var sendRelay = Task.Factory.StartNew(() =>
if(sb!=null) {
if (sb != null)
clientStream.CopyToAsync(sb.ToString(), tunnelStream, BUFFER_SIZE); clientStream.CopyToAsync(sb.ToString(), tunnelStream, BUFFER_SIZE);
else else
clientStream.CopyToAsync(tunnelStream, BUFFER_SIZE); clientStream.CopyToAsync(tunnelStream, BUFFER_SIZE);
...@@ -89,7 +90,5 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -89,7 +90,5 @@ namespace Titanium.Web.Proxy.Helpers
throw; throw;
} }
} }
} }
} }
\ No newline at end of file
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Titanium.Web.Proxy.Models namespace Titanium.Web.Proxy.Models
{ {
public class HttpHeader public class HttpHeader
{ {
public string Name { get; set; }
public string Value { get; set; }
public HttpHeader(string name, string value) public HttpHeader(string name, string value)
{ {
if (string.IsNullOrEmpty(name)) throw new Exception("Name cannot be null"); if (string.IsNullOrEmpty(name)) throw new Exception("Name cannot be null");
this.Name = name.Trim(); Name = name.Trim();
this.Value = value.Trim(); Value = value.Trim();
} }
public string Name { get; set; }
public string Value { get; set; }
public override string ToString() public override string ToString()
{ {
return String.Format("{0}: {1}", this.Name, this.Value); return string.Format("{0}: {1}", Name, Value);
} }
} }
} }
\ No newline at end of file
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
// set of attributes. Change these attribute values to modify the information // set of attributes. Change these attribute values to modify the information
// associated with an assembly. // associated with an assembly.
[assembly: AssemblyTitle("Titanium.Web.Proxy.Properties")] [assembly: AssemblyTitle("Titanium.Web.Proxy.Properties")]
[assembly: AssemblyDescription("")] [assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
...@@ -17,9 +17,11 @@ using System.Runtime.InteropServices; ...@@ -17,9 +17,11 @@ using System.Runtime.InteropServices;
// 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
// COM, set the ComVisible attribute to true on that type. // COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)] [assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM // The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("5036e0b7-a0d0-4070-8eb0-72c129dee9b3")] [assembly: Guid("5036e0b7-a0d0-4070-8eb0-72c129dee9b3")]
// Version information for an assembly consists of the following four values: // Version information for an assembly consists of the following four values:
...@@ -29,5 +31,6 @@ using System.Runtime.InteropServices; ...@@ -29,5 +31,6 @@ using System.Runtime.InteropServices;
// Build Number // Build Number
// Revision // Revision
// //
[assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")]
\ No newline at end of file
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Threading;
using System.IO;
using System.Net; using System.Net;
using System.Net.Sockets;
using System.Net.Security; using System.Net.Security;
using System.Security.Authentication; using System.Net.Sockets;
using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.X509Certificates;
using System.Diagnostics; using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using Titanium.Web.Proxy.EventArguments; using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Helpers; using Titanium.Web.Proxy.Helpers;
using System.Text;
namespace Titanium.Web.Proxy namespace Titanium.Web.Proxy
{ {
/// <summary> /// <summary>
/// Proxy Server Main class /// Proxy Server Main class
/// </summary> /// </summary>
public partial class ProxyServer public partial class ProxyServer
{ {
private static readonly int BUFFER_SIZE = 8192; private static readonly int BUFFER_SIZE = 8192;
private static readonly char[] semiSplit = new char[] { ';' }; private static readonly char[] SemiSplit = {';'};
private static readonly String[] colonSpaceSplit = new string[] { ": " }; private static readonly string[] ColonSpaceSplit = {": "};
private static readonly char[] spaceSplit = new char[] { ' ' }; private static readonly char[] SpaceSplit = {' '};
private static readonly Regex cookieSplitRegEx = new Regex(@",(?! )"); private static readonly Regex CookieSplitRegEx = new Regex(@",(?! )");
private static readonly byte[] chunkTrail = Encoding.ASCII.GetBytes(Environment.NewLine); private static readonly byte[] ChunkTrail = Encoding.ASCII.GetBytes(Environment.NewLine);
private static readonly byte[] ChunkEnd = Encoding.ASCII.GetBytes(0.ToString("x2") + Environment.NewLine + Environment.NewLine);
private static object certificateAccessLock = new object(); private static readonly byte[] ChunkEnd =
Encoding.ASCII.GetBytes(0.ToString("x2") + Environment.NewLine + Environment.NewLine);
private static TcpListener listener; private static TcpListener _listener;
private static CertificateManager CertManager { get; set; }
public static List<string> ExcludedHttpsHostNameRegex = new List<string>(); public static List<string> ExcludedHttpsHostNameRegex = new List<string>();
public static event EventHandler<SessionEventArgs> BeforeRequest;
public static event EventHandler<SessionEventArgs> BeforeResponse;
public static string RootCertificateName { get; set; }
public static bool EnableSSL { get; set; }
public static bool SetAsSystemProxy { get; set; }
public static Int32 ListeningPort { get; set; }
public static IPAddress ListeningIpAddress { get; set; }
static ProxyServer() static ProxyServer()
{ {
CertManager = new CertificateManager("Titanium", CertManager = new CertificateManager("Titanium",
...@@ -61,74 +45,89 @@ namespace Titanium.Web.Proxy ...@@ -61,74 +45,89 @@ namespace Titanium.Web.Proxy
Initialize(); Initialize();
} }
private static CertificateManager CertManager { get; set; }
public static string RootCertificateName { get; set; }
public static bool EnableSsl { get; set; }
public static bool SetAsSystemProxy { get; set; }
public static int ListeningPort { get; set; }
public static IPAddress ListeningIpAddress { get; set; }
public static event EventHandler<SessionEventArgs> BeforeRequest;
public static event EventHandler<SessionEventArgs> BeforeResponse;
public static void Initialize() public static void Initialize()
{ {
ServicePointManager.Expect100Continue = false;
System.Net.ServicePointManager.Expect100Continue = false; WebRequest.DefaultWebProxy = null;
System.Net.WebRequest.DefaultWebProxy = null; ServicePointManager.DefaultConnectionLimit = 10;
System.Net.ServicePointManager.DefaultConnectionLimit = 10; ServicePointManager.DnsRefreshTimeout = 3*60*1000; //3 minutes
ServicePointManager.DnsRefreshTimeout = 3 * 60 * 1000;//3 minutes ServicePointManager.MaxServicePointIdleTime = 3*60*1000;
ServicePointManager.MaxServicePointIdleTime = 3 * 60 * 1000;
//HttpWebRequest certificate validation callback //HttpWebRequest certificate validation callback
ServicePointManager.ServerCertificateValidationCallback = delegate(object s, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) ServicePointManager.ServerCertificateValidationCallback =
{ delegate(object s, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
if (sslPolicyErrors == SslPolicyErrors.None) return true; {
else if (sslPolicyErrors == SslPolicyErrors.None) return true;
return false; return false;
}; };
//Fix a bug in .NET 4.0 //Fix a bug in .NET 4.0
NetFrameworkHelper.URLPeriodFix(); NetFrameworkHelper.UrlPeriodFix();
//useUnsafeHeaderParsing //useUnsafeHeaderParsing
NetFrameworkHelper.ToggleAllowUnsafeHeaderParsing(true); NetFrameworkHelper.ToggleAllowUnsafeHeaderParsing(true);
} }
public static bool Start() public static bool Start()
{ {
listener = new TcpListener(ListeningIpAddress, ListeningPort); _listener = new TcpListener(ListeningIpAddress, ListeningPort);
listener.Start(); _listener.Start();
ListeningPort = ((IPEndPoint)listener.LocalEndpoint).Port; ListeningPort = ((IPEndPoint) _listener.LocalEndpoint).Port;
// accept clients asynchronously // accept clients asynchronously
listener.BeginAcceptTcpClient(OnAcceptConnection, listener); _listener.BeginAcceptTcpClient(OnAcceptConnection, _listener);
if (SetAsSystemProxy) if (SetAsSystemProxy)
{ {
SystemProxyHelper.EnableProxyHTTP(ListeningIpAddress == IPAddress.Any ? "127.0.0.1" : ListeningIpAddress.ToString(), ListeningPort); SystemProxyHelper.EnableProxyHttp(
Equals(ListeningIpAddress, IPAddress.Any) ? "127.0.0.1" : ListeningIpAddress.ToString(), ListeningPort);
FireFoxHelper.AddFirefox(); FireFoxHelper.AddFirefox();
if (EnableSSL) if (EnableSsl)
{ {
RootCertificateName = RootCertificateName == null ? "Titanium_Proxy_Test_Root" : RootCertificateName; RootCertificateName = RootCertificateName ?? "Titanium_Proxy_Test_Root";
bool certTrusted = CertManager.CreateTrustedRootCertificate(); var certTrusted = CertManager.CreateTrustedRootCertificate();
//If certificate was trusted by the machine //If certificate was trusted by the machine
if (certTrusted) if (certTrusted)
{ {
SystemProxyHelper.EnableProxyHTTPS(ListeningIpAddress == IPAddress.Any ? "127.0.0.1" : ListeningIpAddress.ToString(), ListeningPort); SystemProxyHelper.EnableProxyHttps(
Equals(ListeningIpAddress, IPAddress.Any) ? "127.0.0.1" : ListeningIpAddress.ToString(),
ListeningPort);
} }
} }
} }
return true; return true;
} }
private static void OnAcceptConnection(IAsyncResult asyn) private static void OnAcceptConnection(IAsyncResult asyn)
{ {
try try
{ {
// Get the listener that handles the client request. // Get the listener that handles the client request.
listener.BeginAcceptTcpClient(OnAcceptConnection, listener); _listener.BeginAcceptTcpClient(OnAcceptConnection, _listener);
TcpClient client = listener.EndAcceptTcpClient(asyn); var client = _listener.EndAcceptTcpClient(asyn);
Task.Factory.StartNew(() => HandleClient(client)); Task.Factory.StartNew(() => HandleClient(client));
} }
catch { } catch
{
// ignored
}
} }
...@@ -140,9 +139,8 @@ namespace Titanium.Web.Proxy ...@@ -140,9 +139,8 @@ namespace Titanium.Web.Proxy
FireFoxHelper.RemoveFirefox(); FireFoxHelper.RemoveFirefox();
} }
listener.Stop(); _listener.Stop();
CertManager.Dispose(); CertManager.Dispose();
} }
} }
} }
\ No newline at end of file
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Globalization;
using System.Text;
using System.Threading;
using System.IO; using System.IO;
using System.Linq;
using System.Net; using System.Net;
using System.Net.Security; using System.Net.Security;
using System.Security.Authentication;
using System.Net.Sockets; using System.Net.Sockets;
using System.Diagnostics; using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates; using System.Text;
using System.Reflection; using System.Text.RegularExpressions;
using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.EventArguments;
using System.Threading.Tasks; using System.Threading.Tasks;
using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Extensions; using Titanium.Web.Proxy.Extensions;
using System.Text.RegularExpressions; using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Models; using Titanium.Web.Proxy.Models;
namespace Titanium.Web.Proxy namespace Titanium.Web.Proxy
...@@ -25,22 +22,22 @@ namespace Titanium.Web.Proxy ...@@ -25,22 +22,22 @@ namespace Titanium.Web.Proxy
private static void HandleClient(TcpClient client) private static void HandleClient(TcpClient client)
{ {
Stream clientStream = client.GetStream(); Stream clientStream = client.GetStream();
CustomBinaryReader clientStreamReader = new CustomBinaryReader(clientStream, Encoding.ASCII); var clientStreamReader = new CustomBinaryReader(clientStream, Encoding.ASCII);
StreamWriter clientStreamWriter = new StreamWriter(clientStream); var clientStreamWriter = new StreamWriter(clientStream);
Uri httpRemoteUri; Uri httpRemoteUri;
try try
{ {
//read the first line HTTP command //read the first line HTTP command
String httpCmd = clientStreamReader.ReadLine(); var httpCmd = clientStreamReader.ReadLine();
if (String.IsNullOrEmpty(httpCmd)) if (string.IsNullOrEmpty(httpCmd))
{ {
throw new EndOfStreamException(); throw new EndOfStreamException();
} }
//break up the line into three components (method, remote URL & Http Version) //break up the line into three components (method, remote URL & Http Version)
String[] httpCmdSplit = httpCmd.Split(spaceSplit, 3); var httpCmdSplit = httpCmd.Split(SpaceSplit, 3);
var httpVerb = httpCmdSplit[0]; var httpVerb = httpCmdSplit[0];
...@@ -56,13 +53,12 @@ namespace Titanium.Web.Proxy ...@@ -56,13 +53,12 @@ namespace Titanium.Web.Proxy
//Client wants to create a secure tcp tunnel (its a HTTPS request) //Client wants to create a secure tcp tunnel (its a HTTPS request)
if (httpVerb.ToUpper() == "CONNECT" && !excluded && httpRemoteUri.Port == 443) if (httpVerb.ToUpper() == "CONNECT" && !excluded && httpRemoteUri.Port == 443)
{ {
httpRemoteUri = new Uri("https://" + httpCmdSplit[1]); httpRemoteUri = new Uri("https://" + httpCmdSplit[1]);
clientStreamReader.ReadAllLines(); clientStreamReader.ReadAllLines();
WriteConnectResponse(clientStreamWriter, httpVersion); WriteConnectResponse(clientStreamWriter, httpVersion);
var certificate = ProxyServer.CertManager.CreateCertificate(httpRemoteUri.Host); var certificate = CertManager.CreateCertificate(httpRemoteUri.Host);
SslStream sslStream = null; SslStream sslStream = null;
...@@ -70,7 +66,8 @@ namespace Titanium.Web.Proxy ...@@ -70,7 +66,8 @@ namespace Titanium.Web.Proxy
{ {
sslStream = new SslStream(clientStream, true); sslStream = new SslStream(clientStream, true);
//Successfully managed to authenticate the client using the fake certificate //Successfully managed to authenticate the client using the fake certificate
sslStream.AuthenticateAsServer(certificate, false, SslProtocols.Tls | SslProtocols.Ssl3 | SslProtocols.Ssl2, false); sslStream.AuthenticateAsServer(certificate, false,
SslProtocols.Tls | SslProtocols.Ssl3 | SslProtocols.Ssl2, false);
clientStreamReader = new CustomBinaryReader(sslStream, Encoding.ASCII); clientStreamReader = new CustomBinaryReader(sslStream, Encoding.ASCII);
clientStreamWriter = new StreamWriter(sslStream); clientStreamWriter = new StreamWriter(sslStream);
...@@ -87,52 +84,52 @@ namespace Titanium.Web.Proxy ...@@ -87,52 +84,52 @@ namespace Titanium.Web.Proxy
} }
httpCmd = clientStreamReader.ReadLine(); httpCmd = clientStreamReader.ReadLine();
} }
else if (httpVerb.ToUpper() == "CONNECT") else if (httpVerb.ToUpper() == "CONNECT")
{ {
clientStreamReader.ReadAllLines(); clientStreamReader.ReadAllLines();
WriteConnectResponse(clientStreamWriter, httpVersion); WriteConnectResponse(clientStreamWriter, httpVersion);
TcpHelper.SendRaw(clientStreamReader.BaseStream, null, null, httpRemoteUri.Host, httpRemoteUri.Port, false); TcpHelper.SendRaw(clientStreamReader.BaseStream, null, null, httpRemoteUri.Host, httpRemoteUri.Port,
false);
Dispose(client, clientStream, clientStreamReader, clientStreamWriter, null); Dispose(client, clientStream, clientStreamReader, clientStreamWriter, null);
return; return;
} }
//Now create the request //Now create the request
Task.Factory.StartNew(() => HandleHttpSessionRequest(client, httpCmd, clientStream, clientStreamReader, clientStreamWriter, httpRemoteUri.Scheme == Uri.UriSchemeHttps ? httpRemoteUri.OriginalString : null)); Task.Factory.StartNew(
() =>
HandleHttpSessionRequest(client, httpCmd, clientStream, clientStreamReader, clientStreamWriter,
httpRemoteUri.Scheme == Uri.UriSchemeHttps ? httpRemoteUri.OriginalString : null));
} }
catch catch
{ {
Dispose(client, clientStream, clientStreamReader, clientStreamWriter, null); Dispose(client, clientStream, clientStreamReader, clientStreamWriter, null);
} }
} }
private static void HandleHttpSessionRequest(TcpClient client, string httpCmd, Stream clientStream, CustomBinaryReader clientStreamReader, StreamWriter clientStreamWriter, string secureTunnelHostName) private static void HandleHttpSessionRequest(TcpClient client, string httpCmd, Stream clientStream,
CustomBinaryReader clientStreamReader, StreamWriter clientStreamWriter, string secureTunnelHostName)
{ {
if (string.IsNullOrEmpty(httpCmd))
if (String.IsNullOrEmpty(httpCmd))
{ {
Dispose(client, clientStream, clientStreamReader, clientStreamWriter, null); Dispose(client, clientStream, clientStreamReader, clientStreamWriter, null);
return; return;
} }
var args = new SessionEventArgs(BUFFER_SIZE); var args = new SessionEventArgs(BUFFER_SIZE);
args.client = client; args.Client = client;
try try
{ {
//break up the line into three components (method, remote URL & Http Version) //break up the line into three components (method, remote URL & Http Version)
String[] httpCmdSplit = httpCmd.Split(spaceSplit, 3); var httpCmdSplit = httpCmd.Split(SpaceSplit, 3);
var httpMethod = httpCmdSplit[0]; var httpMethod = httpCmdSplit[0];
var httpRemoteUri = new Uri(secureTunnelHostName == null ? httpCmdSplit[1] : (secureTunnelHostName + httpCmdSplit[1])); var httpRemoteUri =
new Uri(secureTunnelHostName == null ? httpCmdSplit[1] : (secureTunnelHostName + httpCmdSplit[1]));
var httpVersion = httpCmdSplit[2]; var httpVersion = httpCmdSplit[2];
Version version; Version version;
...@@ -147,29 +144,29 @@ namespace Titanium.Web.Proxy ...@@ -147,29 +144,29 @@ namespace Titanium.Web.Proxy
if (httpRemoteUri.Scheme == Uri.UriSchemeHttps) if (httpRemoteUri.Scheme == Uri.UriSchemeHttps)
{ {
args.isHttps = true; args.IsHttps = true;
} }
args.requestHeaders = new List<HttpHeader>(); args.RequestHeaders = new List<HttpHeader>();
string tmpLine = null; string tmpLine;
while (!String.IsNullOrEmpty(tmpLine = clientStreamReader.ReadLine())) while (!string.IsNullOrEmpty(tmpLine = clientStreamReader.ReadLine()))
{ {
String[] header = tmpLine.Split(colonSpaceSplit, 2, StringSplitOptions.None); var header = tmpLine.Split(ColonSpaceSplit, 2, StringSplitOptions.None);
args.requestHeaders.Add(new HttpHeader(header[0], header[1])); args.RequestHeaders.Add(new HttpHeader(header[0], header[1]));
} }
for (int i = 0; i < args.requestHeaders.Count; i++) for (var i = 0; i < args.RequestHeaders.Count; i++)
{ {
var rawHeader = args.requestHeaders[i]; var rawHeader = args.RequestHeaders[i];
//if request was upgrade to web-socket protocol then relay the request without proxying //if request was upgrade to web-socket protocol then relay the request without proxying
if ((rawHeader.Name.ToLower() == "upgrade") && (rawHeader.Value.ToLower() == "websocket")) if ((rawHeader.Name.ToLower() == "upgrade") && (rawHeader.Value.ToLower() == "websocket"))
{ {
TcpHelper.SendRaw(clientStreamReader.BaseStream, httpCmd, args.RequestHeaders,
TcpHelper.SendRaw(clientStreamReader.BaseStream, httpCmd, args.requestHeaders, httpRemoteUri.Host, httpRemoteUri.Port, httpRemoteUri.Scheme == Uri.UriSchemeHttps); httpRemoteUri.Host, httpRemoteUri.Port, httpRemoteUri.Scheme == Uri.UriSchemeHttps);
Dispose(client, clientStream, clientStreamReader, clientStreamWriter, args); Dispose(client, clientStream, clientStreamReader, clientStreamWriter, args);
return; return;
} }
...@@ -177,52 +174,51 @@ namespace Titanium.Web.Proxy ...@@ -177,52 +174,51 @@ namespace Titanium.Web.Proxy
//construct the web request that we are going to issue on behalf of the client. //construct the web request that we are going to issue on behalf of the client.
args.proxyRequest = (HttpWebRequest)HttpWebRequest.Create(httpRemoteUri); args.ProxyRequest = (HttpWebRequest) WebRequest.Create(httpRemoteUri);
args.proxyRequest.Proxy = null; args.ProxyRequest.Proxy = null;
args.proxyRequest.UseDefaultCredentials = true; args.ProxyRequest.UseDefaultCredentials = true;
args.proxyRequest.Method = httpMethod; args.ProxyRequest.Method = httpMethod;
args.proxyRequest.ProtocolVersion = version; args.ProxyRequest.ProtocolVersion = version;
args.clientStream = clientStream; args.ClientStream = clientStream;
args.clientStreamReader = clientStreamReader; args.ClientStreamReader = clientStreamReader;
args.clientStreamWriter = clientStreamWriter; args.ClientStreamWriter = clientStreamWriter;
args.proxyRequest.AllowAutoRedirect = false; args.ProxyRequest.AllowAutoRedirect = false;
args.proxyRequest.AutomaticDecompression = DecompressionMethods.None; args.ProxyRequest.AutomaticDecompression = DecompressionMethods.None;
args.requestHostname = args.proxyRequest.RequestUri.Host; args.RequestHostname = args.ProxyRequest.RequestUri.Host;
args.requestURL = args.proxyRequest.RequestUri.OriginalString; args.RequestUrl = args.ProxyRequest.RequestUri.OriginalString;
args.clientPort = ((IPEndPoint)client.Client.RemoteEndPoint).Port; args.ClientPort = ((IPEndPoint) client.Client.RemoteEndPoint).Port;
args.clientIpAddress = ((IPEndPoint)client.Client.RemoteEndPoint).Address; args.ClientIpAddress = ((IPEndPoint) client.Client.RemoteEndPoint).Address;
args.requestHttpVersion = version; args.RequestHttpVersion = version;
args.requestIsAlive = args.proxyRequest.KeepAlive; args.RequestIsAlive = args.ProxyRequest.KeepAlive;
args.proxyRequest.ConnectionGroupName = args.requestHostname; args.ProxyRequest.ConnectionGroupName = args.RequestHostname;
args.proxyRequest.AllowWriteStreamBuffering = true; args.ProxyRequest.AllowWriteStreamBuffering = true;
//If requested interception //If requested interception
if (BeforeRequest != null) if (BeforeRequest != null)
{ {
args.requestEncoding = args.proxyRequest.GetEncoding(); args.RequestEncoding = args.ProxyRequest.GetEncoding();
BeforeRequest(null, args); BeforeRequest(null, args);
} }
args.RequestLocked = true; args.RequestLocked = true;
if (args.cancelRequest) if (args.CancelRequest)
{ {
Dispose(client, clientStream, clientStreamReader, clientStreamWriter, args); Dispose(client, clientStream, clientStreamReader, clientStreamWriter, args);
return; return;
} }
SetRequestHeaders(args.requestHeaders, args.proxyRequest); SetRequestHeaders(args.RequestHeaders, args.ProxyRequest);
//If request was modified by user //If request was modified by user
if (args.requestBodyRead) if (args.RequestBodyRead)
{ {
args.proxyRequest.ContentLength = args.requestBody.Length; args.ProxyRequest.ContentLength = args.RequestBody.Length;
Stream newStream = args.proxyRequest.GetRequestStream(); var newStream = args.ProxyRequest.GetRequestStream();
newStream.Write(args.requestBody, 0, args.requestBody.Length); newStream.Write(args.RequestBody, 0, args.RequestBody.Length);
args.proxyRequest.BeginGetResponse(new AsyncCallback(HandleHttpSessionResponse), args);
args.ProxyRequest.BeginGetResponse(HandleHttpSessionResponse, args);
} }
else else
{ {
...@@ -232,38 +228,36 @@ namespace Titanium.Web.Proxy ...@@ -232,38 +228,36 @@ namespace Titanium.Web.Proxy
SendClientRequestBody(args); SendClientRequestBody(args);
} }
//Http request body sent, now wait asynchronously for response //Http request body sent, now wait asynchronously for response
args.proxyRequest.BeginGetResponse(new AsyncCallback(HandleHttpSessionResponse), args); args.ProxyRequest.BeginGetResponse(HandleHttpSessionResponse, args);
} }
//Now read the next request (if keep-Alive is enabled, otherwise exit this thread) //Now read the next request (if keep-Alive is enabled, otherwise exit this thread)
//If client is pipeling the request, this will be immediately hit before response for previous request was made //If client is pipeling the request, this will be immediately hit before response for previous request was made
httpCmd = clientStreamReader.ReadLine(); httpCmd = clientStreamReader.ReadLine();
//Http request body sent, now wait for next request //Http request body sent, now wait for next request
Task.Factory.StartNew(() => HandleHttpSessionRequest(args.client, httpCmd, args.clientStream, args.clientStreamReader, args.clientStreamWriter, secureTunnelHostName)); Task.Factory.StartNew(
() =>
HandleHttpSessionRequest(args.Client, httpCmd, args.ClientStream, args.ClientStreamReader,
args.ClientStreamWriter, secureTunnelHostName));
} }
catch catch
{ {
Dispose(client, clientStream, clientStreamReader, clientStreamWriter, args); Dispose(client, clientStream, clientStreamReader, clientStreamWriter, args);
} }
} }
private static void WriteConnectResponse(StreamWriter clientStreamWriter, string httpVersion) private static void WriteConnectResponse(StreamWriter clientStreamWriter, string httpVersion)
{ {
clientStreamWriter.WriteLine(httpVersion + " 200 Connection established"); clientStreamWriter.WriteLine(httpVersion + " 200 Connection established");
clientStreamWriter.WriteLine(String.Format("Timestamp: {0}", DateTime.Now.ToString())); clientStreamWriter.WriteLine("Timestamp: {0}", DateTime.Now);
clientStreamWriter.WriteLine(String.Format("connection:close")); clientStreamWriter.WriteLine("connection:close");
clientStreamWriter.WriteLine(); clientStreamWriter.WriteLine();
clientStreamWriter.Flush(); clientStreamWriter.Flush();
} }
private static void SetRequestHeaders(List<HttpHeader> requestHeaders, HttpWebRequest webRequest) private static void SetRequestHeaders(List<HttpHeader> requestHeaders, HttpWebRequest webRequest)
{ {
for (var i = 0; i < requestHeaders.Count; i++)
for (int i = 0; i < requestHeaders.Count; i++)
{ {
switch (requestHeaders[i].Name.ToLower()) switch (requestHeaders[i].Name.ToLower())
{ {
...@@ -300,7 +294,7 @@ namespace Titanium.Web.Proxy ...@@ -300,7 +294,7 @@ namespace Titanium.Web.Proxy
webRequest.Host = requestHeaders[i].Value; webRequest.Host = requestHeaders[i].Value;
break; break;
case "if-modified-since": case "if-modified-since":
String[] sb = requestHeaders[i].Value.Trim().Split(semiSplit); var sb = requestHeaders[i].Value.Trim().Split(SemiSplit);
DateTime d; DateTime d;
if (DateTime.TryParse(sb[0], out d)) if (DateTime.TryParse(sb[0], out d))
webRequest.IfModifiedSince = d; webRequest.IfModifiedSince = d;
...@@ -311,7 +305,12 @@ namespace Titanium.Web.Proxy ...@@ -311,7 +305,12 @@ namespace Titanium.Web.Proxy
break; break;
case "range": case "range":
var startEnd = requestHeaders[i].Value.Replace(Environment.NewLine, "").Remove(0, 6).Split('-'); var startEnd = requestHeaders[i].Value.Replace(Environment.NewLine, "").Remove(0, 6).Split('-');
if (startEnd.Length > 1) { if (!String.IsNullOrEmpty(startEnd[1])) webRequest.AddRange(int.Parse(startEnd[0]), int.Parse(startEnd[1])); else webRequest.AddRange(int.Parse(startEnd[0])); } if (startEnd.Length > 1)
{
if (!string.IsNullOrEmpty(startEnd[1]))
webRequest.AddRange(int.Parse(startEnd[0]), int.Parse(startEnd[1]));
else webRequest.AddRange(int.Parse(startEnd[0]));
}
else else
webRequest.AddRange(int.Parse(startEnd[0])); webRequest.AddRange(int.Parse(startEnd[0]));
break; break;
...@@ -340,109 +339,92 @@ namespace Titanium.Web.Proxy ...@@ -340,109 +339,92 @@ namespace Titanium.Web.Proxy
break; break;
} }
} }
} }
//This is called when the request is PUT/POST to read the body //This is called when the request is PUT/POST to read the body
private static void SendClientRequestBody(SessionEventArgs args) private static void SendClientRequestBody(SessionEventArgs args)
{ {
// End the operation // End the operation
Stream postStream = args.proxyRequest.GetRequestStream(); var postStream = args.ProxyRequest.GetRequestStream();
if (args.proxyRequest.ContentLength > 0) if (args.ProxyRequest.ContentLength > 0)
{ {
args.proxyRequest.AllowWriteStreamBuffering = true; args.ProxyRequest.AllowWriteStreamBuffering = true;
try try
{ {
var totalbytesRead = 0;
int totalbytesRead = 0;
int bytesToRead; int bytesToRead;
if (args.proxyRequest.ContentLength < BUFFER_SIZE) if (args.ProxyRequest.ContentLength < BUFFER_SIZE)
{ {
bytesToRead = (int)args.proxyRequest.ContentLength; bytesToRead = (int) args.ProxyRequest.ContentLength;
} }
else else
bytesToRead = BUFFER_SIZE; bytesToRead = BUFFER_SIZE;
while (totalbytesRead < (int)args.proxyRequest.ContentLength) while (totalbytesRead < (int) args.ProxyRequest.ContentLength)
{ {
var buffer = args.clientStreamReader.ReadBytes(bytesToRead); var buffer = args.ClientStreamReader.ReadBytes(bytesToRead);
totalbytesRead += buffer.Length; totalbytesRead += buffer.Length;
int RemainingBytes = (int)args.proxyRequest.ContentLength - totalbytesRead; var remainingBytes = (int) args.ProxyRequest.ContentLength - totalbytesRead;
if (RemainingBytes < bytesToRead) if (remainingBytes < bytesToRead)
{ {
bytesToRead = RemainingBytes; bytesToRead = remainingBytes;
} }
postStream.Write(buffer, 0, buffer.Length); postStream.Write(buffer, 0, buffer.Length);
} }
postStream.Close(); postStream.Close();
} }
catch catch
{ {
if (postStream != null) postStream.Close();
{ postStream.Dispose();
postStream.Close();
postStream.Dispose();
}
throw; throw;
} }
} }
//Need to revist, find any potential bugs //Need to revist, find any potential bugs
else if (args.proxyRequest.SendChunked) else if (args.ProxyRequest.SendChunked)
{ {
args.proxyRequest.AllowWriteStreamBuffering = true; args.ProxyRequest.AllowWriteStreamBuffering = true;
try try
{ {
while (true) while (true)
{ {
var chuchkHead = args.clientStreamReader.ReadLine(); var chuchkHead = args.ClientStreamReader.ReadLine();
var chunkSize = int.Parse(chuchkHead, System.Globalization.NumberStyles.HexNumber); var chunkSize = int.Parse(chuchkHead, NumberStyles.HexNumber);
if (chunkSize != 0) if (chunkSize != 0)
{ {
var buffer = args.clientStreamReader.ReadBytes(chunkSize); var buffer = args.ClientStreamReader.ReadBytes(chunkSize);
postStream.Write(buffer, 0, buffer.Length); postStream.Write(buffer, 0, buffer.Length);
//chunk trail
var chunkTrail = args.clientStreamReader.ReadLine(); args.ClientStreamReader.ReadLine();
} }
else else
{ {
args.clientStreamReader.ReadLine(); args.ClientStreamReader.ReadLine();
break; break;
} }
} }
postStream.Close(); postStream.Close();
} }
catch catch
{ {
if (postStream != null) postStream.Close();
{ postStream.Dispose();
postStream.Close();
postStream.Dispose();
}
throw; throw;
} }
} }
} }
} }
} }
\ No newline at end of file
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.IO; using System.IO;
using System.Linq;
using System.Net; using System.Net;
using System.Net.Security; using System.Net.Sockets;
using System.Threading; using System.Text;
using System.Security.Authentication;
using System.Diagnostics;
using Titanium.Web.Proxy.EventArguments; using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Helpers;
using System.Threading.Tasks;
using Titanium.Web.Proxy.Extensions; using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Models; using Titanium.Web.Proxy.Models;
namespace Titanium.Web.Proxy namespace Titanium.Web.Proxy
...@@ -22,94 +17,89 @@ namespace Titanium.Web.Proxy ...@@ -22,94 +17,89 @@ namespace Titanium.Web.Proxy
//Called asynchronously when a request was successfully and we received the response //Called asynchronously when a request was successfully and we received the response
private static void HandleHttpSessionResponse(IAsyncResult asynchronousResult) private static void HandleHttpSessionResponse(IAsyncResult asynchronousResult)
{ {
SessionEventArgs args = (SessionEventArgs)asynchronousResult.AsyncState; var args = (SessionEventArgs)asynchronousResult.AsyncState;
try try
{ {
args.serverResponse = (HttpWebResponse)args.proxyRequest.EndGetResponse(asynchronousResult); args.ServerResponse = (HttpWebResponse)args.ProxyRequest.EndGetResponse(asynchronousResult);
} }
catch (WebException webEx) catch (WebException webEx)
{ {
//Things line 404, 500 etc //Things line 404, 500 etc
args.serverResponse = webEx.Response as HttpWebResponse; args.ServerResponse = webEx.Response as HttpWebResponse;
} }
try try
{ {
if (args.serverResponse != null) if (args.ServerResponse != null)
{ {
args.responseHeaders = ReadResponseHeaders(args.serverResponse); args.ResponseHeaders = ReadResponseHeaders(args.ServerResponse);
args.responseStream = args.serverResponse.GetResponseStream(); args.ResponseStream = args.ServerResponse.GetResponseStream();
if (BeforeResponse != null) if (BeforeResponse != null)
{ {
args.responseEncoding = args.serverResponse.GetEncoding(); args.ResponseEncoding = args.ServerResponse.GetEncoding();
BeforeResponse(null, args); BeforeResponse(null, args);
} }
args.ResponseLocked = true; args.ResponseLocked = true;
if (args.responseBodyRead) if (args.ResponseBodyRead)
{ {
bool isChunked = args.serverResponse.GetResponseHeader("transfer-encoding") == null ? false : args.serverResponse.GetResponseHeader("transfer-encoding").ToLower().Contains("chunked") ? true : false; var isChunked = args.ServerResponse.GetResponseHeader("transfer-encoding").ToLower().Contains("chunked");
var contentEncoding = args.serverResponse.ContentEncoding; var contentEncoding = args.ServerResponse.ContentEncoding;
if (contentEncoding != null) switch (contentEncoding.ToLower())
switch (contentEncoding.ToLower()) {
{ case "gzip":
case "gzip": args.ResponseBody = CompressionHelper.CompressGzip(args.ResponseBody);
args.responseBody = CompressionHelper.CompressGzip(args.responseBody); break;
break; case "deflate":
case "deflate": args.ResponseBody = CompressionHelper.CompressDeflate(args.ResponseBody);
args.responseBody = CompressionHelper.CompressDeflate(args.responseBody); break;
break; case "zlib":
case "zlib": args.ResponseBody = CompressionHelper.CompressZlib(args.ResponseBody);
args.responseBody = CompressionHelper.CompressZlib(args.responseBody); break;
break; }
default:
break; WriteResponseStatus(args.ServerResponse.ProtocolVersion, args.ServerResponse.StatusCode,
} args.ServerResponse.StatusDescription, args.ClientStreamWriter);
WriteResponseHeaders(args.ClientStreamWriter, args.ResponseHeaders, args.ResponseBody.Length,
WriteResponseStatus(args.serverResponse.ProtocolVersion, args.serverResponse.StatusCode, args.serverResponse.StatusDescription, args.clientStreamWriter); isChunked);
WriteResponseHeaders(args.clientStreamWriter, args.responseHeaders, args.responseBody.Length, isChunked); WriteResponseBody(args.ClientStream, args.ResponseBody, isChunked);
WriteResponseBody(args.clientStream, args.responseBody, isChunked);
} }
else else
{ {
bool isChunked = args.serverResponse.GetResponseHeader("transfer-encoding") == null ? false : args.serverResponse.GetResponseHeader("transfer-encoding").ToLower().Contains("chunked") ? true : false; var isChunked = args.ServerResponse.GetResponseHeader("transfer-encoding").ToLower().Contains("chunked");
WriteResponseStatus(args.serverResponse.ProtocolVersion, args.serverResponse.StatusCode, args.serverResponse.StatusDescription, args.clientStreamWriter);
WriteResponseHeaders(args.clientStreamWriter, args.responseHeaders);
WriteResponseBody(args.responseStream, args.clientStream, isChunked);
WriteResponseStatus(args.ServerResponse.ProtocolVersion, args.ServerResponse.StatusCode,
args.ServerResponse.StatusDescription, args.ClientStreamWriter);
WriteResponseHeaders(args.ClientStreamWriter, args.ResponseHeaders);
WriteResponseBody(args.ResponseStream, args.ClientStream, isChunked);
} }
args.clientStream.Flush(); args.ClientStream.Flush();
} }
} }
catch catch
{ {
Dispose(args.client, args.clientStream, args.clientStreamReader, args.clientStreamWriter, args); Dispose(args.Client, args.ClientStream, args.ClientStreamReader, args.ClientStreamWriter, args);
} }
finally finally
{ {
if (args != null) args.Dispose();
args.Dispose();
} }
} }
private static List<HttpHeader> ReadResponseHeaders(HttpWebResponse response) private static List<HttpHeader> ReadResponseHeaders(HttpWebResponse response)
{ {
var returnHeaders = new List<HttpHeader>(); var returnHeaders = new List<HttpHeader>();
String cookieHeaderName = null; string cookieHeaderName = null;
String cookieHeaderValue = null; string cookieHeaderValue = null;
foreach (String headerKey in response.Headers.Keys) foreach (string headerKey in response.Headers.Keys)
{ {
if (headerKey.ToLower() == "set-cookie") if (headerKey.ToLower() == "set-cookie")
{ {
...@@ -120,21 +110,21 @@ namespace Titanium.Web.Proxy ...@@ -120,21 +110,21 @@ namespace Titanium.Web.Proxy
returnHeaders.Add(new HttpHeader(headerKey, response.Headers[headerKey])); returnHeaders.Add(new HttpHeader(headerKey, response.Headers[headerKey]));
} }
if (!String.IsNullOrWhiteSpace(cookieHeaderValue)) if (!string.IsNullOrWhiteSpace(cookieHeaderValue))
{ {
response.Headers.Remove(cookieHeaderName); response.Headers.Remove(cookieHeaderName);
String[] cookies = cookieSplitRegEx.Split(cookieHeaderValue); var cookies = CookieSplitRegEx.Split(cookieHeaderValue);
foreach (String cookie in cookies) foreach (var cookie in cookies)
returnHeaders.Add(new HttpHeader("Set-Cookie", cookie)); returnHeaders.Add(new HttpHeader("Set-Cookie", cookie));
} }
return returnHeaders; return returnHeaders;
} }
private static void WriteResponseStatus(Version version, HttpStatusCode code, String description, StreamWriter responseWriter) private static void WriteResponseStatus(Version version, HttpStatusCode code, string description,
StreamWriter responseWriter)
{ {
String s = String.Format("HTTP/{0}.{1} {2} {3}", version.Major, version.Minor, (Int32)code, description); var s = string.Format("HTTP/{0}.{1} {2} {3}", version.Major, version.Minor, (int)code, description);
responseWriter.WriteLine(s); responseWriter.WriteLine(s);
} }
...@@ -150,9 +140,10 @@ namespace Titanium.Web.Proxy ...@@ -150,9 +140,10 @@ namespace Titanium.Web.Proxy
responseWriter.WriteLine(); responseWriter.WriteLine();
responseWriter.Flush(); responseWriter.Flush();
} }
private static void WriteResponseHeaders(StreamWriter responseWriter, List<HttpHeader> headers, int length, bool isChunked)
private static void WriteResponseHeaders(StreamWriter responseWriter, List<HttpHeader> headers, int length,
bool isChunked)
{ {
if (!isChunked) if (!isChunked)
{ {
...@@ -175,7 +166,6 @@ namespace Titanium.Web.Proxy ...@@ -175,7 +166,6 @@ namespace Titanium.Web.Proxy
responseWriter.WriteLine(); responseWriter.WriteLine();
responseWriter.Flush(); responseWriter.Flush();
} }
private static void WriteResponseBody(Stream clientStream, byte[] data, bool isChunked) private static void WriteResponseBody(Stream clientStream, byte[] data, bool isChunked)
...@@ -192,7 +182,7 @@ namespace Titanium.Web.Proxy ...@@ -192,7 +182,7 @@ namespace Titanium.Web.Proxy
{ {
if (!isChunked) if (!isChunked)
{ {
Byte[] buffer = new Byte[BUFFER_SIZE]; var buffer = new byte[BUFFER_SIZE];
int bytesRead; int bytesRead;
while ((bytesRead = inStream.Read(buffer, 0, buffer.Length)) > 0) while ((bytesRead = inStream.Read(buffer, 0, buffer.Length)) > 0)
...@@ -203,11 +193,11 @@ namespace Titanium.Web.Proxy ...@@ -203,11 +193,11 @@ namespace Titanium.Web.Proxy
else else
WriteResponseBodyChunked(inStream, outStream); WriteResponseBodyChunked(inStream, outStream);
} }
//Send chunked response //Send chunked response
private static void WriteResponseBodyChunked(Stream inStream, Stream outStream) private static void WriteResponseBodyChunked(Stream inStream, Stream outStream)
{ {
var buffer = new byte[BUFFER_SIZE];
Byte[] buffer = new Byte[BUFFER_SIZE];
int bytesRead; int bytesRead;
while ((bytesRead = inStream.Read(buffer, 0, buffer.Length)) > 0) while ((bytesRead = inStream.Read(buffer, 0, buffer.Length)) > 0)
...@@ -215,31 +205,29 @@ namespace Titanium.Web.Proxy ...@@ -215,31 +205,29 @@ namespace Titanium.Web.Proxy
var chunkHead = Encoding.ASCII.GetBytes(bytesRead.ToString("x2")); var chunkHead = Encoding.ASCII.GetBytes(bytesRead.ToString("x2"));
outStream.Write(chunkHead, 0, chunkHead.Length); outStream.Write(chunkHead, 0, chunkHead.Length);
outStream.Write(chunkTrail, 0, chunkTrail.Length); outStream.Write(ChunkTrail, 0, ChunkTrail.Length);
outStream.Write(buffer, 0, bytesRead); outStream.Write(buffer, 0, bytesRead);
outStream.Write(chunkTrail, 0, chunkTrail.Length); outStream.Write(ChunkTrail, 0, ChunkTrail.Length);
} }
outStream.Write(ChunkEnd, 0, ChunkEnd.Length); outStream.Write(ChunkEnd, 0, ChunkEnd.Length);
} }
private static void WriteResponseBodyChunked(byte[] data, Stream outStream) private static void WriteResponseBodyChunked(byte[] data, Stream outStream)
{ {
Byte[] buffer = new Byte[BUFFER_SIZE];
var chunkHead = Encoding.ASCII.GetBytes(data.Length.ToString("x2")); var chunkHead = Encoding.ASCII.GetBytes(data.Length.ToString("x2"));
outStream.Write(chunkHead, 0, chunkHead.Length); outStream.Write(chunkHead, 0, chunkHead.Length);
outStream.Write(chunkTrail, 0, chunkTrail.Length); outStream.Write(ChunkTrail, 0, ChunkTrail.Length);
outStream.Write(data, 0, data.Length); outStream.Write(data, 0, data.Length);
outStream.Write(chunkTrail, 0, chunkTrail.Length); outStream.Write(ChunkTrail, 0, ChunkTrail.Length);
outStream.Write(ChunkEnd, 0, ChunkEnd.Length); outStream.Write(ChunkEnd, 0, ChunkEnd.Length);
} }
private static void Dispose(TcpClient client, Stream clientStream, CustomBinaryReader clientStreamReader, StreamWriter clientStreamWriter, SessionEventArgs args) private static void Dispose(TcpClient client, IDisposable clientStream, IDisposable clientStreamReader,
IDisposable clientStreamWriter, IDisposable args)
{ {
if (args != null) if (args != null)
args.Dispose(); args.Dispose();
......
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="DotNetZip" version="1.9.3" targetFramework="net40-Client" /> <package id="DotNetZip" version="1.9.3" targetFramework="net40-Client" />
</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