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