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 + ")");
}
}
}