2009-06-12 Bill Holmes <billholmes54@gmail.com>
[mono.git] / mcs / class / System / System.Net / WebClient.cs
1 //
2 // System.Net.WebClient
3 //
4 // Authors:
5 //      Lawrence Pit (loz@cable.a2000.nl)
6 //      Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 //      Atsushi Enomoto (atsushi@ximian.com)
8 //      Miguel de Icaza (miguel@ximian.com)
9 //
10 // Copyright 2003 Ximian, Inc. (http://www.ximian.com)
11 // Copyright 2006, 2007 Novell, Inc. (http://www.novell.com)
12 //
13 //
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
21 // 
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
24 // 
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 //
33 //
34 // Notes on CancelAsync and Async methods:
35 //
36 //    WebClient.CancelAsync is implemented by calling Thread.Interrupt
37 //    in our helper thread.   The various async methods have to cancel
38 //    any ongoing requests by calling request.Abort () at that point.
39 //    In a few places (UploadDataCore, UploadValuesCore,
40 //    UploadFileCore) we catch the ThreadInterruptedException and
41 //    abort the request there.
42 //
43 //    Higher level routines (the async callbacks) also need to catch
44 //    the exception and raise the OnXXXXCompleted events there with
45 //    the "canceled" flag set to true. 
46 //
47 //    In a few other places where these helper routines are not used
48 //    (OpenReadAsync for example) catching the ThreadAbortException
49 //    also must abort the request.
50 //
51 //    The Async methods currently differ in their implementation from
52 //    the .NET implementation in that we manually catch any other
53 //    exceptions and correctly raise the OnXXXXCompleted passing the
54 //    Exception that caused the problem.   The .NET implementation
55 //    does not seem to have a mechanism to flag errors that happen
56 //    during downloads though.    We do this because we still need to
57 //    catch the exception on these helper threads, or we would
58 //    otherwise kill the application (on the 2.x profile, uncaught
59 //    exceptions in threads terminate the application).
60 //
61 using System;
62 using System.Collections.Specialized;
63 using System.ComponentModel;
64 using System.IO;
65 using System.Runtime.InteropServices;
66 using System.Runtime.Serialization;
67 using System.Text;
68 using System.Threading;
69 #if NET_2_0
70 using System.Net.Cache;
71 #endif
72
73 namespace System.Net 
74 {
75         [ComVisible(true)]
76         public
77 #if !NET_2_0
78         sealed
79 #endif
80         class WebClient : Component
81         {
82                 static readonly string urlEncodedCType = "application/x-www-form-urlencoded";
83                 static byte [] hexBytes;
84                 ICredentials credentials;
85                 WebHeaderCollection headers;
86                 WebHeaderCollection responseHeaders;
87                 Uri baseAddress;
88                 string baseString;
89                 NameValueCollection queryString;
90                 bool is_busy;
91 #if NET_2_0
92                 bool async;
93                 Thread async_thread;
94                 Encoding encoding = Encoding.Default;
95                 IWebProxy proxy;
96 #endif
97
98                 // Constructors
99                 static WebClient ()
100                 {
101                         hexBytes = new byte [16];
102                         int index = 0;
103                         for (int i = '0'; i <= '9'; i++, index++)
104                                 hexBytes [index] = (byte) i;
105
106                         for (int i = 'A'; i <= 'F'; i++, index++)
107                                 hexBytes [index] = (byte) i;
108                 }
109                 
110                 public WebClient ()
111                 {
112                 }
113                 
114                 // Properties
115                 
116                 public string BaseAddress {
117                         get {
118                                 if (baseString == null) {
119                                         if (baseAddress == null)
120                                                 return "";
121                                 }
122
123                                 baseString = baseAddress.ToString ();
124                                 return baseString;
125                         }
126                         
127                         set {
128                                 if (value == null || value == "") {
129                                         baseAddress = null;
130                                 } else {
131                                         baseAddress = new Uri (value);
132                                 }
133                         }
134                 }
135
136 #if NET_2_0
137                 static Exception GetMustImplement ()
138                 {
139                         return new NotImplementedException ();
140                 }
141                 
142                 [MonoTODO]
143                 public RequestCachePolicy CachePolicy
144                 {
145                         get {
146                                 throw GetMustImplement ();
147                         }
148                         set {
149                                 throw GetMustImplement ();
150                         }
151                 }
152
153                 [MonoTODO]
154                 public bool UseDefaultCredentials
155                 {
156                         get {
157                                 throw GetMustImplement ();
158                         }
159                         set {
160                                 throw GetMustImplement ();
161                         }
162                 }
163 #endif
164                 
165                 public ICredentials Credentials {
166                         get { return credentials; }
167                         set { credentials = value; }
168                 }
169
170                 public WebHeaderCollection Headers {
171                         get {
172                                 if (headers == null)
173                                         headers = new WebHeaderCollection ();
174
175                                 return headers;
176                         }
177                         set { headers = value; }
178                 }
179                 
180                 public NameValueCollection QueryString {
181                         get {
182                                 if (queryString == null)
183                                         queryString = new NameValueCollection ();
184
185                                 return queryString;
186                         }
187                         set { queryString = value; }
188                 }
189                 
190                 public WebHeaderCollection ResponseHeaders {
191                         get { return responseHeaders; }
192                 }
193
194 #if NET_2_0
195                 public Encoding Encoding {
196                         get { return encoding; }
197                         set {
198                                 if (value == null)
199                                         throw new ArgumentNullException ("value");
200                                 encoding = value;
201                         }
202                 }
203
204                 public IWebProxy Proxy {
205                         get { return proxy; }
206                         set { proxy = value; }
207                 }
208 #endif
209
210 #if NET_2_0
211                 public bool IsBusy {
212                         get { return is_busy; } 
213                 }
214 #else
215                 bool IsBusy {
216                         get { return is_busy; }
217                 }
218 #endif
219
220                 // Methods
221
222                 void CheckBusy ()
223                 {
224                         if (IsBusy)
225                                 throw new NotSupportedException ("WebClient does not support conccurent I/O operations.");
226                 }
227
228                 void SetBusy ()
229                 {
230                         lock (this) {
231                                 CheckBusy ();
232                                 is_busy = true;
233                         }
234                 }
235
236                 //   DownloadData
237
238                 public byte [] DownloadData (string address)
239                 {
240 #if NET_2_0
241                         if (address == null)
242                                 throw new ArgumentNullException ("address");
243 #endif
244
245                         return DownloadData (CreateUri (address));
246                 }
247
248 #if NET_2_0
249                 public
250 #endif
251                 byte [] DownloadData (Uri address)
252                 {
253 #if NET_2_0
254                         if (address == null)
255                                 throw new ArgumentNullException ("address");
256 #endif
257
258                         try {
259                                 SetBusy ();
260 #if NET_2_0                             
261                                 async = false;
262 #endif                          
263                                 return DownloadDataCore (address, null);
264                         } finally {
265                                 is_busy = false;
266                         }
267                 }
268
269                 byte [] DownloadDataCore (Uri address, object userToken)
270                 {
271                         WebRequest request = null;
272                         
273                         try {
274                                 request = SetupRequest (address);
275                                 WebResponse response = request.GetResponse ();
276                                 Stream st = ProcessResponse (response);
277                                 return ReadAll (st, (int) response.ContentLength, userToken);
278                         } catch (ThreadInterruptedException){
279                                 if (request != null)
280                                         request.Abort ();
281                                 throw;
282                         } catch (Exception ex) {
283                                 throw new WebException ("An error occurred " +
284                                         "performing a WebClient request.", ex);
285                         }
286                 }
287
288                 //   DownloadFile
289
290                 public void DownloadFile (string address, string fileName)
291                 {
292 #if NET_2_0
293                         if (address == null)
294                                 throw new ArgumentNullException ("address");
295 #endif
296
297                         DownloadFile (CreateUri (address), fileName);
298                 }
299
300 #if NET_2_0
301                 public
302 #endif
303                 void DownloadFile (Uri address, string fileName)
304                 {
305 #if NET_2_0
306                         if (address == null)
307                                 throw new ArgumentNullException ("address");
308                         if (fileName == null)
309                                 throw new ArgumentNullException ("fileName");
310 #endif
311
312                         try {
313                                 SetBusy ();
314 #if NET_2_0                             
315                                 async = false;
316 #endif                          
317                                 DownloadFileCore (address, fileName, null);
318                         } catch (Exception ex) {
319                                 throw new WebException ("An error occurred " +
320                                         "performing a WebClient request.", ex);
321                         } finally {
322                                 is_busy = false;
323                         }
324                 }
325
326                 void DownloadFileCore (Uri address, string fileName, object userToken)
327                 {
328                         WebRequest request = null;
329                         
330                         using (FileStream f = new FileStream (fileName, FileMode.Create)) {
331                                 try {
332                                         request = SetupRequest (address);
333                                         WebResponse response = request.GetResponse ();
334                                         Stream st = ProcessResponse (response);
335                                         
336                                         int cLength = (int) response.ContentLength;
337                                         int length = (cLength <= -1 || cLength > 32*1024) ? 32*1024 : cLength;
338                                         byte [] buffer = new byte [length];
339                                         
340                                         int nread = 0;
341 #if NET_2_0
342                                         long notify_total = 0;
343 #endif                                  
344                                         while ((nread = st.Read (buffer, 0, length)) != 0){
345 #if NET_2_0
346                                                 if (async){
347                                                         notify_total += nread;
348                                                         OnDownloadProgressChanged (
349                                                                 new DownloadProgressChangedEventArgs (notify_total, response.ContentLength, userToken));
350                                                                                                       
351                                                 }
352 #endif
353                                                 f.Write (buffer, 0, nread);
354                                         }
355                                 } catch (ThreadInterruptedException){
356                                         if (request != null)
357                                                 request.Abort ();
358                                         throw;
359                                 }
360                         }
361                 }
362
363                 //   OpenRead
364
365                 public Stream OpenRead (string address)
366                 {
367 #if NET_2_0
368                         if (address == null)
369                                 throw new ArgumentNullException ("address");
370 #endif
371
372                         return OpenRead (CreateUri (address));
373                 }
374
375 #if NET_2_0
376                 public
377 #endif
378                 Stream OpenRead (Uri address)
379                 {
380 #if NET_2_0
381                         if (address == null)
382                                 throw new ArgumentNullException ("address");
383 #endif
384
385                         WebRequest request = null;
386                         try {
387                                 SetBusy ();
388 #if NET_2_0                             
389                                 async = false;
390 #endif                          
391                                 request = SetupRequest (address);
392                                 WebResponse response = request.GetResponse ();
393                                 return ProcessResponse (response);
394                         } catch (Exception ex) {
395                                 throw new WebException ("An error occurred " +
396                                         "performing a WebClient request.", ex);
397                         } finally {
398                                 is_busy = false;
399                         }
400                 }
401
402                 //   OpenWrite
403
404                 public Stream OpenWrite (string address)
405                 {
406 #if NET_2_0
407                         if (address == null)
408                                 throw new ArgumentNullException ("address");
409 #endif
410
411                         return OpenWrite (CreateUri (address));
412                 }
413                 
414                 public Stream OpenWrite (string address, string method)
415                 {
416 #if NET_2_0
417                         if (address == null)
418                                 throw new ArgumentNullException ("address");
419 #endif
420
421                         return OpenWrite (CreateUri (address), method);
422                 }
423
424 #if NET_2_0
425                 public
426 #endif
427                 Stream OpenWrite (Uri address)
428                 {
429                         return OpenWrite (address, (string) null);
430                 }
431
432 #if NET_2_0
433                 public
434 #endif
435                 Stream OpenWrite (Uri address, string method)
436                 {
437 #if NET_2_0
438                         if (address == null)
439                                 throw new ArgumentNullException ("address");
440 #endif
441
442                         try {
443                                 SetBusy ();
444 #if NET_2_0                             
445                                 async = false;
446 #endif                          
447                                 WebRequest request = SetupRequest (address, method, true);
448                                 return request.GetRequestStream ();
449                         } catch (Exception ex) {
450                                 throw new WebException ("An error occurred " +
451                                         "performing a WebClient request.", ex);
452                         } finally {
453                                 is_busy = false;
454                         }
455                 }
456
457                 private string DetermineMethod (Uri address, string method, bool is_upload)
458                 {
459                         if (method != null)
460                                 return method;
461
462 #if NET_2_0
463                         if (address.Scheme == Uri.UriSchemeFtp)
464                                 return (is_upload) ? "STOR" : "RETR";
465 #endif
466                         return (is_upload) ? "POST" : "GET";
467                 }
468
469                 //   UploadData
470
471                 public byte [] UploadData (string address, byte [] data)
472                 {
473 #if NET_2_0
474                         if (address == null)
475                                 throw new ArgumentNullException ("address");
476 #endif
477
478                         return UploadData (CreateUri (address), data);
479                 }
480                 
481                 public byte [] UploadData (string address, string method, byte [] data)
482                 {
483 #if NET_2_0
484                         if (address == null)
485                                 throw new ArgumentNullException ("address");
486 #endif
487
488                         return UploadData (CreateUri (address), method, data);
489                 }
490
491 #if NET_2_0
492                 public
493 #endif
494                 byte [] UploadData (Uri address, byte [] data)
495                 {
496                         return UploadData (address, (string) null, data);
497                 }
498
499 #if NET_2_0
500                 public
501 #endif
502                 byte [] UploadData (Uri address, string method, byte [] data)
503                 {
504 #if NET_2_0
505                         if (address == null)
506                                 throw new ArgumentNullException ("address");
507                         if (data == null)
508                                 throw new ArgumentNullException ("data");
509 #endif
510
511                         try {
512                                 SetBusy ();
513 #if NET_2_0                             
514                                 async = false;
515 #endif                          
516                                 return UploadDataCore (address, method, data, null);
517                         } catch (WebException) {
518                                 throw;
519                         } catch (Exception ex) {
520                                 throw new WebException ("An error occurred " +
521                                         "performing a WebClient request.", ex);
522                         } finally {
523                                 is_busy = false;
524                         }
525                 }
526
527                 byte [] UploadDataCore (Uri address, string method, byte [] data, object userToken)
528                 {
529 #if ONLY_1_1
530                         if (address == null)
531                                 throw new ArgumentNullException ("address");
532                         if (data == null)
533                                 throw new ArgumentNullException ("data");
534 #endif
535
536                         WebRequest request = SetupRequest (address, method, true);
537                         try {
538                                 int contentLength = data.Length;
539                                 request.ContentLength = contentLength;
540                                 using (Stream stream = request.GetRequestStream ()) {
541                                         stream.Write (data, 0, contentLength);
542                                 }
543                                 
544                                 WebResponse response = request.GetResponse ();
545                                 Stream st = ProcessResponse (response);
546                                 return ReadAll (st, (int) response.ContentLength, userToken);
547                         } catch (ThreadInterruptedException){
548                                 if (request != null)
549                                         request.Abort ();
550                                 throw;
551                         }
552                 }
553
554                 //   UploadFile
555
556                 public byte [] UploadFile (string address, string fileName)
557                 {
558 #if NET_2_0
559                         if (address == null)
560                                 throw new ArgumentNullException ("address");
561 #endif
562
563                         return UploadFile (CreateUri (address), fileName);
564                 }
565
566 #if NET_2_0
567                 public
568 #endif
569                 byte [] UploadFile (Uri address, string fileName)
570                 {
571                         return UploadFile (address, (string) null, fileName);
572                 }
573                 
574                 public byte [] UploadFile (string address, string method, string fileName)
575                 {
576                         return UploadFile (CreateUri (address), method, fileName);
577                 }
578
579 #if NET_2_0
580                 public
581 #endif
582                 byte [] UploadFile (Uri address, string method, string fileName)
583                 {
584 #if NET_2_0
585                         if (address == null)
586                                 throw new ArgumentNullException ("address");
587                         if (fileName == null)
588                                 throw new ArgumentNullException ("fileName");
589 #endif
590
591                         try {
592                                 SetBusy ();
593 #if NET_2_0                             
594                                 async = false;
595 #endif                          
596                                 return UploadFileCore (address, method, fileName, null);
597                         } catch (Exception ex) {
598                                 throw new WebException ("An error occurred " +
599                                         "performing a WebClient request.", ex);
600                         } finally {
601                                 is_busy = false;
602                         }
603                 }
604
605                 byte [] UploadFileCore (Uri address, string method, string fileName, object userToken)
606                 {
607 #if ONLY_1_1
608                         if (address == null)
609                                 throw new ArgumentNullException ("address");
610 #endif
611
612                         string fileCType = Headers ["Content-Type"];
613                         if (fileCType != null) {
614                                 string lower = fileCType.ToLower ();
615                                 if (lower.StartsWith ("multipart/"))
616                                         throw new WebException ("Content-Type cannot be set to a multipart" +
617                                                                 " type for this request.");
618                         } else {
619                                 fileCType = "application/octet-stream";
620                         }
621
622                         string boundary = "------------" + DateTime.Now.Ticks.ToString ("x");
623                         Headers ["Content-Type"] = String.Format ("multipart/form-data; boundary={0}", boundary);
624                         Stream reqStream = null;
625                         Stream fStream = null;
626                         byte [] resultBytes = null;
627
628                         fileName = Path.GetFullPath (fileName);
629
630                         WebRequest request = null;
631                         try {
632                                 fStream = File.OpenRead (fileName);
633                                 request = SetupRequest (address, method, true);
634                                 reqStream = request.GetRequestStream ();
635                                 byte [] realBoundary = Encoding.ASCII.GetBytes ("--" + boundary + "\r\n");
636                                 reqStream.Write (realBoundary, 0, realBoundary.Length);
637                                 string partHeaders = String.Format ("Content-Disposition: form-data; " +
638                                                                     "name=\"file\"; filename=\"{0}\"\r\n" +
639                                                                     "Content-Type: {1}\r\n\r\n",
640                                                                     Path.GetFileName (fileName), fileCType);
641
642                                 byte [] partHeadersBytes = Encoding.UTF8.GetBytes (partHeaders);
643                                 reqStream.Write (partHeadersBytes, 0, partHeadersBytes.Length);
644                                 int nread;
645                                 byte [] buffer = new byte [4096];
646                                 while ((nread = fStream.Read (buffer, 0, 4096)) != 0)
647                                         reqStream.Write (buffer, 0, nread);
648
649                                 reqStream.WriteByte ((byte) '\r');
650                                 reqStream.WriteByte ((byte) '\n');
651                                 reqStream.Write (realBoundary, 0, realBoundary.Length);
652                                 reqStream.Close ();
653                                 reqStream = null;
654                                 WebResponse response = request.GetResponse ();
655                                 Stream st = ProcessResponse (response);
656                                 resultBytes = ReadAll (st, (int) response.ContentLength, userToken);
657                         } catch (ThreadInterruptedException){
658                                 if (request != null)
659                                         request.Abort ();
660                                 throw;
661                         } finally {
662                                 if (fStream != null)
663                                         fStream.Close ();
664
665                                 if (reqStream != null)
666                                         reqStream.Close ();
667                         }
668                         
669                         return resultBytes;
670                 }
671                 
672                 public byte[] UploadValues (string address, NameValueCollection data)
673                 {
674 #if NET_2_0
675                         if (address == null)
676                                 throw new ArgumentNullException ("address");
677 #endif
678
679                         return UploadValues (CreateUri (address), data);
680                 }
681                 
682                 public byte[] UploadValues (string address, string method, NameValueCollection data)
683                 {
684 #if NET_2_0
685                         if (address == null)
686                                 throw new ArgumentNullException ("address");
687 #endif
688
689                         return UploadValues (CreateUri (address), method, data);
690                 }
691
692 #if NET_2_0
693                 public
694 #endif
695                 byte[] UploadValues (Uri address, NameValueCollection data)
696                 {
697                         return UploadValues (address, (string) null, data);
698                 }
699
700 #if NET_2_0
701                 public
702 #endif
703                 byte[] UploadValues (Uri address, string method, NameValueCollection data)
704                 {
705 #if NET_2_0
706                         if (address == null)
707                                 throw new ArgumentNullException ("address");
708                         if (data == null)
709                                 throw new ArgumentNullException ("data");
710 #endif
711
712                         try {
713                                 SetBusy ();
714 #if NET_2_0                             
715                                 async = false;
716 #endif                          
717                                 return UploadValuesCore (address, method, data, null);
718                         } catch (Exception ex) {
719                                 throw new WebException ("An error occurred " +
720                                         "performing a WebClient request.", ex);
721                         } finally {
722                                 is_busy = false;
723                         }
724                 }
725
726                 byte[] UploadValuesCore (Uri uri, string method, NameValueCollection data, object userToken)
727                 {
728 #if ONLY_1_1
729                         if (data == null)
730                                 throw new ArgumentNullException ("data");
731 #endif
732
733                         string cType = Headers ["Content-Type"];
734                         if (cType != null && String.Compare (cType, urlEncodedCType, true) != 0)
735                                 throw new WebException ("Content-Type header cannot be changed from its default " +
736                                                         "value for this request.");
737
738                         Headers ["Content-Type"] = urlEncodedCType;
739                         WebRequest request = SetupRequest (uri, method, true);
740                         try {
741                                 Stream rqStream = request.GetRequestStream ();
742                                 MemoryStream tmpStream = new MemoryStream ();
743                                 foreach (string key in data) {
744                                         byte [] bytes = Encoding.UTF8.GetBytes (key);
745                                         UrlEncodeAndWrite (tmpStream, bytes);
746                                         tmpStream.WriteByte ((byte) '=');
747                                         bytes = Encoding.UTF8.GetBytes (data [key]);
748                                         UrlEncodeAndWrite (tmpStream, bytes);
749                                         tmpStream.WriteByte ((byte) '&');
750                                 }
751                                 
752                                 int length = (int) tmpStream.Length;
753                                 if (length > 0)
754                                         tmpStream.SetLength (--length); // remove trailing '&'
755                                 
756                                 byte [] buf = tmpStream.GetBuffer ();
757                                 rqStream.Write (buf, 0, length);
758                                 rqStream.Close ();
759                                 tmpStream.Close ();
760                                 
761                                 WebResponse response = request.GetResponse ();
762                                 Stream st = ProcessResponse (response);
763                                 return ReadAll (st, (int) response.ContentLength, userToken);
764                         } catch (ThreadInterruptedException) {
765                                 request.Abort ();
766                                 throw;
767                         }
768                 }
769
770 #if NET_2_0
771                 public string DownloadString (string address)
772                 {
773                         if (address == null)
774                                 throw new ArgumentNullException ("address");
775
776                         return encoding.GetString (DownloadData (CreateUri (address)));
777                 }
778
779                 public string DownloadString (Uri address)
780                 {
781                         if (address == null)
782                                 throw new ArgumentNullException ("address");
783
784                         return encoding.GetString (DownloadData (CreateUri (address)));
785                 }
786
787                 public string UploadString (string address, string data)
788                 {
789                         if (address == null)
790                                 throw new ArgumentNullException ("address");
791                         if (data == null)
792                                 throw new ArgumentNullException ("data");
793
794                         byte [] resp = UploadData (address, encoding.GetBytes (data));
795                         return encoding.GetString (resp);
796                 }
797
798                 public string UploadString (string address, string method, string data)
799                 {
800                         if (address == null)
801                                 throw new ArgumentNullException ("address");
802                         if (data == null)
803                                 throw new ArgumentNullException ("data");
804
805                         byte [] resp = UploadData (address, method, encoding.GetBytes (data));
806                         return encoding.GetString (resp);
807                 }
808
809                 public string UploadString (Uri address, string data)
810                 {
811                         if (address == null)
812                                 throw new ArgumentNullException ("address");
813                         if (data == null)
814                                 throw new ArgumentNullException ("data");
815
816                         byte [] resp = UploadData (address, encoding.GetBytes (data));
817                         return encoding.GetString (resp);
818                 }
819
820                 public string UploadString (Uri address, string method, string data)
821                 {
822                         if (address == null)
823                                 throw new ArgumentNullException ("address");
824                         if (data == null)
825                                 throw new ArgumentNullException ("data");
826
827                         byte [] resp = UploadData (address, method, encoding.GetBytes (data));
828                         return encoding.GetString (resp);
829                 }
830
831                 public event DownloadDataCompletedEventHandler DownloadDataCompleted;
832                 public event AsyncCompletedEventHandler DownloadFileCompleted;
833                 public event DownloadProgressChangedEventHandler DownloadProgressChanged;
834                 public event DownloadStringCompletedEventHandler DownloadStringCompleted;
835                 public event OpenReadCompletedEventHandler OpenReadCompleted;
836                 public event OpenWriteCompletedEventHandler OpenWriteCompleted;
837                 public event UploadDataCompletedEventHandler UploadDataCompleted;
838                 public event UploadFileCompletedEventHandler UploadFileCompleted;
839                 public event UploadProgressChangedEventHandler UploadProgressChanged;
840                 public event UploadStringCompletedEventHandler UploadStringCompleted;
841                 public event UploadValuesCompletedEventHandler UploadValuesCompleted;
842 #endif
843
844                 Uri CreateUri (string address)
845                 {
846 #if ONLY_1_1
847                         try {
848                                 return MakeUri (address);
849                         } catch (Exception ex) {
850                                 throw new WebException ("An error occurred " +
851                                         "performing a WebClient request.", ex);
852                         }
853 #else
854                         return MakeUri (address);
855 #endif
856                 }
857
858 #if NET_2_0
859                 Uri CreateUri (Uri address)
860                 {
861                         string query = address.Query;
862                         if (String.IsNullOrEmpty (query))
863                                 query = GetQueryString (true);
864
865                         if (baseAddress == null && query == null)
866                                 return address;
867
868                         if (baseAddress == null)
869                                 return new Uri (address.ToString () + query, (query != null));
870
871                         if (query == null)
872                                 return new Uri (baseAddress, address.ToString ());
873
874                         return new Uri (baseAddress, address.ToString () + query, (query != null));
875
876                 }
877 #endif
878
879                 string GetQueryString (bool add_qmark)
880                 {
881                         if (queryString == null || queryString.Count == 0)
882                                 return null;
883
884                         StringBuilder sb = new StringBuilder ();
885                         if (add_qmark)
886                                 sb.Append ('?');
887
888                         foreach (string key in queryString)
889                                 sb.AppendFormat ("{0}={1}&", key, UrlEncode (queryString [key]));
890
891                         if (sb.Length != 0)
892                                 sb.Length--; // removes last '&' or the '?' if empty.
893
894                         if (sb.Length == 0)
895                                 return null;
896
897                         return sb.ToString ();
898                 }
899
900                 Uri MakeUri (string path)
901                 {
902                         string query = GetQueryString (true);
903                         if (baseAddress == null && query == null) {
904                                 try {
905                                         return new Uri (path);
906 #if NET_2_0
907                                 } catch (ArgumentNullException) {
908                                         path = Path.GetFullPath (path);
909                                         return new Uri ("file://" + path);
910 #endif
911                                 } catch (UriFormatException) {
912                                         path = Path.GetFullPath (path);
913                                         return new Uri ("file://" + path);
914                                 }
915                         }
916
917                         if (baseAddress == null)
918                                 return new Uri (path + query, (query != null));
919
920                         if (query == null)
921                                 return new Uri (baseAddress, path);
922
923                         return new Uri (baseAddress, path + query, (query != null));
924                 }
925                 
926                 WebRequest SetupRequest (Uri uri)
927                 {
928                         WebRequest request = WebRequest.Create (uri);
929 #if NET_2_0
930                         if (Proxy != null)
931                                 request.Proxy = Proxy;
932 #endif
933                         request.Credentials = credentials;
934
935                         // Special headers. These are properties of HttpWebRequest.
936                         // What do we do with other requests differnt from HttpWebRequest?
937                         if (headers != null && headers.Count != 0 && (request is HttpWebRequest)) {
938                                 HttpWebRequest req = (HttpWebRequest) request;
939                                 string expect = headers ["Expect"];
940                                 string contentType = headers ["Content-Type"];
941                                 string accept = headers ["Accept"];
942                                 string connection = headers ["Connection"];
943                                 string userAgent = headers ["User-Agent"];
944                                 string referer = headers ["Referer"];
945                                 headers.RemoveInternal ("Expect");
946                                 headers.RemoveInternal ("Content-Type");
947                                 headers.RemoveInternal ("Accept");
948                                 headers.RemoveInternal ("Connection");
949                                 headers.RemoveInternal ("Referer");
950                                 headers.RemoveInternal ("User-Agent");
951                                 request.Headers = headers;
952
953                                 if (expect != null && expect.Length > 0)
954                                         req.Expect = expect;
955
956                                 if (accept != null && accept.Length > 0)
957                                         req.Accept = accept;
958
959                                 if (contentType != null && contentType.Length > 0)
960                                         req.ContentType = contentType;
961
962                                 if (connection != null && connection.Length > 0)
963                                         req.Connection = connection;
964
965                                 if (userAgent != null && userAgent.Length > 0)
966                                         req.UserAgent = userAgent;
967
968                                 if (referer != null && referer.Length > 0)
969                                         req.Referer = referer;
970                         }
971
972                         responseHeaders = null;
973                         return request;
974                 }
975
976                 WebRequest SetupRequest (Uri uri, string method, bool is_upload)
977                 {
978                         WebRequest request = SetupRequest (uri);
979                         request.Method = DetermineMethod (uri, method, is_upload);
980                         return request;
981                 }
982
983                 Stream ProcessResponse (WebResponse response)
984                 {
985                         responseHeaders = response.Headers;
986                         return response.GetResponseStream ();
987                 }
988
989                 byte [] ReadAll (Stream stream, int length, object userToken)
990                 {
991                         MemoryStream ms = null;
992                         
993                         bool nolength = (length == -1);
994                         int size = ((nolength) ? 8192 : length);
995                         if (nolength)
996                                 ms = new MemoryStream ();
997
998 //                      long total = 0;
999                         int nread = 0;
1000                         int offset = 0;
1001                         byte [] buffer = new byte [size];
1002                         while ((nread = stream.Read (buffer, offset, size)) != 0) {
1003                                 if (nolength) {
1004                                         ms.Write (buffer, 0, nread);
1005                                 } else {
1006                                         offset += nread;
1007                                         size -= nread;
1008                                 }
1009 #if NET_2_0
1010                                 if (async){
1011 //                                      total += nread;
1012                                         OnDownloadProgressChanged (new DownloadProgressChangedEventArgs (nread, length, userToken));
1013                                 }
1014 #endif
1015                         }
1016
1017                         if (nolength)
1018                                 return ms.ToArray ();
1019
1020                         return buffer;
1021                 }
1022
1023                 string UrlEncode (string str)
1024                 {
1025                         StringBuilder result = new StringBuilder ();
1026
1027                         int len = str.Length;
1028                         for (int i = 0; i < len; i++) {
1029                                 char c = str [i];
1030                                 if (c == ' ')
1031                                         result.Append ('+');
1032                                 else if ((c < '0' && c != '-' && c != '.') ||
1033                                          (c < 'A' && c > '9') ||
1034                                          (c > 'Z' && c < 'a' && c != '_') ||
1035                                          (c > 'z')) {
1036                                         result.Append ('%');
1037                                         int idx = ((int) c) >> 4;
1038                                         result.Append ((char) hexBytes [idx]);
1039                                         idx = ((int) c) & 0x0F;
1040                                         result.Append ((char) hexBytes [idx]);
1041                                 } else {
1042                                         result.Append (c);
1043                                 }
1044                         }
1045
1046                         return result.ToString ();
1047                 }
1048
1049                 static void UrlEncodeAndWrite (Stream stream, byte [] bytes)
1050                 {
1051                         if (bytes == null)
1052                                 return;
1053
1054                         int len = bytes.Length;
1055                         if (len == 0)
1056                                 return;
1057
1058                         for (int i = 0; i < len; i++) {
1059                                 char c = (char) bytes [i];
1060                                 if (c == ' ')
1061                                         stream.WriteByte ((byte) '+');
1062                                 else if ((c < '0' && c != '-' && c != '.') ||
1063                                          (c < 'A' && c > '9') ||
1064                                          (c > 'Z' && c < 'a' && c != '_') ||
1065                                          (c > 'z')) {
1066                                         stream.WriteByte ((byte) '%');
1067                                         int idx = ((int) c) >> 4;
1068                                         stream.WriteByte (hexBytes [idx]);
1069                                         idx = ((int) c) & 0x0F;
1070                                         stream.WriteByte (hexBytes [idx]);
1071                                 } else {
1072                                         stream.WriteByte ((byte) c);
1073                                 }
1074                         }
1075                 }
1076
1077 #if NET_2_0
1078                 public void CancelAsync ()
1079                 {
1080                         lock (this){
1081                                 if (async_thread == null)
1082                                         return;
1083
1084                                 //
1085                                 // We first flag things as done, in case the Interrupt hangs
1086                                 // or the thread decides to hang in some other way inside the
1087                                 // event handlers, or if we are stuck somewhere else.  This
1088                                 // ensures that the WebClient object is reusable immediately
1089                                 //
1090                                 Thread t = async_thread;
1091                                 CompleteAsync ();
1092                                 t.Interrupt ();
1093                         }
1094                 }
1095
1096                 void CompleteAsync ()
1097                 {
1098                         lock (this){
1099                                 is_busy = false;
1100                                 async_thread = null;
1101                         }
1102                 }
1103
1104                 //    DownloadDataAsync
1105
1106                 public void DownloadDataAsync (Uri address)
1107                 {
1108                         DownloadDataAsync (address, null);
1109                 }
1110
1111                 public void DownloadDataAsync (Uri address, object userToken)
1112                 {
1113                         if (address == null)
1114                                 throw new ArgumentNullException ("address");
1115                         
1116                         lock (this) {
1117                                 SetBusy ();
1118                                 async = true;
1119                                 
1120                                 async_thread = new Thread (delegate (object state) {
1121                                         object [] args = (object []) state;
1122                                         try {
1123                                                 byte [] data = DownloadDataCore ((Uri) args [0], args [1]);
1124                                                 OnDownloadDataCompleted (
1125                                                         new DownloadDataCompletedEventArgs (data, null, false, args [1]));
1126                                         } catch (ThreadInterruptedException){
1127                                                 OnDownloadDataCompleted (
1128                                                         new DownloadDataCompletedEventArgs (null, null, true, args [1]));
1129                                                 throw;
1130                                         } catch (Exception e){
1131                                                 OnDownloadDataCompleted (
1132                                                         new DownloadDataCompletedEventArgs (null, e, false, args [1]));
1133                                         }
1134                                 });
1135                                 object [] cb_args = new object [] {address, userToken};
1136                                 async_thread.Start (cb_args);
1137                         }
1138                 }
1139
1140                 //    DownloadFileAsync
1141
1142                 public void DownloadFileAsync (Uri address, string fileName)
1143                 {
1144                         DownloadFileAsync (address, fileName, null);
1145                 }
1146
1147                 public void DownloadFileAsync (Uri address, string fileName, object userToken)
1148                 {
1149                         if (address == null)
1150                                 throw new ArgumentNullException ("address");
1151                         if (fileName == null)
1152                                 throw new ArgumentNullException ("fileName");
1153                         
1154                         lock (this) {
1155                                 SetBusy ();
1156                                 async = true;
1157
1158                                 async_thread = new Thread (delegate (object state) {
1159                                         object [] args = (object []) state;
1160                                         try {
1161                                                 DownloadFileCore ((Uri) args [0], (string) args [1], args [2]);
1162                                                 OnDownloadFileCompleted (
1163                                                         new AsyncCompletedEventArgs (null, false, args [2]));
1164                                         } catch (ThreadInterruptedException){
1165                                                 OnDownloadFileCompleted (
1166                                                         new AsyncCompletedEventArgs (null, true, args [2]));
1167                                         } catch (Exception e){
1168                                                 OnDownloadFileCompleted (
1169                                                         new AsyncCompletedEventArgs (e, false, args [2]));
1170                                         }});
1171                                 object [] cb_args = new object [] {address, fileName, userToken};
1172                                 async_thread.Start (cb_args);
1173                         }
1174                 }
1175
1176                 //    DownloadStringAsync
1177
1178                 public void DownloadStringAsync (Uri address)
1179                 {
1180                         DownloadStringAsync (address, null);
1181                 }
1182
1183                 public void DownloadStringAsync (Uri address, object userToken)
1184                 {
1185                         if (address == null)
1186                                 throw new ArgumentNullException ("address");
1187                         
1188                         lock (this) {
1189                                 SetBusy ();
1190                                 async = true;
1191
1192                                 async_thread = new Thread (delegate (object state) {
1193                                         object [] args = (object []) state;
1194                                         try {
1195                                                 string data = encoding.GetString (DownloadDataCore ((Uri) args [0], args [1]));
1196                                                 OnDownloadStringCompleted (
1197                                                         new DownloadStringCompletedEventArgs (data, null, false, args [1]));
1198                                         } catch (ThreadInterruptedException){
1199                                                 OnDownloadStringCompleted (
1200                                                         new DownloadStringCompletedEventArgs (null, null, true, args [1]));
1201                                         } catch (Exception e){
1202                                                 OnDownloadStringCompleted (
1203                                                         new DownloadStringCompletedEventArgs (null, e, false, args [1]));
1204                                         }});
1205                                 object [] cb_args = new object [] {address, userToken};
1206                                 async_thread.Start (cb_args);
1207                         }
1208                 }
1209
1210                 //    OpenReadAsync
1211
1212                 public void OpenReadAsync (Uri address)
1213                 {
1214                         OpenReadAsync (address, null);
1215                 }
1216
1217                 public void OpenReadAsync (Uri address, object userToken)
1218                 {
1219                         if (address == null)
1220                                 throw new ArgumentNullException ("address");
1221                         
1222                         lock (this) {
1223                                 SetBusy ();
1224                                 async = true;
1225
1226                                 async_thread = new Thread (delegate (object state) {
1227                                         object [] args = (object []) state;
1228                                         WebRequest request = null;
1229                                         try {
1230                                                 request = SetupRequest ((Uri) args [0]);
1231                                                 WebResponse response = request.GetResponse ();
1232                                                 Stream stream = ProcessResponse (response);
1233                                                 OnOpenReadCompleted (
1234                                                         new OpenReadCompletedEventArgs (stream, null, false, args [1]));
1235                                         } catch (ThreadInterruptedException){
1236                                                 if (request != null)
1237                                                         request.Abort ();
1238                                                 
1239                                                 OnOpenReadCompleted (new OpenReadCompletedEventArgs (null, null, true, args [1]));
1240                                         } catch (Exception e){
1241                                                 OnOpenReadCompleted (new OpenReadCompletedEventArgs (null, e, false, args [1]));
1242                                         } });
1243                                 object [] cb_args = new object [] {address, userToken};
1244                                 async_thread.Start (cb_args);
1245                         }
1246                 }
1247
1248                 //    OpenWriteAsync
1249
1250                 public void OpenWriteAsync (Uri address)
1251                 {
1252                         OpenWriteAsync (address, null);
1253                 }
1254
1255                 public void OpenWriteAsync (Uri address, string method)
1256                 {
1257                         OpenWriteAsync (address, method, null);
1258                 }
1259
1260                 public void OpenWriteAsync (Uri address, string method, object userToken)
1261                 {
1262                         if (address == null)
1263                                 throw new ArgumentNullException ("address");
1264
1265                         lock (this) {
1266                                 SetBusy ();
1267                                 async = true;
1268
1269                                 async_thread = new Thread (delegate (object state) {
1270                                         object [] args = (object []) state;
1271                                         WebRequest request = null;
1272                                         try {
1273                                                 request = SetupRequest ((Uri) args [0], (string) args [1], true);
1274                                                 Stream stream = request.GetRequestStream ();
1275                                                 OnOpenWriteCompleted (
1276                                                         new OpenWriteCompletedEventArgs (stream, null, false, args [2]));
1277                                         } catch (ThreadInterruptedException){
1278                                                 if (request != null)
1279                                                         request.Abort ();
1280                                                 OnOpenWriteCompleted (
1281                                                         new OpenWriteCompletedEventArgs (null, null, true, args [2]));
1282                                         } catch (Exception e){
1283                                                 OnOpenWriteCompleted (
1284                                                         new OpenWriteCompletedEventArgs (null, e, false, args [2]));
1285                                         }});
1286                                 object [] cb_args = new object [] {address, method, userToken};
1287                                 async_thread.Start (cb_args);
1288                         }
1289                 }
1290
1291                 //    UploadDataAsync
1292
1293                 public void UploadDataAsync (Uri address, byte [] data)
1294                 {
1295                         UploadDataAsync (address, null, data);
1296                 }
1297
1298                 public void UploadDataAsync (Uri address, string method, byte [] data)
1299                 {
1300                         UploadDataAsync (address, method, data, null);
1301                 }
1302
1303                 public void UploadDataAsync (Uri address, string method, byte [] data, object userToken)
1304                 {
1305                         if (address == null)
1306                                 throw new ArgumentNullException ("address");
1307                         if (data == null)
1308                                 throw new ArgumentNullException ("data");
1309                         
1310                         lock (this) {
1311                                 SetBusy ();
1312                                 async = true;
1313
1314                                 async_thread = new Thread (delegate (object state) {
1315                                         object [] args = (object []) state;
1316                                         byte [] data2;
1317
1318                                         try {
1319                                                 data2 = UploadDataCore ((Uri) args [0], (string) args [1], (byte []) args [2], args [3]);
1320                                         
1321                                                 OnUploadDataCompleted (
1322                                                         new UploadDataCompletedEventArgs (data2, null, false, args [3]));
1323                                         } catch (ThreadInterruptedException){
1324                                                 OnUploadDataCompleted (
1325                                                         new UploadDataCompletedEventArgs (null, null, true, args [3]));
1326                                         } catch (Exception e){
1327                                                 OnUploadDataCompleted (
1328                                                         new UploadDataCompletedEventArgs (null, e, false, args [3]));
1329                                         }});
1330                                 object [] cb_args = new object [] {address, method, data,  userToken};
1331                                 async_thread.Start (cb_args);
1332                         }
1333                 }
1334
1335                 //    UploadFileAsync
1336
1337                 public void UploadFileAsync (Uri address, string fileName)
1338                 {
1339                         UploadFileAsync (address, null, fileName);
1340                 }
1341
1342                 public void UploadFileAsync (Uri address, string method, string fileName)
1343                 {
1344                         UploadFileAsync (address, method, fileName, null);
1345                 }
1346
1347                 public void UploadFileAsync (Uri address, string method, string fileName, object userToken)
1348                 {
1349                         if (address == null)
1350                                 throw new ArgumentNullException ("address");
1351                         if (fileName == null)
1352                                 throw new ArgumentNullException ("fileName");
1353
1354                         lock (this) {
1355                                 SetBusy ();
1356                                 async = true;
1357
1358                                 async_thread = new Thread (delegate (object state) {
1359                                         object [] args = (object []) state;
1360                                         byte [] data;
1361
1362                                         try {
1363                                                 data = UploadFileCore ((Uri) args [0], (string) args [1], (string) args [2], args [3]);
1364                                                 OnUploadFileCompleted (
1365                                                         new UploadFileCompletedEventArgs (data, null, false, args [3]));
1366                                         } catch (ThreadInterruptedException){
1367                                                 OnUploadFileCompleted (
1368                                                         new UploadFileCompletedEventArgs (null, null, true, args [3]));
1369                                         } catch (Exception e){
1370                                                 OnUploadFileCompleted (
1371                                                         new UploadFileCompletedEventArgs (null, e, false, args [3]));
1372                                         }});
1373                                 object [] cb_args = new object [] {address, method, fileName,  userToken};
1374                                 async_thread.Start (cb_args);
1375                         }
1376                 }
1377
1378                 //    UploadStringAsync
1379
1380                 public void UploadStringAsync (Uri address, string data)
1381                 {
1382                         UploadStringAsync (address, null, data);
1383                 }
1384
1385                 public void UploadStringAsync (Uri address, string method, string data)
1386                 {
1387                         UploadStringAsync (address, method, data, null);
1388                 }
1389
1390                 public void UploadStringAsync (Uri address, string method, string data, object userToken)
1391                 {
1392                         if (address == null)
1393                                 throw new ArgumentNullException ("address");
1394                         if (data == null)
1395                                 throw new ArgumentNullException ("data");
1396                         
1397                         lock (this) {
1398                                 SetBusy ();
1399                                 async = true;
1400                                 
1401                                 async_thread = new Thread (delegate (object state) {
1402                                         object [] args = (object []) state;
1403
1404                                         try {
1405                                                 string data2 = UploadString ((Uri) args [0], (string) args [1], (string) args [2]);
1406                                                 OnUploadStringCompleted (
1407                                                         new UploadStringCompletedEventArgs (data2, null, false, args [3]));
1408                                         } catch (ThreadInterruptedException){
1409                                                 OnUploadStringCompleted (
1410                                                         new UploadStringCompletedEventArgs (null, null, true, args [3]));
1411                                         } catch (Exception e){
1412                                                 OnUploadStringCompleted (
1413                                                         new UploadStringCompletedEventArgs (null, e, false, args [3]));
1414                                         }});
1415                                 object [] cb_args = new object [] {address, method, data, userToken};
1416                                 async_thread.Start (cb_args);
1417                         }
1418                 }
1419
1420                 //    UploadValuesAsync
1421
1422                 public void UploadValuesAsync (Uri address, NameValueCollection values)
1423                 {
1424                         UploadValuesAsync (address, null, values);
1425                 }
1426
1427                 public void UploadValuesAsync (Uri address, string method, NameValueCollection values)
1428                 {
1429                         UploadValuesAsync (address, method, values, null);
1430                 }
1431
1432                 public void UploadValuesAsync (Uri address, string method, NameValueCollection values, object userToken)
1433                 {
1434                         if (address == null)
1435                                 throw new ArgumentNullException ("address");
1436                         if (values == null)
1437                                 throw new ArgumentNullException ("values");
1438
1439                         lock (this) {
1440                                 CheckBusy ();
1441                                 async = true;
1442
1443                                 async_thread = new Thread (delegate (object state) {
1444                                         object [] args = (object []) state;
1445                                         try {
1446                                                 byte [] data = UploadValuesCore ((Uri) args [0], (string) args [1], (NameValueCollection) args [2], args [3]);
1447                                                 OnUploadValuesCompleted (
1448                                                         new UploadValuesCompletedEventArgs (data, null, false, args [3]));
1449                                         } catch (ThreadInterruptedException){
1450                                                 OnUploadValuesCompleted (
1451                                                         new UploadValuesCompletedEventArgs (null, null, true, args [3]));
1452                                         } catch (Exception e){
1453                                                 OnUploadValuesCompleted (
1454                                                         new UploadValuesCompletedEventArgs (null, e, false, args [3]));
1455                                         }});
1456                                 object [] cb_args = new object [] {address, method, values,  userToken};
1457                                 async_thread.Start (cb_args);
1458                         }
1459                 }
1460
1461                 protected virtual void OnDownloadDataCompleted (DownloadDataCompletedEventArgs args)
1462                 {
1463                         CompleteAsync ();
1464                         if (DownloadDataCompleted != null)
1465                                 DownloadDataCompleted (this, args);
1466                 }
1467
1468                 protected virtual void OnDownloadFileCompleted (AsyncCompletedEventArgs args)
1469                 {
1470                         CompleteAsync ();
1471                         if (DownloadFileCompleted != null)
1472                                 DownloadFileCompleted (this, args);
1473                 }
1474
1475                 protected virtual void OnDownloadProgressChanged (DownloadProgressChangedEventArgs e)
1476                 {
1477                         if (DownloadProgressChanged != null)
1478                                 DownloadProgressChanged (this, e);
1479                 }
1480
1481                 protected virtual void OnDownloadStringCompleted (DownloadStringCompletedEventArgs args)
1482                 {
1483                         CompleteAsync ();
1484                         if (DownloadStringCompleted != null)
1485                                 DownloadStringCompleted (this, args);
1486                 }
1487
1488                 protected virtual void OnOpenReadCompleted (OpenReadCompletedEventArgs args)
1489                 {
1490                         CompleteAsync ();
1491                         if (OpenReadCompleted != null)
1492                                 OpenReadCompleted (this, args);
1493                 }
1494
1495                 protected virtual void OnOpenWriteCompleted (OpenWriteCompletedEventArgs args)
1496                 {
1497                         CompleteAsync ();
1498                         if (OpenWriteCompleted != null)
1499                                 OpenWriteCompleted (this, args);
1500                 }
1501
1502                 protected virtual void OnUploadDataCompleted (UploadDataCompletedEventArgs args)
1503                 {
1504                         CompleteAsync ();
1505                         if (UploadDataCompleted != null)
1506                                 UploadDataCompleted (this, args);
1507                 }
1508
1509                 protected virtual void OnUploadFileCompleted (UploadFileCompletedEventArgs args)
1510                 {
1511                         CompleteAsync ();
1512                         if (UploadFileCompleted != null)
1513                                 UploadFileCompleted (this, args);
1514                 }
1515
1516                 protected virtual void OnUploadProgressChanged (UploadProgressChangedEventArgs e)
1517                 {
1518                         if (UploadProgressChanged != null)
1519                                 UploadProgressChanged (this, e);
1520                 }
1521
1522                 protected virtual void OnUploadStringCompleted (UploadStringCompletedEventArgs args)
1523                 {
1524                         CompleteAsync ();
1525                         if (UploadStringCompleted != null)
1526                                 UploadStringCompleted (this, args);
1527                 }
1528
1529                 protected virtual void OnUploadValuesCompleted (UploadValuesCompletedEventArgs args)
1530                 {
1531                         CompleteAsync ();
1532                         if (UploadValuesCompleted != null)
1533                                 UploadValuesCompleted (this, args);
1534                 }
1535
1536                 [MonoNotSupported("")]
1537                 protected virtual WebRequest GetWebRequest (Uri address)
1538                 {
1539                         throw new NotImplementedException ();
1540                 }
1541
1542                 protected virtual WebResponse GetWebResponse (WebRequest request)
1543                 {
1544                         return request.GetResponse ();
1545                 }
1546
1547                 protected virtual WebResponse GetWebResponse (WebRequest request, IAsyncResult result)
1548                 {
1549                         return request.EndGetResponse (result);
1550                 }
1551 #endif
1552         }
1553 }