2016-08-03 10:59:49 +00:00
//------------------------------------------------------------------------------
// <copyright file="webproxy.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
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.Runtime.Serialization ;
using System.Collections.Generic ;
using System.Diagnostics.CodeAnalysis ;
class WebProxyData {
internal bool bypassOnLocal ;
internal bool automaticallyDetectSettings ;
internal Uri proxyAddress ;
internal Hashtable proxyHostAddresses ;
internal Uri scriptLocation ;
#if USE_WINIET_AUTODETECT_CACHE
internal Uri lkgScriptLocation ;
#endif
internal ArrayList bypassList ;
}
// Handles default proxy setting implementation for the Http proxy.
//
// The following order is used when determinig proxy settings:
// 1. web.config/app.config: if available, use settings specified in <system.net><defaultProxy>
// 2. If the config file doesn't contain proxy settings, read the IE proxy settings
//
// If the IE proxy settings contain invalid settings (e.g. "invalid;host" - note the semicolon), then
// a FormatException will be thrown.
[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 ;
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public WebProxy ( )
: this ( ( Uri ) null , false , null , null ) {
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public WebProxy ( Uri Address )
: this ( Address , false , null , null ) {
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public WebProxy ( Uri Address , bool BypassOnLocal )
: this ( Address , BypassOnLocal , null , null ) {
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public WebProxy ( Uri Address , bool BypassOnLocal , string [ ] BypassList )
: this ( Address , BypassOnLocal , BypassList , null ) {
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
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 ;
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public WebProxy ( string Host , int Port )
: this ( new Uri ( "http://" + Host + ":" + Port . ToString ( CultureInfo . InvariantCulture ) ) , false , null , null ) {
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public WebProxy ( string Address )
: this ( CreateProxyUri ( Address ) , false , null , null ) {
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public WebProxy ( string Address , bool BypassOnLocal )
: this ( CreateProxyUri ( Address ) , BypassOnLocal , null , null ) {
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public WebProxy ( string Address , bool BypassOnLocal , string [ ] BypassList )
: this ( CreateProxyUri ( Address ) , BypassOnLocal , BypassList , null ) {
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public WebProxy ( string Address , bool BypassOnLocal , string [ ] BypassList , ICredentials Credentials )
: this ( CreateProxyUri ( Address ) , BypassOnLocal , BypassList , Credentials ) {
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
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 ;
}
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
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 ;
}
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
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 ;
}
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public bool BypassProxyOnLocal {
get {
#if ! FEATURE_PAL
CheckForChanges ( ) ;
#endif // !FEATURE_PAL
return _BypassOnLocal ;
}
set {
_UseRegistry = false ;
DeleteScriptEngine ( ) ;
_BypassOnLocal = value ;
}
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
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 ) ;
}
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public ICredentials Credentials {
get {
return _Credentials ;
}
set {
_Credentials = value ;
}
}
/// <devdoc>
/// <para>Sets Credentials to CredentialCache.DefaultCredentials</para>
/// </devdoc>
public bool UseDefaultCredentials {
get {
return ( Credentials is SystemNetworkCredential ) ? true : false ;
}
set {
_Credentials = value ? CredentialCache . DefaultCredentials : null ;
}
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
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 ( ) ;
}
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public Uri GetProxy ( Uri destination ) {
GlobalLog . Print ( "WebProxy#" + ValidationHelper . HashString ( this ) + "::GetProxy() destination:" + ValidationHelper . ToString ( destination ) ) ;
if ( destination = = null )
{
throw new ArgumentNullException ( "destination" ) ;
}
Uri result ;
if ( GetProxyAuto ( destination , out result ) ) {
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 ;
}
/// <devdoc>
/// Determines if the host Uri should be routed locally or go through the proxy.
/// </devdoc>
private bool IsLocal ( Uri host ) {
string hostString = host . Host ;
IPAddress hostAddress ;
if ( IPAddress . TryParse ( hostString , out hostAddress ) )
{
return ( IPAddress . IsLoopback ( hostAddress ) | | NclUtilities . IsAddressLocal ( hostAddress ) ) ;
}
int dot = hostString . IndexOf ( '.' ) ;
// No dot? Local.
if ( dot = = - 1 )
{
return true ;
}
// 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 ;
}
/// <devdoc>
/// Determines if the host Uri should be routed locally or go through a proxy.
/// </devdoc>
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 ;
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public bool IsBypassed ( Uri host ) {
GlobalLog . Print ( "WebProxy#" + ValidationHelper . HashString ( this ) + "::IsBypassed() destination:" + ValidationHelper . ToString ( host ) ) ;
if ( host = = null )
{
throw new ArgumentNullException ( "host" ) ;
}
bool result ;
if ( IsBypassedAuto ( host , out result ) ) {
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 ) ;
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[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 ( ) {
2017-04-10 11:41:01 +00:00
#if MONO_FEATURE_CAS
2016-08-03 10:59:49 +00:00
ExceptionHelper . WebPermissionUnrestricted . Demand ( ) ;
2016-11-10 13:04:39 +00:00
#endif
2016-08-03 10:59:49 +00:00
return new WebProxy ( true ) ;
}
//
// ISerializable constructor
//
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
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)
2017-04-10 11:41:01 +00:00
#if MONO_FEATURE_CAS
2016-08-03 10:59:49 +00:00
ExceptionHelper . WebPermissionUnrestricted . Demand ( ) ;
2016-11-10 13:04:39 +00:00
#endif
2016-08-03 10:59:49 +00:00
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
//
/// <internalonly/>
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Justification = "System.dll is still using pre-v4 security model and needs this demand")]
[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 ) ;
}
}
/// <summary>
/// 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.
/// </summary>
private AutoWebProxyScriptEngine m_ScriptEngine ;
internal AutoWebProxyScriptEngine ScriptEngine {
get {
return m_ScriptEngine ;
}
set {
m_ScriptEngine = value ;
}
}
2016-11-10 13:04:39 +00:00
#if MONO
public static IWebProxy CreateDefaultProxy ( )
{
2017-08-21 15:34:15 +00:00
#if FEATURE_NO_BSD_SOCKETS
2016-11-10 13:04:39 +00:00
throw new PlatformNotSupportedException ( ) ;
#elif MONOTOUCH
return Mono . Net . CFNetwork . GetDefaultProxy ( ) ;
2019-05-18 08:35:58 +00:00
#elif MONODROID & & ! MOBILE_DESKTOP_HOST
2016-11-10 13:04:39 +00:00
// Return the system web proxy. This only works for ICS+.
var data = AndroidPlatform . GetDefaultProxy ( ) ;
if ( data ! = null )
return data ;
2017-04-10 11:41:01 +00:00
2017-08-21 15:34:15 +00:00
return new WebProxy ( true ) ;
#elif ORBIS
2017-04-10 11:41:01 +00:00
return new WebProxy ( true ) ;
2016-11-10 13:04:39 +00:00
#else
if ( Platform . IsMacOS ) {
var data = Mono . Net . CFNetwork . GetDefaultProxy ( ) ;
if ( data ! = null )
return data ;
}
return new WebProxy ( true ) ;
2017-04-10 11:41:01 +00:00
#endif
2016-11-10 13:04:39 +00:00
}
#endif
2016-08-03 10:59:49 +00:00
// 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 ;
2016-11-10 13:04:39 +00:00
#if ! FEATURE_PAL | | ! MOBILE
2016-08-03 10:59:49 +00:00
ScriptEngine = new AutoWebProxyScriptEngine ( this , true ) ;
WebProxyData webProxyData = ScriptEngine . GetWebProxyData ( ) ;
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 ;
_ProxyHostAddresses = webProxyData . proxyHostAddresses ;
_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
}
/// <devdoc>
/// <para>
/// 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.
/// </para>
/// </devdoc>
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 bool GetProxyAuto ( Uri destination , out Uri proxyUri ) {
GlobalLog . Print ( "WebProxy#" + ValidationHelper . HashString ( this ) + "::GetProxyAuto() destination:" + ValidationHelper . ToString ( destination ) ) ;
proxyUri = null ;
if ( ScriptEngine = = null ) {
return false ;
}
IList < string > proxies = null ;
if ( ! ScriptEngine . GetProxies ( destination , out proxies ) ) {
return false ;
}
// Returning null in case 'proxies.Count == 0' means, no proxy available (incl. DIRECT), the request is prohibited.
if ( proxies . Count > 0 ) {
if ( AreAllBypassed ( proxies , true ) ) {
// this is the broken behaviour of IWebProxy. Returning the same destination means bypass
proxyUri = destination ;
}
else {
proxyUri = ProxyUri ( proxies [ 0 ] ) ;
}
}
return true ;
}
private bool IsBypassedAuto ( Uri destination , out bool isBypassed ) {
GlobalLog . Print ( "WebProxy#" + ValidationHelper . HashString ( this ) + "::IsBypassedAuto() destination:" + ValidationHelper . ToString ( destination ) ) ;
isBypassed = true ;
if ( ScriptEngine = = null ) {
return false ;
}
IList < string > proxyList ;
if ( ! ScriptEngine . GetProxies ( destination , out proxyList ) ) {
return false ;
}
if ( proxyList . Count = = 0 ) {
isBypassed = false ;
}
else {
isBypassed = AreAllBypassed ( proxyList , true ) ;
}
return true ;
}
internal Uri [ ] GetProxiesAuto ( Uri destination , ref int syncStatus )
{
GlobalLog . Print ( "WebProxy#" + ValidationHelper . HashString ( this ) + "::GetProxiesAuto() destination:" + ValidationHelper . ToString ( destination ) ) ;
if ( ScriptEngine = = null ) {
return null ;
}
IList < string > proxyList = null ;
if ( ! ScriptEngine . GetProxies ( destination , out proxyList , ref syncStatus ) ) {
return null ;
}
Uri [ ] proxyUris = null ;
if ( proxyList . Count = = 0 ) {
proxyUris = new Uri [ ] { } ;
}
else if ( AreAllBypassed ( proxyList , false ) ) {
proxyUris = new Uri [ ] { null } ;
}
else {
proxyUris = new Uri [ proxyList . Count ] ;
for ( int i = 0 ; i < proxyList . Count ; i + + ) {
proxyUris [ i ] = ProxyUri ( proxyList [ i ] ) ;
}
}
return proxyUris ;
}
internal void AbortGetProxiesAuto ( ref int syncStatus )
{
if ( ScriptEngine ! = null )
{
ScriptEngine . Abort ( ref syncStatus ) ;
}
}
internal Uri GetProxyAutoFailover ( Uri destination )
{
if ( IsBypassedManual ( destination ) )
{
return null ;
}
Uri proxy = _ProxyAddress ;
Hashtable proxyHostAddresses = _ProxyHostAddresses ;
if ( proxyHostAddresses ! = null )
{
proxy = proxyHostAddresses [ destination . Scheme ] as Uri ;
}
return proxy ;
}
private static bool AreAllBypassed ( IEnumerable < string > proxies , bool checkFirstOnly ) {
bool isBypassed = true ;
foreach ( string proxy in proxies ) {
isBypassed = string . IsNullOrEmpty ( proxy ) ;
if ( checkFirstOnly | | ! isBypassed ) {
break ;
}
}
return isBypassed ;
}
private static Uri ProxyUri ( string proxyName ) {
return proxyName = = null | | proxyName . Length = = 0 ? null : new Uri ( "http://" + proxyName ) ;
}
}
}