├── SharpProxy ├── main.ico ├── app.config ├── Properties │ ├── Settings.settings │ ├── Settings.Designer.cs │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ └── Resources.resx ├── Program.cs ├── SharpProxy.csproj ├── ProxyThread.cs ├── frmMain.cs ├── frmMain.Designer.cs └── frmMain.resx ├── README.txt ├── .gitignore └── SharpProxy.sln /SharpProxy/main.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocull/SharpProxy/HEAD/SharpProxy/main.ico -------------------------------------------------------------------------------- /SharpProxy/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /SharpProxy/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | SharpProxy is a simple proxy server developed with the intent of being able to open up local ASP.NET development servers. 2 | 3 | This allows you to test, hit breakpoints, and generally do development by using other machines and mobile devices. 4 | 5 | Simply enter the local port number of your .NET development server and map it with an external port to host on. -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | #ignore thumbnails created by windows 3 | Thumbs.db 4 | #Ignore files build by Visual Studio 5 | *.obj 6 | *.exe 7 | *.pdb 8 | *.user 9 | *.aps 10 | *.pch 11 | *.vspscc 12 | *_i.c 13 | *_p.c 14 | *.ncb 15 | *.suo 16 | *.tlb 17 | *.tlh 18 | *.bak 19 | *.cache 20 | *.ilk 21 | *.log 22 | [Bb]in 23 | [Dd]ebug*/ 24 | *.lib 25 | *.sbr 26 | obj/ 27 | [Rr]elease*/ 28 | _ReSharper*/ 29 | [Tt]est[Rr]esult* -------------------------------------------------------------------------------- /SharpProxy/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Windows.Forms; 4 | 5 | namespace SharpProxy 6 | { 7 | static class Program 8 | { 9 | /// 10 | /// The main entry point for the application. 11 | /// 12 | [STAThread] 13 | static void Main() 14 | { 15 | Application.EnableVisualStyles(); 16 | Application.SetCompatibleTextRenderingDefault(false); 17 | Application.Run(new frmMain()); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /SharpProxy.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpProxy", "SharpProxy\SharpProxy.csproj", "{AED54322-48BB-4587-ADE3-45FE2D2318AC}" 5 | EndProject 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{AE1ED7D8-B282-4B84-AD12-E5FB1A736314}" 7 | ProjectSection(SolutionItems) = preProject 8 | README.txt = README.txt 9 | EndProjectSection 10 | EndProject 11 | Global 12 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 13 | Debug|x86 = Debug|x86 14 | Release|x86 = Release|x86 15 | EndGlobalSection 16 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 17 | {AED54322-48BB-4587-ADE3-45FE2D2318AC}.Debug|x86.ActiveCfg = Debug|x86 18 | {AED54322-48BB-4587-ADE3-45FE2D2318AC}.Debug|x86.Build.0 = Debug|x86 19 | {AED54322-48BB-4587-ADE3-45FE2D2318AC}.Release|x86.ActiveCfg = Release|x86 20 | {AED54322-48BB-4587-ADE3-45FE2D2318AC}.Release|x86.Build.0 = Release|x86 21 | EndGlobalSection 22 | GlobalSection(SolutionProperties) = preSolution 23 | HideSolutionNode = FALSE 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /SharpProxy/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.18444 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace SharpProxy.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /SharpProxy/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("SharpProxy")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("James O'Cull")] 12 | [assembly: AssemblyProduct("SharpProxy")] 13 | [assembly: AssemblyCopyright("Copyright © James O'Cull 2011")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("04551f25-ff67-480c-9c96-70d56ef1a4aa")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("0.6.*")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /SharpProxy/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.18444 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace SharpProxy.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SharpProxy.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /SharpProxy/SharpProxy.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | x86 6 | 8.0.30703 7 | 2.0 8 | {AED54322-48BB-4587-ADE3-45FE2D2318AC} 9 | WinExe 10 | Properties 11 | SharpProxy 12 | SharpProxy 13 | v4.0 14 | 15 | 16 | 512 17 | publish\ 18 | true 19 | Disk 20 | false 21 | Foreground 22 | 7 23 | Days 24 | false 25 | false 26 | true 27 | 0 28 | 1.0.0.%2a 29 | false 30 | false 31 | true 32 | 33 | 34 | x86 35 | true 36 | full 37 | false 38 | bin\Debug\ 39 | DEBUG;TRACE 40 | prompt 41 | 4 42 | 43 | 44 | x86 45 | pdbonly 46 | true 47 | bin\Release\ 48 | TRACE 49 | prompt 50 | 4 51 | 52 | 53 | main.ico 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | Form 70 | 71 | 72 | frmMain.cs 73 | 74 | 75 | 76 | 77 | 78 | frmMain.cs 79 | 80 | 81 | ResXFileCodeGenerator 82 | Resources.Designer.cs 83 | Designer 84 | 85 | 86 | True 87 | Resources.resx 88 | True 89 | 90 | 91 | 92 | SettingsSingleFileGenerator 93 | Settings.Designer.cs 94 | 95 | 96 | True 97 | Settings.settings 98 | True 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | False 107 | .NET Framework 3.5 SP1 Client Profile 108 | false 109 | 110 | 111 | False 112 | .NET Framework 3.5 SP1 113 | true 114 | 115 | 116 | False 117 | Windows Installer 3.1 118 | true 119 | 120 | 121 | 122 | 129 | -------------------------------------------------------------------------------- /SharpProxy/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /SharpProxy/ProxyThread.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Net.Sockets; 5 | using System.Net; 6 | using System.Threading; 7 | using System.IO; 8 | using System.Linq; 9 | using System.Diagnostics; 10 | 11 | namespace SharpProxy 12 | { 13 | public class ProxyThread 14 | { 15 | public int ExternalPort { get; set; } 16 | public int InternalPort { get; set; } 17 | public bool RewriteHostHeaders { get; set; } 18 | public bool Stopped { get; set; } 19 | 20 | private TcpListener Listener { get; set; } 21 | 22 | private readonly long PROXY_TIMEOUT_TICKS = new TimeSpan(0, 1, 0).Ticks; 23 | 24 | private const string HTTP_SEPARATOR = "\r\n"; 25 | private const string HTTP_HEADER_BREAK = HTTP_SEPARATOR + HTTP_SEPARATOR; 26 | 27 | private readonly string[] HTTP_SEPARATORS = new string[] { HTTP_SEPARATOR }; 28 | private readonly string[] HTTP_HEADER_BREAKS = new string[] { HTTP_HEADER_BREAK }; 29 | 30 | public ProxyThread(int extPort, int intPort, bool rewriteHostHeaders) 31 | { 32 | this.ExternalPort = extPort; 33 | this.InternalPort = intPort; 34 | this.RewriteHostHeaders = rewriteHostHeaders; 35 | this.Stopped = false; 36 | this.Listener = null; 37 | 38 | new Thread(new ThreadStart(Listen)).Start(); 39 | } 40 | 41 | public void Stop() 42 | { 43 | Stopped = true; 44 | if (Listener != null) 45 | { 46 | Listener.Stop(); 47 | } 48 | } 49 | 50 | protected void Listen() 51 | { 52 | Listener = new TcpListener(new IPEndPoint(IPAddress.Any, this.ExternalPort)); 53 | Listener.Start(); 54 | 55 | while (!Stopped) 56 | { 57 | try 58 | { 59 | TcpClient client = Listener.AcceptTcpClient(); 60 | //Dispatch the thread and continue listening... 61 | new Thread(new ThreadStart(() => Proxy(client))).Start(); 62 | } 63 | catch (Exception ex) 64 | { 65 | //TODO: Remove this. Only here to catch breakpoints. 66 | bool failed = true; 67 | } 68 | } 69 | } 70 | 71 | protected void Proxy(object arg) 72 | { 73 | byte[] buffer = new byte[16384]; 74 | int clientRead = -1; 75 | int hostRead = -1; 76 | 77 | long lastTime = DateTime.Now.Ticks; 78 | 79 | try 80 | { 81 | //Setup connections 82 | using (TcpClient client = (TcpClient)arg) 83 | using (TcpClient host = new TcpClient()) 84 | { 85 | host.Connect(new IPEndPoint(IPAddress.Loopback, this.InternalPort)); 86 | 87 | //Setup our streams 88 | using (BinaryReader clientIn = new BinaryReader(client.GetStream())) 89 | using (BinaryWriter clientOut = new BinaryWriter(client.GetStream())) 90 | using (BinaryReader hostIn = new BinaryReader(host.GetStream())) 91 | using (BinaryWriter hostOut = new BinaryWriter(host.GetStream())) 92 | { 93 | //Start funneling data! 94 | while (clientRead != 0 || hostRead != 0 || (DateTime.Now.Ticks - lastTime) <= PROXY_TIMEOUT_TICKS) 95 | { 96 | while (client.Connected && (clientRead = client.Available) > 0) 97 | { 98 | clientRead = clientIn.Read(buffer, 0, buffer.Length); 99 | 100 | //Rewrite the host header? 101 | if (this.RewriteHostHeaders && clientRead > 0) 102 | { 103 | string str = Encoding.UTF8.GetString(buffer, 0, clientRead); 104 | 105 | int startIdx = str.IndexOf(HTTP_SEPARATOR + "Host:"); 106 | if (startIdx >= 0) 107 | { 108 | int endIdx = str.IndexOf(HTTP_SEPARATOR, startIdx + 1, str.Length - (startIdx + 1)); 109 | if (endIdx > 0) 110 | { 111 | string replace = str.Substring(startIdx, endIdx - startIdx); 112 | string replaceWith = HTTP_SEPARATOR + "Host: localhost:" + InternalPort; 113 | 114 | Trace.WriteLine("Incoming HTTP header:\n\n" + str); 115 | 116 | str = str.Replace(replace, replaceWith); 117 | 118 | Trace.WriteLine("Rewritten HTTP header:\n\n" + str); 119 | 120 | byte[] strBytes = Encoding.UTF8.GetBytes(str); 121 | Array.Clear(buffer, 0, buffer.Length); 122 | Array.Copy(strBytes, buffer, strBytes.Length); 123 | clientRead = strBytes.Length; 124 | } 125 | } 126 | } 127 | 128 | hostOut.Write(buffer, 0, clientRead); 129 | lastTime = DateTime.Now.Ticks; 130 | hostOut.Flush(); 131 | } 132 | while (host.Connected && (hostRead = host.Available) > 0) 133 | { 134 | hostRead = hostIn.Read(buffer, 0, buffer.Length); 135 | clientOut.Write(buffer, 0, hostRead); 136 | lastTime = DateTime.Now.Ticks; 137 | clientOut.Flush(); 138 | } 139 | 140 | //Sleepy time? 141 | if (this.Stopped) 142 | return; 143 | if (clientRead == 0 && hostRead == 0) 144 | { 145 | Thread.Sleep(100); 146 | } 147 | } 148 | 149 | long waitTime = DateTime.Now.Ticks - lastTime; 150 | } 151 | } 152 | } 153 | catch (Exception ex) 154 | { 155 | //TODO: Remove this. Only here to catch breakpoints. 156 | bool failed = true; 157 | } 158 | } 159 | } 160 | } -------------------------------------------------------------------------------- /SharpProxy/frmMain.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Drawing; 6 | using System.Text; 7 | using System.Windows.Forms; 8 | using System.Net; 9 | using System.Net.NetworkInformation; 10 | using System.Net.Sockets; 11 | using System.Linq; 12 | using System.IO; 13 | 14 | namespace SharpProxy 15 | { 16 | public partial class frmMain : Form 17 | { 18 | private const int MIN_PORT = 1; 19 | private const int MAX_PORT = 65535; 20 | 21 | public static readonly string CommonDataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "SharpProxy"); 22 | public static readonly string ConfigInfoPath = Path.Combine(CommonDataPath, "config.txt"); 23 | 24 | private ProxyThread ProxyThreadListener = null; 25 | 26 | public frmMain() 27 | { 28 | InitializeComponent(); 29 | this.Text += " " + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString(); 30 | 31 | var ips = getLocalIPs().OrderBy(x => x); 32 | if (ips.Any()) 33 | { 34 | cmbIPAddress.Items.Clear(); 35 | foreach (string ip in ips) 36 | { 37 | cmbIPAddress.Items.Add(ip); 38 | } 39 | cmbIPAddress.Text = cmbIPAddress.Items[0].ToString(); 40 | } 41 | 42 | int port = 5000; 43 | while (!checkPortAvailability(port)) 44 | { 45 | port++; 46 | } 47 | txtExternalPort.Text = port.ToString(); 48 | } 49 | 50 | private void frmMain_Shown(object sender, EventArgs e) 51 | { 52 | txtInternalPort.Focus(); 53 | 54 | //Try to load config 55 | try 56 | { 57 | using (StreamReader sr = new StreamReader(ConfigInfoPath)) 58 | { 59 | var values = sr.ReadToEnd().Split('\n') 60 | .Select(x => x.Trim()) 61 | .ToArray(); 62 | 63 | txtInternalPort.Text = values[0]; 64 | chkRewriteHostHeaders.Checked = bool.Parse(values[1]); 65 | } 66 | } 67 | catch { } 68 | } 69 | 70 | private void frmMain_FormClosing(object sender, FormClosingEventArgs e) 71 | { 72 | if (ProxyThreadListener != null) 73 | { 74 | ProxyThreadListener.Stop(); 75 | } 76 | 77 | //Try to save config 78 | try 79 | { 80 | if (!Directory.Exists(CommonDataPath)) 81 | { 82 | Directory.CreateDirectory(CommonDataPath); 83 | } 84 | using (StreamWriter sw = new StreamWriter(ConfigInfoPath)) 85 | { 86 | sw.WriteLine(txtInternalPort.Text); 87 | sw.WriteLine(chkRewriteHostHeaders.Checked); 88 | } 89 | } 90 | catch { } 91 | } 92 | 93 | private void btnStart_Click(object sender, EventArgs e) 94 | { 95 | int externalPort = 0; 96 | int internalPort = 0; 97 | //Validation 98 | int.TryParse(txtExternalPort.Text, out externalPort); 99 | int.TryParse(txtInternalPort.Text, out internalPort); 100 | if (!checkPortRange(externalPort) 101 | || !checkPortRange(internalPort) 102 | || externalPort == internalPort) 103 | { 104 | showError("Ports must be between " + MIN_PORT + "-" + MAX_PORT + " and must not be the same."); 105 | return; 106 | } 107 | if (!checkPortAvailability(externalPort)) 108 | { 109 | showError("Port " + externalPort + " is not available, please select a different port."); 110 | return; 111 | } 112 | 113 | ProxyThreadListener = new ProxyThread(externalPort, internalPort, chkRewriteHostHeaders.Checked); 114 | 115 | toggleButtons(); 116 | } 117 | 118 | private void btnStop_Click(object sender, EventArgs e) 119 | { 120 | ProxyThreadListener.Stop(); 121 | 122 | toggleButtons(); 123 | } 124 | 125 | private void showError(string msg) 126 | { 127 | MessageBox.Show(msg, "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error); 128 | } 129 | 130 | private bool checkPortRange(int port) 131 | { 132 | if (port < MIN_PORT || port > MAX_PORT) 133 | return false; 134 | return true; 135 | } 136 | 137 | private List getLocalIPs() 138 | { 139 | //Try to find our internal IP address... 140 | string myHost = System.Net.Dns.GetHostName(); 141 | IPAddress[] addresses = System.Net.Dns.GetHostEntry(myHost).AddressList; 142 | List myIPs = new List(); 143 | string fallbackIP = ""; 144 | 145 | for (int i = 0; i < addresses.Length; i++) 146 | { 147 | //Is this a valid IPv4 address? 148 | if (addresses[i].AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) 149 | { 150 | string thisAddress = addresses[i].ToString(); 151 | //Loopback is not our preference... 152 | if (thisAddress == "127.0.0.1") 153 | continue; 154 | //169.x.x.x addresses are self-assigned "private network" IP by Windows 155 | if (thisAddress.StartsWith("169")) 156 | { 157 | fallbackIP = thisAddress; 158 | continue; 159 | } 160 | myIPs.Add(thisAddress); 161 | } 162 | } 163 | if (myIPs.Count == 0 && !string.IsNullOrEmpty(fallbackIP)) 164 | { 165 | myIPs.Add(fallbackIP); 166 | } 167 | 168 | return myIPs; 169 | } 170 | 171 | private void toggleButtons() 172 | { 173 | btnStop.Enabled = !btnStop.Enabled; 174 | btnStart.Enabled = !btnStart.Enabled; 175 | txtExternalPort.Enabled = !txtExternalPort.Enabled; 176 | txtInternalPort.Enabled = !txtInternalPort.Enabled; 177 | chkRewriteHostHeaders.Enabled = !chkRewriteHostHeaders.Enabled; 178 | } 179 | 180 | private bool checkPortAvailability(int port) 181 | { 182 | //http://stackoverflow.com/questions/570098/in-c-how-to-check-if-a-tcp-port-is-available 183 | 184 | // Evaluate current system tcp connections. This is the same information provided 185 | // by the netstat command line application, just in .Net strongly-typed object 186 | // form. We will look through the list, and if our port we would like to use 187 | // in our TcpClient is occupied, we will set isAvailable to false. 188 | IPGlobalProperties ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties(); 189 | TcpConnectionInformation[] tcpConnInfoArray = ipGlobalProperties.GetActiveTcpConnections(); 190 | 191 | foreach (TcpConnectionInformation tcpi in tcpConnInfoArray) 192 | { 193 | if (tcpi.LocalEndPoint.Port == port) 194 | return false; 195 | } 196 | 197 | try 198 | { 199 | TcpListener listener = new TcpListener(new IPEndPoint(IPAddress.Any, port)); 200 | listener.Start(); 201 | listener.Stop(); 202 | } 203 | catch (Exception) 204 | { 205 | return false; 206 | } 207 | 208 | return true; 209 | } 210 | 211 | private void txtPorts_KeyPress(object sender, KeyPressEventArgs e) 212 | { 213 | if (e.KeyChar == (char)Keys.Enter) 214 | { 215 | btnStart_Click(null, null); 216 | } 217 | } 218 | } 219 | } 220 | -------------------------------------------------------------------------------- /SharpProxy/frmMain.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace SharpProxy 2 | { 3 | partial class frmMain 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(frmMain)); 32 | this.btnStart = new System.Windows.Forms.Button(); 33 | this.btnStop = new System.Windows.Forms.Button(); 34 | this.label1 = new System.Windows.Forms.Label(); 35 | this.txtExternalPort = new System.Windows.Forms.TextBox(); 36 | this.txtInternalPort = new System.Windows.Forms.TextBox(); 37 | this.label2 = new System.Windows.Forms.Label(); 38 | this.label3 = new System.Windows.Forms.Label(); 39 | this.cmbIPAddress = new System.Windows.Forms.ComboBox(); 40 | this.chkRewriteHostHeaders = new System.Windows.Forms.CheckBox(); 41 | this.SuspendLayout(); 42 | // 43 | // btnStart 44 | // 45 | this.btnStart.Location = new System.Drawing.Point(11, 154); 46 | this.btnStart.Name = "btnStart"; 47 | this.btnStart.Size = new System.Drawing.Size(75, 23); 48 | this.btnStart.TabIndex = 0; 49 | this.btnStart.Text = "&Start"; 50 | this.btnStart.UseVisualStyleBackColor = true; 51 | this.btnStart.Click += new System.EventHandler(this.btnStart_Click); 52 | // 53 | // btnStop 54 | // 55 | this.btnStop.Enabled = false; 56 | this.btnStop.Location = new System.Drawing.Point(125, 154); 57 | this.btnStop.Name = "btnStop"; 58 | this.btnStop.Size = new System.Drawing.Size(75, 23); 59 | this.btnStop.TabIndex = 1; 60 | this.btnStop.Text = "S&top"; 61 | this.btnStop.UseVisualStyleBackColor = true; 62 | this.btnStop.Click += new System.EventHandler(this.btnStop_Click); 63 | // 64 | // label1 65 | // 66 | this.label1.AutoSize = true; 67 | this.label1.Location = new System.Drawing.Point(12, 49); 68 | this.label1.Name = "label1"; 69 | this.label1.Size = new System.Drawing.Size(67, 13); 70 | this.label1.TabIndex = 2; 71 | this.label1.Text = "External Port"; 72 | // 73 | // txtExternalPort 74 | // 75 | this.txtExternalPort.Location = new System.Drawing.Point(11, 65); 76 | this.txtExternalPort.MaxLength = 7; 77 | this.txtExternalPort.Name = "txtExternalPort"; 78 | this.txtExternalPort.Size = new System.Drawing.Size(189, 20); 79 | this.txtExternalPort.TabIndex = 3; 80 | this.txtExternalPort.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.txtPorts_KeyPress); 81 | // 82 | // txtInternalPort 83 | // 84 | this.txtInternalPort.Location = new System.Drawing.Point(11, 104); 85 | this.txtInternalPort.MaxLength = 7; 86 | this.txtInternalPort.Name = "txtInternalPort"; 87 | this.txtInternalPort.Size = new System.Drawing.Size(189, 20); 88 | this.txtInternalPort.TabIndex = 5; 89 | this.txtInternalPort.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.txtPorts_KeyPress); 90 | // 91 | // label2 92 | // 93 | this.label2.AutoSize = true; 94 | this.label2.Location = new System.Drawing.Point(12, 88); 95 | this.label2.Name = "label2"; 96 | this.label2.Size = new System.Drawing.Size(64, 13); 97 | this.label2.TabIndex = 4; 98 | this.label2.Text = "Internal Port"; 99 | // 100 | // label3 101 | // 102 | this.label3.AutoSize = true; 103 | this.label3.Location = new System.Drawing.Point(12, 9); 104 | this.label3.Name = "label3"; 105 | this.label3.Size = new System.Drawing.Size(83, 13); 106 | this.label3.TabIndex = 6; 107 | this.label3.Text = "Your IP Address"; 108 | // 109 | // cmbIPAddress 110 | // 111 | this.cmbIPAddress.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; 112 | this.cmbIPAddress.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 113 | this.cmbIPAddress.FormattingEnabled = true; 114 | this.cmbIPAddress.Location = new System.Drawing.Point(11, 25); 115 | this.cmbIPAddress.Name = "cmbIPAddress"; 116 | this.cmbIPAddress.Size = new System.Drawing.Size(189, 21); 117 | this.cmbIPAddress.TabIndex = 8; 118 | // 119 | // chkRewriteHostHeaders 120 | // 121 | this.chkRewriteHostHeaders.AutoSize = true; 122 | this.chkRewriteHostHeaders.Checked = true; 123 | this.chkRewriteHostHeaders.CheckState = System.Windows.Forms.CheckState.Checked; 124 | this.chkRewriteHostHeaders.Location = new System.Drawing.Point(13, 131); 125 | this.chkRewriteHostHeaders.Name = "chkRewriteHostHeaders"; 126 | this.chkRewriteHostHeaders.Size = new System.Drawing.Size(188, 17); 127 | this.chkRewriteHostHeaders.TabIndex = 9; 128 | this.chkRewriteHostHeaders.Text = "&Rewrite host headers (IIS Express)"; 129 | this.chkRewriteHostHeaders.UseVisualStyleBackColor = true; 130 | // 131 | // frmMain 132 | // 133 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 134 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 135 | this.ClientSize = new System.Drawing.Size(212, 185); 136 | this.Controls.Add(this.chkRewriteHostHeaders); 137 | this.Controls.Add(this.cmbIPAddress); 138 | this.Controls.Add(this.label3); 139 | this.Controls.Add(this.txtInternalPort); 140 | this.Controls.Add(this.label2); 141 | this.Controls.Add(this.txtExternalPort); 142 | this.Controls.Add(this.label1); 143 | this.Controls.Add(this.btnStop); 144 | this.Controls.Add(this.btnStart); 145 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow; 146 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); 147 | this.MaximizeBox = false; 148 | this.Name = "frmMain"; 149 | this.Text = "SharpProxy"; 150 | this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.frmMain_FormClosing); 151 | this.Shown += new System.EventHandler(this.frmMain_Shown); 152 | this.ResumeLayout(false); 153 | this.PerformLayout(); 154 | 155 | } 156 | 157 | #endregion 158 | 159 | private System.Windows.Forms.Button btnStart; 160 | private System.Windows.Forms.Button btnStop; 161 | private System.Windows.Forms.Label label1; 162 | private System.Windows.Forms.TextBox txtExternalPort; 163 | private System.Windows.Forms.TextBox txtInternalPort; 164 | private System.Windows.Forms.Label label2; 165 | private System.Windows.Forms.Label label3; 166 | private System.Windows.Forms.ComboBox cmbIPAddress; 167 | private System.Windows.Forms.CheckBox chkRewriteHostHeaders; 168 | } 169 | } 170 | 171 | -------------------------------------------------------------------------------- /SharpProxy/frmMain.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 122 | 123 | AAABAAQAEBAQAAEABAAoAQAARgAAACAgEAABAAQA6AIAAG4BAAAwMBAAAQAEAGgGAABWBAAAQEAQAAEA 124 | BABoCgAAvgoAACgAAAAQAAAAIAAAAAEABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AAAA 125 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 126 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQAAAAAREREREQAAABER 127 | ERERAAAAAAAAEQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 128 | AAD+/wAA/v8AAP4/AAD+vwAA/j8AAP//AAD8HwAAAAAAAAAAAAD8HwAA//8AAP4/AAD/vwAA/j8AAP7/ 129 | AAD+PwAAKAAAACAAAABAAAAAAQAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8AAAAAAAAA 130 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 131 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 132 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 133 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 134 | AAAAAAAAAAAREQAAAAAAAAAAAAAAAAAAEREAAAAAAAAAABEREREREREREREAAAAAAAARERERERERERER 135 | AAAAAAAAEREREREREREREQAAAAAAABEREREREREREREAAAAAAAAAAAAAAAAREQAAAAAAAAAAAAAAAAAA 136 | EREAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 137 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 138 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 139 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/8/////P////z////8/////A////wP///8z////M////wP///8 140 | D//////////////wA///8AP/AAAAAAAAAAAAAAAAAAAAAP/wA///8AP//////////////A////wP//// 141 | z////8////wP///8D////P////z////8D////A//KAAAADAAAABgAAAAAQAEAAAAAAAAAAAAAAAAAAAA 142 | AAAAAAAAAAAAAAAAAAAAAP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 143 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 144 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 145 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 146 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 147 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 148 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 149 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 150 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAREREAAAAAAAAAAAAAAAAAAAAAAAAAAAAR 151 | EREAAAAAAAAAAAAAAAAAAAAAAAAAAAAREREAAAAAAAAAAAAAAAAREREREREREREREREREREAAAAAAAAA 152 | AAAREREREREREREREREREREAAAAAAAAAAAAREREREREREREREREREREAAAAAAAAAAAARERERERERERER 153 | EREREREAAAAAAAAAAAAREREREREREREREREREREAAAAAAAAAAAAREREREREREREREREREREAAAAAAAAA 154 | AAAAAAAAAAAAAAAREREAAAAAAAAAAAAAAAAAAAAAAAAAAAAREREAAAAAAAAAAAAAAAAAAAAAAAAAAAAR 155 | EREAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 156 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 157 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 158 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 159 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 160 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 161 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 162 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///j///8AAP//+P///wAA///4////AAD///j///8AAP// 163 | +P///wAA///4////AAD///gD//8AAP//+AP//wAA///4A///AAD///jj//8AAP//+OP//wAA///44/// 164 | AAD///gD//8AAP//+AP//wAA///4A///AAD///////8AAP///////wAA////////AAD//8AAf/8AAP// 165 | wAB//wAA///AAH//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 166 | AAD//8AAf/8AAP//wAB//wAA///AAH//AAD///////8AAP///////wAA////////AAD///gD//8AAP// 167 | +AP//wAA///4A///AAD////j//8AAP///+P//wAA////4///AAD///gD//8AAP//+AP//wAA///4A/// 168 | AAD///j///8AAP//+P///wAA///4////AAD///gD//8AAP//+AP//wAA///4A///AAAoAAAAQAAAAIAA 169 | AAABAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 170 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 171 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 172 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 173 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 174 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 175 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 176 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 177 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 178 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 179 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 180 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 181 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 182 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 183 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEREREAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 184 | AAAAAAAAEREREQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARERERAAAAAAAAAAAAAAAAAAAAAAAA 185 | AAAAAAAAAAAAABEREREAAAAAAAAAAAAAAAAAAAAAEREREREREREREREREREREREREREAAAAAAAAAAAAA 186 | AAAREREREREREREREREREREREREREQAAAAAAAAAAAAAAABERERERERERERERERERERERERERAAAAAAAA 187 | AAAAAAAAEREREREREREREREREREREREREREAAAAAAAAAAAAAAAAREREREREREREREREREREREREREQAA 188 | AAAAAAAAAAAAABERERERERERERERERERERERERERAAAAAAAAAAAAAAAAERERERERERERERERERERERER 189 | EREAAAAAAAAAAAAAAAAREREREREREREREREREREREREREQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABER 190 | EREAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEREREQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 191 | AAARERERAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEREREAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 192 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 193 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 194 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 195 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 196 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 197 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 198 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 199 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 200 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 201 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 202 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 203 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 204 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////8P/////////w//////// 205 | //D/////////8P/////////w//////////D/////////8P/////////w//////////AA////////8AD/ 206 | ///////wAP////////AA////////8PD////////w8P////////Dw////////8PD////////wAP////// 207 | //AA////////8AD////////wAP//////////////////////////////////////////////////AAAP 208 | //////8AAA///////wAAD///////AAAP//8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 209 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AAAP//////8AAA///////wAAD///////AAAP 210 | //////////////////////////////////////////////////AA////////8AD////////wAP////// 211 | //AA//////////D/////////8P/////////w//////////D////////wAP////////AA////////8AD/ 212 | ///////wAP////////D/////////8P/////////w//////////D/////////8AD////////wAP////// 213 | //AA////////8AD///8= 214 | 215 | 216 | --------------------------------------------------------------------------------