Flush (work in progress)
[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.Runtime.Serialization;
35 using System.Globalization;
36 #if NET_2_0
37 using System.Net.Configuration;
38 using System.Net.Security;
39 using System.Net.Cache;
40 using System.Security.Principal;
41 #endif
42
43 #if NET_2_1
44 using ConfigurationException = System.ArgumentException;
45
46 namespace System.Net.Configuration {
47         class Dummy {}
48 }
49 #endif
50
51 namespace System.Net 
52 {
53 #if MOONLIGHT
54         internal abstract class WebRequest : ISerializable {
55 #else
56         [Serializable]
57         public abstract class WebRequest : MarshalByRefObject, ISerializable {
58 #endif
59                 static HybridDictionary prefixes = new HybridDictionary ();
60 #if NET_2_0
61                 static bool isDefaultWebProxySet;
62                 static IWebProxy defaultWebProxy;
63 #endif
64                 
65                 // Constructors
66                 
67                 static WebRequest ()
68                 {
69 #if NET_2_1
70                         AddPrefix ("http", typeof (HttpRequestCreator));
71                         AddPrefix ("https", typeof (HttpRequestCreator));
72         #if MONOTOUCH
73                         AddPrefix ("file", typeof (FileWebRequestCreator));
74                         AddPrefix ("ftp", typeof (FtpRequestCreator));
75         #endif
76 #else
77         #if NET_2_0 && CONFIGURATION_DEP
78                         object cfg = ConfigurationManager.GetSection ("system.net/webRequestModules");
79                         WebRequestModulesSection s = cfg as WebRequestModulesSection;
80                         if (s != null) {
81                                 foreach (WebRequestModuleElement el in
82                                          s.WebRequestModules)
83                                         AddPrefix (el.Prefix, el.Type);
84                                 return;
85                         }
86         #endif
87                         ConfigurationSettings.GetConfig ("system.net/webRequestModules");
88 #endif
89                 }
90                 
91                 protected WebRequest () 
92                 {
93                 }
94                 
95                 protected WebRequest (SerializationInfo serializationInfo, StreamingContext streamingContext) 
96                 {
97 #if ONLY_1_1
98                         throw GetMustImplement ();
99 #endif
100                 }
101
102                 static Exception GetMustImplement ()
103                 {
104                         return new NotImplementedException ("This method must be implemented in derived classes");
105                 }
106                 
107                 // Properties
108
109 #if NET_2_0
110                 private AuthenticationLevel authentication_level = AuthenticationLevel.MutualAuthRequested;
111                 
112                 public AuthenticationLevel AuthenticationLevel
113                 {
114                         get {
115                                 return(authentication_level);
116                         }
117                         set {
118                                 authentication_level = value;
119                         }
120                 }
121
122                 public virtual RequestCachePolicy CachePolicy
123                 {
124                         get {
125                                 throw GetMustImplement ();
126                         }
127                         set {
128                         }
129                 }
130 #endif
131                 
132                 public virtual string ConnectionGroupName {
133                         get { throw GetMustImplement (); }
134                         set { throw GetMustImplement (); }
135                 }
136                 
137                 public virtual long ContentLength { 
138                         get { throw GetMustImplement (); }
139                         set { throw GetMustImplement (); }
140                 }
141                 
142                 public virtual string ContentType { 
143                         get { throw GetMustImplement (); }
144                         set { throw GetMustImplement (); }
145                 }
146                 
147                 public virtual ICredentials Credentials { 
148                         get { throw GetMustImplement (); }
149                         set { throw GetMustImplement (); }
150                 }
151
152 #if NET_2_0
153                 public static RequestCachePolicy DefaultCachePolicy
154                 {
155                         get {
156                                 throw GetMustImplement ();
157                         }
158                         set {
159                                 throw GetMustImplement ();
160                         }
161                 }
162 #endif
163                 
164                 public virtual WebHeaderCollection Headers { 
165                         get { throw GetMustImplement (); }
166                         set { throw GetMustImplement (); }
167                 }
168                 
169 #if NET_2_0 && !MOONLIGHT
170                 public TokenImpersonationLevel ImpersonationLevel {
171                         get { throw GetMustImplement (); }
172                         set { throw GetMustImplement (); }
173                 }
174 #endif
175                 public virtual string Method { 
176                         get { throw GetMustImplement (); }
177                         set { throw GetMustImplement (); }
178                 }
179                 
180                 public virtual bool PreAuthenticate { 
181                         get { throw GetMustImplement (); }
182                         set { throw GetMustImplement (); }
183                 }
184                 
185                 public virtual IWebProxy Proxy { 
186                         get { throw GetMustImplement (); }
187                         set { throw GetMustImplement (); }
188                 }
189                 
190                 public virtual Uri RequestUri { 
191                         get { throw GetMustImplement (); }
192                 }
193                 
194                 public virtual int Timeout { 
195                         get { throw GetMustImplement (); }
196                         set { throw GetMustImplement (); }
197                 }
198                 
199 #if NET_2_0
200                 public virtual bool UseDefaultCredentials
201                 {
202                         get {
203                                 throw GetMustImplement ();
204                         }
205                         set {
206                                 throw GetMustImplement ();
207                         }
208                 }
209                 
210 //              volatile static IWebProxy proxy;
211                 static readonly object lockobj = new object ();
212                 
213                 public static IWebProxy DefaultWebProxy {
214                         get {
215                                 if (!isDefaultWebProxySet) {
216                                         lock (lockobj) {
217                                                 if (defaultWebProxy == null)
218                                                         defaultWebProxy = GetDefaultWebProxy ();
219                                         }
220                                 }
221                                 return defaultWebProxy;
222                         }
223                         set {
224                                 /* MS documentation states that a null value would cause an ArgumentNullException
225                                  * but that's not the way it behaves:
226                                  * https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=304724
227                                  */
228                                 defaultWebProxy = value;
229                                 isDefaultWebProxySet = true;
230                         }
231                 }
232                 
233                 [MonoTODO("Needs to respect Module, Proxy.AutoDetect, and Proxy.ScriptLocation config settings")]
234                 static IWebProxy GetDefaultWebProxy ()
235                 {
236                         WebProxy p = null;
237                         
238 #if CONFIGURATION_DEP
239                         DefaultProxySection sec = ConfigurationManager.GetSection ("system.net/defaultProxy") as DefaultProxySection;
240                         if (sec == null)
241                                 return GetSystemWebProxy ();
242                         
243                         ProxyElement pe = sec.Proxy;
244                         
245                         if ((pe.UseSystemDefault != ProxyElement.UseSystemDefaultValues.False) && (pe.ProxyAddress == null))
246                                 p = (WebProxy) GetSystemWebProxy ();
247                         else
248                                 p = new WebProxy ();
249                         
250                         if (pe.ProxyAddress != null)
251                                 p.Address = pe.ProxyAddress;
252                         
253                         if (pe.BypassOnLocal != ProxyElement.BypassOnLocalValues.Unspecified)
254                                 p.BypassProxyOnLocal = (pe.BypassOnLocal == ProxyElement.BypassOnLocalValues.True);
255 #endif
256                         return p;
257                 }
258 #endif
259
260                 // Methods
261                 
262                 public virtual void Abort()
263                 {
264                         throw GetMustImplement ();
265                 }
266                 
267                 public virtual IAsyncResult BeginGetRequestStream (AsyncCallback callback, object state) 
268                 {
269                         throw GetMustImplement ();
270                 }
271                 
272                 public virtual IAsyncResult BeginGetResponse (AsyncCallback callback, object state)
273                 {
274                         throw GetMustImplement ();
275                 }
276
277                 public static WebRequest Create (string requestUriString) 
278                 {
279                         if (requestUriString == null)
280                                 throw new ArgumentNullException ("requestUriString");
281                         return Create (new Uri (requestUriString));
282                 }
283                                 
284                 public static WebRequest Create (Uri requestUri) 
285                 {
286                         if (requestUri == null)
287                                 throw new ArgumentNullException ("requestUri");
288                         return GetCreator (requestUri.AbsoluteUri).Create (requestUri);
289                 }
290                 
291                 public static WebRequest CreateDefault (Uri requestUri)
292                 {
293                         if (requestUri == null)
294                                 throw new ArgumentNullException ("requestUri");
295                         return GetCreator (requestUri.Scheme).Create (requestUri);
296                 }
297
298                 public virtual Stream EndGetRequestStream (IAsyncResult asyncResult)
299                 {
300                         throw GetMustImplement ();
301                 }
302                 
303                 public virtual WebResponse EndGetResponse (IAsyncResult asyncResult)
304                 {
305                         throw GetMustImplement ();
306                 }
307                 
308                 public virtual Stream GetRequestStream()
309                 {
310                         throw GetMustImplement ();
311                 }
312                 
313                 public virtual WebResponse GetResponse()
314                 {
315                         throw GetMustImplement ();
316                 }
317                 
318 #if NET_2_0
319                 [MonoTODO("Look in other places for proxy config info")]
320                 public static IWebProxy GetSystemWebProxy ()
321                 {
322                         string address = Environment.GetEnvironmentVariable ("http_proxy");
323                         if (address == null)
324                                 address = Environment.GetEnvironmentVariable ("HTTP_PROXY");
325
326                         if (address != null) {
327                                 try {
328                                         if (!address.StartsWith ("http://"))
329                                                 address = "http://" + address;
330                                         Uri uri = new Uri (address);
331                                         IPAddress ip;
332                                         if (IPAddress.TryParse (uri.Host, out ip)) {
333                                                 if (IPAddress.Any.Equals (ip)) {
334                                                         UriBuilder builder = new UriBuilder (uri);
335                                                         builder.Host = "127.0.0.1";
336                                                         uri = builder.Uri;
337                                                 } else if (IPAddress.IPv6Any.Equals (ip)) {
338                                                         UriBuilder builder = new UriBuilder (uri);
339                                                         builder.Host = "[::1]";
340                                                         uri = builder.Uri;
341                                                 }
342                                         }
343                                         return new WebProxy (uri);
344                                 } catch (UriFormatException) { }
345                         }
346                         return new WebProxy ();
347                 }
348 #endif
349
350                 void ISerializable.GetObjectData
351                 (SerializationInfo serializationInfo,
352                                                   StreamingContext streamingContext)
353                 {
354                         throw new NotSupportedException ();
355                 }
356
357
358 #if NET_2_0
359                 protected virtual void GetObjectData (SerializationInfo serializationInfo, StreamingContext streamingContext)
360                 {
361                         throw GetMustImplement ();
362                 }
363 #endif
364
365                 public static bool RegisterPrefix (string prefix, IWebRequestCreate creator)
366                 {
367                         if (prefix == null)
368                                 throw new ArgumentNullException ("prefix");
369                         if (creator == null)
370                                 throw new ArgumentNullException ("creator");
371                         
372                         lock (prefixes.SyncRoot) {
373                                 string lowerCasePrefix = prefix.ToLower (CultureInfo.InvariantCulture);
374                                 if (prefixes.Contains (lowerCasePrefix))
375                                         return false;
376                                 prefixes.Add (lowerCasePrefix, creator);
377                         }
378                         return true;
379                 }
380                 
381                 private static IWebRequestCreate GetCreator (string prefix)
382                 {
383                         int longestPrefix = -1;
384                         IWebRequestCreate creator = null;
385
386                         prefix = prefix.ToLower (CultureInfo.InvariantCulture);
387
388                         IDictionaryEnumerator e = prefixes.GetEnumerator ();
389                         while (e.MoveNext ()) {
390                                 string key = e.Key as string;
391
392                                 if (key.Length <= longestPrefix) 
393                                         continue;
394                                 
395                                 if (!prefix.StartsWith (key))
396                                         continue;
397                                         
398                                 longestPrefix = key.Length;
399                                 creator = (IWebRequestCreate) e.Value;
400                         }
401                         
402                         if (creator == null) 
403                                 throw new NotSupportedException (prefix);
404                                 
405                         return creator;
406                 }
407
408                 internal static void ClearPrefixes ()
409                 {
410                         prefixes.Clear ();
411                 }
412
413                 internal static void RemovePrefix (string prefix)
414                 {
415                         prefixes.Remove (prefix);
416                 }
417
418                 internal static void AddPrefix (string prefix, string typeName)
419                 {
420                         Type type = Type.GetType (typeName);
421                         if (type == null)
422                                 throw new ConfigurationException (String.Format ("Type {0} not found", typeName));
423                         AddPrefix (prefix, type);
424                 }
425
426                 internal static void AddPrefix (string prefix, Type type)
427                 {
428                         object o = Activator.CreateInstance (type, true);
429                         prefixes [prefix] = o;
430                 }
431         }
432 }
433