webproxy.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ DotNET / DotNET / 8.0 / untmp / whidbey / REDBITS / ndp / fx / src / Net / System / Net / webproxy.cs / 1 / webproxy.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

namespace System.Net { 
    using System.Net.NetworkInformation; 
    using System.Globalization;
    using System.Security.Permissions; 
    using System.Text;
    using System.Text.RegularExpressions;
    using System.Collections;
    using System.Collections.Specialized; 
    using System.Runtime.Serialization;
    using System.ComponentModel; 
    using System.Threading; 

    class WebProxyData { 
        internal bool bypassOnLocal;
        internal bool automaticallyDetectSettings;
        internal Uri proxyAddress;
        internal Uri scriptLocation; 
#if USE_WINIET_AUTODETECT_CACHE
        internal Uri lkgScriptLocation; 
#endif 
        internal ArrayList bypassList;
    } 

    /// 
    ///    
    ///       Handles default proxy setting implimentation for the Http proxy. 
    ///    
    ///  
    [Serializable] 
    public class WebProxy : IAutoWebProxy, ISerializable {
        // these are settable by the user 
        private bool _UseRegistry;    // This is just around for serialization. Can we get rid of it?
        private bool _BypassOnLocal;
        private bool m_EnableAutoproxy;
        private Uri _ProxyAddress; 
        private ArrayList _BypassList;
        private ICredentials _Credentials; 
 
        // these are computed on the fly
        private Regex[] _RegExBypassList; 
        private Hashtable _ProxyHostAddresses;

        /// 
        ///    [To be supplied.] 
        /// 
        public WebProxy() 
            : this((Uri) null, false, null, null) { 
        }
 
        /// 
        ///    [To be supplied.]
        /// 
        public WebProxy(Uri Address) 
            : this(Address, false, null, null) {
        } 
 
        /// 
        ///    [To be supplied.] 
        /// 
        public WebProxy(Uri Address, bool BypassOnLocal)
            : this(Address, BypassOnLocal, null, null) {
        } 

        ///  
        ///    [To be supplied.] 
        /// 
        public WebProxy(Uri Address, bool BypassOnLocal, string[] BypassList) 
            : this(Address, BypassOnLocal, BypassList, null) {
        }

        ///  
        ///    [To be supplied.]
        ///  
        internal WebProxy(Hashtable proxyHostAddresses, bool BypassOnLocal, string[] BypassList) 
            : this((Uri) null, BypassOnLocal, BypassList, null) {
            _ProxyHostAddresses = proxyHostAddresses; 
            if (_ProxyHostAddresses != null ) {
                _ProxyAddress = (Uri) proxyHostAddresses["http"];
            }
        } 

        ///  
        ///    [To be supplied.] 
        /// 
        public WebProxy(Uri Address, bool BypassOnLocal, string[] BypassList, ICredentials Credentials) { 
            _ProxyAddress = Address;
            _BypassOnLocal = BypassOnLocal;
            if (BypassList != null) {
                _BypassList = new ArrayList(BypassList); 
                UpdateRegExList(true);
            } 
            _Credentials = Credentials; 
            m_EnableAutoproxy = true;
        } 

        /// 
        ///    [To be supplied.]
        ///  
        public WebProxy(string Host, int Port)
            : this(new Uri("http://" + Host + ":" + Port.ToString(CultureInfo.InvariantCulture)), false, null, null) { 
        } 

        ///  
        ///    [To be supplied.]
        /// 
        public WebProxy(string Address)
            : this(CreateProxyUri(Address), false, null, null) { 
        }
 
        ///  
        ///    [To be supplied.]
        ///  
        public WebProxy(string Address, bool BypassOnLocal)
            : this(CreateProxyUri(Address), BypassOnLocal, null, null) {
        }
 
        /// 
        ///    [To be supplied.] 
        ///  
        public WebProxy(string Address, bool BypassOnLocal, string[] BypassList)
            : this(CreateProxyUri(Address), BypassOnLocal, BypassList, null) { 
        }

        /// 
        ///    [To be supplied.] 
        /// 
        public WebProxy(string Address, bool BypassOnLocal, string[] BypassList, ICredentials Credentials) 
            : this(CreateProxyUri(Address), BypassOnLocal, BypassList, Credentials) { 
        }
 
        /// 
        ///    [To be supplied.]
        /// 
        public Uri Address { 
            get {
#if !FEATURE_PAL 
                CheckForChanges(); 
#endif // !FEATURE_PAL
               return _ProxyAddress; 
            }
            set {
                _UseRegistry = false;
                DeleteScriptEngine(); 
               _ProxyHostAddresses = null;  // hash list of proxies <
               _ProxyAddress = value; 
            } 
        }
 
        /// 
        ///    [To be supplied.]
        /// 
        internal bool AutoDetect 
        {
            set { 
                GlobalLog.Assert(_UseRegistry == false, "Cannot set AutoDetect if we are using registry for proxy settings"); 
                GlobalLog.Assert(m_EnableAutoproxy, "WebProxy#{0}::.ctor()|Cannot set AutoDetect if usesystemdefault is set.", ValidationHelper.HashString(this));
 
                if (ScriptEngine == null)
                {
                    ScriptEngine = new AutoWebProxyScriptEngine(this, false);
                } 
                ScriptEngine.AutomaticallyDetectSettings = value;
            } 
        } 

        ///  
        ///    [To be supplied.]
        /// 
        internal Uri ScriptLocation {
            set { 
                GlobalLog.Assert(value != null, "Cannot set ScriptLocation to null");
                GlobalLog.Assert(_UseRegistry == false, "Cannot set AutoDetect if we are using registry for proxy settings"); 
                GlobalLog.Assert(m_EnableAutoproxy, "WebProxy#{0}::.ctor()|Cannot set ScriptLocation if usesystemdefault is set.", ValidationHelper.HashString(this)); 

                if (ScriptEngine == null) 
                {
                    ScriptEngine = new AutoWebProxyScriptEngine(this, false);
                }
                ScriptEngine.AutomaticConfigurationScript = value; 
            }
        } 
 
        /// 
        ///    [To be supplied.] 
        /// 
        public bool BypassProxyOnLocal {
            get {
#if !FEATURE_PAL 
                CheckForChanges();
#endif // !FEATURE_PAL 
                return _BypassOnLocal; 
            }
            set { 
                _UseRegistry = false;
                DeleteScriptEngine();
                _BypassOnLocal = value;
            } 
        }
 
        ///  
        ///    [To be supplied.]
        ///  
        public string[] BypassList {
            get {
#if !FEATURE_PAL
                CheckForChanges(); 
#endif // !FEATURE_PAL
                if (_BypassList == null) { 
                    _BypassList = new ArrayList(); 
                }
                return (string[])_BypassList.ToArray(typeof(string)); 
            }
            set {
                _UseRegistry = false;
                DeleteScriptEngine(); 
                _BypassList = new ArrayList(value);
                UpdateRegExList(true); 
            } 
        }
 
        /// 
        ///    [To be supplied.]
        /// 
        public ICredentials Credentials { 
            get {
                return _Credentials; 
            } 
            set {
                _Credentials = value; 
            }
        }

        ///  
        ///    Sets Credentials to CredentialCache.DefaultCredentials
        ///  
        public bool UseDefaultCredentials  { 
            get {
                return (Credentials is SystemNetworkCredential) ? true : false; 
            }
            set {
                _Credentials = value ? CredentialCache.DefaultCredentials : null;
            } 
        }
 
        ///  
        ///    [To be supplied.]
        ///  
        public ArrayList BypassArrayList {
            get {
#if !FEATURE_PAL
                CheckForChanges(); 
#endif // !FEATURE_PAL
                if ( _BypassList == null ) { 
                    _BypassList = new ArrayList(); 
                }
                return _BypassList; 
            }
        }

        internal void CheckForChanges() { 
            if (ScriptEngine != null)
            { 
                ScriptEngine.CheckForChanges(); 
            }
        } 

        /// 
        ///    [To be supplied.]
        ///  
        public Uri GetProxy(Uri destination) {
            GlobalLog.Print("WebProxy#" + ValidationHelper.HashString(this) + "::GetProxy() destination:" + ValidationHelper.ToString(destination)); 
            if (destination == null) 
            {
                throw new ArgumentNullException("destination"); 
            }

            AutoWebProxyState autoWebProxyState;
            Uri result = GetProxyAuto(destination, out autoWebProxyState); 
            if (autoWebProxyState==AutoWebProxyState.ExecutionSuccess) {
                return result; 
            } 
            if (IsBypassedManual(destination)) {
                return destination; 
            }
            Hashtable proxyHostAddresses = _ProxyHostAddresses;
            Uri proxy = proxyHostAddresses!=null ? proxyHostAddresses[destination.Scheme] as Uri : _ProxyAddress;
            return proxy!=null? proxy : destination; 
        }
 
        // 
        // CreateProxyUri - maps string to Uri
        // 

        private static Uri CreateProxyUri(string address) {
            if (address == null) {
                return null; 
            }
            if (address.IndexOf("://") == -1) { 
                address = "http://" + address; 
            }
            return new Uri(address); 
        }

        //
        // UpdateRegExList - Update internal _RegExBypassList 
        //  warning - can throw if the RegEx doesn't parse??
        // 
        private void UpdateRegExList(bool canThrow) { 
            Regex[] regExBypassList = null;
            ArrayList bypassList = _BypassList; 
            try {
                if ( bypassList != null && bypassList.Count > 0 ) {
                    regExBypassList = new Regex[bypassList.Count];
                    for (int i = 0; i < bypassList.Count; i++ ) { 
                        regExBypassList[i] = new Regex((string)bypassList[i], RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
                    } 
                } 
            }
            catch { 
                if (!canThrow) {
                    _RegExBypassList = null;
                    return;
                } 
                throw;
            } 
            // only update here, cause it could throw earlier in the loop 
            _RegExBypassList = regExBypassList;
        } 

        //
        // IsMatchInBypassList - match input against _RegExBypassList
        // 
        private bool IsMatchInBypassList(Uri input) {
            UpdateRegExList(false); 
            if ( _RegExBypassList == null ) { 
                return false;
            } 
            string matchUriString = input.Scheme + "://" + input.Host + (!input.IsDefaultPort ? (":"+input.Port) : "" );
            for (int i = 0; i < _BypassList.Count; i++ ) {
                if (_RegExBypassList[i].IsMatch(matchUriString)) {
                    return true; 
                }
            } 
            return false; 
        }
 
        /// 
        /// Determines if the host Uri should be routed locally or go through the proxy.
        /// 
        private bool IsLocal(Uri host) { 
            string hostString = host.Host;
 
            // If and only if the host has a colon or is all numbers and dots, it is an IP address. 
            // If no dot, it is local.  (If it has both a dot and a colon, undefined.)
            int dot = -1; 
            bool isIp4 = true;
            bool isIp6 = false;
            for (int i = 0; i < hostString.Length; i++)
            { 
                if (hostString[i] == '.')
                { 
                    if (dot == -1) 
                    {
                        dot = i; 
                        if (!isIp4)
                        {
                            break;
                        } 
                    }
 
                    continue; 
                }
 
                if (hostString[i] == ':')
                {
                    isIp6 = true;
                    isIp4 = false; 
                    break;
                } 
 
                if (hostString[i] < '0' || hostString[i] > '9')
                { 
                    isIp4 = false;
                    if (dot != -1)
                    {
                        break; 
                    }
                } 
            } 

            // No dot?  Local. 
            // The case of all digits is a little weird.  Technically it could be a v4 IP, but practically it can only
            // be interpreted as an intranet name.
            if (dot == -1 && !isIp6)
            { 
                return true;
            } 
 
            if (isIp4 || isIp6)
            { 
                // I don't see why this would fail, but in case it does, it's not an IP.
                try
                {
                    IPAddress hostAddress = IPAddress.Parse(hostString); 
                    if (IPAddress.IsLoopback(hostAddress))
                    { 
                        return true; 
                    }
                    return NclUtilities.IsAddressLocal(hostAddress); 
                }
                catch (FormatException) { }
            }
 
            // If it matches the primary domain, it's local.  (Whether or not the hostname matches.)
            string local = "." + IPGlobalProperties.InternalGetIPGlobalProperties().DomainName; 
            if (local !=  null && local.Length == (hostString.Length - dot) && 
                string.Compare(local, 0, hostString, dot, local.Length, StringComparison.OrdinalIgnoreCase ) == 0) {
                return true; 
            }
            return false;
        }
 
        /// 
        /// Determines if the host Uri should be routed locally or go through a proxy. 
        ///  
        private bool IsLocalInProxyHash(Uri host) {
            Hashtable proxyHostAddresses = _ProxyHostAddresses; 
            if (proxyHostAddresses != null) {
                Uri proxy = (Uri) proxyHostAddresses[host.Scheme];
                if (proxy == null) {
                    return true; // no proxy entry for this scheme, then bypass 
                }
            } 
            return false; 
        }
 

        /// 
        ///    [To be supplied.]
        ///  
        public bool IsBypassed(Uri host) {
            GlobalLog.Print("WebProxy#" + ValidationHelper.HashString(this) + "::IsBypassed() destination:" + ValidationHelper.ToString(host)); 
            if (host == null) 
            {
                throw new ArgumentNullException("host"); 
            }

            AutoWebProxyState autoWebProxyState;
            bool result = IsBypassedAuto(host, out autoWebProxyState); 
            if (autoWebProxyState==AutoWebProxyState.ExecutionSuccess) {
                return result; 
            } 
            return IsBypassedManual(host);
        } 

        private bool IsBypassedManual(Uri host) {
            if (host.IsLoopback) {
                return true; // bypass localhost from using a proxy. 
            }
            return (_ProxyAddress==null && _ProxyHostAddresses==null) || (_BypassOnLocal && IsLocal(host)) || IsMatchInBypassList(host) || IsLocalInProxyHash(host); 
        } 

        ///  
        ///    [To be supplied.]
        /// 
        [Obsolete("This method has been deprecated. Please use the proxy selected for you by default. http://go.microsoft.com/fwlink/?linkid=14202")]
        public static WebProxy GetDefaultProxy() { 
            ExceptionHelper.WebPermissionUnrestricted.Demand();
            return new WebProxy(true); 
        } 

        // 
        // ISerializable constructor
        //
        /// 
        ///    [To be supplied.] 
        /// 
        protected WebProxy(SerializationInfo serializationInfo, StreamingContext streamingContext) { 
            // first check for useRegistry on the serialized proxy 
            bool useRegistry = false;
            try { 
                useRegistry = serializationInfo.GetBoolean("_UseRegistry");
            }
            catch {
            } 
            if (useRegistry) {
                // just make the proxy advanced, don't populate with any settings 
                // note - this will happen in the context of the user performing the deserialization (their proxy settings get read) 
                ExceptionHelper.WebPermissionUnrestricted.Demand();
                UnsafeUpdateFromRegistry(); 
                return;
            }
            // normal proxy
            _ProxyAddress   = (Uri)serializationInfo.GetValue("_ProxyAddress", typeof(Uri)); 
            _BypassOnLocal  = serializationInfo.GetBoolean("_BypassOnLocal");
            _BypassList     = (ArrayList)serializationInfo.GetValue("_BypassList", typeof(ArrayList)); 
            try { 
                UseDefaultCredentials = serializationInfo.GetBoolean("_UseDefaultCredentials");
            } 
            catch {
            }
        }
 
        //
        // ISerializable method 
        // 
        /// 
        ///  
        ///    [To be supplied.]
        /// 
        [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.SerializationFormatter, SerializationFormatter=true)]
        void ISerializable.GetObjectData(SerializationInfo serializationInfo, StreamingContext streamingContext) 
        {
            GetObjectData(serializationInfo, streamingContext); 
        } 

        // 
        // FxCop: provide a way for derived classes to access this method even if they reimplement ISerializable.
        //
        [SecurityPermission(SecurityAction.LinkDemand, SerializationFormatter=true)]
        protected virtual void GetObjectData(SerializationInfo serializationInfo, StreamingContext streamingContext) 
        {
            serializationInfo.AddValue("_BypassOnLocal", _BypassOnLocal); 
            serializationInfo.AddValue("_ProxyAddress", _ProxyAddress); 
            serializationInfo.AddValue("_BypassList", _BypassList);
            serializationInfo.AddValue("_UseDefaultCredentials", UseDefaultCredentials); 
            if (_UseRegistry) {
                serializationInfo.AddValue("_UseRegistry", true);
            }
        } 

 
        ///  
        ///     Handles proxy settings by using Internet Explorer based settings,
        ///     keep in mind the security implications when downloading and running 
        ///     script from any network source configured in Internet Explorer.
        /// 

        private AutoWebProxyScriptEngine m_ScriptEngine; 

        internal AutoWebProxyScriptEngine ScriptEngine { 
            get { 
                return m_ScriptEngine;
            } 
            set {
                m_ScriptEngine = value;
            }
        } 

        // This constructor is used internally to make WebProxies that read their state from the registry. 
        // 
        internal WebProxy(bool enableAutoproxy)
        { 
            m_EnableAutoproxy = enableAutoproxy;
            UnsafeUpdateFromRegistry();
        }
 
        internal void DeleteScriptEngine() {
            if (ScriptEngine != null) { 
                ScriptEngine.Close(); 
                ScriptEngine = null;
            } 
        }

        internal void UnsafeUpdateFromRegistry() {
            GlobalLog.Assert(!_UseRegistry, "WebProxy#{0}::UnsafeUpdateFromRegistry()|_UseRegistry ScriptEngine#{1}", ValidationHelper.HashString(this), ValidationHelper.HashString(m_ScriptEngine)); 
            _UseRegistry = true;
#if !FEATURE_PAL 
            ScriptEngine = new AutoWebProxyScriptEngine(this, true); 
            WebProxyData webProxyData = ProxyRegBlob.GetWebProxyData(ScriptEngine.Connectoid, ScriptEngine.CurrentUserKey);
            Update(webProxyData); 
#endif
        }

        internal void Update(WebProxyData webProxyData) { 
#if TRAVE
            GlobalLog.Print("WebProxy#" + ValidationHelper.HashString(this) + "::Update() Before " + DumpIWebProxy(this)); 
#endif 
            // update needs to happen atomically
            lock (this) { 
                _BypassOnLocal = webProxyData.bypassOnLocal;
                _ProxyAddress = webProxyData.proxyAddress;
                _BypassList = webProxyData.bypassList;
 
                ScriptEngine.AutomaticallyDetectSettings = m_EnableAutoproxy && webProxyData.automaticallyDetectSettings;
                ScriptEngine.AutomaticConfigurationScript = m_EnableAutoproxy ? webProxyData.scriptLocation : null; 
            } 
#if TRAVE
            GlobalLog.Print("WebProxy#" + ValidationHelper.HashString(this) + "::Update() After " + DumpIWebProxy(this)); 
#endif
        }

        ///  
        /// 
        /// We really didn't want to expose this. IWebProxy is kind of broken so we needed 
        /// a different way of calling into IsBypassed/GetProxy with a single method call. 
        /// We need to make it public though, so it is. This API will return null if
        /// the proxy is to be bypassed, otherwise it returns an array of Uri to proxise 
        /// that may be used to access the destination. If an entry in the array is null
        /// we want to try a direct access. Today we only attempt using the first entry.
        /// 
        ///  
        ProxyChain IAutoWebProxy.GetProxies(Uri destination) {
            GlobalLog.Print("WebProxy#" + ValidationHelper.HashString(this) + "::GetProxies() destination:" + ValidationHelper.ToString(destination)); 
            if (destination == null) 
            {
                throw new ArgumentNullException("destination"); 
            }
            return new ProxyScriptChain(this, destination);
        }
 
#if TRAVE
        internal static string DumpIWebProxy(IWebProxy proxy) { 
            StringBuilder stringBuilder = new StringBuilder(); 
            stringBuilder.Append(" Type: " + ValidationHelper.ToString(proxy.GetType()) + "\r\n");
            WebProxy webProxy = proxy as WebProxy; 
            if (webProxy!=null) {
                stringBuilder.Append(" - Address: " + ValidationHelper.ToString(webProxy._ProxyAddress) + "\r\n");
                stringBuilder.Append(" - BypassProxyOnLocal: " + ValidationHelper.ToString(webProxy._BypassOnLocal) + "\r\n");
            } 
            stringBuilder.Append(" - -------------------------------------------------");
            return stringBuilder.ToString(); 
        } 
#endif
 
        //
        // IWebProxy implementation
        //
 
        // Get proxies can never return null in the case of ExecutionSuccess.
        private Uri GetProxyAuto(Uri destination, out AutoWebProxyState autoWebProxyState) { 
            GlobalLog.Print("WebProxy#" + ValidationHelper.HashString(this) + "::GetProxyAuto() destination:" + ValidationHelper.ToString(destination)); 
            if (ScriptEngine == null) {
                autoWebProxyState = AutoWebProxyState.Uninitialized; 
                return null;
            }
            StringCollection proxies = ScriptEngine.GetProxies(destination, true, out autoWebProxyState);
            if (autoWebProxyState!=AutoWebProxyState.ExecutionSuccess) { 
                return null;
            } 
            if (proxies.Count == 0) 
            {
                // Null here means, no proxy available (incl. DIRECT), the request is prohibited. 
                return null;
            }
            if (AreAllBypassed(proxies, true)) {
                // this is the broken behaviour of IWebProxy. Returning the same destination means bypass 
                return destination;
            } 
            return ProxyUri(proxies[0]); 
        }
 
        private bool IsBypassedAuto(Uri destination, out AutoWebProxyState autoWebProxyState) {
            GlobalLog.Print("WebProxy#" + ValidationHelper.HashString(this) + "::IsBypassedAuto() destination:" + ValidationHelper.ToString(destination));
            if (ScriptEngine == null) {
                autoWebProxyState = AutoWebProxyState.Uninitialized; 
                return true;
            } 
            StringCollection proxies = ScriptEngine.GetProxies(destination, true, out autoWebProxyState); 
            if (autoWebProxyState!=AutoWebProxyState.ExecutionSuccess) {
                return true; 
            }
            if (proxies.Count == 0)
            {
                return false; 
            }
            return AreAllBypassed(proxies, true); 
        } 

        internal Uri[] GetProxiesAuto(Uri destination, out AutoWebProxyState autoWebProxyState, ref int syncStatus) 
        {
            GlobalLog.Print("WebProxy#" + ValidationHelper.HashString(this) + "::GetProxiesAuto() destination:" + ValidationHelper.ToString(destination));
            if (ScriptEngine == null) {
                autoWebProxyState = AutoWebProxyState.Uninitialized; 
                return null;
            } 
            StringCollection proxies = ScriptEngine.GetProxies(destination, false, out autoWebProxyState, ref syncStatus); 
            if (autoWebProxyState!=AutoWebProxyState.ExecutionSuccess) {
                return null; 
            }
            if (proxies.Count == 0)
            {
                return new Uri[] { }; 
            }
            if (AreAllBypassed(proxies, false)) 
            { 
                return new Uri[] { null };
            } 
            Uri[] proxyUris = new Uri[proxies.Count];
            for (int i=0; i

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK