context: //
  // System.Net.WebRequest
  //
  // Authors:
  //  Lawrence Pit (loz@cable.a2000.nl)
  //	Marek Safar (marek.safar@gmail.com)
  //
  // Copyright 2011 Xamarin Inc.
  //
  // Permission is hereby granted, free of charge, to any person obtaining
  // a copy of this software and associated documentation files (the
  // "Software"), to deal in the Software without restriction, including
  // without limitation the rights to use, copy, modify, merge, publish,
  // distribute, sublicense, and/or sell copies of the Software, and to
  // permit persons to whom the Software is furnished to do so, subject to
  // the following conditions:
  // 
  // The above copyright notice and this permission notice shall be
  // included in all copies or substantial portions of the Software.
  // 
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  //
  
  using System;
  using System.Collections;
  using System.Collections.Specialized;
  using System.Configuration;
  using System.IO;
  using System.Reflection;
  using System.Runtime.Serialization;
  using System.Globalization;
  using System.Net.Configuration;
  using System.Net.Security;
  using System.Net.Cache;
  using System.Security.Principal;
  #if NET_4_5
  using System.Threading.Tasks;
  #endif
  
  #if NET_2_1
  using ConfigurationException = System.ArgumentException;
  
  namespace System.Net.Configuration {
  	class Dummy {}
  }
  #endif
  
  namespace System.Net 
  {
  	[Serializable]
  	public abstract class WebRequest : MarshalByRefObject, ISerializable {
  		static HybridDictionary prefixes = new HybridDictionary ();
  		static bool isDefaultWebProxySet;
  		static IWebProxy defaultWebProxy;
  		static RequestCachePolicy defaultCachePolicy;
  
  		static WebRequest ()
  		{
  #if MOBILE
  			IWebRequestCreate http = new HttpRequestCreator ();
  			RegisterPrefix ("http", http);
  			RegisterPrefix ("https", http);
  			RegisterPrefix ("file", new FileWebRequestCreator ());
  			RegisterPrefix ("ftp", new FtpRequestCreator ());
  #else
  	#if CONFIGURATION_DEP
  			object cfg = ConfigurationManager.GetSection ("system.net/webRequestModules");
  			WebRequestModulesSection s = cfg as WebRequestModulesSection;
  			if (s != null) {
  				foreach (WebRequestModuleElement el in
  					 s.WebRequestModules)
  					AddPrefix (el.Prefix, el.Type);
  				return;
  			}
  	#endif
  			ConfigurationSettings.GetConfig ("system.net/webRequestModules");
  #endif
  		}
  		
  		protected WebRequest () 
  		{
  		}
  		
  		protected WebRequest (SerializationInfo serializationInfo, StreamingContext streamingContext) 
  		{
  		}
  
  		static Exception GetMustImplement ()
  		{
  			return new NotImplementedException ("This method must be implemented in derived classes");
  		}
  		
  		// Properties
  
  		private AuthenticationLevel authentication_level = AuthenticationLevel.MutualAuthRequested;
  		
  		public AuthenticationLevel AuthenticationLevel
  		{
  			get {
  				return(authentication_level);
  			}
  			set {
  				authentication_level = value;
  			}
  		}
  		
  		public virtual string ConnectionGroupName {
  			get { throw GetMustImplement (); }
  			set { throw GetMustImplement (); }
  		}
  		
  		public virtual long ContentLength { 
  			get { throw GetMustImplement (); }
  			set { throw GetMustImplement (); }
  		}
  		
  		public virtual string ContentType { 
  			get { throw GetMustImplement (); }
  			set { throw GetMustImplement (); }
  		}
  		
  		public virtual ICredentials Credentials { 
  			get { throw GetMustImplement (); }
  			set { throw GetMustImplement (); }
  		}
  
  		[MonoTODO ("Implement the caching system. Currently always returns a policy with the NoCacheNoStore level")]
  		public virtual RequestCachePolicy CachePolicy
  		{
  			get { return DefaultCachePolicy; }
  			set {
  			}
  		}
  		
  		public static RequestCachePolicy DefaultCachePolicy {
  			get {
  				return defaultCachePolicy ?? (defaultCachePolicy = new HttpRequestCachePolicy (HttpRequestCacheLevel.NoCacheNoStore));
  			}
  			set {
  				throw GetMustImplement ();
  			}
  		}
  		
  		public virtual WebHeaderCollection Headers { 
  			get { throw GetMustImplement (); }
  			set { throw GetMustImplement (); }
  		}
  		
  		public TokenImpersonationLevel ImpersonationLevel {
  			get { throw GetMustImplement (); }
  			set { throw GetMustImplement (); }
  		}
  
  		public virtual string Method { 
  			get { throw GetMustImplement (); }
  			set { throw GetMustImplement (); }
  		}
  		
  		public virtual bool PreAuthenticate { 
  			get { throw GetMustImplement (); }
  			set { throw GetMustImplement (); }
  		}
  		
  		public virtual IWebProxy Proxy { 
  			get { throw GetMustImplement (); }
  			set { throw GetMustImplement (); }
  		}
  		
  		public virtual Uri RequestUri { 
  			get { throw GetMustImplement (); }
  		}
  		
  		public virtual int Timeout { 
  			get { throw GetMustImplement (); }
  			set { throw GetMustImplement (); }
  		}
  		
  		public virtual bool UseDefaultCredentials
  		{
  			get {
  				throw GetMustImplement ();
  			}
  			set {
  				throw GetMustImplement ();
  			}
  		}
  		
  //		volatile static IWebProxy proxy;
  		static readonly object lockobj = new object ();
  		
  		public static IWebProxy DefaultWebProxy {
  			get {
  				if (!isDefaultWebProxySet) {
  					lock (lockobj) {
  						if (defaultWebProxy == null)
  							defaultWebProxy = GetDefaultWebProxy ();
  					}
  				}
  				return defaultWebProxy;
  			}
  			set {
  				/* MS documentation states that a null value would cause an ArgumentNullException
  				 * but that's not the way it behaves:
  				 * https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=304724
  				 */
  				defaultWebProxy = value;
  				isDefaultWebProxySet = true;
  			}
  		}
  		
  		[MonoTODO("Needs to respect Module, Proxy.AutoDetect, and Proxy.ScriptLocation config settings")]
  		static IWebProxy GetDefaultWebProxy ()
  		{
  #if CONFIGURATION_DEP
  			DefaultProxySection sec = ConfigurationManager.GetSection ("system.net/defaultProxy") as DefaultProxySection;
  			WebProxy p;
  			
  			if (sec == null)
  				return GetSystemWebProxy ();
  			
  			ProxyElement pe = sec.Proxy;
  			
  			if ((pe.UseSystemDefault != ProxyElement.UseSystemDefaultValues.False) && (pe.ProxyAddress == null)) {
  				IWebProxy proxy = GetSystemWebProxy ();
  				
  				if (!(proxy is WebProxy))
  					return proxy;
  				
  				p = (WebProxy) proxy;
  			} else
  				p = new WebProxy ();
  			
  			if (pe.ProxyAddress != null)
  				p.Address = pe.ProxyAddress;
  			
  			if (pe.BypassOnLocal != ProxyElement.BypassOnLocalValues.Unspecified)
  				p.BypassProxyOnLocal = (pe.BypassOnLocal == ProxyElement.BypassOnLocalValues.True);
  				
  			foreach(BypassElement elem in sec.BypassList)
  				p.BypassArrayList.Add(elem.Address);
  			
  			return p;
  #else
  			return GetSystemWebProxy ();
  #endif
  		}
  
  		// Methods
  		
  		public virtual void Abort()
  		{
  			throw GetMustImplement ();
  		}
  		
  		public virtual IAsyncResult BeginGetRequestStream (AsyncCallback callback, object state) 
  		{
  			throw GetMustImplement ();
  		}
  		
  		public virtual IAsyncResult BeginGetResponse (AsyncCallback callback, object state)
  		{
  			throw GetMustImplement ();
  		}
  
  		public static WebRequest Create (string requestUriString) 
  		{
  			if (requestUriString == null)
  				throw new ArgumentNullException ("requestUriString");
  			return Create (new Uri (requestUriString));
  		}
  				
  		public static WebRequest Create (Uri requestUri) 
  		{
  			if (requestUri == null)
  				throw new ArgumentNullException ("requestUri");
  			return GetCreator (requestUri.AbsoluteUri).Create (requestUri);
  		}
  		
  		public static WebRequest CreateDefault (Uri requestUri)
  		{
  			if (requestUri == null)
  				throw new ArgumentNullException ("requestUri");
  			return GetCreator (requestUri.Scheme).Create (requestUri);
  		}
  #if NET_4_0
  		[MonoTODO ("for portable library support")]
  		public static HttpWebRequest CreateHttp (string requestUriString)
  		{
  			throw new NotImplementedException ();
  		}
  			
  		[MonoTODO ("for portable library support")]
  		public static HttpWebRequest CreateHttp (Uri requestUri)
  		{
  			throw new NotImplementedException ();
  		}
  #endif
  		public virtual Stream EndGetRequestStream (IAsyncResult asyncResult)
  		{
  			throw GetMustImplement ();
  		}
  		
  		public virtual WebResponse EndGetResponse (IAsyncResult asyncResult)
  		{
  			throw GetMustImplement ();
  		}
  		
  		public virtual Stream GetRequestStream()
  		{
  			throw GetMustImplement ();
  		}
  		
  		public virtual WebResponse GetResponse()
  		{
  			throw GetMustImplement ();
  		}
  		
  		[MonoTODO("Look in other places for proxy config info")]
  		public static IWebProxy GetSystemWebProxy ()
  		{
  #if MONOTOUCH
  			return CFNetwork.GetDefaultProxy ();
  #else
  #if MONODROID
  			// Return the system web proxy.  This only works for ICS+.
  			var androidProxy = AndroidPlatform.GetDefaultProxy ();
  			if (androidProxy != null)
  				return androidProxy;
  #endif
  #if !NET_2_1
  			if (IsWindows ()) {
  				int iProxyEnable = (int)Microsoft.Win32.Registry.GetValue ("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", "ProxyEnable", 0);
  
  				if (iProxyEnable > 0) {
  					string strHttpProxy = "";					
  					bool bBypassOnLocal = false;
  
gt: 					ArrayList al = new ArrayList ();