The Labs \ Source Viewer \ SSCLI \ System.Net \ WebProxy

  1. //------------------------------------------------------------------------------
  2. // <copyright file="webproxy.cs" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. //------------------------------------------------------------------------------
  15. namespace System.Net
  16. {
  17.     using System.Net.NetworkInformation;
  18.     using System.Globalization;
  19.     using System.Security.Permissions;
  20.     using System.Text;
  21.     using System.Text.RegularExpressions;
  22.     using System.Collections;
  23.     using System.Collections.Specialized;
  24.     using System.Runtime.Serialization;
  25.     using System.ComponentModel;
  26.     using System.Threading;
  27.    
  28.     class WebProxyData
  29.     {
  30.         internal bool bypassOnLocal;
  31.         internal bool automaticallyDetectSettings;
  32.         internal Uri proxyAddress;
  33.         internal Uri scriptLocation;
  34.         internal ArrayList bypassList;
  35.     }
  36.    
  37.     /// <devdoc>
  38.     /// <para>
  39.     /// Handles default proxy setting implimentation for the Http proxy.
  40.     /// </para>
  41.     /// </devdoc>
  42.     [Serializable()]
  43.     public class WebProxy : IAutoWebProxy, ISerializable
  44.     {
  45.         // these are settable by the user
  46.         private bool _UseRegistry;
  47.         // This is just around for serialization. Can we get rid of it?
  48.         private bool _BypassOnLocal;
  49.         private bool m_EnableAutoproxy;
  50.         private Uri _ProxyAddress;
  51.         private ArrayList _BypassList;
  52.         private ICredentials _Credentials;
  53.        
  54.         // these are computed on the fly
  55.         private Regex[] _RegExBypassList;
  56.         private Hashtable _ProxyHostAddresses;
  57.        
  58.         /// <devdoc>
  59.         /// <para>[To be supplied.]</para>
  60.         /// </devdoc>
  61.         public WebProxy() : this((Uri)null, false, null, null)
  62.         {
  63.         }
  64.        
  65.         /// <devdoc>
  66.         /// <para>[To be supplied.]</para>
  67.         /// </devdoc>
  68.         public WebProxy(Uri Address) : this(Address, false, null, null)
  69.         {
  70.         }
  71.        
  72.         /// <devdoc>
  73.         /// <para>[To be supplied.]</para>
  74.         /// </devdoc>
  75.         public WebProxy(Uri Address, bool BypassOnLocal) : this(Address, BypassOnLocal, null, null)
  76.         {
  77.         }
  78.        
  79.         /// <devdoc>
  80.         /// <para>[To be supplied.]</para>
  81.         /// </devdoc>
  82.         public WebProxy(Uri Address, bool BypassOnLocal, string[] BypassList) : this(Address, BypassOnLocal, BypassList, null)
  83.         {
  84.         }
  85.        
  86.         /// <devdoc>
  87.         /// <para>[To be supplied.]</para>
  88.         /// </devdoc>
  89.         internal WebProxy(Hashtable proxyHostAddresses, bool BypassOnLocal, string[] BypassList) : this((Uri)null, BypassOnLocal, BypassList, null)
  90.         {
  91.             _ProxyHostAddresses = proxyHostAddresses;
  92.             if (_ProxyHostAddresses != null) {
  93.                 _ProxyAddress = (Uri)proxyHostAddresses["http"];
  94.             }
  95.         }
  96.        
  97.         /// <devdoc>
  98.         /// <para>[To be supplied.]</para>
  99.         /// </devdoc>
  100.         public WebProxy(Uri Address, bool BypassOnLocal, string[] BypassList, ICredentials Credentials)
  101.         {
  102.             _ProxyAddress = Address;
  103.             _BypassOnLocal = BypassOnLocal;
  104.             if (BypassList != null) {
  105.                 _BypassList = new ArrayList(BypassList);
  106.                 UpdateRegExList(true);
  107.             }
  108.             _Credentials = Credentials;
  109.             m_EnableAutoproxy = true;
  110.         }
  111.        
  112.         /// <devdoc>
  113.         /// <para>[To be supplied.]</para>
  114.         /// </devdoc>
  115.         public WebProxy(string Host, int Port) : this(new Uri("http://" + Host + ":" + Port.ToString(CultureInfo.InvariantCulture)), false, null, null)
  116.         {
  117.         }
  118.        
  119.         /// <devdoc>
  120.         /// <para>[To be supplied.]</para>
  121.         /// </devdoc>
  122.         public WebProxy(string Address) : this(CreateProxyUri(Address), false, null, null)
  123.         {
  124.         }
  125.        
  126.         /// <devdoc>
  127.         /// <para>[To be supplied.]</para>
  128.         /// </devdoc>
  129.         public WebProxy(string Address, bool BypassOnLocal) : this(CreateProxyUri(Address), BypassOnLocal, null, null)
  130.         {
  131.         }
  132.        
  133.         /// <devdoc>
  134.         /// <para>[To be supplied.]</para>
  135.         /// </devdoc>
  136.         public WebProxy(string Address, bool BypassOnLocal, string[] BypassList) : this(CreateProxyUri(Address), BypassOnLocal, BypassList, null)
  137.         {
  138.         }
  139.        
  140.         /// <devdoc>
  141.         /// <para>[To be supplied.]</para>
  142.         /// </devdoc>
  143.         public WebProxy(string Address, bool BypassOnLocal, string[] BypassList, ICredentials Credentials) : this(CreateProxyUri(Address), BypassOnLocal, BypassList, Credentials)
  144.         {
  145.         }
  146.        
  147.         /// <devdoc>
  148.         /// <para>[To be supplied.]</para>
  149.         /// </devdoc>
  150.         public Uri Address {
  151.             get { return _ProxyAddress; }
  152.             set {
  153.                 _UseRegistry = false;
  154.                 DeleteScriptEngine();
  155.                 _ProxyHostAddresses = null;
  156.                 // hash list of proxies
  157.                 _ProxyAddress = value;
  158.             }
  159.         }
  160.        
  161.         /// <devdoc>
  162.         /// <para>[To be supplied.]</para>
  163.         /// </devdoc>
  164.         internal bool AutoDetect {
  165.             set {
  166.                 GlobalLog.Assert(_UseRegistry == false, "Cannot set AutoDetect if we are using registry for proxy settings");
  167.                 GlobalLog.Assert(m_EnableAutoproxy, "WebProxy#{0}::.ctor()|Cannot set AutoDetect if usesystemdefault is set.", ValidationHelper.HashString(this));
  168.                
  169.                 if (ScriptEngine == null) {
  170.                     ScriptEngine = new AutoWebProxyScriptEngine(this, false);
  171.                 }
  172.                 ScriptEngine.AutomaticallyDetectSettings = value;
  173.             }
  174.         }
  175.        
  176.         /// <devdoc>
  177.         /// <para>[To be supplied.]</para>
  178.         /// </devdoc>
  179.         internal Uri ScriptLocation {
  180.             set {
  181.                 GlobalLog.Assert(value != null, "Cannot set ScriptLocation to null");
  182.                 GlobalLog.Assert(_UseRegistry == false, "Cannot set AutoDetect if we are using registry for proxy settings");
  183.                 GlobalLog.Assert(m_EnableAutoproxy, "WebProxy#{0}::.ctor()|Cannot set ScriptLocation if usesystemdefault is set.", ValidationHelper.HashString(this));
  184.                
  185.                 if (ScriptEngine == null) {
  186.                     ScriptEngine = new AutoWebProxyScriptEngine(this, false);
  187.                 }
  188.                 ScriptEngine.AutomaticConfigurationScript = value;
  189.             }
  190.         }
  191.        
  192.         /// <devdoc>
  193.         /// <para>[To be supplied.]</para>
  194.         /// </devdoc>
  195.         public bool BypassProxyOnLocal {
  196.             get { return _BypassOnLocal; }
  197.             set {
  198.                 _UseRegistry = false;
  199.                 DeleteScriptEngine();
  200.                 _BypassOnLocal = value;
  201.             }
  202.         }
  203.        
  204.         /// <devdoc>
  205.         /// <para>[To be supplied.]</para>
  206.         /// </devdoc>
  207.         public string[] BypassList {
  208.             get {
  209.                 if (_BypassList == null) {
  210.                     _BypassList = new ArrayList();
  211.                 }
  212.                 return (string[])_BypassList.ToArray(typeof(string));
  213.             }
  214.             set {
  215.                 _UseRegistry = false;
  216.                 DeleteScriptEngine();
  217.                 _BypassList = new ArrayList(value);
  218.                 UpdateRegExList(true);
  219.             }
  220.         }
  221.        
  222.         /// <devdoc>
  223.         /// <para>[To be supplied.]</para>
  224.         /// </devdoc>
  225.         public ICredentials Credentials {
  226.             get { return _Credentials; }
  227.             set { _Credentials = value; }
  228.         }
  229.        
  230.         /// <devdoc>
  231.         /// <para>Sets Credentials to CredentialCache.DefaultCredentials</para>
  232.         /// </devdoc>
  233.         public bool UseDefaultCredentials {
  234.             get { return (Credentials is SystemNetworkCredential) ? true : false; }
  235.             set { _Credentials = value ? CredentialCache.DefaultCredentials : null; }
  236.         }
  237.        
  238.         /// <devdoc>
  239.         /// <para>[To be supplied.]</para>
  240.         /// </devdoc>
  241.         public ArrayList BypassArrayList {
  242.             get {
  243.                 if (_BypassList == null) {
  244.                     _BypassList = new ArrayList();
  245.                 }
  246.                 return _BypassList;
  247.             }
  248.         }
  249.        
  250.         internal void CheckForChanges()
  251.         {
  252.         }
  253.        
  254.         /// <devdoc>
  255.         /// <para>[To be supplied.]</para>
  256.         /// </devdoc>
  257.         public Uri GetProxy(Uri destination)
  258.         {
  259.             GlobalLog.Print("WebProxy#" + ValidationHelper.HashString(this) + "::GetProxy() destination:" + ValidationHelper.ToString(destination));
  260.             if (destination == null) {
  261.                 throw new ArgumentNullException("destination");
  262.             }
  263.            
  264.             AutoWebProxyState autoWebProxyState;
  265.             Uri result = GetProxyAuto(destination, out autoWebProxyState);
  266.             if (autoWebProxyState == AutoWebProxyState.ExecutionSuccess) {
  267.                 return result;
  268.             }
  269.             if (IsBypassedManual(destination)) {
  270.                 return destination;
  271.             }
  272.             Hashtable proxyHostAddresses = _ProxyHostAddresses;
  273.             Uri proxy = proxyHostAddresses != null ? proxyHostAddresses[destination.Scheme] as Uri : _ProxyAddress;
  274.             return proxy != null ? proxy : destination;
  275.         }
  276.        
  277.         //
  278.         // CreateProxyUri - maps string to Uri
  279.         //
  280.        
  281.         private static Uri CreateProxyUri(string address)
  282.         {
  283.             if (address == null) {
  284.                 return null;
  285.             }
  286.             if (address.IndexOf("://") == -1) {
  287.                 address = "http://" + address;
  288.             }
  289.             return new Uri(address);
  290.         }
  291.        
  292.         //
  293.         // UpdateRegExList - Update internal _RegExBypassList
  294.         // warning - can throw if the RegEx doesn't parse??
  295.         //
  296.         private void UpdateRegExList(bool canThrow)
  297.         {
  298.             Regex[] regExBypassList = null;
  299.             ArrayList bypassList = _BypassList;
  300.             try {
  301.                 if (bypassList != null && bypassList.Count > 0) {
  302.                     regExBypassList = new Regex[bypassList.Count];
  303.                     for (int i = 0; i < bypassList.Count; i++) {
  304.                         regExBypassList[i] = new Regex((string)bypassList[i], RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
  305.                     }
  306.                 }
  307.             }
  308.             catch {
  309.                 if (!canThrow) {
  310.                     _RegExBypassList = null;
  311.                     return;
  312.                 }
  313.                 throw;
  314.             }
  315.             // only update here, cause it could throw earlier in the loop
  316.             _RegExBypassList = regExBypassList;
  317.         }
  318.        
  319.         //
  320.         // IsMatchInBypassList - match input against _RegExBypassList
  321.         //
  322.         private bool IsMatchInBypassList(Uri input)
  323.         {
  324.             UpdateRegExList(false);
  325.             if (_RegExBypassList == null) {
  326.                 return false;
  327.             }
  328.             string matchUriString = input.Scheme + "://" + input.Host + (!input.IsDefaultPort ? (":" + input.Port) : "");
  329.             for (int i = 0; i < _BypassList.Count; i++) {
  330.                 if (_RegExBypassList[i].IsMatch(matchUriString)) {
  331.                     return true;
  332.                 }
  333.             }
  334.             return false;
  335.         }
  336.        
  337.         /// <devdoc>
  338.         /// Determines if the host Uri should be routed locally or go through the proxy.
  339.         /// </devdoc>
  340.         private bool IsLocal(Uri host)
  341.         {
  342.             string hostString = host.Host;
  343.            
  344.             // If and only if the host has a colon or is all numbers and dots, it is an IP address.
  345.             // If no dot, it is local. (If it has both a dot and a colon, undefined.)
  346.             int dot = -1;
  347.             bool isIp4 = true;
  348.             bool isIp6 = false;
  349.             for (int i = 0; i < hostString.Length; i++) {
  350.                 if (hostString[i] == '.') {
  351.                     if (dot == -1) {
  352.                         dot = i;
  353.                         if (!isIp4) {
  354.                             break;
  355.                         }
  356.                     }
  357.                    
  358.                     continue;
  359.                 }
  360.                
  361.                 if (hostString[i] == ':') {
  362.                     isIp6 = true;
  363.                     isIp4 = false;
  364.                     break;
  365.                 }
  366.                
  367.                 if (hostString[i] < '0' || hostString[i] > '9') {
  368.                     isIp4 = false;
  369.                     if (dot != -1) {
  370.                         break;
  371.                     }
  372.                 }
  373.             }
  374.            
  375.             // No dot? Local.
  376.             // The case of all digits is a little weird. Technically it could be a v4 IP, but practically it can only
  377.             // be interpreted as an intranet name.
  378.             if (dot == -1 && !isIp6) {
  379.                 return true;
  380.             }
  381.            
  382.             if (isIp4 || isIp6) {
  383.                 // I don't see why this would fail, but in case it does, it's not an IP.
  384.                 try {
  385.                     IPAddress hostAddress = IPAddress.Parse(hostString);
  386.                     if (IPAddress.IsLoopback(hostAddress)) {
  387.                         return true;
  388.                     }
  389.                     return NclUtilities.IsAddressLocal(hostAddress);
  390.                 }
  391.                 catch (FormatException) {
  392.                 }
  393.             }
  394.            
  395.             // If it matches the primary domain, it's local. (Whether or not the hostname matches.)
  396.             string local = "." + IPGlobalProperties.InternalGetIPGlobalProperties().DomainName;
  397.             if (local != null && local.Length == (hostString.Length - dot) && string.Compare(local, 0, hostString, dot, local.Length, StringComparison.OrdinalIgnoreCase) == 0) {
  398.                 return true;
  399.             }
  400.             return false;
  401.         }
  402.        
  403.         /// <devdoc>
  404.         /// Determines if the host Uri should be routed locally or go through a proxy.
  405.         /// </devdoc>
  406.         private bool IsLocalInProxyHash(Uri host)
  407.         {
  408.             Hashtable proxyHostAddresses = _ProxyHostAddresses;
  409.             if (proxyHostAddresses != null) {
  410.                 Uri proxy = (Uri)proxyHostAddresses[host.Scheme];
  411.                 if (proxy == null) {
  412.                     return true;
  413.                     // no proxy entry for this scheme, then bypass
  414.                 }
  415.             }
  416.             return false;
  417.         }
  418.        
  419.        
  420.         /// <devdoc>
  421.         /// <para>[To be supplied.]</para>
  422.         /// </devdoc>
  423.         public bool IsBypassed(Uri host)
  424.         {
  425.             GlobalLog.Print("WebProxy#" + ValidationHelper.HashString(this) + "::IsBypassed() destination:" + ValidationHelper.ToString(host));
  426.             if (host == null) {
  427.                 throw new ArgumentNullException("host");
  428.             }
  429.            
  430.             AutoWebProxyState autoWebProxyState;
  431.             bool result = IsBypassedAuto(host, out autoWebProxyState);
  432.             if (autoWebProxyState == AutoWebProxyState.ExecutionSuccess) {
  433.                 return result;
  434.             }
  435.             return IsBypassedManual(host);
  436.         }
  437.        
  438.         private bool IsBypassedManual(Uri host)
  439.         {
  440.             if (host.IsLoopback) {
  441.                 return true;
  442.                 // bypass localhost from using a proxy.
  443.             }
  444.             return (_ProxyAddress == null && _ProxyHostAddresses == null) || (_BypassOnLocal && IsLocal(host)) || IsMatchInBypassList(host) || IsLocalInProxyHash(host);
  445.         }
  446.        
  447.         /// <devdoc>
  448.         /// <para>[To be supplied.]</para>
  449.         /// </devdoc>
  450.         [Obsolete("This method has been deprecated. Please use the proxy selected for you by default. http://go.microsoft.com/fwlink/?linkid=14202")]
  451.         public static WebProxy GetDefaultProxy()
  452.         {
  453.             ExceptionHelper.WebPermissionUnrestricted.Demand();
  454.             return new WebProxy(true);
  455.         }
  456.        
  457.         //
  458.         // ISerializable constructor
  459.         //
  460.         /// <devdoc>
  461.         /// <para>[To be supplied.]</para>
  462.         /// </devdoc>
  463.         protected WebProxy(SerializationInfo serializationInfo, StreamingContext streamingContext)
  464.         {
  465.             // first check for useRegistry on the serialized proxy
  466.             bool useRegistry = false;
  467.             try {
  468.                 useRegistry = serializationInfo.GetBoolean("_UseRegistry");
  469.             }
  470.             catch {
  471.             }
  472.             if (useRegistry) {
  473.                 // just make the proxy advanced, don't populate with any settings
  474.                 // note - this will happen in the context of the user performing the deserialization (their proxy settings get read)
  475.                 ExceptionHelper.WebPermissionUnrestricted.Demand();
  476.                 UnsafeUpdateFromRegistry();
  477.                 return;
  478.             }
  479.             // normal proxy
  480.             _ProxyAddress = (Uri)serializationInfo.GetValue("_ProxyAddress", typeof(Uri));
  481.             _BypassOnLocal = serializationInfo.GetBoolean("_BypassOnLocal");
  482.             _BypassList = (ArrayList)serializationInfo.GetValue("_BypassList", typeof(ArrayList));
  483.             try {
  484.                 UseDefaultCredentials = serializationInfo.GetBoolean("_UseDefaultCredentials");
  485.             }
  486.             catch {
  487.             }
  488.         }
  489.        
  490.         //
  491.         // ISerializable method
  492.         //
  493.         /// <internalonly/>
  494.         /// <devdoc>
  495.         /// <para>[To be supplied.]</para>
  496.         /// </devdoc>
  497.         [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter, SerializationFormatter = true)]
  498.         void ISerializable.GetObjectData(SerializationInfo serializationInfo, StreamingContext streamingContext)
  499.         {
  500.             GetObjectData(serializationInfo, streamingContext);
  501.         }
  502.        
  503.         //
  504.         // FxCop: provide a way for derived classes to access this method even if they reimplement ISerializable.
  505.         //
  506.         [SecurityPermission(SecurityAction.LinkDemand, SerializationFormatter = true)]
  507.         protected virtual void GetObjectData(SerializationInfo serializationInfo, StreamingContext streamingContext)
  508.         {
  509.             serializationInfo.AddValue("_BypassOnLocal", _BypassOnLocal);
  510.             serializationInfo.AddValue("_ProxyAddress", _ProxyAddress);
  511.             serializationInfo.AddValue("_BypassList", _BypassList);
  512.             serializationInfo.AddValue("_UseDefaultCredentials", UseDefaultCredentials);
  513.             if (_UseRegistry) {
  514.                 serializationInfo.AddValue("_UseRegistry", true);
  515.             }
  516.         }
  517.        
  518.        
  519.         /// <summary>
  520.         /// Handles proxy settings by using Internet Explorer based settings,
  521.         /// keep in mind the security implications when downloading and running
  522.         /// script from any network source configured in Internet Explorer.
  523.         /// </summary>
  524.        
  525.         private AutoWebProxyScriptEngine m_ScriptEngine;
  526.        
  527.         internal AutoWebProxyScriptEngine ScriptEngine {
  528.             get { return m_ScriptEngine; }
  529.             set { m_ScriptEngine = value; }
  530.         }
  531.        
  532.         internal WebProxy(bool enableAutoproxy)
  533.         {
  534.             m_EnableAutoproxy = enableAutoproxy;
  535.             UnsafeUpdateFromRegistry();
  536.         }
  537.        
  538.         internal void DeleteScriptEngine()
  539.         {
  540.             if (ScriptEngine != null) {
  541.                 ScriptEngine.Close();
  542.                 ScriptEngine = null;
  543.             }
  544.         }
  545.        
  546.         internal void UnsafeUpdateFromRegistry()
  547.         {
  548.             GlobalLog.Assert(!_UseRegistry, "WebProxy#{0}::UnsafeUpdateFromRegistry()|_UseRegistry ScriptEngine#{1}", ValidationHelper.HashString(this), ValidationHelper.HashString(m_ScriptEngine));
  549.             _UseRegistry = true;
  550.         }
  551.        
  552.         internal void Update(WebProxyData webProxyData)
  553.         {
  554.             // update needs to happen atomically
  555.             lock (this) {
  556.                 _BypassOnLocal = webProxyData.bypassOnLocal;
  557.                 _ProxyAddress = webProxyData.proxyAddress;
  558.                 _BypassList = webProxyData.bypassList;
  559.                
  560.                 ScriptEngine.AutomaticallyDetectSettings = m_EnableAutoproxy && webProxyData.automaticallyDetectSettings;
  561.                 ScriptEngine.AutomaticConfigurationScript = m_EnableAutoproxy ? webProxyData.scriptLocation : null;
  562.             }
  563.         }
  564.        
  565.         ProxyChain IAutoWebProxy.GetProxies(Uri destination)
  566.         {
  567.             GlobalLog.Print("WebProxy#" + ValidationHelper.HashString(this) + "::GetProxies() destination:" + ValidationHelper.ToString(destination));
  568.             if (destination == null) {
  569.                 throw new ArgumentNullException("destination");
  570.             }
  571.             return new ProxyScriptChain(this, destination);
  572.         }
  573.        
  574.        
  575.         //
  576.         // IWebProxy implementation
  577.         //
  578.        
  579.         // Get proxies can never return null in the case of ExecutionSuccess.
  580.         private Uri GetProxyAuto(Uri destination, out AutoWebProxyState autoWebProxyState)
  581.         {
  582.             GlobalLog.Print("WebProxy#" + ValidationHelper.HashString(this) + "::GetProxyAuto() destination:" + ValidationHelper.ToString(destination));
  583.             if (ScriptEngine == null) {
  584.                 autoWebProxyState = AutoWebProxyState.Uninitialized;
  585.                 return null;
  586.             }
  587.             StringCollection proxies = ScriptEngine.GetProxies(destination, true, out autoWebProxyState);
  588.             if (autoWebProxyState != AutoWebProxyState.ExecutionSuccess) {
  589.                 return null;
  590.             }
  591.             if (proxies.Count == 0) {
  592.                 // Null here means, no proxy available (incl. DIRECT), the request is prohibited.
  593.                 return null;
  594.             }
  595.             if (AreAllBypassed(proxies, true)) {
  596.                 return destination;
  597.             }
  598.             return ProxyUri(proxies[0]);
  599.         }
  600.        
  601.         private bool IsBypassedAuto(Uri destination, out AutoWebProxyState autoWebProxyState)
  602.         {
  603.             GlobalLog.Print("WebProxy#" + ValidationHelper.HashString(this) + "::IsBypassedAuto() destination:" + ValidationHelper.ToString(destination));
  604.             if (ScriptEngine == null) {
  605.                 autoWebProxyState = AutoWebProxyState.Uninitialized;
  606.                 return true;
  607.             }
  608.             StringCollection proxies = ScriptEngine.GetProxies(destination, true, out autoWebProxyState);
  609.             if (autoWebProxyState != AutoWebProxyState.ExecutionSuccess) {
  610.                 return true;
  611.             }
  612.             if (proxies.Count == 0) {
  613.                 return false;
  614.             }
  615.             return AreAllBypassed(proxies, true);
  616.         }
  617.        
  618.         internal Uri[] GetProxiesAuto(Uri destination, out AutoWebProxyState autoWebProxyState, ref int syncStatus)
  619.         {
  620.             GlobalLog.Print("WebProxy#" + ValidationHelper.HashString(this) + "::GetProxiesAuto() destination:" + ValidationHelper.ToString(destination));
  621.             if (ScriptEngine == null) {
  622.                 autoWebProxyState = AutoWebProxyState.Uninitialized;
  623.                 return null;
  624.             }
  625.             StringCollection proxies = ScriptEngine.GetProxies(destination, false, out autoWebProxyState, ref syncStatus);
  626.             if (autoWebProxyState != AutoWebProxyState.ExecutionSuccess) {
  627.                 return null;
  628.             }
  629.             if (proxies.Count == 0) {
  630.                 return new Uri[] {};
  631.             }
  632.             if (AreAllBypassed(proxies, false)) {
  633.                 return new Uri[] {null};
  634.             }
  635.             Uri[] proxyUris = new Uri[proxies.Count];
  636.             for (int i = 0; i < proxies.Count; i++) {
  637.                 proxyUris[i] = ProxyUri(proxies[i]);
  638.             }
  639.             return proxyUris;
  640.         }
  641.        
  642.         internal void AbortGetProxiesAuto(ref int syncStatus)
  643.         {
  644.             if (ScriptEngine != null) {
  645.                 ScriptEngine.Abort(ref syncStatus);
  646.             }
  647.         }
  648.        
  649.         internal Uri GetProxyAutoFailover(Uri destination)
  650.         {
  651.             if (IsBypassedManual(destination)) {
  652.                 return null;
  653.             }
  654.            
  655.             Uri proxy = _ProxyAddress;
  656.             Hashtable proxyHostAddresses = _ProxyHostAddresses;
  657.             if (proxyHostAddresses != null) {
  658.                 proxy = proxyHostAddresses[destination.Scheme] as Uri;
  659.             }
  660.             return proxy;
  661.         }
  662.        
  663.         private static bool AreAllBypassed(StringCollection proxies, bool checkFirstOnly)
  664.         {
  665.             bool isBypassed = true;
  666.             for (int i = 0; isBypassed && i < proxies.Count; i++) {
  667.                 isBypassed = ValidationHelper.IsBlankString(proxies[i]);
  668.                 if (checkFirstOnly) {
  669.                     break;
  670.                 }
  671.             }
  672.             return isBypassed;
  673.         }
  674.        
  675.         private static Uri ProxyUri(string proxyName)
  676.         {
  677.             return proxyName == null || proxyName.Length == 0 ? null : new Uri("http://" + proxyName);
  678.         }
  679.     }
  680. }

Developer Fusion