// Lawrence Pit (loz@cable.a2000.nl)
// Gonzalo Paniagua Javier (gonzalo@ximian.com)
// Atsushi Enomoto (atsushi@ximian.com)
+// Miguel de Icaza (miguel@ximian.com)
//
-// (c) 2003 Ximian, Inc. (http://www.ximian.com)
-// (C) 2006 Novell, Inc. (http://www.novell.com)
+// Copyright 2003 Ximian, Inc. (http://www.ximian.com)
+// Copyright 2006, 2007 Novell, Inc. (http://www.novell.com)
//
-
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-
+//
+// Notes on CancelAsync and Async methods:
+//
+// WebClient.CancelAsync is implemented by calling Thread.Interrupt
+// in our helper thread. The various async methods have to cancel
+// any ongoing requests by calling request.Abort () at that point.
+// In a few places (UploadDataCore, UploadValuesCore,
+// UploadFileCore) we catch the ThreadInterruptedException and
+// abort the request there.
+//
+// Higher level routines (the async callbacks) also need to catch
+// the exception and raise the OnXXXXCompleted events there with
+// the "canceled" flag set to true.
+//
+// In a few other places where these helper routines are not used
+// (OpenReadAsync for example) catching the ThreadAbortException
+// also must abort the request.
+//
+// The Async methods currently differ in their implementation from
+// the .NET implementation in that we manually catch any other
+// exceptions and correctly raise the OnXXXXCompleted passing the
+// Exception that caused the problem. The .NET implementation
+// does not seem to have a mechanism to flag errors that happen
+// during downloads though. We do this because we still need to
+// catch the exception on these helper threads, or we would
+// otherwise kill the application (on the 2.x profile, uncaught
+// exceptions in threads terminate the application).
+//
using System;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Text;
-#if NET_2_0
-using System.Collections.Generic;
using System.Threading;
+#if NET_2_0
+using System.Net.Cache;
#endif
namespace System.Net
Uri baseAddress;
string baseString;
NameValueCollection queryString;
- bool isBusy;
+ bool is_busy;
#if NET_2_0
+ bool async;
+ Thread async_thread;
Encoding encoding = Encoding.Default;
IWebProxy proxy;
#endif
}
}
}
+
+#if NET_2_0
+ static Exception GetMustImplement ()
+ {
+ return new NotImplementedException ();
+ }
+
+ [MonoTODO]
+ public RequestCachePolicy CachePolicy
+ {
+ get {
+ throw GetMustImplement ();
+ }
+ set {
+ throw GetMustImplement ();
+ }
+ }
+
+ [MonoTODO]
+ public bool UseDefaultCredentials
+ {
+ get {
+ throw GetMustImplement ();
+ }
+ set {
+ throw GetMustImplement ();
+ }
+ }
+#endif
public ICredentials Credentials {
get { return credentials; }
#if NET_2_0
public bool IsBusy {
- get { return isBusy || wait_handles != null && wait_handles.Count > 0; }
+ get { return is_busy; }
}
#else
bool IsBusy {
- get { return isBusy; }
+ get { return is_busy; }
}
#endif
{
lock (this) {
CheckBusy ();
- isBusy = true;
+ is_busy = true;
}
}
public byte [] DownloadData (string address)
{
- return DownloadData (MakeUri (address));
+#if NET_2_0
+ if (address == null)
+ throw new ArgumentNullException ("address");
+#endif
+
+ return DownloadData (CreateUri (address));
}
#if NET_2_0
#endif
byte [] DownloadData (Uri address)
{
+#if NET_2_0
+ if (address == null)
+ throw new ArgumentNullException ("address");
+#endif
+
try {
SetBusy ();
- return DownloadDataCore (address);
+#if NET_2_0
+ async = false;
+#endif
+ return DownloadDataCore (address, null);
} finally {
- isBusy = false;
+ is_busy = false;
}
}
- byte [] DownloadDataCore (Uri address)
+ byte [] DownloadDataCore (Uri address, object userToken)
{
- WebRequest request = SetupRequest (address, "GET");
- WebResponse response = request.GetResponse ();
- Stream st = ProcessResponse (response);
- return ReadAll (st, (int) response.ContentLength);
+ WebRequest request = null;
+
+ try {
+ request = SetupRequest (address);
+ WebResponse response = request.GetResponse ();
+ Stream st = ProcessResponse (response);
+ return ReadAll (st, (int) response.ContentLength, userToken);
+ } catch (ThreadInterruptedException){
+ if (request != null)
+ request.Abort ();
+ throw;
+ } catch (Exception ex) {
+ throw new WebException ("An error occurred " +
+ "performing a WebClient request.", ex);
+ }
}
// DownloadFile
public void DownloadFile (string address, string fileName)
{
- DownloadFile (MakeUri (address), fileName);
+#if NET_2_0
+ if (address == null)
+ throw new ArgumentNullException ("address");
+#endif
+
+ DownloadFile (CreateUri (address), fileName);
}
#if NET_2_0
#endif
void DownloadFile (Uri address, string fileName)
{
+#if NET_2_0
+ if (address == null)
+ throw new ArgumentNullException ("address");
+ if (fileName == null)
+ throw new ArgumentNullException ("fileName");
+#endif
+
try {
SetBusy ();
- DownloadFileCore (address, fileName);
+#if NET_2_0
+ async = false;
+#endif
+ DownloadFileCore (address, fileName, null);
+ } catch (Exception ex) {
+ throw new WebException ("An error occurred " +
+ "performing a WebClient request.", ex);
} finally {
- isBusy = false;
+ is_busy = false;
}
}
- void DownloadFileCore (Uri address, string fileName)
+ void DownloadFileCore (Uri address, string fileName, object userToken)
{
- WebRequest request = SetupRequest (address);
- WebResponse response = request.GetResponse ();
- Stream st = ProcessResponse (response);
-
- int cLength = (int) response.ContentLength;
- int length = (cLength <= -1 || cLength > 8192) ? 8192 : cLength;
- byte [] buffer = new byte [length];
- FileStream f = new FileStream (fileName, FileMode.CreateNew);
-
- int nread = 0;
- while ((nread = st.Read (buffer, 0, length)) != 0)
- f.Write (buffer, 0, nread);
-
- f.Close ();
+ WebRequest request = null;
+
+ using (FileStream f = new FileStream (fileName, FileMode.Create)) {
+ try {
+ request = SetupRequest (address);
+ WebResponse response = request.GetResponse ();
+ Stream st = ProcessResponse (response);
+
+ int cLength = (int) response.ContentLength;
+ int length = (cLength <= -1 || cLength > 32*1024) ? 32*1024 : cLength;
+ byte [] buffer = new byte [length];
+
+ int nread = 0;
+#if NET_2_0
+ long notify_total = 0;
+#endif
+ while ((nread = st.Read (buffer, 0, length)) != 0){
+#if NET_2_0
+ if (async){
+ notify_total += nread;
+ OnDownloadProgressChanged (
+ new DownloadProgressChangedEventArgs (notify_total, response.ContentLength, userToken));
+
+ }
+#endif
+ f.Write (buffer, 0, nread);
+ }
+ } catch (ThreadInterruptedException){
+ if (request != null)
+ request.Abort ();
+ throw;
+ }
+ }
}
// OpenRead
public Stream OpenRead (string address)
{
- return OpenRead (MakeUri (address));
+#if NET_2_0
+ if (address == null)
+ throw new ArgumentNullException ("address");
+#endif
+
+ return OpenRead (CreateUri (address));
}
#if NET_2_0
#endif
Stream OpenRead (Uri address)
{
+#if NET_2_0
+ if (address == null)
+ throw new ArgumentNullException ("address");
+#endif
+
+ WebRequest request = null;
try {
SetBusy ();
- WebRequest request = SetupRequest (address);
+#if NET_2_0
+ async = false;
+#endif
+ request = SetupRequest (address);
WebResponse response = request.GetResponse ();
return ProcessResponse (response);
+ } catch (Exception ex) {
+ throw new WebException ("An error occurred " +
+ "performing a WebClient request.", ex);
} finally {
- isBusy = false;
+ is_busy = false;
}
}
public Stream OpenWrite (string address)
{
- return OpenWrite (MakeUri (address));
+#if NET_2_0
+ if (address == null)
+ throw new ArgumentNullException ("address");
+#endif
+
+ return OpenWrite (CreateUri (address));
}
public Stream OpenWrite (string address, string method)
{
- return OpenWrite (MakeUri (address), method);
+#if NET_2_0
+ if (address == null)
+ throw new ArgumentNullException ("address");
+#endif
+
+ return OpenWrite (CreateUri (address), method);
}
#if NET_2_0
#endif
Stream OpenWrite (Uri address)
{
- return OpenWrite (address, DetermineMethod (address));
+ return OpenWrite (address, (string) null);
}
#if NET_2_0
#endif
Stream OpenWrite (Uri address, string method)
{
+#if NET_2_0
+ if (address == null)
+ throw new ArgumentNullException ("address");
+#endif
+
try {
SetBusy ();
- WebRequest request = SetupRequest (address, method);
+#if NET_2_0
+ async = false;
+#endif
+ WebRequest request = SetupRequest (address, method, true);
return request.GetRequestStream ();
+ } catch (Exception ex) {
+ throw new WebException ("An error occurred " +
+ "performing a WebClient request.", ex);
} finally {
- isBusy = false;
+ is_busy = false;
}
}
- private string DetermineMethod (Uri address)
+ private string DetermineMethod (Uri address, string method, bool is_upload)
{
- if (address == null)
- throw new ArgumentNullException ("address");
+ if (method != null)
+ return method;
+
#if NET_2_0
if (address.Scheme == Uri.UriSchemeFtp)
- return "RETR";
+ return (is_upload) ? "STOR" : "RETR";
#endif
- return "POST";
+ return (is_upload) ? "POST" : "GET";
}
// UploadData
public byte [] UploadData (string address, byte [] data)
{
- return UploadData (MakeUri (address), data);
+#if NET_2_0
+ if (address == null)
+ throw new ArgumentNullException ("address");
+#endif
+
+ return UploadData (CreateUri (address), data);
}
public byte [] UploadData (string address, string method, byte [] data)
{
- return UploadData (MakeUri (address), method, data);
+#if NET_2_0
+ if (address == null)
+ throw new ArgumentNullException ("address");
+#endif
+
+ return UploadData (CreateUri (address), method, data);
}
#if NET_2_0
#endif
byte [] UploadData (Uri address, byte [] data)
{
- return UploadData (address, DetermineMethod (address), data);
+ return UploadData (address, (string) null, data);
}
#if NET_2_0
#endif
byte [] UploadData (Uri address, string method, byte [] data)
{
+#if NET_2_0
+ if (address == null)
+ throw new ArgumentNullException ("address");
+ if (data == null)
+ throw new ArgumentNullException ("data");
+#endif
+
try {
SetBusy ();
- return UploadDataCore (address, method, data);
+#if NET_2_0
+ async = false;
+#endif
+ return UploadDataCore (address, method, data, null);
+ } catch (WebException) {
+ throw;
+ } catch (Exception ex) {
+ throw new WebException ("An error occurred " +
+ "performing a WebClient request.", ex);
} finally {
- isBusy = false;
+ is_busy = false;
}
}
- byte [] UploadDataCore (Uri address, string method, byte [] data)
+ byte [] UploadDataCore (Uri address, string method, byte [] data, object userToken)
{
+#if ONLY_1_1
+ if (address == null)
+ throw new ArgumentNullException ("address");
if (data == null)
throw new ArgumentNullException ("data");
+#endif
- int contentLength = data.Length;
- WebRequest request = SetupRequest (address, method, contentLength);
- using (Stream stream = request.GetRequestStream ()) {
- stream.Write (data, 0, contentLength);
+ WebRequest request = SetupRequest (address, method, true);
+ try {
+ int contentLength = data.Length;
+ request.ContentLength = contentLength;
+ using (Stream stream = request.GetRequestStream ()) {
+ stream.Write (data, 0, contentLength);
+ }
+
+ WebResponse response = request.GetResponse ();
+ Stream st = ProcessResponse (response);
+ return ReadAll (st, (int) response.ContentLength, userToken);
+ } catch (ThreadInterruptedException){
+ if (request != null)
+ request.Abort ();
+ throw;
}
-
- WebResponse response = request.GetResponse ();
- Stream st = ProcessResponse (response);
- return ReadAll (st, (int) response.ContentLength);
}
// UploadFile
public byte [] UploadFile (string address, string fileName)
{
- return UploadFile (MakeUri (address), fileName);
+#if NET_2_0
+ if (address == null)
+ throw new ArgumentNullException ("address");
+#endif
+
+ return UploadFile (CreateUri (address), fileName);
}
#if NET_2_0
#endif
byte [] UploadFile (Uri address, string fileName)
{
- return UploadFile (address, DetermineMethod (address), fileName);
+ return UploadFile (address, (string) null, fileName);
}
public byte [] UploadFile (string address, string method, string fileName)
{
- return UploadFile (MakeUri (address), method, fileName);
+ return UploadFile (CreateUri (address), method, fileName);
}
#if NET_2_0
#endif
byte [] UploadFile (Uri address, string method, string fileName)
{
+#if NET_2_0
+ if (address == null)
+ throw new ArgumentNullException ("address");
+ if (fileName == null)
+ throw new ArgumentNullException ("fileName");
+#endif
+
try {
SetBusy ();
- return UploadFileCore (address, method, fileName);
+#if NET_2_0
+ async = false;
+#endif
+ return UploadFileCore (address, method, fileName, null);
+ } catch (Exception ex) {
+ throw new WebException ("An error occurred " +
+ "performing a WebClient request.", ex);
} finally {
- isBusy = false;
+ is_busy = false;
}
}
- byte [] UploadFileCore (Uri address, string method, string fileName)
+ byte [] UploadFileCore (Uri address, string method, string fileName, object userToken)
{
+#if ONLY_1_1
+ if (address == null)
+ throw new ArgumentNullException ("address");
+#endif
+
string fileCType = Headers ["Content-Type"];
if (fileCType != null) {
string lower = fileCType.ToLower ();
string boundary = "------------" + DateTime.Now.Ticks.ToString ("x");
Headers ["Content-Type"] = String.Format ("multipart/form-data; boundary={0}", boundary);
- WebRequest request = SetupRequest (address, method);
Stream reqStream = null;
Stream fStream = null;
byte [] resultBytes = null;
+ fileName = Path.GetFullPath (fileName);
+
+ WebRequest request = null;
try {
fStream = File.OpenRead (fileName);
+ request = SetupRequest (address, method, true);
reqStream = request.GetRequestStream ();
byte [] realBoundary = Encoding.ASCII.GetBytes ("--" + boundary + "\r\n");
reqStream.Write (realBoundary, 0, realBoundary.Length);
reqStream = null;
WebResponse response = request.GetResponse ();
Stream st = ProcessResponse (response);
- resultBytes = ReadAll (st, (int) response.ContentLength);
- } catch (WebException) {
+ resultBytes = ReadAll (st, (int) response.ContentLength, userToken);
+ } catch (ThreadInterruptedException){
+ if (request != null)
+ request.Abort ();
throw;
- } catch (Exception e) {
- throw new WebException ("Error uploading file.", e);
} finally {
if (fStream != null)
fStream.Close ();
reqStream.Close ();
}
- return resultBytes;
+ return resultBytes;
}
public byte[] UploadValues (string address, NameValueCollection data)
{
- return UploadValues (MakeUri (address), data);
+#if NET_2_0
+ if (address == null)
+ throw new ArgumentNullException ("address");
+#endif
+
+ return UploadValues (CreateUri (address), data);
}
public byte[] UploadValues (string address, string method, NameValueCollection data)
{
- return UploadValues (MakeUri (address), method, data);
+#if NET_2_0
+ if (address == null)
+ throw new ArgumentNullException ("address");
+#endif
+
+ return UploadValues (CreateUri (address), method, data);
}
#if NET_2_0
#endif
byte[] UploadValues (Uri address, NameValueCollection data)
{
- return UploadValues (address, DetermineMethod (address), data);
+ return UploadValues (address, (string) null, data);
}
#if NET_2_0
public
#endif
- byte[] UploadValues (Uri uri, string method, NameValueCollection data)
+ byte[] UploadValues (Uri address, string method, NameValueCollection data)
{
+#if NET_2_0
+ if (address == null)
+ throw new ArgumentNullException ("address");
+ if (data == null)
+ throw new ArgumentNullException ("data");
+#endif
+
try {
SetBusy ();
- return UploadValuesCore (uri, method, data);
+#if NET_2_0
+ async = false;
+#endif
+ return UploadValuesCore (address, method, data, null);
+ } catch (Exception ex) {
+ throw new WebException ("An error occurred " +
+ "performing a WebClient request.", ex);
} finally {
- isBusy = false;
+ is_busy = false;
}
}
- byte[] UploadValuesCore (Uri uri, string method, NameValueCollection data)
+ byte[] UploadValuesCore (Uri uri, string method, NameValueCollection data, object userToken)
{
+#if ONLY_1_1
if (data == null)
- throw new ArgumentNullException ("data"); // MS throws a nullref
+ throw new ArgumentNullException ("data");
+#endif
string cType = Headers ["Content-Type"];
if (cType != null && String.Compare (cType, urlEncodedCType, true) != 0)
"value for this request.");
Headers ["Content-Type"] = urlEncodedCType;
- WebRequest request = SetupRequest (uri, method);
- Stream rqStream = request.GetRequestStream ();
- MemoryStream tmpStream = new MemoryStream ();
- foreach (string key in data) {
- byte [] bytes = Encoding.ASCII.GetBytes (key);
- UrlEncodeAndWrite (tmpStream, bytes);
- tmpStream.WriteByte ((byte) '=');
- bytes = Encoding.ASCII.GetBytes (data [key]);
- UrlEncodeAndWrite (tmpStream, bytes);
- tmpStream.WriteByte ((byte) '&');
+ WebRequest request = SetupRequest (uri, method, true);
+ try {
+ Stream rqStream = request.GetRequestStream ();
+ MemoryStream tmpStream = new MemoryStream ();
+ foreach (string key in data) {
+ byte [] bytes = Encoding.UTF8.GetBytes (key);
+ UrlEncodeAndWrite (tmpStream, bytes);
+ tmpStream.WriteByte ((byte) '=');
+ bytes = Encoding.UTF8.GetBytes (data [key]);
+ UrlEncodeAndWrite (tmpStream, bytes);
+ tmpStream.WriteByte ((byte) '&');
+ }
+
+ int length = (int) tmpStream.Length;
+ if (length > 0)
+ tmpStream.SetLength (--length); // remove trailing '&'
+
+ byte [] buf = tmpStream.GetBuffer ();
+ rqStream.Write (buf, 0, length);
+ rqStream.Close ();
+ tmpStream.Close ();
+
+ WebResponse response = request.GetResponse ();
+ Stream st = ProcessResponse (response);
+ return ReadAll (st, (int) response.ContentLength, userToken);
+ } catch (ThreadInterruptedException) {
+ request.Abort ();
+ throw;
}
-
- int length = (int) tmpStream.Length;
- if (length > 0)
- tmpStream.SetLength (--length); // remove trailing '&'
-
- tmpStream.WriteByte ((byte) '\r');
- tmpStream.WriteByte ((byte) '\n');
-
- byte [] buf = tmpStream.GetBuffer ();
- rqStream.Write (buf, 0, length + 2);
- rqStream.Close ();
- tmpStream.Close ();
-
- WebResponse response = request.GetResponse ();
- Stream st = ProcessResponse (response);
- return ReadAll (st, (int) response.ContentLength);
}
#if NET_2_0
public string DownloadString (string address)
{
- return encoding.GetString (DownloadData (address));
+ if (address == null)
+ throw new ArgumentNullException ("address");
+
+ return encoding.GetString (DownloadData (CreateUri (address)));
}
public string DownloadString (Uri address)
{
- return encoding.GetString (DownloadData (address));
+ if (address == null)
+ throw new ArgumentNullException ("address");
+
+ return encoding.GetString (DownloadData (CreateUri (address)));
}
public string UploadString (string address, string data)
{
+ if (address == null)
+ throw new ArgumentNullException ("address");
+ if (data == null)
+ throw new ArgumentNullException ("data");
+
byte [] resp = UploadData (address, encoding.GetBytes (data));
return encoding.GetString (resp);
}
public string UploadString (string address, string method, string data)
{
+ if (address == null)
+ throw new ArgumentNullException ("address");
+ if (data == null)
+ throw new ArgumentNullException ("data");
+
byte [] resp = UploadData (address, method, encoding.GetBytes (data));
return encoding.GetString (resp);
}
public string UploadString (Uri address, string data)
{
+ if (address == null)
+ throw new ArgumentNullException ("address");
+ if (data == null)
+ throw new ArgumentNullException ("data");
+
byte [] resp = UploadData (address, encoding.GetBytes (data));
return encoding.GetString (resp);
}
public string UploadString (Uri address, string method, string data)
{
+ if (address == null)
+ throw new ArgumentNullException ("address");
+ if (data == null)
+ throw new ArgumentNullException ("data");
+
byte [] resp = UploadData (address, method, encoding.GetBytes (data));
return encoding.GetString (resp);
}
public event UploadValuesCompletedEventHandler UploadValuesCompleted;
#endif
- Uri MakeUri (string path)
+ Uri CreateUri (string address)
{
- string query = null;
- if (queryString != null && queryString.Count != 0) {
- // This is not the same as UploadValues, because these 'keys' are not
- // urlencoded here.
- StringBuilder sb = new StringBuilder ();
+#if ONLY_1_1
+ try {
+ return MakeUri (address);
+ } catch (Exception ex) {
+ throw new WebException ("An error occurred " +
+ "performing a WebClient request.", ex);
+ }
+#else
+ return MakeUri (address);
+#endif
+ }
+
+#if NET_2_0
+ Uri CreateUri (Uri address)
+ {
+ string query = address.Query;
+ if (String.IsNullOrEmpty (query))
+ query = GetQueryString (true);
+
+ if (baseAddress == null && query == null)
+ return address;
+
+ if (baseAddress == null)
+ return new Uri (address.ToString () + query, (query != null));
+
+ if (query == null)
+ return new Uri (baseAddress, address.ToString ());
+
+ return new Uri (baseAddress, address.ToString () + query, (query != null));
+
+ }
+#endif
+
+ string GetQueryString (bool add_qmark)
+ {
+ if (queryString == null || queryString.Count == 0)
+ return null;
+
+ StringBuilder sb = new StringBuilder ();
+ if (add_qmark)
sb.Append ('?');
- foreach (string key in queryString)
- sb.AppendFormat ("{0}={1}&", key, UrlEncode (queryString [key]));
- if (sb.Length != 0) {
- sb.Length--; // remove trailing '&'
- query = sb.ToString ();
- }
- }
-
+ foreach (string key in queryString)
+ sb.AppendFormat ("{0}={1}&", key, UrlEncode (queryString [key]));
+ if (sb.Length != 0)
+ sb.Length--; // removes last '&' or the '?' if empty.
+
+ if (sb.Length == 0)
+ return null;
+
+ return sb.ToString ();
+ }
+
+ Uri MakeUri (string path)
+ {
+ string query = GetQueryString (true);
if (baseAddress == null && query == null) {
try {
return new Uri (path);
- }
- catch (System.UriFormatException) {
- if ((path[0] == Path.DirectorySeparatorChar) || (path[1] == ':' && Char.ToLower(path[0]) > 'a' && Char.ToLower(path[0]) < 'z')) {
- return new Uri ("file://" + path);
- }
- else {
- return new Uri ("file://" + Environment.CurrentDirectory + Path.DirectorySeparatorChar + path);
- }
+#if NET_2_0
+ } catch (ArgumentNullException) {
+ path = Path.GetFullPath (path);
+ return new Uri ("file://" + path);
+#endif
+ } catch (UriFormatException) {
+ path = Path.GetFullPath (path);
+ return new Uri ("file://" + path);
}
}
headers.RemoveInternal ("User-Agent");
request.Headers = headers;
- if (expect != null && expect != "")
+ if (expect != null && expect.Length > 0)
req.Expect = expect;
- if (accept != null && accept != "")
+ if (accept != null && accept.Length > 0)
req.Accept = accept;
- if (contentType != null && contentType != "")
+ if (contentType != null && contentType.Length > 0)
req.ContentType = contentType;
- if (connection != null && connection != "")
+ if (connection != null && connection.Length > 0)
req.Connection = connection;
- if (userAgent != null && userAgent != "")
+ if (userAgent != null && userAgent.Length > 0)
req.UserAgent = userAgent;
- if (referer != null && referer != "")
+ if (referer != null && referer.Length > 0)
req.Referer = referer;
}
return request;
}
- WebRequest SetupRequest (Uri uri, string method)
+ WebRequest SetupRequest (Uri uri, string method, bool is_upload)
{
WebRequest request = SetupRequest (uri);
- request.Method = method;
- return request;
- }
-
- WebRequest SetupRequest (Uri uri, string method, int contentLength)
- {
- WebRequest request = SetupRequest (uri, method);
- request.ContentLength = contentLength;
+ request.Method = DetermineMethod (uri, method, is_upload);
return request;
}
return response.GetResponseStream ();
}
- static byte [] ReadAll (Stream stream, int length)
+ byte [] ReadAll (Stream stream, int length, object userToken)
{
MemoryStream ms = null;
if (nolength)
ms = new MemoryStream ();
+// long total = 0;
int nread = 0;
int offset = 0;
byte [] buffer = new byte [size];
offset += nread;
size -= nread;
}
+#if NET_2_0
+ if (async){
+// total += nread;
+ OnDownloadProgressChanged (new DownloadProgressChangedEventArgs (nread, length, userToken));
+ }
+#endif
}
if (nolength)
}
#if NET_2_0
- List<RegisteredWaitHandle> wait_handles;
-
- List<RegisteredWaitHandle> WaitHandles {
- get {
- if (wait_handles == null)
- wait_handles = new List<RegisteredWaitHandle> ();
- return wait_handles;
+ public void CancelAsync ()
+ {
+ lock (this){
+ if (async_thread == null)
+ return;
+
+ //
+ // We first flag things as done, in case the Interrupt hangs
+ // or the thread decides to hang in some other way inside the
+ // event handlers, or if we are stuck somewhere else. This
+ // ensures that the WebClient object is reusable immediately
+ //
+ Thread t = async_thread;
+ CompleteAsync ();
+ t.Interrupt ();
}
}
- [MonoTODO ("Is it enough to just unregister wait handles from ThreadPool?")]
- public void CancelAsync ()
+ void CompleteAsync ()
{
- if (wait_handles == null)
- return;
- lock (wait_handles) {
- foreach (RegisteredWaitHandle handle in wait_handles)
- handle.Unregister (null);
- wait_handles.Clear ();
+ lock (this){
+ is_busy = false;
+ async_thread = null;
}
}
// DownloadDataAsync
- public void DownloadDataAsync (Uri uri)
+ public void DownloadDataAsync (Uri address)
{
- DownloadDataAsync (uri, null);
+ DownloadDataAsync (address, null);
}
- public void DownloadDataAsync (Uri uri, object asyncState)
+ public void DownloadDataAsync (Uri address, object userToken)
{
+ if (address == null)
+ throw new ArgumentNullException ("address");
+
lock (this) {
- CheckBusy ();
-
- object [] cbArgs = new object [] {uri, asyncState};
- WaitOrTimerCallback cb = delegate (object state, bool timedOut) {
+ SetBusy ();
+ async = true;
+
+ async_thread = new Thread (delegate (object state) {
object [] args = (object []) state;
- byte [] data = timedOut ? null : DownloadData ((Uri) args [0]);
- OnDownloadDataCompleted (
- new DownloadDataCompletedEventArgs (data, null, timedOut, args [1]));
- };
- AutoResetEvent ev = new AutoResetEvent (true);
- WaitHandles.Add (ThreadPool.RegisterWaitForSingleObject (ev, cb, cbArgs, -1, true));
+ try {
+ byte [] data = DownloadDataCore ((Uri) args [0], args [1]);
+ OnDownloadDataCompleted (
+ new DownloadDataCompletedEventArgs (data, null, false, args [1]));
+ } catch (ThreadInterruptedException){
+ OnDownloadDataCompleted (
+ new DownloadDataCompletedEventArgs (null, null, true, args [1]));
+ throw;
+ } catch (Exception e){
+ OnDownloadDataCompleted (
+ new DownloadDataCompletedEventArgs (null, e, false, args [1]));
+ }
+ });
+ object [] cb_args = new object [] {address, userToken};
+ async_thread.Start (cb_args);
}
}
// DownloadFileAsync
- public void DownloadFileAsync (Uri uri, string method)
+ public void DownloadFileAsync (Uri address, string fileName)
{
- DownloadFileAsync (uri, method, null);
+ DownloadFileAsync (address, fileName, null);
}
- public void DownloadFileAsync (Uri uri, string method, object asyncState)
+ public void DownloadFileAsync (Uri address, string fileName, object userToken)
{
+ if (address == null)
+ throw new ArgumentNullException ("address");
+ if (fileName == null)
+ throw new ArgumentNullException ("fileName");
+
lock (this) {
- CheckBusy ();
+ SetBusy ();
+ async = true;
- object [] cbArgs = new object [] {uri, method, asyncState};
- WaitOrTimerCallback cb = delegate (object innerState, bool timedOut) {
- object [] args = (object []) innerState;
- if (!timedOut)
- DownloadFile ((Uri) args [0], (string) args [1]);
- OnDownloadFileCompleted (
- new AsyncCompletedEventArgs (null, timedOut, args [2]));
- };
- AutoResetEvent ev = new AutoResetEvent (true);
- WaitHandles.Add (ThreadPool.RegisterWaitForSingleObject (ev, cb, cbArgs, -1, true));
+ async_thread = new Thread (delegate (object state) {
+ object [] args = (object []) state;
+ try {
+ DownloadFileCore ((Uri) args [0], (string) args [1], args [2]);
+ OnDownloadFileCompleted (
+ new AsyncCompletedEventArgs (null, false, args [2]));
+ } catch (ThreadInterruptedException){
+ OnDownloadFileCompleted (
+ new AsyncCompletedEventArgs (null, true, args [2]));
+ } catch (Exception e){
+ OnDownloadFileCompleted (
+ new AsyncCompletedEventArgs (e, false, args [2]));
+ }});
+ object [] cb_args = new object [] {address, fileName, userToken};
+ async_thread.Start (cb_args);
}
}
// DownloadStringAsync
- public void DownloadStringAsync (Uri uri)
+ public void DownloadStringAsync (Uri address)
{
- DownloadStringAsync (uri, null);
+ DownloadStringAsync (address, null);
}
- public void DownloadStringAsync (Uri uri, object asyncState)
+ public void DownloadStringAsync (Uri address, object userToken)
{
+ if (address == null)
+ throw new ArgumentNullException ("address");
+
lock (this) {
- CheckBusy ();
+ SetBusy ();
+ async = true;
- object [] cbArgs = new object [] {uri, asyncState};
- WaitOrTimerCallback cb = delegate (object innerState, bool timedOut) {
- object [] args = (object []) innerState;
- string data = timedOut ? null : DownloadString ((Uri) args [0]);
- OnDownloadStringCompleted (
- new DownloadStringCompletedEventArgs (data, null, timedOut, args [1]));
- };
- AutoResetEvent ev = new AutoResetEvent (true);
- WaitHandles.Add (ThreadPool.RegisterWaitForSingleObject (ev, cb, cbArgs, -1, true));
+ async_thread = new Thread (delegate (object state) {
+ object [] args = (object []) state;
+ try {
+ string data = encoding.GetString (DownloadDataCore ((Uri) args [0], args [1]));
+ OnDownloadStringCompleted (
+ new DownloadStringCompletedEventArgs (data, null, false, args [1]));
+ } catch (ThreadInterruptedException){
+ OnDownloadStringCompleted (
+ new DownloadStringCompletedEventArgs (null, null, true, args [1]));
+ } catch (Exception e){
+ OnDownloadStringCompleted (
+ new DownloadStringCompletedEventArgs (null, e, false, args [1]));
+ }});
+ object [] cb_args = new object [] {address, userToken};
+ async_thread.Start (cb_args);
}
}
// OpenReadAsync
- public void OpenReadAsync (Uri uri)
+ public void OpenReadAsync (Uri address)
{
- OpenReadAsync (uri, null);
+ OpenReadAsync (address, null);
}
- public void OpenReadAsync (Uri uri, object asyncState)
+ public void OpenReadAsync (Uri address, object userToken)
{
+ if (address == null)
+ throw new ArgumentNullException ("address");
+
lock (this) {
- CheckBusy ();
+ SetBusy ();
+ async = true;
- object [] cbArgs = new object [] {uri, asyncState};
- WaitOrTimerCallback cb = delegate (object innerState, bool timedOut) {
- object [] args = (object []) innerState;
- Stream stream = timedOut ? null : OpenRead ((Uri) args [0]);
- OnOpenReadCompleted (
- new OpenReadCompletedEventArgs (stream, null, timedOut, args [1]));
- };
- AutoResetEvent ev = new AutoResetEvent (true);
- WaitHandles.Add (ThreadPool.RegisterWaitForSingleObject (ev, cb, cbArgs, -1, true));
+ async_thread = new Thread (delegate (object state) {
+ object [] args = (object []) state;
+ WebRequest request = null;
+ try {
+ request = SetupRequest ((Uri) args [0]);
+ WebResponse response = request.GetResponse ();
+ Stream stream = ProcessResponse (response);
+ OnOpenReadCompleted (
+ new OpenReadCompletedEventArgs (stream, null, false, args [1]));
+ } catch (ThreadInterruptedException){
+ if (request != null)
+ request.Abort ();
+
+ OnOpenReadCompleted (new OpenReadCompletedEventArgs (null, null, true, args [1]));
+ } catch (Exception e){
+ OnOpenReadCompleted (new OpenReadCompletedEventArgs (null, e, false, args [1]));
+ } });
+ object [] cb_args = new object [] {address, userToken};
+ async_thread.Start (cb_args);
}
}
// OpenWriteAsync
- public void OpenWriteAsync (Uri uri)
+ public void OpenWriteAsync (Uri address)
{
- OpenWriteAsync (uri, null);
+ OpenWriteAsync (address, null);
}
- public void OpenWriteAsync (Uri uri, string method)
+ public void OpenWriteAsync (Uri address, string method)
{
- OpenWriteAsync (uri, method, null);
+ OpenWriteAsync (address, method, null);
}
- public void OpenWriteAsync (Uri uri, string method, object asyncState)
+ public void OpenWriteAsync (Uri address, string method, object userToken)
{
+ if (address == null)
+ throw new ArgumentNullException ("address");
+
lock (this) {
- CheckBusy ();
+ SetBusy ();
+ async = true;
- object [] cbArgs = new object [] {uri, method, asyncState};
- WaitOrTimerCallback cb = delegate (object innerState, bool timedOut) {
- object [] args = (object []) innerState;
- Stream stream = timedOut ? null : OpenWrite ((Uri) args [0], (string) args [1]);
- OnOpenWriteCompleted (
- new OpenWriteCompletedEventArgs (stream, null, timedOut, args [2]));
- };
- AutoResetEvent ev = new AutoResetEvent (true);
- WaitHandles.Add (ThreadPool.RegisterWaitForSingleObject (ev, cb, cbArgs, -1, true));
+ async_thread = new Thread (delegate (object state) {
+ object [] args = (object []) state;
+ WebRequest request = null;
+ try {
+ request = SetupRequest ((Uri) args [0], (string) args [1], true);
+ Stream stream = request.GetRequestStream ();
+ OnOpenWriteCompleted (
+ new OpenWriteCompletedEventArgs (stream, null, false, args [2]));
+ } catch (ThreadInterruptedException){
+ if (request != null)
+ request.Abort ();
+ OnOpenWriteCompleted (
+ new OpenWriteCompletedEventArgs (null, null, true, args [2]));
+ } catch (Exception e){
+ OnOpenWriteCompleted (
+ new OpenWriteCompletedEventArgs (null, e, false, args [2]));
+ }});
+ object [] cb_args = new object [] {address, method, userToken};
+ async_thread.Start (cb_args);
}
}
// UploadDataAsync
- public void UploadDataAsync (Uri uri, byte [] data)
+ public void UploadDataAsync (Uri address, byte [] data)
{
- UploadDataAsync (uri, null, data);
+ UploadDataAsync (address, null, data);
}
- public void UploadDataAsync (Uri uri, string method, byte [] data)
+ public void UploadDataAsync (Uri address, string method, byte [] data)
{
- UploadDataAsync (uri, method, data, null);
+ UploadDataAsync (address, method, data, null);
}
- public void UploadDataAsync (Uri uri, string method, byte [] data, object asyncState)
+ public void UploadDataAsync (Uri address, string method, byte [] data, object userToken)
{
+ if (address == null)
+ throw new ArgumentNullException ("address");
+ if (data == null)
+ throw new ArgumentNullException ("data");
+
lock (this) {
- CheckBusy ();
+ SetBusy ();
+ async = true;
- object [] cbArgs = new object [] {uri, method, data, asyncState};
- WaitOrTimerCallback cb = delegate (object innerState, bool timedOut) {
- object [] args = (object []) innerState;
- byte [] data2 = timedOut ? null : UploadData ((Uri) args [0], (string) args [1], (byte []) args [2]);
- OnUploadDataCompleted (
- new UploadDataCompletedEventArgs (data2, null, timedOut, args [3]));
- };
- AutoResetEvent ev = new AutoResetEvent (true);
- WaitHandles.Add (ThreadPool.RegisterWaitForSingleObject (ev, cb, cbArgs, -1, true));
+ async_thread = new Thread (delegate (object state) {
+ object [] args = (object []) state;
+ byte [] data2;
+
+ try {
+ data2 = UploadDataCore ((Uri) args [0], (string) args [1], (byte []) args [2], args [3]);
+
+ OnUploadDataCompleted (
+ new UploadDataCompletedEventArgs (data2, null, false, args [3]));
+ } catch (ThreadInterruptedException){
+ OnUploadDataCompleted (
+ new UploadDataCompletedEventArgs (null, null, true, args [3]));
+ } catch (Exception e){
+ OnUploadDataCompleted (
+ new UploadDataCompletedEventArgs (null, e, false, args [3]));
+ }});
+ object [] cb_args = new object [] {address, method, data, userToken};
+ async_thread.Start (cb_args);
}
}
// UploadFileAsync
- public void UploadFileAsync (Uri uri, string file)
+ public void UploadFileAsync (Uri address, string fileName)
{
- UploadFileAsync (uri, null, file);
+ UploadFileAsync (address, null, fileName);
}
- public void UploadFileAsync (Uri uri, string method, string file)
+ public void UploadFileAsync (Uri address, string method, string fileName)
{
- UploadFileAsync (uri, method, file, null);
+ UploadFileAsync (address, method, fileName, null);
}
- public void UploadFileAsync (Uri uri, string method, string file, object asyncState)
+ public void UploadFileAsync (Uri address, string method, string fileName, object userToken)
{
+ if (address == null)
+ throw new ArgumentNullException ("address");
+ if (fileName == null)
+ throw new ArgumentNullException ("fileName");
+
lock (this) {
- CheckBusy ();
+ SetBusy ();
+ async = true;
- object [] cbArgs = new object [] {uri, method, file, asyncState};
- WaitOrTimerCallback cb = delegate (object innerState, bool timedOut) {
- object [] args = (object []) innerState;
- byte [] data = timedOut ? null : UploadFile ((Uri) args [0], (string) args [1], (string) args [2]);
- OnUploadFileCompleted (
- new UploadFileCompletedEventArgs (data, null, timedOut, args [3]));
- };
- AutoResetEvent ev = new AutoResetEvent (true);
- WaitHandles.Add (ThreadPool.RegisterWaitForSingleObject (ev, cb, cbArgs, -1, true));
+ async_thread = new Thread (delegate (object state) {
+ object [] args = (object []) state;
+ byte [] data;
+
+ try {
+ data = UploadFileCore ((Uri) args [0], (string) args [1], (string) args [2], args [3]);
+ OnUploadFileCompleted (
+ new UploadFileCompletedEventArgs (data, null, false, args [3]));
+ } catch (ThreadInterruptedException){
+ OnUploadFileCompleted (
+ new UploadFileCompletedEventArgs (null, null, true, args [3]));
+ } catch (Exception e){
+ OnUploadFileCompleted (
+ new UploadFileCompletedEventArgs (null, e, false, args [3]));
+ }});
+ object [] cb_args = new object [] {address, method, fileName, userToken};
+ async_thread.Start (cb_args);
}
}
// UploadStringAsync
- public void UploadStringAsync (Uri uri, string data)
+ public void UploadStringAsync (Uri address, string data)
{
- UploadStringAsync (uri, null, data);
+ UploadStringAsync (address, null, data);
}
- public void UploadStringAsync (Uri uri, string method, string data)
+ public void UploadStringAsync (Uri address, string method, string data)
{
- UploadStringAsync (uri, method, data, null);
+ UploadStringAsync (address, method, data, null);
}
- public void UploadStringAsync (Uri uri, string method, string data, object asyncState)
+ public void UploadStringAsync (Uri address, string method, string data, object userToken)
{
+ if (address == null)
+ throw new ArgumentNullException ("address");
+ if (data == null)
+ throw new ArgumentNullException ("data");
+
lock (this) {
- CheckBusy ();
+ SetBusy ();
+ async = true;
+
+ async_thread = new Thread (delegate (object state) {
+ object [] args = (object []) state;
- object [] cbArgs = new object [] {uri, method, data, asyncState};
- WaitOrTimerCallback cb = delegate (object innerState, bool timedOut) {
- object [] args = (object []) innerState;
- string data2 = timedOut ? null : UploadString ((Uri) args [0], (string) args [1], (string) args [2]);
- OnUploadStringCompleted (
- new UploadStringCompletedEventArgs (data2, null, timedOut, args [3]));
- };
- AutoResetEvent ev = new AutoResetEvent (true);
- WaitHandles.Add (ThreadPool.RegisterWaitForSingleObject (ev, cb, cbArgs, -1, true));
+ try {
+ string data2 = UploadString ((Uri) args [0], (string) args [1], (string) args [2]);
+ OnUploadStringCompleted (
+ new UploadStringCompletedEventArgs (data2, null, false, args [3]));
+ } catch (ThreadInterruptedException){
+ OnUploadStringCompleted (
+ new UploadStringCompletedEventArgs (null, null, true, args [3]));
+ } catch (Exception e){
+ OnUploadStringCompleted (
+ new UploadStringCompletedEventArgs (null, e, false, args [3]));
+ }});
+ object [] cb_args = new object [] {address, method, data, userToken};
+ async_thread.Start (cb_args);
}
}
// UploadValuesAsync
- public void UploadValuesAsync (Uri uri, NameValueCollection values)
+ public void UploadValuesAsync (Uri address, NameValueCollection values)
{
- UploadValuesAsync (uri, null, values);
+ UploadValuesAsync (address, null, values);
}
- public void UploadValuesAsync (Uri uri, string method, NameValueCollection values)
+ public void UploadValuesAsync (Uri address, string method, NameValueCollection values)
{
- UploadValuesAsync (uri, method, values, null);
+ UploadValuesAsync (address, method, values, null);
}
- public void UploadValuesAsync (Uri uri, string method, NameValueCollection values, object asyncState)
+ public void UploadValuesAsync (Uri address, string method, NameValueCollection values, object userToken)
{
+ if (address == null)
+ throw new ArgumentNullException ("address");
+ if (values == null)
+ throw new ArgumentNullException ("values");
+
lock (this) {
CheckBusy ();
+ async = true;
- object [] cbArgs = new object [] {uri, method, values, asyncState};
- WaitOrTimerCallback cb = delegate (object innerState, bool timedOut) {
- object [] args = (object []) innerState;
- byte [] data = timedOut ? null : UploadValues ((Uri) args [0], (string) args [1], (NameValueCollection) args [2]);
- OnUploadValuesCompleted (
- new UploadValuesCompletedEventArgs (data, null, timedOut, args [3]));
- };
- AutoResetEvent ev = new AutoResetEvent (true);
- WaitHandles.Add (ThreadPool.RegisterWaitForSingleObject (ev, cb, cbArgs, -1, true));
+ async_thread = new Thread (delegate (object state) {
+ object [] args = (object []) state;
+ try {
+ byte [] data = UploadValuesCore ((Uri) args [0], (string) args [1], (NameValueCollection) args [2], args [3]);
+ OnUploadValuesCompleted (
+ new UploadValuesCompletedEventArgs (data, null, false, args [3]));
+ } catch (ThreadInterruptedException){
+ OnUploadValuesCompleted (
+ new UploadValuesCompletedEventArgs (null, null, true, args [3]));
+ } catch (Exception e){
+ OnUploadValuesCompleted (
+ new UploadValuesCompletedEventArgs (null, e, false, args [3]));
+ }});
+ object [] cb_args = new object [] {address, method, values, userToken};
+ async_thread.Start (cb_args);
}
}
- protected virtual void OnDownloadDataCompleted (
- DownloadDataCompletedEventArgs args)
+ protected virtual void OnDownloadDataCompleted (DownloadDataCompletedEventArgs args)
{
+ CompleteAsync ();
if (DownloadDataCompleted != null)
DownloadDataCompleted (this, args);
}
- protected virtual void OnDownloadFileCompleted (
- AsyncCompletedEventArgs args)
+ protected virtual void OnDownloadFileCompleted (AsyncCompletedEventArgs args)
{
+ CompleteAsync ();
if (DownloadFileCompleted != null)
DownloadFileCompleted (this, args);
}
- protected virtual void OnDownloadStringCompleted (
- DownloadStringCompletedEventArgs args)
+ protected virtual void OnDownloadProgressChanged (DownloadProgressChangedEventArgs e)
+ {
+ if (DownloadProgressChanged != null)
+ DownloadProgressChanged (this, e);
+ }
+
+ protected virtual void OnDownloadStringCompleted (DownloadStringCompletedEventArgs args)
{
+ CompleteAsync ();
if (DownloadStringCompleted != null)
DownloadStringCompleted (this, args);
}
- protected virtual void OnOpenReadCompleted (
- OpenReadCompletedEventArgs args)
+ protected virtual void OnOpenReadCompleted (OpenReadCompletedEventArgs args)
{
+ CompleteAsync ();
if (OpenReadCompleted != null)
OpenReadCompleted (this, args);
}
- protected virtual void OnOpenWriteCompleted (
- OpenWriteCompletedEventArgs args)
+ protected virtual void OnOpenWriteCompleted (OpenWriteCompletedEventArgs args)
{
+ CompleteAsync ();
if (OpenWriteCompleted != null)
OpenWriteCompleted (this, args);
}
- protected virtual void OnUploadDataCompleted (
- UploadDataCompletedEventArgs args)
+ protected virtual void OnUploadDataCompleted (UploadDataCompletedEventArgs args)
{
+ CompleteAsync ();
if (UploadDataCompleted != null)
UploadDataCompleted (this, args);
}
- protected virtual void OnUploadFileCompleted (
- UploadFileCompletedEventArgs args)
+ protected virtual void OnUploadFileCompleted (UploadFileCompletedEventArgs args)
{
+ CompleteAsync ();
if (UploadFileCompleted != null)
UploadFileCompleted (this, args);
}
- protected virtual void OnUploadStringCompleted (
- UploadStringCompletedEventArgs args)
+ protected virtual void OnUploadProgressChanged (UploadProgressChangedEventArgs e)
{
+ if (UploadProgressChanged != null)
+ UploadProgressChanged (this, e);
+ }
+
+ protected virtual void OnUploadStringCompleted (UploadStringCompletedEventArgs args)
+ {
+ CompleteAsync ();
if (UploadStringCompleted != null)
UploadStringCompleted (this, args);
}
- protected virtual void OnUploadValuesCompleted (
- UploadValuesCompletedEventArgs args)
+ protected virtual void OnUploadValuesCompleted (UploadValuesCompletedEventArgs args)
{
+ CompleteAsync ();
if (UploadValuesCompleted != null)
UploadValuesCompleted (this, args);
}
+
+ [MonoNotSupported("")]
+ protected virtual WebRequest GetWebRequest (Uri address)
+ {
+ throw new NotImplementedException ();
+ }
+
+ protected virtual WebResponse GetWebResponse (WebRequest request)
+ {
+ return request.GetResponse ();
+ }
+
+ protected virtual WebResponse GetWebResponse (WebRequest request, IAsyncResult result)
+ {
+ return request.EndGetResponse (result);
+ }
#endif
}
}
-