Fix bug #311: On LinkedList.Clear, detach each node instead of dropping them en masse.
[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 #if CONFIGURATION_DEP
251                         DefaultProxySection sec = ConfigurationManager.GetSection ("system.net/defaultProxy") as DefaultProxySection;
252                         WebProxy p;
253                         
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                         
270                         return p;
271 #else
272                         return GetSystemWebProxy ();
273 #endif
274                 }
275 #endif
276
277                 // Methods
278                 
279                 public virtual void Abort()
280                 {
281                         throw GetMustImplement ();
282                 }
283                 
284                 public virtual IAsyncResult BeginGetRequestStream (AsyncCallback callback, object state) 
285                 {
286                         throw GetMustImplement ();
287                 }
288                 
289                 public virtual IAsyncResult BeginGetResponse (AsyncCallback callback, object state)
290                 {
291                         throw GetMustImplement ();
292                 }
293
294                 public static WebRequest Create (string requestUriString) 
295                 {
296                         if (requestUriString == null)
297                                 throw new ArgumentNullException ("requestUriString");
298                         return Create (new Uri (requestUriString));
299                 }
300                                 
301                 public static WebRequest Create (Uri requestUri) 
302                 {
303                         if (requestUri == null)
304                                 throw new ArgumentNullException ("requestUri");
305                         return GetCreator (requestUri.AbsoluteUri).Create (requestUri);
306                 }
307                 
308                 public static WebRequest CreateDefault (Uri requestUri)
309                 {
310                         if (requestUri == null)
311                                 throw new ArgumentNullException ("requestUri");
312                         return GetCreator (requestUri.Scheme).Create (requestUri);
313                 }
314
315                 public virtual Stream EndGetRequestStream (IAsyncResult asyncResult)
316                 {
317                         throw GetMustImplement ();
318                 }
319                 
320                 public virtual WebResponse EndGetResponse (IAsyncResult asyncResult)
321                 {
322                         throw GetMustImplement ();
323                 }
324                 
325                 public virtual Stream GetRequestStream()
326                 {
327                         throw GetMustImplement ();
328                 }
329                 
330                 public virtual WebResponse GetResponse()
331                 {
332                         throw GetMustImplement ();
333                 }
334                 
335 #if NET_2_0
336                 [MonoTODO("Look in other places for proxy config info")]
337                 public static IWebProxy GetSystemWebProxy ()
338                 {
339                         string address = Environment.GetEnvironmentVariable ("http_proxy");
340                         if (address == null)
341                                 address = Environment.GetEnvironmentVariable ("HTTP_PROXY");
342
343                         if (address != null) {
344                                 try {
345                                         if (!address.StartsWith ("http://"))
346                                                 address = "http://" + address;
347                                         Uri uri = new Uri (address);
348                                         IPAddress ip;
349                                         if (IPAddress.TryParse (uri.Host, out ip)) {
350                                                 if (IPAddress.Any.Equals (ip)) {
351                                                         UriBuilder builder = new UriBuilder (uri);
352                                                         builder.Host = "127.0.0.1";
353                                                         uri = builder.Uri;
354                                                 } else if (IPAddress.IPv6Any.Equals (ip)) {
355                                                         UriBuilder builder = new UriBuilder (uri);
356                                                         builder.Host = "[::1]";
357                                                         uri = builder.Uri;
358                                                 }
359                                         }
360                                         return new WebProxy (uri);
361                                 } catch (UriFormatException) { }
362                         }
363                         
364                         if (cfGetDefaultProxy != null)
365                                 return (IWebProxy) cfGetDefaultProxy.Invoke (null, null);
366                         
367                         return new WebProxy ();
368                 }
369 #endif
370
371                 void ISerializable.GetObjectData
372                 (SerializationInfo serializationInfo,
373                                                   StreamingContext streamingContext)
374                 {
375                         throw new NotSupportedException ();
376                 }
377
378
379 #if NET_2_0
380                 protected virtual void GetObjectData (SerializationInfo serializationInfo, StreamingContext streamingContext)
381                 {
382                         throw GetMustImplement ();
383                 }
384 #endif
385
386                 public static bool RegisterPrefix (string prefix, IWebRequestCreate creator)
387                 {
388                         if (prefix == null)
389                                 throw new ArgumentNullException ("prefix");
390                         if (creator == null)
391                                 throw new ArgumentNullException ("creator");
392                         
393                         lock (prefixes.SyncRoot) {
394                                 string lowerCasePrefix = prefix.ToLower (CultureInfo.InvariantCulture);
395                                 if (prefixes.Contains (lowerCasePrefix))
396                                         return false;
397                                 prefixes.Add (lowerCasePrefix, creator);
398                         }
399                         return true;
400                 }
401                 
402                 private static IWebRequestCreate GetCreator (string prefix)
403                 {
404                         int longestPrefix = -1;
405                         IWebRequestCreate creator = null;
406
407                         prefix = prefix.ToLower (CultureInfo.InvariantCulture);
408
409                         IDictionaryEnumerator e = prefixes.GetEnumerator ();
410                         while (e.MoveNext ()) {
411                                 string key = e.Key as string;
412
413                                 if (key.Length <= longestPrefix) 
414                                         continue;
415                                 
416                                 if (!prefix.StartsWith (key))
417                                         continue;
418                                         
419                                 longestPrefix = key.Length;
420                                 creator = (IWebRequestCreate) e.Value;
421                         }
422                         
423                         if (creator == null) 
424                                 throw new NotSupportedException (prefix);
425                                 
426                         return creator;
427                 }
428
429                 internal static void ClearPrefixes ()
430                 {
431                         prefixes.Clear ();
432                 }
433
434                 internal static void RemovePrefix (string prefix)
435                 {
436                         prefixes.Remove (prefix);
437                 }
438
439                 internal static void AddPrefix (string prefix, string typeName)
440                 {
441                         Type type = Type.GetType (typeName);
442                         if (type == null)
443                                 throw new ConfigurationException (String.Format ("Type {0} not found", typeName));
444                         AddPrefix (prefix, type);
445                 }
446
447                 internal static void AddPrefix (string prefix, Type type)
448                 {
449                         object o = Activator.CreateInstance (type, true);
450                         prefixes [prefix] = o;
451                 }
452         }
453 }
454