PageRenderTime 74ms CodeModel.GetById 43ms app.highlight 19ms RepoModel.GetById 1ms app.codeStats 0ms

/mcs/class/System/System.Net/WebRequest.cs

https://github.com/iainlane/mono
C# | 517 lines | 396 code | 85 blank | 36 comment | 64 complexity | 8a3b7077767dd845beb3745546dc08e9 MD5 | raw file
  1//
  2// System.Net.WebRequest
  3//
  4// Authors:
  5//  Lawrence Pit (loz@cable.a2000.nl)
  6//	Marek Safar (marek.safar@gmail.com)
  7//
  8// Copyright 2011 Xamarin Inc.
  9//
 10// Permission is hereby granted, free of charge, to any person obtaining
 11// a copy of this software and associated documentation files (the
 12// "Software"), to deal in the Software without restriction, including
 13// without limitation the rights to use, copy, modify, merge, publish,
 14// distribute, sublicense, and/or sell copies of the Software, and to
 15// permit persons to whom the Software is furnished to do so, subject to
 16// the following conditions:
 17// 
 18// The above copyright notice and this permission notice shall be
 19// included in all copies or substantial portions of the Software.
 20// 
 21// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 22// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 23// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 24// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 25// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 26// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 27// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 28//
 29
 30using System;
 31using System.Collections;
 32using System.Collections.Specialized;
 33using System.Configuration;
 34using System.IO;
 35using System.Reflection;
 36using System.Runtime.Serialization;
 37using System.Globalization;
 38using System.Net.Configuration;
 39using System.Net.Security;
 40using System.Net.Cache;
 41using System.Security.Principal;
 42#if NET_4_5
 43using System.Threading.Tasks;
 44#endif
 45
 46#if NET_2_1
 47using ConfigurationException = System.ArgumentException;
 48
 49namespace System.Net.Configuration {
 50	class Dummy {}
 51}
 52#endif
 53
 54namespace System.Net 
 55{
 56#if MOONLIGHT
 57	internal abstract class WebRequest : ISerializable {
 58#else
 59	[Serializable]
 60	public abstract class WebRequest : MarshalByRefObject, ISerializable {
 61#endif
 62		static HybridDictionary prefixes = new HybridDictionary ();
 63		static bool isDefaultWebProxySet;
 64		static IWebProxy defaultWebProxy;
 65		static RequestCachePolicy defaultCachePolicy;
 66		static MethodInfo cfGetDefaultProxy;
 67		
 68		// Constructors
 69		
 70		static WebRequest ()
 71		{
 72			if (Platform.IsMacOS) {
 73#if MONOTOUCH
 74				Type type = Type.GetType ("MonoTouch.CoreFoundation.CFNetwork, monotouch");
 75#else
 76				Type type = Type.GetType ("MonoMac.CoreFoundation.CFNetwork, monomac");
 77#endif
 78				if (type != null)
 79					cfGetDefaultProxy = type.GetMethod ("GetDefaultProxy");
 80			}
 81			
 82#if NET_2_1
 83			IWebRequestCreate http = new HttpRequestCreator ();
 84			RegisterPrefix ("http", http);
 85			RegisterPrefix ("https", http);
 86	#if MOBILE
 87			RegisterPrefix ("file", new FileWebRequestCreator ());
 88			RegisterPrefix ("ftp", new FtpRequestCreator ());
 89	#endif
 90#else
 91			defaultCachePolicy = new HttpRequestCachePolicy (HttpRequestCacheLevel.NoCacheNoStore);
 92	#if CONFIGURATION_DEP
 93			object cfg = ConfigurationManager.GetSection ("system.net/webRequestModules");
 94			WebRequestModulesSection s = cfg as WebRequestModulesSection;
 95			if (s != null) {
 96				foreach (WebRequestModuleElement el in
 97					 s.WebRequestModules)
 98					AddPrefix (el.Prefix, el.Type);
 99				return;
100			}
101	#endif
102			ConfigurationSettings.GetConfig ("system.net/webRequestModules");
103#endif
104		}
105		
106		protected WebRequest () 
107		{
108		}
109		
110		protected WebRequest (SerializationInfo serializationInfo, StreamingContext streamingContext) 
111		{
112		}
113
114		static Exception GetMustImplement ()
115		{
116			return new NotImplementedException ("This method must be implemented in derived classes");
117		}
118		
119		// Properties
120
121		private AuthenticationLevel authentication_level = AuthenticationLevel.MutualAuthRequested;
122		
123		public AuthenticationLevel AuthenticationLevel
124		{
125			get {
126				return(authentication_level);
127			}
128			set {
129				authentication_level = value;
130			}
131		}
132
133		[MonoTODO ("Implement the caching system. Currently always returns a policy with the NoCacheNoStore level")]
134		public virtual RequestCachePolicy CachePolicy
135		{
136			get { return DefaultCachePolicy; }
137			set {
138			}
139		}
140		
141		public virtual string ConnectionGroupName {
142			get { throw GetMustImplement (); }
143			set { throw GetMustImplement (); }
144		}
145		
146		public virtual long ContentLength { 
147			get { throw GetMustImplement (); }
148			set { throw GetMustImplement (); }
149		}
150		
151		public virtual string ContentType { 
152			get { throw GetMustImplement (); }
153			set { throw GetMustImplement (); }
154		}
155		
156		public virtual ICredentials Credentials { 
157			get { throw GetMustImplement (); }
158			set { throw GetMustImplement (); }
159		}
160
161		public static RequestCachePolicy DefaultCachePolicy
162		{
163			get { return defaultCachePolicy; }
164			set {
165				throw GetMustImplement ();
166			}
167		}
168		
169		public virtual WebHeaderCollection Headers { 
170			get { throw GetMustImplement (); }
171			set { throw GetMustImplement (); }
172		}
173		
174#if !MOONLIGHT
175		public TokenImpersonationLevel ImpersonationLevel {
176			get { throw GetMustImplement (); }
177			set { throw GetMustImplement (); }
178		}
179#endif
180		public virtual string Method { 
181			get { throw GetMustImplement (); }
182			set { throw GetMustImplement (); }
183		}
184		
185		public virtual bool PreAuthenticate { 
186			get { throw GetMustImplement (); }
187			set { throw GetMustImplement (); }
188		}
189		
190		public virtual IWebProxy Proxy { 
191			get { throw GetMustImplement (); }
192			set { throw GetMustImplement (); }
193		}
194		
195		public virtual Uri RequestUri { 
196			get { throw GetMustImplement (); }
197		}
198		
199		public virtual int Timeout { 
200			get { throw GetMustImplement (); }
201			set { throw GetMustImplement (); }
202		}
203		
204		public virtual bool UseDefaultCredentials
205		{
206			get {
207				throw GetMustImplement ();
208			}
209			set {
210				throw GetMustImplement ();
211			}
212		}
213		
214//		volatile static IWebProxy proxy;
215		static readonly object lockobj = new object ();
216		
217		public static IWebProxy DefaultWebProxy {
218			get {
219				if (!isDefaultWebProxySet) {
220					lock (lockobj) {
221						if (defaultWebProxy == null)
222							defaultWebProxy = GetDefaultWebProxy ();
223					}
224				}
225				return defaultWebProxy;
226			}
227			set {
228				/* MS documentation states that a null value would cause an ArgumentNullException
229				 * but that's not the way it behaves:
230				 * https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=304724
231				 */
232				defaultWebProxy = value;
233				isDefaultWebProxySet = true;
234			}
235		}
236		
237		[MonoTODO("Needs to respect Module, Proxy.AutoDetect, and Proxy.ScriptLocation config settings")]
238		static IWebProxy GetDefaultWebProxy ()
239		{
240#if CONFIGURATION_DEP
241			DefaultProxySection sec = ConfigurationManager.GetSection ("system.net/defaultProxy") as DefaultProxySection;
242			WebProxy p;
243			
244			if (sec == null)
245				return GetSystemWebProxy ();
246			
247			ProxyElement pe = sec.Proxy;
248			
249			if ((pe.UseSystemDefault != ProxyElement.UseSystemDefaultValues.False) && (pe.ProxyAddress == null))
250				p = (WebProxy) GetSystemWebProxy ();
251			else
252				p = new WebProxy ();
253			
254			if (pe.ProxyAddress != null)
255				p.Address = pe.ProxyAddress;
256			
257			if (pe.BypassOnLocal != ProxyElement.BypassOnLocalValues.Unspecified)
258				p.BypassProxyOnLocal = (pe.BypassOnLocal == ProxyElement.BypassOnLocalValues.True);
259				
260			foreach(BypassElement elem in sec.BypassList)
261				p.BypassArrayList.Add(elem.Address);
262			
263			return p;
264#else
265			return GetSystemWebProxy ();
266#endif
267		}
268
269		// Methods
270		
271		public virtual void Abort()
272		{
273			throw GetMustImplement ();
274		}
275		
276		public virtual IAsyncResult BeginGetRequestStream (AsyncCallback callback, object state) 
277		{
278			throw GetMustImplement ();
279		}
280		
281		public virtual IAsyncResult BeginGetResponse (AsyncCallback callback, object state)
282		{
283			throw GetMustImplement ();
284		}
285
286		public static WebRequest Create (string requestUriString) 
287		{
288			if (requestUriString == null)
289				throw new ArgumentNullException ("requestUriString");
290			return Create (new Uri (requestUriString));
291		}
292				
293		public static WebRequest Create (Uri requestUri) 
294		{
295			if (requestUri == null)
296				throw new ArgumentNullException ("requestUri");
297			return GetCreator (requestUri.AbsoluteUri).Create (requestUri);
298		}
299		
300		public static WebRequest CreateDefault (Uri requestUri)
301		{
302			if (requestUri == null)
303				throw new ArgumentNullException ("requestUri");
304			return GetCreator (requestUri.Scheme).Create (requestUri);
305		}
306
307		public virtual Stream EndGetRequestStream (IAsyncResult asyncResult)
308		{
309			throw GetMustImplement ();
310		}
311		
312		public virtual WebResponse EndGetResponse (IAsyncResult asyncResult)
313		{
314			throw GetMustImplement ();
315		}
316		
317		public virtual Stream GetRequestStream()
318		{
319			throw GetMustImplement ();
320		}
321		
322		public virtual WebResponse GetResponse()
323		{
324			throw GetMustImplement ();
325		}
326		
327		[MonoTODO("Look in other places for proxy config info")]
328		public static IWebProxy GetSystemWebProxy ()
329		{
330#if !NET_2_1
331			if (IsWindows ()) {
332				int iProxyEnable = (int)Microsoft.Win32.Registry.GetValue ("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", "ProxyEnable", 0);
333
334				if (iProxyEnable > 0) {
335					string strHttpProxy = "";					
336					bool bBypassOnLocal = false;
337					ArrayList al = new ArrayList ();
338					
339					string strProxyServer = (string)Microsoft.Win32.Registry.GetValue ("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", "ProxyServer", null);
340					string strProxyOverrride = (string)Microsoft.Win32.Registry.GetValue ("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", "ProxyOverride", null);
341					
342					if (strProxyServer.Contains ("=")) {
343						foreach (string strEntry in strProxyServer.Split (new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
344							if (strEntry.StartsWith ("http=")) {
345								strHttpProxy = strEntry.Substring (5);
346								break;
347							}
348					} else strHttpProxy = strProxyServer;
349					
350					if (strProxyOverrride != null) {						
351						string[] bypassList = strProxyOverrride.Split (new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
352					
353						foreach (string str in bypassList) {
354							if (str != "<local>")
355								al.Add (str);
356							else
357								bBypassOnLocal = true;
358						}
359					}
360					
361					return new WebProxy (strHttpProxy, bBypassOnLocal, al.ToArray (typeof(string)) as string[]);
362				}
363			} else {
364#endif
365				string address = Environment.GetEnvironmentVariable ("http_proxy");
366
367				if (address == null)
368					address = Environment.GetEnvironmentVariable ("HTTP_PROXY");
369				
370				if (address != null) {
371					try {
372						if (!address.StartsWith ("http://"))
373							address = "http://" + address;
374
375						Uri uri = new Uri (address);
376						IPAddress ip;
377						
378						if (IPAddress.TryParse (uri.Host, out ip)) {
379							if (IPAddress.Any.Equals (ip)) {
380								UriBuilder builder = new UriBuilder (uri);
381								builder.Host = "127.0.0.1";
382								uri = builder.Uri;
383							} else if (IPAddress.IPv6Any.Equals (ip)) {
384								UriBuilder builder = new UriBuilder (uri);
385								builder.Host = "[::1]";
386								uri = builder.Uri;
387							}
388						}
389						
390						bool bBypassOnLocal = false;						
391						ArrayList al = new ArrayList ();
392						string bypass = Environment.GetEnvironmentVariable ("no_proxy");
393						
394						if (bypass == null)
395							bypass = Environment.GetEnvironmentVariable ("NO_PROXY");
396						
397						if (bypass != null) {
398							string[] bypassList = bypass.Split (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
399						
400							foreach (string str in bypassList) {
401								if (str != "*.local")
402									al.Add (str);
403								else
404									bBypassOnLocal = true;
405							}
406						}
407						
408						return new WebProxy (uri, bBypassOnLocal, al.ToArray (typeof(string)) as string[]);
409					} catch (UriFormatException) {
410					}
411				}
412#if !NET_2_1
413			}
414#endif
415			
416			if (cfGetDefaultProxy != null)
417				return (IWebProxy) cfGetDefaultProxy.Invoke (null, null);
418			
419			return new WebProxy ();
420		}
421
422		void ISerializable.GetObjectData (SerializationInfo serializationInfo, StreamingContext streamingContext)
423		{
424			throw new NotSupportedException ();
425		}
426
427		protected virtual void GetObjectData (SerializationInfo serializationInfo, StreamingContext streamingContext)
428		{
429			throw GetMustImplement ();
430		}
431
432		public static bool RegisterPrefix (string prefix, IWebRequestCreate creator)
433		{
434			if (prefix == null)
435				throw new ArgumentNullException ("prefix");
436			if (creator == null)
437				throw new ArgumentNullException ("creator");
438			
439			lock (prefixes.SyncRoot) {
440				string lowerCasePrefix = prefix.ToLower (CultureInfo.InvariantCulture);
441				if (prefixes.Contains (lowerCasePrefix))
442					return false;
443				prefixes.Add (lowerCasePrefix, creator);
444			}
445			return true;
446		}
447		
448		private static IWebRequestCreate GetCreator (string prefix)
449		{
450			int longestPrefix = -1;
451			IWebRequestCreate creator = null;
452
453			prefix = prefix.ToLower (CultureInfo.InvariantCulture);
454
455			IDictionaryEnumerator e = prefixes.GetEnumerator ();
456			while (e.MoveNext ()) {
457				string key = e.Key as string;
458
459				if (key.Length <= longestPrefix) 
460					continue;
461				
462				if (!prefix.StartsWith (key))
463					continue;
464					
465				longestPrefix = key.Length;
466				creator = (IWebRequestCreate) e.Value;
467			}
468			
469			if (creator == null) 
470				throw new NotSupportedException (prefix);
471				
472			return creator;
473		}
474		
475		internal static bool IsWindows ()
476		{
477			return (int) Environment.OSVersion.Platform < 4;
478		}
479
480		internal static void ClearPrefixes ()
481		{
482			prefixes.Clear ();
483		}
484
485		internal static void RemovePrefix (string prefix)
486		{
487			prefixes.Remove (prefix);
488		}
489
490		internal static void AddPrefix (string prefix, string typeName)
491		{
492			Type type = Type.GetType (typeName);
493			if (type == null)
494				throw new ConfigurationException (String.Format ("Type {0} not found", typeName));
495			AddPrefix (prefix, type);
496		}
497
498		internal static void AddPrefix (string prefix, Type type)
499		{
500			object o = Activator.CreateInstance (type, true);
501			prefixes [prefix] = o;
502		}
503
504#if NET_4_5
505		public virtual Task<Stream> GetRequestStreamAsync ()
506		{
507			return Task<Stream>.Factory.FromAsync (BeginGetRequestStream, EndGetRequestStream, null);
508		}
509
510		public virtual Task<WebResponse> GetResponseAsync ()
511		{
512			return Task<WebResponse>.Factory.FromAsync (BeginGetResponse, EndGetResponse, null);
513		}
514#endif
515
516	}
517}