Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / whidbey / NetFXspW7 / ndp / fx / src / Net / System / Net / _ProxyRegBlob.cs / 2 / _ProxyRegBlob.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- namespace System.Net { using System; using System.Security.Permissions; using System.Globalization; using System.Text; using System.Text.RegularExpressions; using System.Collections; using System.Collections.Specialized; using System.Net.Sockets; using System.Threading; using System.Runtime.InteropServices; #if USE_WINIET_AUTODETECT_CACHE #if !FEATURE_PAL using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME; #endif // !FEATURE_PAL #endif using Microsoft.Win32; using System.Runtime.Versioning; using System.Diagnostics; internal partial class RegBlobWebProxyDataBuilder : WebProxyDataBuilder { #if !FEATURE_PAL // // Allows us to grob through the registry and read the // IE binary format, note that this should be replaced, // by code that calls Wininet directly, but it can be // expensive to load wininet, in order to do this. // [Flags] private enum ProxyTypeFlags { PROXY_TYPE_DIRECT = 0x00000001, // direct to net PROXY_TYPE_PROXY = 0x00000002, // via named proxy PROXY_TYPE_AUTO_PROXY_URL = 0x00000004, // autoproxy URL PROXY_TYPE_AUTO_DETECT = 0x00000008, // use autoproxy detection } internal const string PolicyKey = @"SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings"; internal const string ProxyKey = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\Connections"; private const string DefaultConnectionSettings = "DefaultConnectionSettings"; private const string ProxySettingsPerUser = "ProxySettingsPerUser"; #if USE_WINIET_AUTODETECT_CACHE // Get the number of MilliSeconds in 7 days and then multiply by 10 because // FILETIME stores data stores time in 100-nanosecond intervals. // internal static UInt64 s_lkgScriptValidTime = (UInt64)(new TimeSpan(7, 0, 0, 0).Ticks); // 7 days #endif const int IE50StrucSize = 60; private byte[] m_RegistryBytes; private int m_ByteOffset; private string m_Connectoid; private SafeRegistryHandle m_Registry; public RegBlobWebProxyDataBuilder(string connectoid, SafeRegistryHandle registry) { Debug.Assert(registry != null); m_Registry = registry; m_Connectoid = connectoid; } // returns true - on successful read of proxy registry settings [RegistryPermission(SecurityAction.Assert, Read=@"HKEY_LOCAL_MACHINE\" + PolicyKey)] [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] private bool ReadRegSettings() { SafeRegistryHandle key = null; RegistryKey lmKey = null; try { bool isPerUser = true; lmKey = Registry.LocalMachine.OpenSubKey(PolicyKey); if (lmKey != null) { object perUser = lmKey.GetValue(ProxySettingsPerUser); if (perUser != null && perUser.GetType() == typeof(int) && 0 == (int) perUser) { isPerUser = false; } } uint errorCode; if (isPerUser) { if (m_Registry != null) { errorCode = m_Registry.RegOpenKeyEx(ProxyKey, 0, UnsafeNclNativeMethods.RegistryHelper.KEY_READ, out key); } else { errorCode = UnsafeNclNativeMethods.ErrorCodes.ERROR_NOT_FOUND; } } else { errorCode = SafeRegistryHandle.RegOpenKeyEx(UnsafeNclNativeMethods.RegistryHelper.HKEY_LOCAL_MACHINE, ProxyKey, 0, UnsafeNclNativeMethods.RegistryHelper.KEY_READ, out key); } if (errorCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS) { key = null; } if (key != null) { // When reading settings from the registry, if connectoid key is missing, the connectoid // was never configured. In this case we have no settings (this is equivalent to always go direct). object data; errorCode = key.QueryValue(m_Connectoid != null ? m_Connectoid : DefaultConnectionSettings, out data); if (errorCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS) { m_RegistryBytes = (byte[]) data; } } } catch (Exception exception) { if (NclUtilities.IsFatal(exception)) throw; } finally { if (lmKey != null) lmKey.Close(); if(key != null) key.RegCloseKey(); } return m_RegistryBytes != null; } #if USE_WINIET_AUTODETECT_CACHE public FILETIME ReadFileTime() { FILETIME ft = new FILETIME(); ft.dwLowDateTime = ReadInt32(); ft.dwHighDateTime = ReadInt32(); return ft; } #endif // // Reads a string from the byte buffer, cached // inside this object, and then updates the // offset, NOTE: Must be in the correct offset // before reading, or will error // public string ReadString() { string stringOut = null; int stringSize = ReadInt32(); if (stringSize>0) { // prevent reading too much int actualSize = m_RegistryBytes.Length - m_ByteOffset; if (stringSize >= actualSize) { stringSize = actualSize; } stringOut = Encoding.UTF8.GetString(m_RegistryBytes, m_ByteOffset, stringSize); m_ByteOffset += stringSize; } return stringOut; } // // Reads a DWORD into a Int32, used to read // a int from the byte buffer. // internal unsafe int ReadInt32() { int intValue = 0; int actualSize = m_RegistryBytes.Length - m_ByteOffset; // copy bytes and increment offset if (actualSize>=sizeof(int)) { fixed (byte* pBuffer = m_RegistryBytes) { if (sizeof(IntPtr)==4) { intValue = *((int*)(pBuffer + m_ByteOffset)); } else { intValue = Marshal.ReadInt32((IntPtr)pBuffer, m_ByteOffset); } } m_ByteOffset += sizeof(int); } // tell caller what we actually read return intValue; } #else // !FEATURE_PAL private static string ReadConfigString(string ConfigName) { const int parameterValueLength = 255; StringBuilder parameterValue = new StringBuilder(parameterValueLength); bool rc = UnsafeNclNativeMethods.FetchConfigurationString(true, ConfigName, parameterValue, parameterValueLength); if (rc) { return parameterValue.ToString(); } return ""; } #endif // !FEATURE_PAL } internal abstract class WebProxyDataBuilder { private static readonly char[] s_AddressListSplitChars = new char[] { ';', '=' }; private static readonly char[] s_BypassListDelimiter = new char[] { ';' }; private WebProxyData m_Result; public WebProxyData Build() { m_Result = new WebProxyData(); BuildInternal(); return m_Result; } protected abstract void BuildInternal(); protected void SetProxyAndBypassList(string addressString, string bypassListString) { Uri actualAddress = null; Hashtable proxyHashTable = null; if (addressString != null) { actualAddress = ParseProxyUri(addressString, true); if (actualAddress == null) { proxyHashTable = ParseProtocolProxies(addressString); } if ((actualAddress != null || proxyHashTable != null) && bypassListString != null) { bool bypassOnLocal = false; m_Result.bypassList = ParseBypassList(bypassListString, out bypassOnLocal); m_Result.bypassOnLocal = bypassOnLocal; } } if (proxyHashTable != null) { Debug.Assert(actualAddress == null); actualAddress = proxyHashTable["http"] as Uri; } m_Result.proxyAddress = actualAddress; } protected void SetAutoProxyUrl(string autoConfigUrl) { if (!string.IsNullOrEmpty(autoConfigUrl)) { Uri scriptLocation = null; if (Uri.TryCreate(autoConfigUrl, UriKind.Absolute, out scriptLocation)) { m_Result.scriptLocation = scriptLocation; } } } protected void SetAutoDetectSettings(bool value) { m_Result.automaticallyDetectSettings = value; } // // Parses out a string from IE and turns it into a URI // private static Uri ParseProxyUri(string proxyString, bool validate) { Debug.Assert(proxyString != null); if (validate) { if (proxyString.Length == 0) { return null; } if (proxyString.IndexOf('=') != -1) { return null; } } if (proxyString.IndexOf("://") == -1) { proxyString = "http://" + proxyString; } try { return new Uri(proxyString); } catch (UriFormatException e) { if (Logging.On) Logging.PrintError(Logging.Web, e.Message); } return null; // we weren't able to get an Uri instance out of proxyString } // // Builds a hashtable containing the protocol and proxy URI to use for it. // private static Hashtable ParseProtocolProxies(string proxyListString) { Debug.Assert(proxyListString != null); if (proxyListString.Length == 0) { return null; } // parse something like "http=http://http-proxy;https=http://https-proxy;ftp=http://ftp-proxy" string[] proxyListStrings = proxyListString.Split(s_AddressListSplitChars); bool protocolPass = true; string protocolString = null; Hashtable proxyListHashTable = new Hashtable(CaseInsensitiveAscii.StaticInstance); foreach (string elementString in proxyListStrings) { string lowerElementString = elementString.Trim().ToLower(CultureInfo.InvariantCulture); if (protocolPass) { protocolString = lowerElementString; } else { proxyListHashTable[protocolString] = ParseProxyUri(lowerElementString, false); } protocolPass = !protocolPass; } if (proxyListHashTable.Count == 0) { return null; } return proxyListHashTable; } // // Converts a simple IE regular expresion string into one // that is compatible with Regex escape sequences. // private static string BypassStringEscape(string rawString) { Debug.Assert(rawString != null); // Break up raw string into scheme, host, port. // This regular expression is used to get the three components. // Scheme and port are optional. // If Match fails just assume whole string is the host. Regex parser = new Regex("^(?.*://)?(? [^:]*)(? :[0-9]{1,5})?$", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); Match results = parser.Match(rawString); string scheme, host, port; if (results.Success) { scheme = results.Groups["scheme"].Value; host = results.Groups["host"].Value; port = results.Groups["port"].Value; } else { // Match method failed - set host to whole bypass string scheme = string.Empty; host = rawString; port = string.Empty; } // Escape any regex reserved chars before constructing final regex. scheme = ConvertRegexReservedChars(scheme); host = ConvertRegexReservedChars(host); port = ConvertRegexReservedChars(port); // If scheme or port not specified use regular // expression "wildcards" for them. if (scheme == string.Empty) { // match any leading scheme plus separator // but don't require it scheme = "(?:.*://)?"; } if (port == string.Empty) { // match a port but don't require it port = "(?::[0-9]{1,5})?"; } // Construct and return final regular expression // with start-of-line and end-of-line anchors. return "^" + scheme + host + port + "$"; } private const string regexReserved = "#$()+.?[\\^{|"; private static string ConvertRegexReservedChars(string rawString) { Debug.Assert(rawString != null); // Regular expressions reserve // (1) "#$()+.?[\^{|" as special chars. // (2) "*" as a special char. // (3) whitespace as a special char. // Convert any char "c" in above list to "\c". // Convert reserved char "*" to ".*". // Leave whitespace as-is. if (rawString.Length == 0) return rawString; StringBuilder builder = new StringBuilder(); foreach (char c in rawString) { if (regexReserved.IndexOf(c) != -1) { builder.Append('\\'); } else if (c == '*') { builder.Append('.'); } builder.Append(c); } return builder.ToString(); } // // Parses out a string of bypass list entries and coverts it to Regex's that can be used // to match against. // private static ArrayList ParseBypassList(string bypassListString, out bool bypassOnLocal) { string[] bypassListStrings = bypassListString.Split(s_BypassListDelimiter); bypassOnLocal = false; if (bypassListStrings.Length == 0) { return null; } ArrayList bypassList = null; foreach (string bypassString in bypassListStrings) { if (bypassString!=null) { string trimmedBypassString = bypassString.Trim(); if (trimmedBypassString.Length>0) { if (string.Compare(trimmedBypassString, " ", StringComparison.OrdinalIgnoreCase)==0) { bypassOnLocal = true; } else { trimmedBypassString = BypassStringEscape(trimmedBypassString); if (bypassList==null) { bypassList = new ArrayList(); } GlobalLog.Print("WebProxyDataBuilder::ParseBypassList() bypassList.Count:" + bypassList.Count + " adding:" + ValidationHelper.ToString(trimmedBypassString)); if (!bypassList.Contains(trimmedBypassString)) { bypassList.Add(trimmedBypassString); GlobalLog.Print("WebProxyDataBuilder::ParseBypassList() bypassList.Count:" + bypassList.Count + " added:" + ValidationHelper.ToString(trimmedBypassString)); } } } } } return bypassList; } } internal partial class RegBlobWebProxyDataBuilder { // // Updates an instance of WbeProxy with the proxy settings from IE for: // the current user and a given connectoid. // [ResourceExposure(ResourceScope.Machine)] // Check scoping on this SafeRegistryHandle [ResourceConsumption(ResourceScope.Machine)] protected override void BuildInternal() { GlobalLog.Enter("RegBlobWebProxyDataBuilder#" + ValidationHelper.HashString(this) + "::BuildInternal() m_Connectoid:" + ValidationHelper.ToString(m_Connectoid)); // DON'T TOUCH THE ORDERING OF THE CALLS TO THE INSTANCE OF ProxyRegBlob bool success = ReadRegSettings(); if (success) { success = ReadInt32() >= IE50StrucSize; } if (!success) { // if registry access fails rely on automatic detection SetAutoDetectSettings(true); return; } // read the rest of the items out ReadInt32(); // incremental version# of current settings (ignored) ProxyTypeFlags proxyFlags = (ProxyTypeFlags)ReadInt32(); // flags GlobalLog.Print("RegBlobWebProxyDataBuilder::BuildInternal() proxyFlags:" + ValidationHelper.ToString(proxyFlags)); string addressString = ReadString(); // proxy name string proxyBypassString = ReadString(); // proxy bypass GlobalLog.Print("RegBlobWebProxyDataBuilder::BuildInternal() proxyAddressString:" + ValidationHelper.ToString(addressString) + " proxyBypassString:" + ValidationHelper.ToString(proxyBypassString)); // // Once we verify that the flag for proxy is enabled, // Parse UriString that is stored, may be in the form, // of "http=http://http-proxy;ftp="ftp=http://..." must // handle this case along with just a URI. // if ((proxyFlags & ProxyTypeFlags.PROXY_TYPE_PROXY) != 0) { SetProxyAndBypassList(addressString, proxyBypassString); } #if !FEATURE_PAL SetAutoDetectSettings((proxyFlags & ProxyTypeFlags.PROXY_TYPE_AUTO_DETECT) != 0); string autoConfigUrlString = ReadString(); // autoconfig url GlobalLog.Print("RegBlobWebProxyDataBuilder::BuildInternal() scriptLocation:" + ValidationHelper.ToString(addressString)); if ((proxyFlags & ProxyTypeFlags.PROXY_TYPE_AUTO_PROXY_URL) != 0) { SetAutoProxyUrl(autoConfigUrlString); } // The final straw against attempting to use the WinInet LKG script location was, it's invalid when IPs have changed even if the // connectoid hadn't. Doing that validation didn't seem worth it (error-prone, expensive, unsupported). #if USE_WINIET_AUTODETECT_CACHE proxyIE5Settings.ReadInt32(); // autodetect flags (ignored) // reuse addressString for lkgScriptLocationString addressString = proxyIE5Settings.ReadString(); // last known good auto-proxy url // read ftLastKnownDetectTime FILETIME ftLastKnownDetectTime = proxyIE5Settings.ReadFileTime(); // Verify if this lkgScriptLocationString has timed out // if (IsValidTimeForLkgScriptLocation(ftLastKnownDetectTime)) { // reuse address for lkgScriptLocation GlobalLog.Print("RegBlobWebProxyDataBuilder::BuildInternal() lkgScriptLocation:" + ValidationHelper.ToString(addressString)); if (Uri.TryCreate(addressString, UriKind.Absolute, out address)) { webProxyData.lkgScriptLocation = address; } } else { #if TRAVE SYSTEMTIME st = new SYSTEMTIME(); bool f = SafeNclNativeMethods.FileTimeToSystemTime(ref ftLastKnownDetectTime, ref st); if (f) GlobalLog.Print("RegBlobWebProxyDataBuilder::BuildInternal() ftLastKnownDetectTime:" + ValidationHelper.ToString(st)); #endif // TRAVE GlobalLog.Print("RegBlobWebProxyDataBuilder::BuildInternal() Ignoring Timed out lkgScriptLocation:" + ValidationHelper.ToString(addressString)); // Now rely on automatic detection settings set above // based on the proxy flags (webProxyData.automaticallyDetectSettings). // } #endif /* // This is some of the rest of the proxy reg key blob parsing. // // Read Inte---- IPs int iftCount = proxyIE5Settings.ReadInt32(); for (int ift = 0; ift < iftCount; ++ift) { proxyIE5Settings.ReadInt32(); } // Read lpszAutoconfigSecondaryUrl string autoconfigSecondaryUrl = proxyIE5Settings.ReadString(); // Read dwAutoconfigReloadDelayMins int autoconfigReloadDelayMins = proxyIE5Settings.ReadInt32(); */ #endif GlobalLog.Leave("RegBlobWebProxyDataBuilder#" + ValidationHelper.HashString(this) + "::BuildInternal()"); } #if USE_WINIET_AUTODETECT_CACHE #if !FEATURE_PAL internal unsafe static bool IsValidTimeForLkgScriptLocation(FILETIME ftLastKnownDetectTime) { // Get Current System Time. FILETIME ftCurrentTime = new FILETIME(); SafeNclNativeMethods.GetSystemTimeAsFileTime(ref ftCurrentTime); UInt64 ftDetect = (UInt64)ftLastKnownDetectTime.dwHighDateTime; ftDetect <<= (sizeof(int) * 8); ftDetect |= (UInt64)(uint)ftLastKnownDetectTime.dwLowDateTime; UInt64 ftCurrent = (UInt64)ftCurrentTime.dwHighDateTime; ftCurrent <<= (sizeof(int) * 8); ftCurrent |= (UInt64)(uint)ftCurrentTime.dwLowDateTime; GlobalLog.Print("RegBlobWebProxyDataBuilder::BuildInternal() Detect Time:" + ValidationHelper.ToString(ftDetect)); GlobalLog.Print("RegBlobWebProxyDataBuilder::BuildInternal() Current Time:" + ValidationHelper.ToString(ftCurrent)); GlobalLog.Print("RegBlobWebProxyDataBuilder::BuildInternal() 7 days:" + ValidationHelper.ToString(s_lkgScriptValidTime)); GlobalLog.Print("RegBlobWebProxyDataBuilder::BuildInternal() Delta Time:" + ValidationHelper.ToString((UInt64)(ftCurrent - ftDetect))); return (ftCurrent - ftDetect) < s_lkgScriptValidTime; } #endif // !FEATURE_PAL #endif } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //------------------------------------------------------------------------------ // // Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- namespace System.Net { using System; using System.Security.Permissions; using System.Globalization; using System.Text; using System.Text.RegularExpressions; using System.Collections; using System.Collections.Specialized; using System.Net.Sockets; using System.Threading; using System.Runtime.InteropServices; #if USE_WINIET_AUTODETECT_CACHE #if !FEATURE_PAL using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME; #endif // !FEATURE_PAL #endif using Microsoft.Win32; using System.Runtime.Versioning; using System.Diagnostics; internal partial class RegBlobWebProxyDataBuilder : WebProxyDataBuilder { #if !FEATURE_PAL // // Allows us to grob through the registry and read the // IE binary format, note that this should be replaced, // by code that calls Wininet directly, but it can be // expensive to load wininet, in order to do this. // [Flags] private enum ProxyTypeFlags { PROXY_TYPE_DIRECT = 0x00000001, // direct to net PROXY_TYPE_PROXY = 0x00000002, // via named proxy PROXY_TYPE_AUTO_PROXY_URL = 0x00000004, // autoproxy URL PROXY_TYPE_AUTO_DETECT = 0x00000008, // use autoproxy detection } internal const string PolicyKey = @"SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings"; internal const string ProxyKey = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\Connections"; private const string DefaultConnectionSettings = "DefaultConnectionSettings"; private const string ProxySettingsPerUser = "ProxySettingsPerUser"; #if USE_WINIET_AUTODETECT_CACHE // Get the number of MilliSeconds in 7 days and then multiply by 10 because // FILETIME stores data stores time in 100-nanosecond intervals. // internal static UInt64 s_lkgScriptValidTime = (UInt64)(new TimeSpan(7, 0, 0, 0).Ticks); // 7 days #endif const int IE50StrucSize = 60; private byte[] m_RegistryBytes; private int m_ByteOffset; private string m_Connectoid; private SafeRegistryHandle m_Registry; public RegBlobWebProxyDataBuilder(string connectoid, SafeRegistryHandle registry) { Debug.Assert(registry != null); m_Registry = registry; m_Connectoid = connectoid; } // returns true - on successful read of proxy registry settings [RegistryPermission(SecurityAction.Assert, Read=@"HKEY_LOCAL_MACHINE\" + PolicyKey)] [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] private bool ReadRegSettings() { SafeRegistryHandle key = null; RegistryKey lmKey = null; try { bool isPerUser = true; lmKey = Registry.LocalMachine.OpenSubKey(PolicyKey); if (lmKey != null) { object perUser = lmKey.GetValue(ProxySettingsPerUser); if (perUser != null && perUser.GetType() == typeof(int) && 0 == (int) perUser) { isPerUser = false; } } uint errorCode; if (isPerUser) { if (m_Registry != null) { errorCode = m_Registry.RegOpenKeyEx(ProxyKey, 0, UnsafeNclNativeMethods.RegistryHelper.KEY_READ, out key); } else { errorCode = UnsafeNclNativeMethods.ErrorCodes.ERROR_NOT_FOUND; } } else { errorCode = SafeRegistryHandle.RegOpenKeyEx(UnsafeNclNativeMethods.RegistryHelper.HKEY_LOCAL_MACHINE, ProxyKey, 0, UnsafeNclNativeMethods.RegistryHelper.KEY_READ, out key); } if (errorCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS) { key = null; } if (key != null) { // When reading settings from the registry, if connectoid key is missing, the connectoid // was never configured. In this case we have no settings (this is equivalent to always go direct). object data; errorCode = key.QueryValue(m_Connectoid != null ? m_Connectoid : DefaultConnectionSettings, out data); if (errorCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS) { m_RegistryBytes = (byte[]) data; } } } catch (Exception exception) { if (NclUtilities.IsFatal(exception)) throw; } finally { if (lmKey != null) lmKey.Close(); if(key != null) key.RegCloseKey(); } return m_RegistryBytes != null; } #if USE_WINIET_AUTODETECT_CACHE public FILETIME ReadFileTime() { FILETIME ft = new FILETIME(); ft.dwLowDateTime = ReadInt32(); ft.dwHighDateTime = ReadInt32(); return ft; } #endif // // Reads a string from the byte buffer, cached // inside this object, and then updates the // offset, NOTE: Must be in the correct offset // before reading, or will error // public string ReadString() { string stringOut = null; int stringSize = ReadInt32(); if (stringSize>0) { // prevent reading too much int actualSize = m_RegistryBytes.Length - m_ByteOffset; if (stringSize >= actualSize) { stringSize = actualSize; } stringOut = Encoding.UTF8.GetString(m_RegistryBytes, m_ByteOffset, stringSize); m_ByteOffset += stringSize; } return stringOut; } // // Reads a DWORD into a Int32, used to read // a int from the byte buffer. // internal unsafe int ReadInt32() { int intValue = 0; int actualSize = m_RegistryBytes.Length - m_ByteOffset; // copy bytes and increment offset if (actualSize>=sizeof(int)) { fixed (byte* pBuffer = m_RegistryBytes) { if (sizeof(IntPtr)==4) { intValue = *((int*)(pBuffer + m_ByteOffset)); } else { intValue = Marshal.ReadInt32((IntPtr)pBuffer, m_ByteOffset); } } m_ByteOffset += sizeof(int); } // tell caller what we actually read return intValue; } #else // !FEATURE_PAL private static string ReadConfigString(string ConfigName) { const int parameterValueLength = 255; StringBuilder parameterValue = new StringBuilder(parameterValueLength); bool rc = UnsafeNclNativeMethods.FetchConfigurationString(true, ConfigName, parameterValue, parameterValueLength); if (rc) { return parameterValue.ToString(); } return ""; } #endif // !FEATURE_PAL } internal abstract class WebProxyDataBuilder { private static readonly char[] s_AddressListSplitChars = new char[] { ';', '=' }; private static readonly char[] s_BypassListDelimiter = new char[] { ';' }; private WebProxyData m_Result; public WebProxyData Build() { m_Result = new WebProxyData(); BuildInternal(); return m_Result; } protected abstract void BuildInternal(); protected void SetProxyAndBypassList(string addressString, string bypassListString) { Uri actualAddress = null; Hashtable proxyHashTable = null; if (addressString != null) { actualAddress = ParseProxyUri(addressString, true); if (actualAddress == null) { proxyHashTable = ParseProtocolProxies(addressString); } if ((actualAddress != null || proxyHashTable != null) && bypassListString != null) { bool bypassOnLocal = false; m_Result.bypassList = ParseBypassList(bypassListString, out bypassOnLocal); m_Result.bypassOnLocal = bypassOnLocal; } } if (proxyHashTable != null) { Debug.Assert(actualAddress == null); actualAddress = proxyHashTable["http"] as Uri; } m_Result.proxyAddress = actualAddress; } protected void SetAutoProxyUrl(string autoConfigUrl) { if (!string.IsNullOrEmpty(autoConfigUrl)) { Uri scriptLocation = null; if (Uri.TryCreate(autoConfigUrl, UriKind.Absolute, out scriptLocation)) { m_Result.scriptLocation = scriptLocation; } } } protected void SetAutoDetectSettings(bool value) { m_Result.automaticallyDetectSettings = value; } // // Parses out a string from IE and turns it into a URI // private static Uri ParseProxyUri(string proxyString, bool validate) { Debug.Assert(proxyString != null); if (validate) { if (proxyString.Length == 0) { return null; } if (proxyString.IndexOf('=') != -1) { return null; } } if (proxyString.IndexOf("://") == -1) { proxyString = "http://" + proxyString; } try { return new Uri(proxyString); } catch (UriFormatException e) { if (Logging.On) Logging.PrintError(Logging.Web, e.Message); } return null; // we weren't able to get an Uri instance out of proxyString } // // Builds a hashtable containing the protocol and proxy URI to use for it. // private static Hashtable ParseProtocolProxies(string proxyListString) { Debug.Assert(proxyListString != null); if (proxyListString.Length == 0) { return null; } // parse something like "http=http://http-proxy;https=http://https-proxy;ftp=http://ftp-proxy" string[] proxyListStrings = proxyListString.Split(s_AddressListSplitChars); bool protocolPass = true; string protocolString = null; Hashtable proxyListHashTable = new Hashtable(CaseInsensitiveAscii.StaticInstance); foreach (string elementString in proxyListStrings) { string lowerElementString = elementString.Trim().ToLower(CultureInfo.InvariantCulture); if (protocolPass) { protocolString = lowerElementString; } else { proxyListHashTable[protocolString] = ParseProxyUri(lowerElementString, false); } protocolPass = !protocolPass; } if (proxyListHashTable.Count == 0) { return null; } return proxyListHashTable; } // // Converts a simple IE regular expresion string into one // that is compatible with Regex escape sequences. // private static string BypassStringEscape(string rawString) { Debug.Assert(rawString != null); // Break up raw string into scheme, host, port. // This regular expression is used to get the three components. // Scheme and port are optional. // If Match fails just assume whole string is the host. Regex parser = new Regex("^(?.*://)?(? [^:]*)(? :[0-9]{1,5})?$", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); Match results = parser.Match(rawString); string scheme, host, port; if (results.Success) { scheme = results.Groups["scheme"].Value; host = results.Groups["host"].Value; port = results.Groups["port"].Value; } else { // Match method failed - set host to whole bypass string scheme = string.Empty; host = rawString; port = string.Empty; } // Escape any regex reserved chars before constructing final regex. scheme = ConvertRegexReservedChars(scheme); host = ConvertRegexReservedChars(host); port = ConvertRegexReservedChars(port); // If scheme or port not specified use regular // expression "wildcards" for them. if (scheme == string.Empty) { // match any leading scheme plus separator // but don't require it scheme = "(?:.*://)?"; } if (port == string.Empty) { // match a port but don't require it port = "(?::[0-9]{1,5})?"; } // Construct and return final regular expression // with start-of-line and end-of-line anchors. return "^" + scheme + host + port + "$"; } private const string regexReserved = "#$()+.?[\\^{|"; private static string ConvertRegexReservedChars(string rawString) { Debug.Assert(rawString != null); // Regular expressions reserve // (1) "#$()+.?[\^{|" as special chars. // (2) "*" as a special char. // (3) whitespace as a special char. // Convert any char "c" in above list to "\c". // Convert reserved char "*" to ".*". // Leave whitespace as-is. if (rawString.Length == 0) return rawString; StringBuilder builder = new StringBuilder(); foreach (char c in rawString) { if (regexReserved.IndexOf(c) != -1) { builder.Append('\\'); } else if (c == '*') { builder.Append('.'); } builder.Append(c); } return builder.ToString(); } // // Parses out a string of bypass list entries and coverts it to Regex's that can be used // to match against. // private static ArrayList ParseBypassList(string bypassListString, out bool bypassOnLocal) { string[] bypassListStrings = bypassListString.Split(s_BypassListDelimiter); bypassOnLocal = false; if (bypassListStrings.Length == 0) { return null; } ArrayList bypassList = null; foreach (string bypassString in bypassListStrings) { if (bypassString!=null) { string trimmedBypassString = bypassString.Trim(); if (trimmedBypassString.Length>0) { if (string.Compare(trimmedBypassString, " ", StringComparison.OrdinalIgnoreCase)==0) { bypassOnLocal = true; } else { trimmedBypassString = BypassStringEscape(trimmedBypassString); if (bypassList==null) { bypassList = new ArrayList(); } GlobalLog.Print("WebProxyDataBuilder::ParseBypassList() bypassList.Count:" + bypassList.Count + " adding:" + ValidationHelper.ToString(trimmedBypassString)); if (!bypassList.Contains(trimmedBypassString)) { bypassList.Add(trimmedBypassString); GlobalLog.Print("WebProxyDataBuilder::ParseBypassList() bypassList.Count:" + bypassList.Count + " added:" + ValidationHelper.ToString(trimmedBypassString)); } } } } } return bypassList; } } internal partial class RegBlobWebProxyDataBuilder { // // Updates an instance of WbeProxy with the proxy settings from IE for: // the current user and a given connectoid. // [ResourceExposure(ResourceScope.Machine)] // Check scoping on this SafeRegistryHandle [ResourceConsumption(ResourceScope.Machine)] protected override void BuildInternal() { GlobalLog.Enter("RegBlobWebProxyDataBuilder#" + ValidationHelper.HashString(this) + "::BuildInternal() m_Connectoid:" + ValidationHelper.ToString(m_Connectoid)); // DON'T TOUCH THE ORDERING OF THE CALLS TO THE INSTANCE OF ProxyRegBlob bool success = ReadRegSettings(); if (success) { success = ReadInt32() >= IE50StrucSize; } if (!success) { // if registry access fails rely on automatic detection SetAutoDetectSettings(true); return; } // read the rest of the items out ReadInt32(); // incremental version# of current settings (ignored) ProxyTypeFlags proxyFlags = (ProxyTypeFlags)ReadInt32(); // flags GlobalLog.Print("RegBlobWebProxyDataBuilder::BuildInternal() proxyFlags:" + ValidationHelper.ToString(proxyFlags)); string addressString = ReadString(); // proxy name string proxyBypassString = ReadString(); // proxy bypass GlobalLog.Print("RegBlobWebProxyDataBuilder::BuildInternal() proxyAddressString:" + ValidationHelper.ToString(addressString) + " proxyBypassString:" + ValidationHelper.ToString(proxyBypassString)); // // Once we verify that the flag for proxy is enabled, // Parse UriString that is stored, may be in the form, // of "http=http://http-proxy;ftp="ftp=http://..." must // handle this case along with just a URI. // if ((proxyFlags & ProxyTypeFlags.PROXY_TYPE_PROXY) != 0) { SetProxyAndBypassList(addressString, proxyBypassString); } #if !FEATURE_PAL SetAutoDetectSettings((proxyFlags & ProxyTypeFlags.PROXY_TYPE_AUTO_DETECT) != 0); string autoConfigUrlString = ReadString(); // autoconfig url GlobalLog.Print("RegBlobWebProxyDataBuilder::BuildInternal() scriptLocation:" + ValidationHelper.ToString(addressString)); if ((proxyFlags & ProxyTypeFlags.PROXY_TYPE_AUTO_PROXY_URL) != 0) { SetAutoProxyUrl(autoConfigUrlString); } // The final straw against attempting to use the WinInet LKG script location was, it's invalid when IPs have changed even if the // connectoid hadn't. Doing that validation didn't seem worth it (error-prone, expensive, unsupported). #if USE_WINIET_AUTODETECT_CACHE proxyIE5Settings.ReadInt32(); // autodetect flags (ignored) // reuse addressString for lkgScriptLocationString addressString = proxyIE5Settings.ReadString(); // last known good auto-proxy url // read ftLastKnownDetectTime FILETIME ftLastKnownDetectTime = proxyIE5Settings.ReadFileTime(); // Verify if this lkgScriptLocationString has timed out // if (IsValidTimeForLkgScriptLocation(ftLastKnownDetectTime)) { // reuse address for lkgScriptLocation GlobalLog.Print("RegBlobWebProxyDataBuilder::BuildInternal() lkgScriptLocation:" + ValidationHelper.ToString(addressString)); if (Uri.TryCreate(addressString, UriKind.Absolute, out address)) { webProxyData.lkgScriptLocation = address; } } else { #if TRAVE SYSTEMTIME st = new SYSTEMTIME(); bool f = SafeNclNativeMethods.FileTimeToSystemTime(ref ftLastKnownDetectTime, ref st); if (f) GlobalLog.Print("RegBlobWebProxyDataBuilder::BuildInternal() ftLastKnownDetectTime:" + ValidationHelper.ToString(st)); #endif // TRAVE GlobalLog.Print("RegBlobWebProxyDataBuilder::BuildInternal() Ignoring Timed out lkgScriptLocation:" + ValidationHelper.ToString(addressString)); // Now rely on automatic detection settings set above // based on the proxy flags (webProxyData.automaticallyDetectSettings). // } #endif /* // This is some of the rest of the proxy reg key blob parsing. // // Read Inte---- IPs int iftCount = proxyIE5Settings.ReadInt32(); for (int ift = 0; ift < iftCount; ++ift) { proxyIE5Settings.ReadInt32(); } // Read lpszAutoconfigSecondaryUrl string autoconfigSecondaryUrl = proxyIE5Settings.ReadString(); // Read dwAutoconfigReloadDelayMins int autoconfigReloadDelayMins = proxyIE5Settings.ReadInt32(); */ #endif GlobalLog.Leave("RegBlobWebProxyDataBuilder#" + ValidationHelper.HashString(this) + "::BuildInternal()"); } #if USE_WINIET_AUTODETECT_CACHE #if !FEATURE_PAL internal unsafe static bool IsValidTimeForLkgScriptLocation(FILETIME ftLastKnownDetectTime) { // Get Current System Time. FILETIME ftCurrentTime = new FILETIME(); SafeNclNativeMethods.GetSystemTimeAsFileTime(ref ftCurrentTime); UInt64 ftDetect = (UInt64)ftLastKnownDetectTime.dwHighDateTime; ftDetect <<= (sizeof(int) * 8); ftDetect |= (UInt64)(uint)ftLastKnownDetectTime.dwLowDateTime; UInt64 ftCurrent = (UInt64)ftCurrentTime.dwHighDateTime; ftCurrent <<= (sizeof(int) * 8); ftCurrent |= (UInt64)(uint)ftCurrentTime.dwLowDateTime; GlobalLog.Print("RegBlobWebProxyDataBuilder::BuildInternal() Detect Time:" + ValidationHelper.ToString(ftDetect)); GlobalLog.Print("RegBlobWebProxyDataBuilder::BuildInternal() Current Time:" + ValidationHelper.ToString(ftCurrent)); GlobalLog.Print("RegBlobWebProxyDataBuilder::BuildInternal() 7 days:" + ValidationHelper.ToString(s_lkgScriptValidTime)); GlobalLog.Print("RegBlobWebProxyDataBuilder::BuildInternal() Delta Time:" + ValidationHelper.ToString((UInt64)(ftCurrent - ftDetect))); return (ftCurrent - ftDetect) < s_lkgScriptValidTime; } #endif // !FEATURE_PAL #endif } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- precedingsibling.cs
- IndentTextWriter.cs
- DataGridViewRowHeaderCell.cs
- TypeProvider.cs
- ImageCodecInfo.cs
- BitmapEffectInput.cs
- WebControlsSection.cs
- XmlNamespaceDeclarationsAttribute.cs
- DayRenderEvent.cs
- TypeConverterMarkupExtension.cs
- NopReturnReader.cs
- BasicViewGenerator.cs
- XslException.cs
- ToolStripRenderEventArgs.cs
- VirtualizedItemProviderWrapper.cs
- HealthMonitoringSectionHelper.cs
- ConstantCheck.cs
- CodeExpressionCollection.cs
- ModelPerspective.cs
- KeyboardDevice.cs
- DocumentSequence.cs
- ByteKeyFrameCollection.cs
- IDispatchConstantAttribute.cs
- ExtractorMetadata.cs
- TypedAsyncResult.cs
- WebConfigurationFileMap.cs
- DataControlImageButton.cs
- FileClassifier.cs
- ExpressionLink.cs
- IncrementalHitTester.cs
- DocumentPageTextView.cs
- TextRunTypographyProperties.cs
- ClonableStack.cs
- BooleanFacetDescriptionElement.cs
- WindowsFormsSectionHandler.cs
- ChannelFactoryBase.cs
- CompiledQuery.cs
- UnsafeNativeMethods.cs
- AttachedPropertiesService.cs
- PermissionAttributes.cs
- WebPartUtil.cs
- DateTimeFormatInfoScanner.cs
- AnnotationDocumentPaginator.cs
- DependencyPropertyAttribute.cs
- CodeFieldReferenceExpression.cs
- LeaseManager.cs
- CssClassPropertyAttribute.cs
- WebPartConnectionsDisconnectVerb.cs
- DynamicQueryableWrapper.cs
- MissingManifestResourceException.cs
- SQLSingleStorage.cs
- DateTimePicker.cs
- PreviewKeyDownEventArgs.cs
- FixedFindEngine.cs
- AllMembershipCondition.cs
- ComponentEvent.cs
- InputScopeAttribute.cs
- ReferenceSchema.cs
- CalloutQueueItem.cs
- SQLSingle.cs
- PolygonHotSpot.cs
- DropTarget.cs
- InternalMappingException.cs
- XsdBuilder.cs
- ReadOnlyObservableCollection.cs
- IsolatedStorageFileStream.cs
- Bezier.cs
- FileStream.cs
- OrthographicCamera.cs
- AdCreatedEventArgs.cs
- ExplicitDiscriminatorMap.cs
- TypeValidationEventArgs.cs
- figurelength.cs
- SecurityState.cs
- safelink.cs
- QilPatternFactory.cs
- ButtonChrome.cs
- Function.cs
- Accessible.cs
- DataGridViewRowConverter.cs
- GridViewEditEventArgs.cs
- ConfigurationPropertyCollection.cs
- CopyOfAction.cs
- FilteredAttributeCollection.cs
- NullableDecimalSumAggregationOperator.cs
- ExpressionNormalizer.cs
- UrlPath.cs
- ListControlBoundActionList.cs
- rsa.cs
- DataBindEngine.cs
- EdmFunctions.cs
- LinkedResource.cs
- SHA512.cs
- BaseProcessor.cs
- SecurityUtils.cs
- QilStrConcatenator.cs
- AuthenticationException.cs
- SqlConnectionHelper.cs
- SiteMapNodeCollection.cs
- AutomationEventArgs.cs