using System; namespace TrotiNet { /// /// Container class for proxy settings /// public class SystemProxySettings { /// /// System/IE option "Use a proxy server for your /// LAN (These settings will not apply to dial-up or VPN connections)." /// public bool ProxyEnable { get { return (proxyEnable == 1); } set { proxyEnable = value ? 1 : 0; } } int proxyEnable; /// /// Correspond to the system/IE advanced option "Exceptions" (do not /// use proxy server for these address prefixes). For example: *.local /// /// /// If the option "Bypass proxy server for local addresses" is /// checked, ";<local>" is appended to ProxyOverride. /// public string ProxyOverride; /// /// Correspond to the system/IE options "Address" and "Port", and the /// advanced option "Servers". /// /// /// - If the proxy is the same for all protocols, use: /// localhost:2000 /// - If the proxy depends on the TCP service, use this syntax: /// ftp=ip1:2002;http=ip2:2000;https=ip3:2001;socks=ip4:2003 /// public string ProxyServer; /// /// Correspond to the system/IE advanced option "Use Automatic /// Configuration Script." /// public string AutoConfigURL; /// /// Constructor /// public SystemProxySettings(bool proxyEnable, string proxyServer, string proxyOverride, string autoConfigURL) { ProxyEnable = proxyEnable; ProxyServer = proxyServer; ProxyOverride = proxyOverride; AutoConfigURL = autoConfigURL; } /// /// Constructor with default (empty) auto config URL /// public SystemProxySettings(bool proxyEnable, string proxyServer, string proxyOverride) : this(proxyEnable, proxyServer, proxyOverride, null) { } /// /// Retrieve the HTTP-specific proxy settings /// public void GetHttpSpecificProxy(out string proxy_host, out int proxy_port) { GetProtocolSpecificProxy("http=", 80, out proxy_host, out proxy_port); } /// /// Retrieve the HTTP-specific proxy settings /// public void GetHttpsSpecificProxy(out string proxy_host, out int proxy_port) { GetProtocolSpecificProxy("https=", 443, out proxy_host, out proxy_port); } /// /// Extract protocol-specific proxy settings /// /// /// One of "ftp=", "socks=", "http=", "https="; it must end with a /// '=' sign. /// /// /// The default port for the protocol, e.g. 80 for HTTP /// /// /// Will be set to the proxy host name /// /// /// Will be set to the proxy port /// void GetProtocolSpecificProxy(string protocol, int default_port, out string proxy_host, out int proxy_port) { System.Diagnostics.Debug.Assert( protocol[protocol.Length - 1] == '='); proxy_host = null; proxy_port = 0; if (!ProxyEnable) return; if (String.IsNullOrEmpty(ProxyServer)) return; // Recall that ProxyServer can have one of these two forms: // [http=]localhost:2000 // ftp=ip1:2002;http=ip2:2000;https=ip3:2001;socks=ip4:2003 string ProtocolProxyServer = null; if (ProxyServer.IndexOf(';') > -1) { // Find the protocol-specific part var items = ProxyServer.Split(';'); for (int i = 0; i < items.Length; i++) if (items[i].StartsWith(protocol)) { ProtocolProxyServer = items[i]; break; } if (ProtocolProxyServer == null) // We didn't find a corresponding entry return; } else // Either "[:]", or "[:]" ProtocolProxyServer = ProxyServer; // Again, we have "[:]" or "[:]" if (ProtocolProxyServer.IndexOf('=') > -1) { // We have "[:]". // Does the "" prefix match? if (ProtocolProxyServer.StartsWith(protocol)) ProtocolProxyServer = ProtocolProxyServer.Substring( protocol.Length); else // The entry is for another protocol return; } // Now we only have "[:]" var c = ProtocolProxyServer.IndexOf(':'); proxy_port = default_port; if (c < 0) // "" proxy_host = ProtocolProxyServer; else { // ":" proxy_host = ProtocolProxyServer.Substring(0, c); Int32.TryParse(ProtocolProxyServer.Substring(c + 1), out proxy_port); } } /// /// Replace the proxy for the HTTP protocol; proxy settings for /// the other protocols are left unchanged /// /// /// ProxyEnable is not modified either, and must be updated separately. /// public void SetHttpSpecificProxy(string proxy_host, int proxy_port) { var GlobalProxyServer = proxy_host + ":" + proxy_port; var HttpProxyServer = "http=" + GlobalProxyServer; if (ProxyServer == null) { ProxyServer = HttpProxyServer; return; } if (ProxyServer.IndexOf(';') > -1) { // Find and modify the http-only part var items = ProxyServer.Split(';'); int i; for (i = 0; i < items.Length; i++) if (items[i].StartsWith("http=")) { items[i] = HttpProxyServer; break; } if (i == items.Length) // We didn't find an entry with "http=", so we add it ProxyServer = ProxyServer + ";" + HttpProxyServer; else ProxyServer = String.Join(";", items); return; } if (ProxyServer.IndexOf('=') < 0) { if (ProxyServer.Equals(GlobalProxyServer)) // No change required (this avoids changing ProxyServer // from, say, "localhost:2000" to // "ftp=localhost:2000;http=localhost:2000;...") return; // Previously, the same proxy was used for all protocols. // We need to introduce a distinction between the different // protocols so that we can use our proxy for HTTP-only. ProxyServer = "ftp=" + ProxyServer + ";" + HttpProxyServer + ";https=" + ProxyServer + ";socks=" + ProxyServer; return; } if (ProxyServer.StartsWith("http=")) // There's only a HTTP-only proxy defined, so we replace it ProxyServer = HttpProxyServer; else // There's a proxy defined for a protocol which isn't HTTP, so // we add our HTTP item. ProxyServer += ";" + HttpProxyServer; } /// /// Human-readable representation /// public override string ToString() { if (!ProxyEnable) return "no proxy"; return ProxyServer + (ProxyOverride == null ? "" : " (bypass: " + ProxyOverride + ")"); } } }