2 // System.Net.WebClient
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 // Stephane Delcroix (sdelcroix@novell.com)
11 // Copyright 2003 Ximian, Inc. (http://www.ximian.com)
12 // Copyright 2006, 2008 Novell, Inc. (http://www.novell.com)
15 // Permission is hereby granted, free of charge, to any person obtaining
16 // a copy of this software and associated documentation files (the
17 // "Software"), to deal in the Software without restriction, including
18 // without limitation the rights to use, copy, modify, merge, publish,
19 // distribute, sublicense, and/or sell copies of the Software, and to
20 // permit persons to whom the Software is furnished to do so, subject to
21 // the following conditions:
23 // The above copyright notice and this permission notice shall be
24 // included in all copies or substantial portions of the Software.
26 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
31 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35 // Notes on CancelAsync and Async methods:
37 // WebClient.CancelAsync is implemented by calling Thread.Interrupt
38 // in our helper thread. The various async methods have to cancel
39 // any ongoing requests by calling request.Abort () at that point.
40 // In a few places (UploadDataCore, UploadValuesCore,
41 // UploadFileCore) we catch the ThreadInterruptedException and
42 // abort the request there.
44 // Higher level routines (the async callbacks) also need to catch
45 // the exception and raise the OnXXXXCompleted events there with
46 // the "canceled" flag set to true.
48 // In a few other places where these helper routines are not used
49 // (OpenReadAsync for example) catching the ThreadAbortException
50 // also must abort the request.
52 // The Async methods currently differ in their implementation from
53 // the .NET implementation in that we manually catch any other
54 // exceptions and correctly raise the OnXXXXCompleted passing the
55 // Exception that caused the problem. The .NET implementation
56 // does not seem to have a mechanism to flag errors that happen
57 // during downloads though. We do this because we still need to
58 // catch the exception on these helper threads, or we would
59 // otherwise kill the application (on the 2.x profile, uncaught
60 // exceptions in threads terminate the application).
63 using System.Security;
64 using System.Collections.Specialized;
65 using System.ComponentModel;
67 using System.Runtime.InteropServices;
68 using System.Runtime.Serialization;
70 using System.Threading;
77 // note: this type is effectively sealed to transparent code since it's default .ctor is marked with [SecuritySafeCritical]
78 public class WebClient
80 private delegate void ProgressChangedDelegate (long read, long length, object state);
82 // static readonly string urlEncodedCType = "application/x-www-form-urlencoded";
83 // static byte [] hexBytes;
84 // ICredentials credentials;
85 WebHeaderCollection headers;
86 // WebHeaderCollection responseHeaders;
89 // NameValueCollection queryString;
92 Encoding encoding = Encoding.UTF8;
93 bool allow_read_buffering = true;
97 // static WebClient ()
99 // hexBytes = new byte [16];
101 // for (int i = '0'; i <= '9'; i++, index++)
102 // hexBytes [index] = (byte) i;
104 // for (int i = 'A'; i <= 'F'; i++, index++)
105 // hexBytes [index] = (byte) i;
110 // kind of calling NativeMethods.plugin_instance_get_source_location (PluginHost.Handle)
111 // but without adding dependency on System.Windows.dll. GetData is [SecurityCritical]
112 // this makes the default .ctor [SecuritySafeCritical] which would be a problem (inheritance)
113 // but it happens that MS SL2 also has this default .ctor as SSC :-)
114 baseAddress = new Uri (AppDomain.CurrentDomain.GetData ("xap_uri") as string);
119 public string BaseAddress {
121 if (baseString == null) {
122 if (baseAddress == null)
125 baseString = baseAddress.ToString ();
131 if (String.IsNullOrEmpty (value)) {
134 baseAddress = new Uri (value);
140 // static Exception GetMustImplement ()
142 // return new NotImplementedException ();
146 // public RequestCachePolicy CachePolicy
149 // throw GetMustImplement ();
152 // throw GetMustImplement ();
157 // public bool UseDefaultCredentials
160 // throw GetMustImplement ();
163 // throw GetMustImplement ();
168 // public ICredentials Credentials {
169 // get { return credentials; }
170 // set { credentials = value; }
173 // this is an unvalidated collection, HttpWebRequest is responsable to validate it
174 public WebHeaderCollection Headers {
177 headers = new WebHeaderCollection ();
181 set { headers = value; }
184 // public NameValueCollection QueryString {
186 // if (queryString == null)
187 // queryString = new NameValueCollection ();
189 // return queryString;
191 // set { queryString = value; }
194 // public WebHeaderCollection ResponseHeaders {
195 // get { return responseHeaders; }
199 public Encoding Encoding {
200 get { return encoding; }
203 throw new ArgumentNullException ("value");
208 // public IWebProxy Proxy {
209 // get { return proxy; }
210 // set { proxy = value; }
215 get { return is_busy; }
218 [MonoTODO ("value is unused")]
219 public bool AllowReadStreamBuffering {
220 get { return allow_read_buffering; }
221 set { allow_read_buffering = value; }
229 throw new NotSupportedException ("WebClient does not support conccurent I/O operations.");
242 // public byte [] DownloadData (string address)
245 // if (address == null)
246 // throw new ArgumentNullException ("address");
249 // return DownloadData (CreateUri (address));
255 // byte [] DownloadData (Uri address)
258 // if (address == null)
259 // throw new ArgumentNullException ("address");
265 // return DownloadDataCore (address, null);
271 Stream DownloadDataCore (Uri address, object userToken)
273 WebRequest request = null;
276 request = SetupRequest (address, "GET");
277 //WebResponse response = request.GetResponse ();
278 IAsyncResult asyncresult = request.BeginGetResponse (null, userToken);
279 asyncresult.AsyncWaitHandle.WaitOne ();
280 WebResponse response = request.EndGetResponse (asyncresult);
281 Stream st = ProcessResponse (response);
282 return ReadAll (st, (int) st.Length, userToken);
283 } catch (ThreadInterruptedException){
287 } catch (Exception ex) {
288 throw new WebException ("An error occurred " +
289 "performing a WebClient request.", ex);
295 // public void DownloadFile (string address, string fileName)
298 // if (address == null)
299 // throw new ArgumentNullException ("address");
302 // DownloadFile (CreateUri (address), fileName);
308 // void DownloadFile (Uri address, string fileName)
311 // if (address == null)
312 // throw new ArgumentNullException ("address");
313 // if (fileName == null)
314 // throw new ArgumentNullException ("fileName");
320 // DownloadFileCore (address, fileName, null);
321 // } catch (Exception ex) {
322 // throw new WebException ("An error occurred " +
323 // "performing a WebClient request.", ex);
329 // void DownloadFileCore (Uri address, string fileName, object userToken)
331 // WebRequest request = null;
333 // using (FileStream f = new FileStream (fileName, FileMode.Create)) {
335 // request = SetupRequest (address);
336 // WebResponse response = request.GetResponse ();
337 // Stream st = ProcessResponse (response);
339 // int cLength = (int) response.ContentLength;
340 // int length = (cLength <= -1 || cLength > 32*1024) ? 32*1024 : cLength;
341 // byte [] buffer = new byte [length];
345 // long notify_total = 0;
347 // while ((nread = st.Read (buffer, 0, length)) != 0){
350 // notify_total += nread;
351 // OnDownloadProgressChanged (
352 // new DownloadProgressChangedEventArgs (notify_total, response.ContentLength, userToken));
356 // f.Write (buffer, 0, nread);
358 // } catch (ThreadInterruptedException){
359 // if (request != null)
368 // public Stream OpenRead (string address)
371 // if (address == null)
372 // throw new ArgumentNullException ("address");
375 // return OpenRead (CreateUri (address));
381 // Stream OpenRead (Uri address)
384 // if (address == null)
385 // throw new ArgumentNullException ("address");
388 // WebRequest request = null;
392 // request = SetupRequest (address);
393 // WebResponse response = request.GetResponse ();
394 // return ProcessResponse (response);
395 // } catch (Exception ex) {
396 // throw new WebException ("An error occurred " +
397 // "performing a WebClient request.", ex);
405 // public Stream OpenWrite (string address)
408 // if (address == null)
409 // throw new ArgumentNullException ("address");
412 // return OpenWrite (CreateUri (address));
415 // public Stream OpenWrite (string address, string method)
418 // if (address == null)
419 // throw new ArgumentNullException ("address");
422 // return OpenWrite (CreateUri (address), method);
428 // Stream OpenWrite (Uri address)
430 // return OpenWrite (address, (string) null);
436 // Stream OpenWrite (Uri address, string method)
439 // if (address == null)
440 // throw new ArgumentNullException ("address");
446 // WebRequest request = SetupRequest (address, method);
447 // return request.GetRequestStream ();
448 // } catch (Exception ex) {
449 // throw new WebException ("An error occurred " +
450 // "performing a WebClient request.", ex);
456 private string DetermineMethod (Uri address, string method)
461 if (address.Scheme == Uri.UriSchemeFtp)
468 // public byte [] UploadData (string address, byte [] data)
471 // if (address == null)
472 // throw new ArgumentNullException ("address");
475 // return UploadData (CreateUri (address), data);
478 // public byte [] UploadData (string address, string method, byte [] data)
481 // if (address == null)
482 // throw new ArgumentNullException ("address");
485 // return UploadData (CreateUri (address), method, data);
491 // byte [] UploadData (Uri address, byte [] data)
493 // return UploadData (address, (string) null, data);
499 // byte [] UploadData (Uri address, string method, byte [] data)
502 // if (address == null)
503 // throw new ArgumentNullException ("address");
505 // throw new ArgumentNullException ("data");
511 // return UploadDataCore (address, method, data, null);
512 // } catch (Exception ex) {
513 // throw new WebException ("An error occurred " +
514 // "performing a WebClient request.", ex);
520 // byte [] UploadDataCore (Uri address, string method, byte [] data, object userToken)
523 // if (address == null)
524 // throw new ArgumentNullException ("address");
526 // throw new ArgumentNullException ("data");
529 // WebRequest request = SetupRequest (address, method);
531 // int contentLength = data.Length;
532 // request.ContentLength = contentLength;
533 // using (Stream stream = request.GetRequestStream ()) {
534 // stream.Write (data, 0, contentLength);
537 // WebResponse response = request.GetResponse ();
538 // Stream st = ProcessResponse (response);
539 // return ReadAll (st, (int) response.ContentLength, userToken);
540 // } catch (ThreadInterruptedException){
541 // if (request != null)
549 // public byte [] UploadFile (string address, string fileName)
552 // if (address == null)
553 // throw new ArgumentNullException ("address");
556 // return UploadFile (CreateUri (address), fileName);
562 // byte [] UploadFile (Uri address, string fileName)
564 // return UploadFile (address, (string) null, fileName);
567 // public byte [] UploadFile (string address, string method, string fileName)
569 // return UploadFile (CreateUri (address), method, fileName);
575 // byte [] UploadFile (Uri address, string method, string fileName)
578 // if (address == null)
579 // throw new ArgumentNullException ("address");
580 // if (fileName == null)
581 // throw new ArgumentNullException ("fileName");
587 // return UploadFileCore (address, method, fileName, null);
588 // } catch (Exception ex) {
589 // throw new WebException ("An error occurred " +
590 // "performing a WebClient request.", ex);
596 // byte [] UploadFileCore (Uri address, string method, string fileName, object userToken)
599 // if (address == null)
600 // throw new ArgumentNullException ("address");
603 // string fileCType = Headers ["Content-Type"];
604 // if (fileCType != null) {
605 // string lower = fileCType.ToLower ();
606 // if (lower.StartsWith ("multipart/"))
607 // throw new WebException ("Content-Type cannot be set to a multipart" +
608 // " type for this request.");
610 // fileCType = "application/octet-stream";
613 // string boundary = "------------" + DateTime.Now.Ticks.ToString ("x");
614 // Headers ["Content-Type"] = String.Format ("multipart/form-data; boundary={0}", boundary);
615 // Stream reqStream = null;
616 // Stream fStream = null;
617 // byte [] resultBytes = null;
619 // fileName = Path.GetFullPath (fileName);
621 // WebRequest request = null;
623 // fStream = File.OpenRead (fileName);
624 // request = SetupRequest (address, method);
625 // reqStream = request.GetRequestStream ();
626 // byte [] realBoundary = Encoding.ASCII.GetBytes ("--" + boundary + "\r\n");
627 // reqStream.Write (realBoundary, 0, realBoundary.Length);
628 // string partHeaders = String.Format ("Content-Disposition: form-data; " +
629 // "name=\"file\"; filename=\"{0}\"\r\n" +
630 // "Content-Type: {1}\r\n\r\n",
631 // Path.GetFileName (fileName), fileCType);
633 // byte [] partHeadersBytes = Encoding.UTF8.GetBytes (partHeaders);
634 // reqStream.Write (partHeadersBytes, 0, partHeadersBytes.Length);
636 // byte [] buffer = new byte [4096];
637 // while ((nread = fStream.Read (buffer, 0, 4096)) != 0)
638 // reqStream.Write (buffer, 0, nread);
640 // reqStream.WriteByte ((byte) '\r');
641 // reqStream.WriteByte ((byte) '\n');
642 // reqStream.Write (realBoundary, 0, realBoundary.Length);
643 // reqStream.Close ();
645 // WebResponse response = request.GetResponse ();
646 // Stream st = ProcessResponse (response);
647 // resultBytes = ReadAll (st, (int) response.ContentLength, userToken);
648 // } catch (ThreadInterruptedException){
649 // if (request != null)
653 // if (fStream != null)
656 // if (reqStream != null)
657 // reqStream.Close ();
660 // return resultBytes;
663 // public byte[] UploadValues (string address, NameValueCollection data)
666 // if (address == null)
667 // throw new ArgumentNullException ("address");
670 // return UploadValues (CreateUri (address), data);
673 // public byte[] UploadValues (string address, string method, NameValueCollection data)
676 // if (address == null)
677 // throw new ArgumentNullException ("address");
680 // return UploadValues (CreateUri (address), method, data);
686 // byte[] UploadValues (Uri address, NameValueCollection data)
688 // return UploadValues (address, (string) null, data);
694 // byte[] UploadValues (Uri address, string method, NameValueCollection data)
697 // if (address == null)
698 // throw new ArgumentNullException ("address");
700 // throw new ArgumentNullException ("data");
706 // return UploadValuesCore (address, method, data, null);
707 // } catch (Exception ex) {
708 // throw new WebException ("An error occurred " +
709 // "performing a WebClient request.", ex);
715 // byte[] UploadValuesCore (Uri uri, string method, NameValueCollection data, object userToken)
719 // throw new ArgumentNullException ("data");
722 // string cType = Headers ["Content-Type"];
723 // if (cType != null && String.Compare (cType, urlEncodedCType, true) != 0)
724 // throw new WebException ("Content-Type header cannot be changed from its default " +
725 // "value for this request.");
727 // Headers ["Content-Type"] = urlEncodedCType;
728 // WebRequest request = SetupRequest (uri, method);
730 // Stream rqStream = request.GetRequestStream ();
731 // MemoryStream tmpStream = new MemoryStream ();
732 // foreach (string key in data) {
733 // byte [] bytes = Encoding.ASCII.GetBytes (key);
734 // UrlEncodeAndWrite (tmpStream, bytes);
735 // tmpStream.WriteByte ((byte) '=');
736 // bytes = Encoding.ASCII.GetBytes (data [key]);
737 // UrlEncodeAndWrite (tmpStream, bytes);
738 // tmpStream.WriteByte ((byte) '&');
741 // int length = (int) tmpStream.Length;
743 // tmpStream.SetLength (--length); // remove trailing '&'
745 // byte [] buf = tmpStream.GetBuffer ();
746 // rqStream.Write (buf, 0, length);
747 // rqStream.Close ();
748 // tmpStream.Close ();
750 // WebResponse response = request.GetResponse ();
751 // Stream st = ProcessResponse (response);
752 // return ReadAll (st, (int) response.ContentLength, userToken);
753 // } catch (ThreadInterruptedException) {
760 // public string DownloadString (string address)
762 // return encoding.GetString (DownloadData (address));
765 // public string DownloadString (Uri address)
767 // return encoding.GetString (DownloadData (address));
770 // public string UploadString (string address, string data)
772 // if (address == null)
773 // throw new ArgumentNullException ("address");
775 // throw new ArgumentNullException ("data");
777 // byte [] resp = UploadData (address, encoding.GetBytes (data));
778 // return encoding.GetString (resp);
781 // public string UploadString (string address, string method, string data)
783 // if (address == null)
784 // throw new ArgumentNullException ("address");
786 // throw new ArgumentNullException ("data");
788 // byte [] resp = UploadData (address, method, encoding.GetBytes (data));
789 // return encoding.GetString (resp);
792 // public string UploadString (Uri address, string data)
794 // if (address == null)
795 // throw new ArgumentNullException ("address");
797 // throw new ArgumentNullException ("data");
799 // byte [] resp = UploadData (address, encoding.GetBytes (data));
800 // return encoding.GetString (resp);
803 // public string UploadString (Uri address, string method, string data)
805 // if (address == null)
806 // throw new ArgumentNullException ("address");
808 // throw new ArgumentNullException ("data");
810 // byte [] resp = UploadData (address, method, encoding.GetBytes (data));
811 // return encoding.GetString (resp);
814 // public event DownloadDataCompletedEventHandler DownloadDataCompleted;
815 // public event AsyncCompletedEventHandler DownloadFileCompleted;
816 public event DownloadProgressChangedEventHandler DownloadProgressChanged;
817 public event DownloadStringCompletedEventHandler DownloadStringCompleted;
818 public event OpenReadCompletedEventHandler OpenReadCompleted;
819 public event OpenWriteCompletedEventHandler OpenWriteCompleted;
820 // public event UploadDataCompletedEventHandler UploadDataCompleted;
821 // public event UploadFileCompletedEventHandler UploadFileCompleted;
822 public event UploadProgressChangedEventHandler UploadProgressChanged;
823 public event UploadStringCompletedEventHandler UploadStringCompleted;
824 // public event UploadValuesCompletedEventHandler UploadValuesCompleted;
825 public event WriteStreamClosedEventHandler WriteStreamClosed;
828 // Uri CreateUri (string address)
832 // return MakeUri (address);
833 // } catch (Exception ex) {
834 // throw new WebException ("An error occurred " +
835 // "performing a WebClient request.", ex);
838 // return MakeUri (address);
842 // Uri MakeUri (string path)
844 // string query = null;
845 // if (queryString != null && queryString.Count != 0) {
846 // // This is not the same as UploadValues, because these 'keys' are not
847 // // urlencoded here.
848 // StringBuilder sb = new StringBuilder ();
850 // foreach (string key in queryString)
851 // sb.AppendFormat ("{0}={1}&", key, UrlEncode (queryString [key]));
853 // if (sb.Length != 0) {
854 // sb.Length--; // remove trailing '&'
855 // query = sb.ToString ();
859 // if (baseAddress == null && query == null) {
861 // return new Uri (path);
863 // } catch (ArgumentNullException) {
864 // path = Path.GetFullPath (path);
865 // return new Uri ("file://" + path);
867 // } catch (UriFormatException) {
868 // path = Path.GetFullPath (path);
869 // return new Uri ("file://" + path);
873 // if (baseAddress == null)
874 // return new Uri (path + query, (query != null));
876 // if (query == null)
877 // return new Uri (baseAddress, path);
879 // return new Uri (baseAddress, path + query, (query != null));
882 // WebRequest SetupRequest (Uri uri)
884 // WebRequest request = WebRequest.CreateInternal (baseAddress != null ? new Uri (baseAddress, uri) : uri, true);
885 // if (Proxy != null)
886 // request.Proxy = Proxy;
887 // request.Credentials = credentials;
889 // Special headers. These are properties of HttpWebRequest.
890 // What do we do with other requests differnt from HttpWebRequest?
891 // if (headers != null && headers.Count != 0 && (request is HttpWebRequest)) {
892 // HttpWebRequest req = (HttpWebRequest) request;
893 // string expect = headers ["Expect"];
894 // string contentType = headers ["Content-Type"];
895 // string accept = headers ["Accept"];
896 // string connection = headers ["Connection"];
897 // string userAgent = headers ["User-Agent"];
898 // string referer = headers ["Referer"];
899 // headers.RemoveInternal ("Expect");
900 // headers.RemoveInternal ("Content-Type");
901 // headers.RemoveInternal ("Accept");
902 // headers.RemoveInternal ("Connection");
903 // headers.RemoveInternal ("Referer");
904 // headers.RemoveInternal ("User-Agent");
905 // request.Headers = headers;
907 // if (expect != null && expect.Length > 0)
908 // req.Expect = expect;
910 // if (accept != null && accept.Length > 0)
911 // req.Accept = accept;
913 // if (contentType != null && contentType.Length > 0)
914 // req.ContentType = contentType;
916 // if (connection != null && connection.Length > 0)
917 // req.Connection = connection;
919 // if (userAgent != null && userAgent.Length > 0)
920 // req.UserAgent = userAgent;
922 // if (referer != null && referer.Length > 0)
923 // req.Referer = referer;
926 // responseHeaders = null;
930 WebRequest SetupRequest (Uri uri, string method)
932 WebRequest request = GetWebRequest (uri);
933 request.Method = DetermineMethod (uri, method);
937 Stream ProcessResponse (WebResponse response)
939 // responseHeaders = response.Headers;
940 return response.GetResponseStream ();
943 Stream ReadAll (Stream stream, int length, object userToken)
945 MemoryStream ms = null;
947 bool nolength = (length == -1);
948 int size = ((nolength) ? 8192 : length);
949 ms = new MemoryStream (size);
952 byte [] buffer = new byte [size];
953 while ((nread = stream.Read (buffer, 0, buffer.Length)) != 0) {
954 ms.Write (buffer, 0, nread);
956 OnDownloadProgressChanged (new DownloadProgressChangedEventArgs (nread, length, userToken));
958 if (!nolength && ms.Length == length) {
967 // string UrlEncode (string str)
969 // StringBuilder result = new StringBuilder ();
971 // int len = str.Length;
972 // for (int i = 0; i < len; i++) {
975 // result.Append ('+');
976 // else if ((c < '0' && c != '-' && c != '.') ||
977 // (c < 'A' && c > '9') ||
978 // (c > 'Z' && c < 'a' && c != '_') ||
980 // result.Append ('%');
981 // int idx = ((int) c) >> 4;
982 // result.Append ((char) hexBytes [idx]);
983 // idx = ((int) c) & 0x0F;
984 // result.Append ((char) hexBytes [idx]);
986 // result.Append (c);
990 // return result.ToString ();
993 // static void UrlEncodeAndWrite (Stream stream, byte [] bytes)
995 // if (bytes == null)
998 // int len = bytes.Length;
1002 // for (int i = 0; i < len; i++) {
1003 // char c = (char) bytes [i];
1005 // stream.WriteByte ((byte) '+');
1006 // else if ((c < '0' && c != '-' && c != '.') ||
1007 // (c < 'A' && c > '9') ||
1008 // (c > 'Z' && c < 'a' && c != '_') ||
1010 // stream.WriteByte ((byte) '%');
1011 // int idx = ((int) c) >> 4;
1012 // stream.WriteByte (hexBytes [idx]);
1013 // idx = ((int) c) & 0x0F;
1014 // stream.WriteByte (hexBytes [idx]);
1016 // stream.WriteByte ((byte) c);
1022 [SecuritySafeCritical]
1023 public void CancelAsync ()
1026 if (async_thread == null)
1030 // We first flag things as done, in case the Interrupt hangs
1031 // or the thread decides to hang in some other way inside the
1032 // event handlers, or if we are stuck somewhere else. This
1033 // ensures that the WebClient object is reusable immediately
1035 Thread t = async_thread;
1041 void CompleteAsync ()
1045 async_thread = null;
1049 // // DownloadDataAsync
1051 // public void DownloadDataAsync (Uri address)
1053 // DownloadDataAsync (address, null);
1056 // public void DownloadDataAsync (Uri address, object userToken)
1058 // if (address == null)
1059 // throw new ArgumentNullException ("address");
1065 // async_thread = new Thread (delegate (object state) {
1066 // object [] args = (object []) state;
1068 // byte [] data = DownloadDataCore ((Uri) args [0], args [1]);
1069 // OnDownloadDataCompleted (
1070 // new DownloadDataCompletedEventArgs (data, null, false, args [1]));
1071 // } catch (ThreadInterruptedException){
1072 // OnDownloadDataCompleted (
1073 // new DownloadDataCompletedEventArgs (null, null, true, args [1]));
1075 // } catch (Exception e){
1076 // OnDownloadDataCompleted (
1077 // new DownloadDataCompletedEventArgs (null, e, false, args [1]));
1080 // object [] cb_args = new object [] {address, userToken};
1081 // async_thread.Start (cb_args);
1085 // // DownloadFileAsync
1087 // public void DownloadFileAsync (Uri address, string fileName)
1089 // DownloadFileAsync (address, fileName, null);
1092 // public void DownloadFileAsync (Uri address, string fileName, object userToken)
1094 // if (address == null)
1095 // throw new ArgumentNullException ("address");
1096 // if (fileName == null)
1097 // throw new ArgumentNullException ("fileName");
1103 // async_thread = new Thread (delegate (object state) {
1104 // object [] args = (object []) state;
1106 // DownloadFileCore ((Uri) args [0], (string) args [1], args [2]);
1107 // OnDownloadFileCompleted (
1108 // new AsyncCompletedEventArgs (null, false, args [2]));
1109 // } catch (ThreadInterruptedException){
1110 // OnDownloadFileCompleted (
1111 // new AsyncCompletedEventArgs (null, true, args [2]));
1112 // } catch (Exception e){
1113 // OnDownloadFileCompleted (
1114 // new AsyncCompletedEventArgs (e, false, args [2]));
1116 // object [] cb_args = new object [] {address, fileName, userToken};
1117 // async_thread.Start (cb_args);
1121 // // DownloadStringAsync
1123 public void DownloadStringAsync (Uri address)
1125 DownloadStringAsync (address, null);
1128 public void DownloadStringAsync (Uri address, object userToken)
1130 if (address == null)
1131 throw new ArgumentNullException ("address");
1137 async_thread = new Thread (delegate (object state) {
1138 object [] args = (object []) state;
1140 Stream bdata = DownloadDataCore ((Uri) args [0], args [1]);
1142 using (StreamReader stream = new StreamReader (bdata, encoding, true))
1143 data = stream.ReadToEnd ();
1145 OnDownloadStringCompleted (
1146 new DownloadStringCompletedEventArgs (data, null, false, args [1]));
1147 } catch (ThreadInterruptedException){
1148 OnDownloadStringCompleted (
1149 new DownloadStringCompletedEventArgs (null, null, true, args [1]));
1150 } catch (Exception e){
1151 OnDownloadStringCompleted (
1152 new DownloadStringCompletedEventArgs (null, e, false, args [1]));
1154 object [] cb_args = new object [] {address, userToken};
1155 async_thread.Start (cb_args);
1161 public void OpenReadAsync (Uri address)
1163 OpenReadAsync (address, null);
1166 public void OpenReadAsync (Uri address, object userToken)
1168 if (address == null)
1169 throw new ArgumentNullException ("address");
1175 async_thread = new Thread (delegate (object state) {
1176 object [] args = (object []) state;
1177 WebRequest request = null;
1179 request = SetupRequest ((Uri) args [0], "GET");
1180 //WebResponse response = request.GetResponse ();
1181 IAsyncResult asyncresult = request.BeginGetResponse (null, userToken);
1182 asyncresult.AsyncWaitHandle.WaitOne ();
1183 WebResponse response = request.EndGetResponse (asyncresult);
1184 Stream stream = ProcessResponse (response);
1185 OnOpenReadCompleted (
1186 new OpenReadCompletedEventArgs (stream, address, null, false, args [1]));
1187 } catch (ThreadInterruptedException){
1188 if (request != null)
1191 OnOpenReadCompleted (new OpenReadCompletedEventArgs (null, null, null, true, args [1]));
1192 } catch (Exception e){
1193 OnOpenReadCompleted (new OpenReadCompletedEventArgs (null, null, e, false, args [1]));
1195 object [] cb_args = new object [] {address, userToken};
1196 async_thread.Start (cb_args);
1200 // // OpenWriteAsync
1202 public void OpenWriteAsync (Uri address)
1204 OpenWriteAsync (address, null);
1207 public void OpenWriteAsync (Uri address, string method)
1209 OpenWriteAsync (address, method, null);
1212 public void OpenWriteAsync (Uri address, string method, object userToken)
1214 if (address == null)
1215 throw new ArgumentNullException ("address");
1217 throw new NotImplementedException ();
1223 // async_thread = new Thread (delegate (object state) {
1224 // object [] args = (object []) state;
1225 // WebRequest request = null;
1227 // request = SetupRequest ((Uri) args [0], (string) args [1]);
1228 // Stream stream = request.GetRequestStream ();
1229 // OnOpenWriteCompleted (
1230 // new OpenWriteCompletedEventArgs (stream, null, false, args [2]));
1231 // } catch (ThreadInterruptedException){
1232 // if (request != null)
1233 // request.Abort ();
1234 // OnOpenWriteCompleted (
1235 // new OpenWriteCompletedEventArgs (null, null, true, args [2]));
1236 // } catch (Exception e){
1237 // OnOpenWriteCompleted (
1238 // new OpenWriteCompletedEventArgs (null, e, false, args [2]));
1240 // object [] cb_args = new object [] {address, method, userToken};
1241 // async_thread.Start (cb_args);
1245 // // UploadDataAsync
1247 // public void UploadDataAsync (Uri address, byte [] data)
1249 // UploadDataAsync (address, null, data);
1252 // public void UploadDataAsync (Uri address, string method, byte [] data)
1254 // UploadDataAsync (address, method, data, null);
1257 // public void UploadDataAsync (Uri address, string method, byte [] data, object userToken)
1259 // if (address == null)
1260 // throw new ArgumentNullException ("address");
1261 // if (data == null)
1262 // throw new ArgumentNullException ("data");
1268 // async_thread = new Thread (delegate (object state) {
1269 // object [] args = (object []) state;
1273 // data2 = UploadDataCore ((Uri) args [0], (string) args [1], (byte []) args [2], args [3]);
1275 // OnUploadDataCompleted (
1276 // new UploadDataCompletedEventArgs (data2, null, false, args [3]));
1277 // } catch (ThreadInterruptedException){
1278 // OnUploadDataCompleted (
1279 // new UploadDataCompletedEventArgs (null, null, true, args [3]));
1280 // } catch (Exception e){
1281 // OnUploadDataCompleted (
1282 // new UploadDataCompletedEventArgs (null, e, false, args [3]));
1284 // object [] cb_args = new object [] {address, method, data, userToken};
1285 // async_thread.Start (cb_args);
1289 // // UploadFileAsync
1291 // public void UploadFileAsync (Uri address, string fileName)
1293 // UploadFileAsync (address, null, fileName);
1296 // public void UploadFileAsync (Uri address, string method, string fileName)
1298 // UploadFileAsync (address, method, fileName, null);
1301 // public void UploadFileAsync (Uri address, string method, string fileName, object userToken)
1303 // if (address == null)
1304 // throw new ArgumentNullException ("address");
1305 // if (fileName == null)
1306 // throw new ArgumentNullException ("fileName");
1312 // async_thread = new Thread (delegate (object state) {
1313 // object [] args = (object []) state;
1317 // data = UploadFileCore ((Uri) args [0], (string) args [1], (string) args [2], args [3]);
1318 // OnUploadFileCompleted (
1319 // new UploadFileCompletedEventArgs (data, null, false, args [3]));
1320 // } catch (ThreadInterruptedException){
1321 // OnUploadFileCompleted (
1322 // new UploadFileCompletedEventArgs (null, null, true, args [3]));
1323 // } catch (Exception e){
1324 // OnUploadFileCompleted (
1325 // new UploadFileCompletedEventArgs (null, e, false, args [3]));
1327 // object [] cb_args = new object [] {address, method, fileName, userToken};
1328 // async_thread.Start (cb_args);
1332 // // UploadStringAsync
1334 public void UploadStringAsync (Uri address, string data)
1336 UploadStringAsync (address, null, data);
1339 public void UploadStringAsync (Uri address, string method, string data)
1341 UploadStringAsync (address, method, data, null);
1344 public void UploadStringAsync (Uri address, string method, string data, object userToken)
1346 if (address == null)
1347 throw new ArgumentNullException ("address");
1349 throw new ArgumentNullException ("data");
1351 throw new NotImplementedException ();
1356 // async_thread = new Thread (delegate (object state) {
1357 // object [] args = (object []) state;
1360 // string data2 = UploadString ((Uri) args [0], (string) args [1], (string) args [2]);
1361 // OnUploadStringCompleted (
1362 // new UploadStringCompletedEventArgs (data2, null, false, args [3]));
1363 // } catch (ThreadInterruptedException){
1364 // OnUploadStringCompleted (
1365 // new UploadStringCompletedEventArgs (null, null, true, args [3]));
1366 // } catch (Exception e){
1367 // OnUploadStringCompleted (
1368 // new UploadStringCompletedEventArgs (null, e, false, args [3]));
1370 // object [] cb_args = new object [] {address, method, data, userToken};
1371 // async_thread.Start (cb_args);
1375 // // UploadValuesAsync
1377 // public void UploadValuesAsync (Uri address, NameValueCollection values)
1379 // UploadValuesAsync (address, null, values);
1382 // public void UploadValuesAsync (Uri address, string method, NameValueCollection values)
1384 // UploadValuesAsync (address, method, values, null);
1387 // public void UploadValuesAsync (Uri address, string method, NameValueCollection values, object userToken)
1389 // if (address == null)
1390 // throw new ArgumentNullException ("address");
1391 // if (values == null)
1392 // throw new ArgumentNullException ("values");
1398 // async_thread = new Thread (delegate (object state) {
1399 // object [] args = (object []) state;
1401 // byte [] data = UploadValuesCore ((Uri) args [0], (string) args [1], (NameValueCollection) args [2], args [3]);
1402 // OnUploadValuesCompleted (
1403 // new UploadValuesCompletedEventArgs (data, null, false, args [3]));
1404 // } catch (ThreadInterruptedException){
1405 // OnUploadValuesCompleted (
1406 // new UploadValuesCompletedEventArgs (null, null, true, args [3]));
1407 // } catch (Exception e){
1408 // OnUploadValuesCompleted (
1409 // new UploadValuesCompletedEventArgs (null, e, false, args [3]));
1411 // object [] cb_args = new object [] {address, method, values, userToken};
1412 // async_thread.Start (cb_args);
1416 // protected virtual void OnDownloadDataCompleted (DownloadDataCompletedEventArgs args)
1418 // CompleteAsync ();
1419 // if (DownloadDataCompleted != null)
1420 // DownloadDataCompleted (this, args);
1423 // protected virtual void OnDownloadFileCompleted (AsyncCompletedEventArgs args)
1425 // CompleteAsync ();
1426 // if (DownloadFileCompleted != null)
1427 // DownloadFileCompleted (this, args);
1430 protected virtual void OnDownloadProgressChanged (DownloadProgressChangedEventArgs e)
1432 if (DownloadProgressChanged != null) {
1433 DownloadProgressChanged (this, e);
1437 private object callback_args;
1439 protected virtual void OnOpenReadCompleted (OpenReadCompletedEventArgs args)
1442 if (OpenReadCompleted != null) {
1443 ManualResetEvent wait_event = new ManualResetEvent (false);
1444 GSourceFunc callback = (GSourceFunc) delegate (IntPtr ctx)
1447 OpenReadCompleted (this, (OpenReadCompletedEventArgs) callback_args);
1448 } catch (Exception ex) {
1450 Console.WriteLine ("Unhandled exception: {0}", ex);
1456 } catch (Exception ex) {
1458 Console.WriteLine ("Unhandled exception: {0}", ex);
1464 callback_args = args;
1466 g_timeout_add (0, callback, IntPtr.Zero);
1468 wait_event.WaitOne ();
1469 GC.KeepAlive (callback);
1473 public delegate bool GSourceFunc (IntPtr data);
1475 [DllImport ("moon")]
1476 static extern uint g_timeout_add (uint delay, GSourceFunc callback, IntPtr data);
1478 protected virtual void OnDownloadStringCompleted (DownloadStringCompletedEventArgs args)
1481 if (DownloadStringCompleted != null) {
1482 ManualResetEvent wait_event = new ManualResetEvent (false);
1483 GSourceFunc callback = (GSourceFunc) delegate (IntPtr ctx)
1486 DownloadStringCompleted (this, (DownloadStringCompletedEventArgs) callback_args);
1487 } catch (Exception ex) {
1489 Console.WriteLine ("Unhandled exception: {0}", ex);
1495 } catch (Exception ex) {
1497 Console.WriteLine ("Unhandled exception: {0}", ex);
1503 callback_args = args;
1505 g_timeout_add (0, callback, IntPtr.Zero);
1507 wait_event.WaitOne ();
1508 GC.KeepAlive (callback);
1513 protected virtual void OnOpenWriteCompleted (OpenWriteCompletedEventArgs args)
1516 if (OpenWriteCompleted != null)
1517 OpenWriteCompleted (this, args);
1520 // protected virtual void OnUploadDataCompleted (UploadDataCompletedEventArgs args)
1522 // CompleteAsync ();
1523 // if (UploadDataCompleted != null)
1524 // UploadDataCompleted (this, args);
1527 // protected virtual void OnUploadFileCompleted (UploadFileCompletedEventArgs args)
1529 // CompleteAsync ();
1530 // if (UploadFileCompleted != null)
1531 // UploadFileCompleted (this, args);
1534 protected virtual void OnUploadProgressChanged (UploadProgressChangedEventArgs e)
1536 if (UploadProgressChanged != null)
1537 UploadProgressChanged (this, e);
1540 protected virtual void OnUploadStringCompleted (UploadStringCompletedEventArgs args)
1543 if (UploadStringCompleted != null)
1544 UploadStringCompleted (this, args);
1547 // protected virtual void OnUploadValuesCompleted (UploadValuesCompletedEventArgs args)
1549 // CompleteAsync ();
1550 // if (UploadValuesCompleted != null)
1551 // UploadValuesCompleted (this, args);
1554 protected virtual void OnWriteStreamClosed (WriteStreamClosedEventArgs e)
1556 throw new NotImplementedException ();
1559 protected virtual WebRequest GetWebRequest (Uri address)
1561 if (address == null)
1562 throw new ArgumentNullException ("address");
1564 // if the URI is relative then we use our base address URI to make an absolute one
1565 Uri uri = address.IsAbsoluteUri ? address : new Uri (baseAddress, address);
1567 WebRequest request = WebRequest.Create (uri);
1569 request.SetupProgressDelegate ((ProgressChangedDelegate) delegate (long read, long length, object state) {
1570 OnDownloadProgressChanged (new DownloadProgressChangedEventArgs (read, length, state));
1575 // protected virtual WebResponse GetWebResponse (WebRequest request)
1577 // return request.GetResponse ();
1580 protected virtual WebResponse GetWebResponse (WebRequest request, IAsyncResult result)
1582 return request.EndGetResponse (result);