Merge pull request #93 from konrad-kruczynski/dispatcher_timer_fix
[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 //
7
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 // 
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29 using System;
30 using System.Collections;
31 using System.Collections.Specialized;
32 using System.Configuration;
33 using System.IO;
34 using System.Reflection;
35 using System.Runtime.Serialization;
36 using System.Globalization;
37 #if NET_2_0
38 using System.Net.Configuration;
39 using System.Net.Security;
40 using System.Net.Cache;
41 using System.Security.Principal;
42 #endif
43
44 #if NET_2_1
45 using ConfigurationException = System.ArgumentException;
46
47 namespace System.Net.Configuration {
48         class Dummy {}
49 }
50 #endif
51
52 namespace System.Net 
53 {
54 #if MOONLIGHT
55         internal abstract class WebRequest : ISerializable {
56 #else
57         [Serializable]
58         public abstract class WebRequest : MarshalByRefObject, ISerializable {
59 #endif
60                 static HybridDictionary prefixes = new HybridDictionary ();
61 #if NET_2_0
62                 static bool isDefaultWebProxySet;
63                 static IWebProxy defaultWebProxy;
64                 static RequestCachePolicy defaultCachePolicy;
65                 static MethodInfo cfGetDefaultProxy;
66 #endif
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         #if NET_2_0
92                         defaultCachePolicy = new HttpRequestCachePolicy (HttpRequestCacheLevel.NoCacheNoStore);
93         #endif
94         #if NET_2_0 && CONFIGURATION_DEP
95                         object cfg = ConfigurationManager.GetSection ("system.net/webRequestModules");
96                         WebRequestModulesSection s = cfg as WebRequestModulesSection;
97                         if (s != null) {
98                                 foreach (WebRequestModuleElement el in
99                                          s.WebRequestModules)
100                                         AddPrefix (el.Prefix, el.Type);
101                                 return;
102                         }
103         #endif
104                         ConfigurationSettings.GetConfig ("system.net/webRequestModules");
105 #endif
106                 }
107                 
108                 protected WebRequest () 
109                 {
110                 }
111                 
112                 protected WebRequest (SerializationInfo serializationInfo, StreamingContext streamingContext) 
113                 {
114 #if ONLY_1_1
115                         throw GetMustImplement ();
116 #endif
117                 }
118
119                 static Exception GetMustImplement ()
120                 {
121                         return new NotImplementedException ("This method must be implemented in derived classes");
122                 }
123                 
124                 // Properties
125
126 #if NET_2_0
127                 private AuthenticationLevel authentication_level = AuthenticationLevel.MutualAuthRequested;
128                 
129                 public AuthenticationLevel AuthenticationLevel
130                 {
131                         get {
132                                 return(authentication_level);
133                         }
134                         set {
135                                 authentication_level = value;
136                         }
137                 }
138
139                 [MonoTODO ("Implement the caching system. Currently always returns a policy with the NoCacheNoStore level")]
140                 public virtual RequestCachePolicy CachePolicy
141                 {
142                         get { return DefaultCachePolicy; }
143                         set {
144                         }
145                 }
146 #endif
147                 
148                 public virtual string ConnectionGroupName {
149                         get { throw GetMustImplement (); }
150                         set { throw GetMustImplement (); }
151                 }
152                 
153                 public virtual long ContentLength { 
154                         get { throw GetMustImplement (); }
155                         set { throw GetMustImplement (); }
156                 }
157                 
158                 public virtual string ContentType { 
159                         get { throw GetMustImplement (); }
160                         set { throw GetMustImplement (); }
161                 }
162                 
163                 public virtual ICredentials Credentials { 
164                         get { throw GetMustImplement (); }
165                         set { throw GetMustImplement (); }
166                 }
167
168 #if NET_2_0
169                 public static RequestCachePolicy DefaultCachePolicy
170                 {
171                         get { return defaultCachePolicy; }
172                         set {
173                                 throw GetMustImplement ();
174                         }
175                 }
176 #endif
177                 
178                 public virtual WebHeaderCollection Headers { 
179                         get { throw GetMustImplement (); }
180                         set { throw GetMustImplement (); }
181                 }
182                 
183 #if NET_2_0 && !MOONLIGHT
184                 public TokenImpersonationLevel ImpersonationLevel {
185                         get { throw GetMustImplement (); }
186                         set { throw GetMustImplement (); }
187                 }
188 #endif
189                 public virtual string Method { 
190                         get { throw GetMustImplement (); }
191                         set { throw GetMustImplement (); }
192                 }
193                 
194                 public virtual bool PreAuthenticate { 
195                         get { throw GetMustImplement (); }
196                         set { throw GetMustImplement (); }
197                 }
198                 
199                 public virtual IWebProxy Proxy { 
200                         get { throw GetMustImplement (); }
201                         set { throw GetMustImplement (); }
202                 }
203                 
204                 public virtual Uri RequestUri { 
205                         get { throw GetMustImplement (); }
206                 }
207                 
208                 public virtual int Timeout { 
209                         get { throw GetMustImplement (); }
210                         set { throw GetMustImplement (); }
211                 }
212                 
213 #if NET_2_0
214                 public virtual bool UseDefaultCredentials
215                 {
216                         get {
217                                 throw GetMustImplement ();
218                         }
219                         set {
220                                 throw GetMustImplement ();
221                         }
222                 }
223                 
224 //              volatile static IWebProxy proxy;
225                 static readonly object lockobj = new object ();
226                 
227                 public static IWebProxy DefaultWebProxy {
228                         get {
229                                 if (!isDefaultWebProxySet) {
230                                         lock (lockobj) {
231                                                 if (defaultWebProxy == null)
232                                                         defaultWebProxy = GetDefaultWebProxy ();
233                                         }
234                                 }
235                                 return defaultWebProxy;
236                         }
237                         set {
238                                 /* MS documentation states that a null value would cause an ArgumentNullException
239                                  * but that's not the way it behaves:
240                                  * https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=304724
241                                  */
242                                 defaultWebProxy = value;
243                                 isDefaultWebProxySet = true;
244                         }
245                 }
246                 
247                 [MonoTODO("Needs to respect Module, Proxy.AutoDetect, and Proxy.ScriptLocation config settings")]
248                 static IWebProxy GetDefaultWebProxy ()
249                 {
250                         WebProxy p = null;
251                         
252 #if CONFIGURATION_DEP
253                         DefaultProxySection sec = ConfigurationManager.GetSection ("system.net/defaultProxy") as DefaultProxySection;
254                         if (sec == null)
255                                 return GetSystemWebProxy ();
256                         
257                         ProxyElement pe = sec.Proxy;
258                         
259                         if ((pe.UseSystemDefault != ProxyElement.UseSystemDefaultValues.False) && (pe.ProxyAddress == null))
260                                 p = (WebProxy) GetSystemWebProxy ();
261                         else
262                                 p = new WebProxy ();
263                         
264                         if (pe.ProxyAddress != null)
265                                 p.Address = pe.ProxyAddress;
266                         
267                         if (pe.BypassOnLocal != ProxyElement.BypassOnLocalValues.Unspecified)
268                                 p.BypassProxyOnLocal = (pe.BypassOnLocal == ProxyElement.BypassOnLocalValues.True);
269 #endif
270                         return p;
271                 }
272 #endif
273
274                 // Methods
275                 
276                 public virtual void Abort()
277                 {
278                         throw GetMustImplement ();
279                 }
280                 
281                 public virtual IAsyncResult BeginGetRequestStream (AsyncCallback callback, object state) 
282                 {
283                         throw GetMustImplement ();
284                 }
285                 
286                 public virtual IAsyncResult BeginGetResponse (AsyncCallback callback, object state)
287                 {
288                         throw GetMustImplement ();
289                 }
290
291                 public static WebRequest Create (string requestUriString) 
292                 {
293                         if (requestUriString == null)
294                                 throw new ArgumentNullException ("requestUriString");
295                         return Create (new Uri (requestUriString));
296                 }
297                                 
298                 public static WebRequest Create (Uri requestUri) 
299                 {
300                         if (requestUri == null)
301                                 throw new ArgumentNullException ("requestUri");
302                         return GetCreator (requestUri.AbsoluteUri).Create (requestUri);
303                 }
304                 
305                 public static WebRequest CreateDefault (Uri requestUri)
306                 {
307                         if (requestUri == null)
308                                 throw new ArgumentNullException ("requestUri");
309                         return GetCreator (requestUri.Scheme).Create (requestUri);
310                 }
311
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 #if NET_2_0
333                 [MonoTODO("Look in other places for proxy config info")]
334                 public static IWebProxy GetSystemWebProxy ()
335                 {
336                         string address = Environment.GetEnvironmentVariable ("http_proxy");
337                         if (address == null)
338                                 address = Environment.GetEnvironmentVariable ("HTTP_PROXY");
339
340                         if (address != null) {
341                                 try {
342                                         if (!address.StartsWith ("http://"))
343                                                 address = "http://" + address;
344                                         Uri uri = new Uri (address);
345                                         IPAddress ip;
346                                         if (IPAddress.TryParse (uri.Host, out ip)) {
347                                                 if (IPAddress.Any.Equals (ip)) {
348                                                         UriBuilder builder = new UriBuilder (uri);
349                                                         builder.Host = "127.0.0.1";
350                                                         uri = builder.Uri;
351                                                 } else if (IPAddress.IPv6Any.Equals (ip)) {
352                                                         UriBuilder builder = new UriBuilder (uri);
353                                                         builder.Host = "[::1]";
354                                                         uri = builder.Uri;
355                                                 }
356                                         }
357                                         return new WebProxy (uri);
358                                 } catch (UriFormatException) { }
359                         }
360                         
361                         if (cfGetDefaultProxy != null)
362                                 return (IWebProxy) cfGetDefaultProxy.Invoke (null, null);
363                         
364                         return new WebProxy ();
365                 }
366 #endif
367
368                 void ISerializable.GetObjectData
369                 (SerializationInfo serializationInfo,
370                                                   StreamingContext streamingContext)
371                 {
372                         throw new NotSupportedException ();
373                 }
374
375
376 #if NET_2_0
377                 protected virtual void GetObjectData (SerializationInfo serializationInfo, StreamingContext streamingContext)
378                 {
379                         throw GetMustImplement ();
380                 }
381 #endif
382
383                 public static bool RegisterPrefix (string prefix, IWebRequestCreate creator)
384                 {
385                         if (prefix == null)
386                                 throw new ArgumentNullException ("prefix");
387                         if (creator == null)
388                                 throw new ArgumentNullException ("creator");
389                         
390                         lock (prefixes.SyncRoot) {
391                                 string lowerCasePrefix = prefix.ToLower (CultureInfo.InvariantCulture);
392                                 if (prefixes.Contains (lowerCasePrefix))
393                                         return false;
394                                 prefixes.Add (lowerCasePrefix, creator);
395                         }
396                         return true;
397                 }
398                 
399                 private static IWebRequestCreate GetCreator (string prefix)
400                 {
401                         int longestPrefix = -1;
402                         IWebRequestCreate creator = null;
403
404                         prefix = prefix.ToLower (CultureInfo.InvariantCulture);
405
406                         IDictionaryEnumerator e = prefixes.GetEnumerator ();
407                         while (e.MoveNext ()) {
408                                 string key = e.Key as string;
409
410                                 if (key.Length <= longestPrefix) 
411                                         continue;
412                                 
413                                 if (!prefix.StartsWith (key))
414                                         continue;
415                                         
416                                 longestPrefix = key.Length;
417                                 creator = (IWebRequestCreate) e.Value;
418                         }
419                         
420                         if (creator == null) 
421                                 throw new NotSupportedException (prefix);
422                                 
423                         return creator;
424                 }
425
426                 internal static void ClearPrefixes ()
427                 {
428                         prefixes.Clear ();
429                 }
430
431                 internal static void RemovePrefix (string prefix)
432                 {
433                         prefixes.Remove (prefix);
434                 }
435
436                 internal static void AddPrefix (string prefix, string typeName)
437                 {
438                         Type type = Type.GetType (typeName);
439                         if (type == null)
440                                 throw new ConfigurationException (String.Format ("Type {0} not found", typeName));
441                         AddPrefix (prefix, type);
442                 }
443
444                 internal static void AddPrefix (string prefix, Type type)
445                 {
446                         object o = Activator.CreateInstance (type, true);
447                         prefixes [prefix] = o;
448                 }
449         }
450 }
451