WebClient.cs 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461
  1. //
  2. // System.Net.WebClient
  3. //
  4. // Authors:
  5. // Lawrence Pit ([email protected])
  6. // Gonzalo Paniagua Javier ([email protected])
  7. // Atsushi Enomoto ([email protected])
  8. // Miguel de Icaza ([email protected])
  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. using System;
  34. using System.Collections.Specialized;
  35. using System.ComponentModel;
  36. using System.IO;
  37. using System.Runtime.InteropServices;
  38. using System.Runtime.Serialization;
  39. using System.Text;
  40. using System.Threading;
  41. #if NET_2_0
  42. using System.Net.Cache;
  43. #endif
  44. namespace System.Net
  45. {
  46. [ComVisible(true)]
  47. public
  48. #if !NET_2_0
  49. sealed
  50. #endif
  51. class WebClient : Component
  52. {
  53. static readonly string urlEncodedCType = "application/x-www-form-urlencoded";
  54. static byte [] hexBytes;
  55. ICredentials credentials;
  56. WebHeaderCollection headers;
  57. WebHeaderCollection responseHeaders;
  58. Uri baseAddress;
  59. string baseString;
  60. NameValueCollection queryString;
  61. bool is_busy, async;
  62. #if NET_2_0
  63. Thread async_thread;
  64. Encoding encoding = Encoding.Default;
  65. IWebProxy proxy;
  66. #endif
  67. // Constructors
  68. static WebClient ()
  69. {
  70. hexBytes = new byte [16];
  71. int index = 0;
  72. for (int i = '0'; i <= '9'; i++, index++)
  73. hexBytes [index] = (byte) i;
  74. for (int i = 'A'; i <= 'F'; i++, index++)
  75. hexBytes [index] = (byte) i;
  76. }
  77. public WebClient ()
  78. {
  79. }
  80. // Properties
  81. public string BaseAddress {
  82. get {
  83. if (baseString == null) {
  84. if (baseAddress == null)
  85. return "";
  86. }
  87. baseString = baseAddress.ToString ();
  88. return baseString;
  89. }
  90. set {
  91. if (value == null || value == "") {
  92. baseAddress = null;
  93. } else {
  94. baseAddress = new Uri (value);
  95. }
  96. }
  97. }
  98. #if NET_2_0
  99. static Exception GetMustImplement ()
  100. {
  101. return new NotImplementedException ();
  102. }
  103. [MonoTODO]
  104. public RequestCachePolicy CachePolicy
  105. {
  106. get {
  107. throw GetMustImplement ();
  108. }
  109. set {
  110. throw GetMustImplement ();
  111. }
  112. }
  113. [MonoTODO]
  114. public bool UseDefaultCredentials
  115. {
  116. get {
  117. throw GetMustImplement ();
  118. }
  119. set {
  120. throw GetMustImplement ();
  121. }
  122. }
  123. #endif
  124. public ICredentials Credentials {
  125. get { return credentials; }
  126. set { credentials = value; }
  127. }
  128. public WebHeaderCollection Headers {
  129. get {
  130. if (headers == null)
  131. headers = new WebHeaderCollection ();
  132. return headers;
  133. }
  134. set { headers = value; }
  135. }
  136. public NameValueCollection QueryString {
  137. get {
  138. if (queryString == null)
  139. queryString = new NameValueCollection ();
  140. return queryString;
  141. }
  142. set { queryString = value; }
  143. }
  144. public WebHeaderCollection ResponseHeaders {
  145. get { return responseHeaders; }
  146. }
  147. #if NET_2_0
  148. public Encoding Encoding {
  149. get { return encoding; }
  150. set {
  151. if (value == null)
  152. throw new ArgumentNullException ("value");
  153. encoding = value;
  154. }
  155. }
  156. public IWebProxy Proxy {
  157. get { return proxy; }
  158. set { proxy = value; }
  159. }
  160. #endif
  161. #if NET_2_0
  162. public bool IsBusy {
  163. get { return is_busy; }
  164. }
  165. #else
  166. bool IsBusy {
  167. get { return is_busy; }
  168. }
  169. #endif
  170. // Methods
  171. void CheckBusy ()
  172. {
  173. if (IsBusy)
  174. throw new NotSupportedException ("WebClient does not support conccurent I/O operations.");
  175. }
  176. void SetBusy ()
  177. {
  178. lock (this) {
  179. CheckBusy ();
  180. is_busy = true;
  181. }
  182. }
  183. // DownloadData
  184. public byte [] DownloadData (string address)
  185. {
  186. #if NET_2_0
  187. if (address == null)
  188. throw new ArgumentNullException ("address");
  189. #endif
  190. return DownloadData (CreateUri (address));
  191. }
  192. #if NET_2_0
  193. public
  194. #endif
  195. byte [] DownloadData (Uri address)
  196. {
  197. #if NET_2_0
  198. if (address == null)
  199. throw new ArgumentNullException ("address");
  200. #endif
  201. try {
  202. SetBusy ();
  203. async = false;
  204. return DownloadDataCore (address, null);
  205. } finally {
  206. is_busy = false;
  207. }
  208. }
  209. byte [] DownloadDataCore (Uri address, object userToken)
  210. {
  211. WebRequest request = null;
  212. try {
  213. request = SetupRequest (address, "GET");
  214. WebResponse response = request.GetResponse ();
  215. Stream st = ProcessResponse (response);
  216. return ReadAll (st, (int) response.ContentLength, userToken);
  217. } catch (ThreadInterruptedException){
  218. if (request != null)
  219. request.Abort ();
  220. throw;
  221. } catch (Exception ex) {
  222. throw new WebException ("An error occurred " +
  223. "performing a WebClient request.", ex);
  224. }
  225. }
  226. // DownloadFile
  227. public void DownloadFile (string address, string fileName)
  228. {
  229. #if NET_2_0
  230. if (address == null)
  231. throw new ArgumentNullException ("address");
  232. #endif
  233. DownloadFile (CreateUri (address), fileName);
  234. }
  235. #if NET_2_0
  236. public
  237. #endif
  238. void DownloadFile (Uri address, string fileName)
  239. {
  240. #if NET_2_0
  241. if (address == null)
  242. throw new ArgumentNullException ("address");
  243. if (fileName == null)
  244. throw new ArgumentNullException ("fileName");
  245. #endif
  246. try {
  247. SetBusy ();
  248. async = false;
  249. DownloadFileCore (address, fileName, null);
  250. } catch (Exception ex) {
  251. throw new WebException ("An error occurred " +
  252. "performing a WebClient request.", ex);
  253. } finally {
  254. is_busy = false;
  255. }
  256. }
  257. void DownloadFileCore (Uri address, string fileName, object userToken)
  258. {
  259. WebRequest request = null;
  260. using (FileStream f = new FileStream (fileName, FileMode.Create)) {
  261. try {
  262. request = SetupRequest (address);
  263. WebResponse response = request.GetResponse ();
  264. Stream st = ProcessResponse (response);
  265. int cLength = (int) response.ContentLength;
  266. int length = (cLength <= -1 || cLength > 32*1024) ? 32*1024 : cLength;
  267. byte [] buffer = new byte [length];
  268. int nread = 0;
  269. long notify_total = 0;
  270. while ((nread = st.Read (buffer, 0, length)) != 0){
  271. #if NET_2_0
  272. if (async && DownloadProgressChanged != null){
  273. notify_total += nread;
  274. DownloadProgressChanged (
  275. this,
  276. new DownloadProgressChangedEventArgs (response.ContentLength, notify_total, userToken));
  277. }
  278. #endif
  279. f.Write (buffer, 0, nread);
  280. }
  281. } catch (ThreadInterruptedException){
  282. if (request != null)
  283. request.Abort ();
  284. throw;
  285. }
  286. }
  287. }
  288. // OpenRead
  289. public Stream OpenRead (string address)
  290. {
  291. #if NET_2_0
  292. if (address == null)
  293. throw new ArgumentNullException ("address");
  294. #endif
  295. return OpenRead (CreateUri (address));
  296. }
  297. #if NET_2_0
  298. public
  299. #endif
  300. Stream OpenRead (Uri address)
  301. {
  302. #if NET_2_0
  303. if (address == null)
  304. throw new ArgumentNullException ("address");
  305. #endif
  306. WebRequest request = null;
  307. try {
  308. SetBusy ();
  309. async = false;
  310. request = SetupRequest (address);
  311. WebResponse response = request.GetResponse ();
  312. return ProcessResponse (response);
  313. } catch (Exception ex) {
  314. throw new WebException ("An error occurred " +
  315. "performing a WebClient request.", ex);
  316. } finally {
  317. is_busy = false;
  318. }
  319. }
  320. // OpenWrite
  321. public Stream OpenWrite (string address)
  322. {
  323. #if NET_2_0
  324. if (address == null)
  325. throw new ArgumentNullException ("address");
  326. #endif
  327. return OpenWrite (CreateUri (address));
  328. }
  329. public Stream OpenWrite (string address, string method)
  330. {
  331. #if NET_2_0
  332. if (address == null)
  333. throw new ArgumentNullException ("address");
  334. #endif
  335. return OpenWrite (CreateUri (address), method);
  336. }
  337. #if NET_2_0
  338. public
  339. #endif
  340. Stream OpenWrite (Uri address)
  341. {
  342. return OpenWrite (address, (string) null);
  343. }
  344. #if NET_2_0
  345. public
  346. #endif
  347. Stream OpenWrite (Uri address, string method)
  348. {
  349. #if NET_2_0
  350. if (address == null)
  351. throw new ArgumentNullException ("address");
  352. #endif
  353. try {
  354. SetBusy ();
  355. async = false;
  356. WebRequest request = SetupRequest (address, method);
  357. return request.GetRequestStream ();
  358. } catch (Exception ex) {
  359. throw new WebException ("An error occurred " +
  360. "performing a WebClient request.", ex);
  361. } finally {
  362. is_busy = false;
  363. }
  364. }
  365. private string DetermineMethod (Uri address, string method)
  366. {
  367. if (method != null)
  368. return method;
  369. #if NET_2_0
  370. if (address.Scheme == Uri.UriSchemeFtp)
  371. return "RETR";
  372. #endif
  373. return "POST";
  374. }
  375. // UploadData
  376. public byte [] UploadData (string address, byte [] data)
  377. {
  378. #if NET_2_0
  379. if (address == null)
  380. throw new ArgumentNullException ("address");
  381. #endif
  382. return UploadData (CreateUri (address), data);
  383. }
  384. public byte [] UploadData (string address, string method, byte [] data)
  385. {
  386. #if NET_2_0
  387. if (address == null)
  388. throw new ArgumentNullException ("address");
  389. #endif
  390. return UploadData (CreateUri (address), method, data);
  391. }
  392. #if NET_2_0
  393. public
  394. #endif
  395. byte [] UploadData (Uri address, byte [] data)
  396. {
  397. return UploadData (address, (string) null, data);
  398. }
  399. #if NET_2_0
  400. public
  401. #endif
  402. byte [] UploadData (Uri address, string method, byte [] data)
  403. {
  404. #if NET_2_0
  405. if (address == null)
  406. throw new ArgumentNullException ("address");
  407. if (data == null)
  408. throw new ArgumentNullException ("data");
  409. #endif
  410. try {
  411. SetBusy ();
  412. async = false;
  413. return UploadDataCore (address, method, data, null);
  414. } catch (Exception ex) {
  415. throw new WebException ("An error occurred " +
  416. "performing a WebClient request.", ex);
  417. } finally {
  418. is_busy = false;
  419. }
  420. }
  421. byte [] UploadDataCore (Uri address, string method, byte [] data, object userToken)
  422. {
  423. #if ONLY_1_1
  424. if (address == null)
  425. throw new ArgumentNullException ("address");
  426. if (data == null)
  427. throw new ArgumentNullException ("data");
  428. #endif
  429. WebRequest request = SetupRequest (address, method);
  430. try {
  431. int contentLength = data.Length;
  432. request.ContentLength = contentLength;
  433. using (Stream stream = request.GetRequestStream ()) {
  434. stream.Write (data, 0, contentLength);
  435. }
  436. WebResponse response = request.GetResponse ();
  437. Stream st = ProcessResponse (response);
  438. return ReadAll (st, (int) response.ContentLength, userToken);
  439. } catch (ThreadInterruptedException){
  440. if (request != null)
  441. request.Abort ();
  442. throw;
  443. }
  444. }
  445. // UploadFile
  446. public byte [] UploadFile (string address, string fileName)
  447. {
  448. #if NET_2_0
  449. if (address == null)
  450. throw new ArgumentNullException ("address");
  451. #endif
  452. return UploadFile (CreateUri (address), fileName);
  453. }
  454. #if NET_2_0
  455. public
  456. #endif
  457. byte [] UploadFile (Uri address, string fileName)
  458. {
  459. return UploadFile (address, (string) null, fileName);
  460. }
  461. public byte [] UploadFile (string address, string method, string fileName)
  462. {
  463. return UploadFile (CreateUri (address), method, fileName);
  464. }
  465. #if NET_2_0
  466. public
  467. #endif
  468. byte [] UploadFile (Uri address, string method, string fileName)
  469. {
  470. #if NET_2_0
  471. if (address == null)
  472. throw new ArgumentNullException ("address");
  473. if (fileName == null)
  474. throw new ArgumentNullException ("fileName");
  475. #endif
  476. try {
  477. SetBusy ();
  478. async = false;
  479. return UploadFileCore (address, method, fileName, null);
  480. } catch (Exception ex) {
  481. throw new WebException ("An error occurred " +
  482. "performing a WebClient request.", ex);
  483. } finally {
  484. is_busy = false;
  485. }
  486. }
  487. byte [] UploadFileCore (Uri address, string method, string fileName, object userToken)
  488. {
  489. #if ONLY_1_1
  490. if (address == null)
  491. throw new ArgumentNullException ("address");
  492. #endif
  493. string fileCType = Headers ["Content-Type"];
  494. if (fileCType != null) {
  495. string lower = fileCType.ToLower ();
  496. if (lower.StartsWith ("multipart/"))
  497. throw new WebException ("Content-Type cannot be set to a multipart" +
  498. " type for this request.");
  499. } else {
  500. fileCType = "application/octet-stream";
  501. }
  502. string boundary = "------------" + DateTime.Now.Ticks.ToString ("x");
  503. Headers ["Content-Type"] = String.Format ("multipart/form-data; boundary={0}", boundary);
  504. Stream reqStream = null;
  505. Stream fStream = null;
  506. byte [] resultBytes = null;
  507. fileName = Path.GetFullPath (fileName);
  508. WebRequest request = null;
  509. try {
  510. fStream = File.OpenRead (fileName);
  511. request = SetupRequest (address, method);
  512. reqStream = request.GetRequestStream ();
  513. byte [] realBoundary = Encoding.ASCII.GetBytes ("--" + boundary + "\r\n");
  514. reqStream.Write (realBoundary, 0, realBoundary.Length);
  515. string partHeaders = String.Format ("Content-Disposition: form-data; " +
  516. "name=\"file\"; filename=\"{0}\"\r\n" +
  517. "Content-Type: {1}\r\n\r\n",
  518. Path.GetFileName (fileName), fileCType);
  519. byte [] partHeadersBytes = Encoding.UTF8.GetBytes (partHeaders);
  520. reqStream.Write (partHeadersBytes, 0, partHeadersBytes.Length);
  521. int nread;
  522. byte [] buffer = new byte [4096];
  523. while ((nread = fStream.Read (buffer, 0, 4096)) != 0)
  524. reqStream.Write (buffer, 0, nread);
  525. reqStream.WriteByte ((byte) '\r');
  526. reqStream.WriteByte ((byte) '\n');
  527. reqStream.Write (realBoundary, 0, realBoundary.Length);
  528. reqStream.Close ();
  529. reqStream = null;
  530. WebResponse response = request.GetResponse ();
  531. Stream st = ProcessResponse (response);
  532. resultBytes = ReadAll (st, (int) response.ContentLength, userToken);
  533. } catch (ThreadInterruptedException){
  534. if (request != null)
  535. request.Abort ();
  536. throw;
  537. } finally {
  538. if (fStream != null)
  539. fStream.Close ();
  540. if (reqStream != null)
  541. reqStream.Close ();
  542. }
  543. return resultBytes;
  544. }
  545. public byte[] UploadValues (string address, NameValueCollection data)
  546. {
  547. #if NET_2_0
  548. if (address == null)
  549. throw new ArgumentNullException ("address");
  550. #endif
  551. return UploadValues (CreateUri (address), data);
  552. }
  553. public byte[] UploadValues (string address, string method, NameValueCollection data)
  554. {
  555. #if NET_2_0
  556. if (address == null)
  557. throw new ArgumentNullException ("address");
  558. #endif
  559. return UploadValues (CreateUri (address), method, data);
  560. }
  561. #if NET_2_0
  562. public
  563. #endif
  564. byte[] UploadValues (Uri address, NameValueCollection data)
  565. {
  566. return UploadValues (address, (string) null, data);
  567. }
  568. #if NET_2_0
  569. public
  570. #endif
  571. byte[] UploadValues (Uri address, string method, NameValueCollection data)
  572. {
  573. #if NET_2_0
  574. if (address == null)
  575. throw new ArgumentNullException ("address");
  576. if (data == null)
  577. throw new ArgumentNullException ("data");
  578. #endif
  579. try {
  580. SetBusy ();
  581. async = false;
  582. return UploadValuesCore (address, method, data, null);
  583. } catch (Exception ex) {
  584. throw new WebException ("An error occurred " +
  585. "performing a WebClient request.", ex);
  586. } finally {
  587. is_busy = false;
  588. }
  589. }
  590. byte[] UploadValuesCore (Uri uri, string method, NameValueCollection data, object userToken)
  591. {
  592. #if ONLY_1_1
  593. if (data == null)
  594. throw new ArgumentNullException ("data");
  595. #endif
  596. string cType = Headers ["Content-Type"];
  597. if (cType != null && String.Compare (cType, urlEncodedCType, true) != 0)
  598. throw new WebException ("Content-Type header cannot be changed from its default " +
  599. "value for this request.");
  600. Headers ["Content-Type"] = urlEncodedCType;
  601. WebRequest request = SetupRequest (uri, method);
  602. try {
  603. Stream rqStream = request.GetRequestStream ();
  604. MemoryStream tmpStream = new MemoryStream ();
  605. foreach (string key in data) {
  606. byte [] bytes = Encoding.ASCII.GetBytes (key);
  607. UrlEncodeAndWrite (tmpStream, bytes);
  608. tmpStream.WriteByte ((byte) '=');
  609. bytes = Encoding.ASCII.GetBytes (data [key]);
  610. UrlEncodeAndWrite (tmpStream, bytes);
  611. tmpStream.WriteByte ((byte) '&');
  612. }
  613. int length = (int) tmpStream.Length;
  614. if (length > 0)
  615. tmpStream.SetLength (--length); // remove trailing '&'
  616. tmpStream.WriteByte ((byte) '\r');
  617. tmpStream.WriteByte ((byte) '\n');
  618. byte [] buf = tmpStream.GetBuffer ();
  619. rqStream.Write (buf, 0, length + 2);
  620. rqStream.Close ();
  621. tmpStream.Close ();
  622. WebResponse response = request.GetResponse ();
  623. Stream st = ProcessResponse (response);
  624. return ReadAll (st, (int) response.ContentLength, userToken);
  625. } catch (ThreadInterruptedException){
  626. request.Abort ();
  627. throw;
  628. }
  629. }
  630. #if NET_2_0
  631. public string DownloadString (string address)
  632. {
  633. return encoding.GetString (DownloadData (address));
  634. }
  635. public string DownloadString (Uri address)
  636. {
  637. return encoding.GetString (DownloadData (address));
  638. }
  639. public string UploadString (string address, string data)
  640. {
  641. if (address == null)
  642. throw new ArgumentNullException ("address");
  643. if (data == null)
  644. throw new ArgumentNullException ("data");
  645. byte [] resp = UploadData (address, encoding.GetBytes (data));
  646. return encoding.GetString (resp);
  647. }
  648. public string UploadString (string address, string method, string data)
  649. {
  650. if (address == null)
  651. throw new ArgumentNullException ("address");
  652. if (data == null)
  653. throw new ArgumentNullException ("data");
  654. byte [] resp = UploadData (address, method, encoding.GetBytes (data));
  655. return encoding.GetString (resp);
  656. }
  657. public string UploadString (Uri address, string data)
  658. {
  659. if (address == null)
  660. throw new ArgumentNullException ("address");
  661. if (data == null)
  662. throw new ArgumentNullException ("data");
  663. byte [] resp = UploadData (address, encoding.GetBytes (data));
  664. return encoding.GetString (resp);
  665. }
  666. public string UploadString (Uri address, string method, string data)
  667. {
  668. if (address == null)
  669. throw new ArgumentNullException ("address");
  670. if (data == null)
  671. throw new ArgumentNullException ("data");
  672. byte [] resp = UploadData (address, method, encoding.GetBytes (data));
  673. return encoding.GetString (resp);
  674. }
  675. public event DownloadDataCompletedEventHandler DownloadDataCompleted;
  676. public event AsyncCompletedEventHandler DownloadFileCompleted;
  677. public event DownloadProgressChangedEventHandler DownloadProgressChanged;
  678. public event DownloadStringCompletedEventHandler DownloadStringCompleted;
  679. public event OpenReadCompletedEventHandler OpenReadCompleted;
  680. public event OpenWriteCompletedEventHandler OpenWriteCompleted;
  681. public event UploadDataCompletedEventHandler UploadDataCompleted;
  682. public event UploadFileCompletedEventHandler UploadFileCompleted;
  683. public event UploadProgressChangedEventHandler UploadProgressChanged;
  684. public event UploadStringCompletedEventHandler UploadStringCompleted;
  685. public event UploadValuesCompletedEventHandler UploadValuesCompleted;
  686. #endif
  687. Uri CreateUri (string address)
  688. {
  689. #if ONLY_1_1
  690. try {
  691. return MakeUri (address);
  692. } catch (Exception ex) {
  693. throw new WebException ("An error occurred " +
  694. "performing a WebClient request.", ex);
  695. }
  696. #else
  697. return MakeUri (address);
  698. #endif
  699. }
  700. Uri MakeUri (string path)
  701. {
  702. string query = null;
  703. if (queryString != null && queryString.Count != 0) {
  704. // This is not the same as UploadValues, because these 'keys' are not
  705. // urlencoded here.
  706. StringBuilder sb = new StringBuilder ();
  707. sb.Append ('?');
  708. foreach (string key in queryString)
  709. sb.AppendFormat ("{0}={1}&", key, UrlEncode (queryString [key]));
  710. if (sb.Length != 0) {
  711. sb.Length--; // remove trailing '&'
  712. query = sb.ToString ();
  713. }
  714. }
  715. if (baseAddress == null && query == null) {
  716. try {
  717. return new Uri (path);
  718. #if NET_2_0
  719. } catch (ArgumentNullException) {
  720. path = Path.GetFullPath (path);
  721. return new Uri ("file://" + path);
  722. #endif
  723. } catch (UriFormatException) {
  724. path = Path.GetFullPath (path);
  725. return new Uri ("file://" + path);
  726. }
  727. }
  728. if (baseAddress == null)
  729. return new Uri (path + query, (query != null));
  730. if (query == null)
  731. return new Uri (baseAddress, path);
  732. return new Uri (baseAddress, path + query, (query != null));
  733. }
  734. WebRequest SetupRequest (Uri uri)
  735. {
  736. WebRequest request = WebRequest.Create (uri);
  737. #if NET_2_0
  738. if (Proxy != null)
  739. request.Proxy = Proxy;
  740. #endif
  741. request.Credentials = credentials;
  742. // Special headers. These are properties of HttpWebRequest.
  743. // What do we do with other requests differnt from HttpWebRequest?
  744. if (headers != null && headers.Count != 0 && (request is HttpWebRequest)) {
  745. HttpWebRequest req = (HttpWebRequest) request;
  746. string expect = headers ["Expect"];
  747. string contentType = headers ["Content-Type"];
  748. string accept = headers ["Accept"];
  749. string connection = headers ["Connection"];
  750. string userAgent = headers ["User-Agent"];
  751. string referer = headers ["Referer"];
  752. headers.RemoveInternal ("Expect");
  753. headers.RemoveInternal ("Content-Type");
  754. headers.RemoveInternal ("Accept");
  755. headers.RemoveInternal ("Connection");
  756. headers.RemoveInternal ("Referer");
  757. headers.RemoveInternal ("User-Agent");
  758. request.Headers = headers;
  759. if (expect != null && expect.Length > 0)
  760. req.Expect = expect;
  761. if (accept != null && accept.Length > 0)
  762. req.Accept = accept;
  763. if (contentType != null && contentType.Length > 0)
  764. req.ContentType = contentType;
  765. if (connection != null && connection.Length > 0)
  766. req.Connection = connection;
  767. if (userAgent != null && userAgent.Length > 0)
  768. req.UserAgent = userAgent;
  769. if (referer != null && referer.Length > 0)
  770. req.Referer = referer;
  771. }
  772. responseHeaders = null;
  773. return request;
  774. }
  775. WebRequest SetupRequest (Uri uri, string method)
  776. {
  777. WebRequest request = SetupRequest (uri);
  778. request.Method = DetermineMethod (uri, method);
  779. return request;
  780. }
  781. Stream ProcessResponse (WebResponse response)
  782. {
  783. responseHeaders = response.Headers;
  784. return response.GetResponseStream ();
  785. }
  786. byte [] ReadAll (Stream stream, int length, object userToken)
  787. {
  788. MemoryStream ms = null;
  789. bool nolength = (length == -1);
  790. int size = ((nolength) ? 8192 : length);
  791. if (nolength)
  792. ms = new MemoryStream ();
  793. long total = 0;
  794. int nread = 0;
  795. int offset = 0;
  796. byte [] buffer = new byte [size];
  797. while ((nread = stream.Read (buffer, offset, size)) != 0) {
  798. if (nolength) {
  799. ms.Write (buffer, 0, nread);
  800. } else {
  801. offset += nread;
  802. size -= nread;
  803. }
  804. #if NET_2_0
  805. if (async && DownloadProgressChanged != null){
  806. total += nread;
  807. DownloadProgressChanged (this, new DownloadProgressChangedEventArgs (nread, length, userToken));
  808. }
  809. #endif
  810. }
  811. if (nolength)
  812. return ms.ToArray ();
  813. return buffer;
  814. }
  815. string UrlEncode (string str)
  816. {
  817. StringBuilder result = new StringBuilder ();
  818. int len = str.Length;
  819. for (int i = 0; i < len; i++) {
  820. char c = str [i];
  821. if (c == ' ')
  822. result.Append ('+');
  823. else if ((c < '0' && c != '-' && c != '.') ||
  824. (c < 'A' && c > '9') ||
  825. (c > 'Z' && c < 'a' && c != '_') ||
  826. (c > 'z')) {
  827. result.Append ('%');
  828. int idx = ((int) c) >> 4;
  829. result.Append ((char) hexBytes [idx]);
  830. idx = ((int) c) & 0x0F;
  831. result.Append ((char) hexBytes [idx]);
  832. } else {
  833. result.Append (c);
  834. }
  835. }
  836. return result.ToString ();
  837. }
  838. static void UrlEncodeAndWrite (Stream stream, byte [] bytes)
  839. {
  840. if (bytes == null)
  841. return;
  842. int len = bytes.Length;
  843. if (len == 0)
  844. return;
  845. for (int i = 0; i < len; i++) {
  846. char c = (char) bytes [i];
  847. if (c == ' ')
  848. stream.WriteByte ((byte) '+');
  849. else if ((c < '0' && c != '-' && c != '.') ||
  850. (c < 'A' && c > '9') ||
  851. (c > 'Z' && c < 'a' && c != '_') ||
  852. (c > 'z')) {
  853. stream.WriteByte ((byte) '%');
  854. int idx = ((int) c) >> 4;
  855. stream.WriteByte (hexBytes [idx]);
  856. idx = ((int) c) & 0x0F;
  857. stream.WriteByte (hexBytes [idx]);
  858. } else {
  859. stream.WriteByte ((byte) c);
  860. }
  861. }
  862. }
  863. #if NET_2_0
  864. public void CancelAsync ()
  865. {
  866. lock (this){
  867. if (async_thread == null)
  868. return;
  869. //
  870. // We first flag things as done, in case the Interrupt hangs
  871. // or the thread decides to hang in some other way inside the
  872. // event handlers, or if we are stuck somewhere else. This
  873. // ensures that the WebClient object is reusable immediately
  874. //
  875. Thread t = async_thread;
  876. CompleteAsync ();
  877. t.Interrupt ();
  878. }
  879. }
  880. void CompleteAsync ()
  881. {
  882. lock (this){
  883. is_busy = false;
  884. async_thread = null;
  885. }
  886. }
  887. // DownloadDataAsync
  888. public void DownloadDataAsync (Uri address)
  889. {
  890. DownloadDataAsync (address, null);
  891. }
  892. public void DownloadDataAsync (Uri address, object userToken)
  893. {
  894. if (address == null)
  895. throw new ArgumentNullException ("address");
  896. lock (this) {
  897. SetBusy ();
  898. async = true;
  899. async_thread = new Thread (delegate (object state) {
  900. object [] args = (object []) state;
  901. try {
  902. byte [] data = DownloadDataCore ((Uri) args [0], args [1]);
  903. OnDownloadDataCompleted (
  904. new DownloadDataCompletedEventArgs (data, null, false, args [1]));
  905. CompleteAsync ();
  906. } catch (ThreadInterruptedException){
  907. OnDownloadDataCompleted (
  908. new DownloadDataCompletedEventArgs (null, null, true, args [1]));
  909. throw;
  910. }
  911. });
  912. object [] cb_args = new object [] {address, userToken};
  913. async_thread.Start (cb_args);
  914. }
  915. }
  916. // DownloadFileAsync
  917. public void DownloadFileAsync (Uri address, string fileName)
  918. {
  919. DownloadFileAsync (address, fileName, null);
  920. }
  921. public void DownloadFileAsync (Uri address, string fileName, object userToken)
  922. {
  923. if (address == null)
  924. throw new ArgumentNullException ("address");
  925. if (fileName == null)
  926. throw new ArgumentNullException ("fileName");
  927. lock (this) {
  928. SetBusy ();
  929. async = true;
  930. async_thread = new Thread (delegate (object state) {
  931. object [] args = (object []) state;
  932. try {
  933. DownloadFileCore ((Uri) args [0], (string) args [1], args [2]);
  934. OnDownloadFileCompleted (
  935. new AsyncCompletedEventArgs (null, false, args [2]));
  936. CompleteAsync ();
  937. } catch (ThreadInterruptedException){
  938. OnDownloadFileCompleted (
  939. new AsyncCompletedEventArgs (null, true, args [2]));
  940. }
  941. });
  942. object [] cb_args = new object [] {address, fileName, userToken};
  943. async_thread.Start (cb_args);
  944. }
  945. }
  946. // DownloadStringAsync
  947. public void DownloadStringAsync (Uri address)
  948. {
  949. DownloadStringAsync (address, null);
  950. }
  951. public void DownloadStringAsync (Uri address, object userToken)
  952. {
  953. if (address == null)
  954. throw new ArgumentNullException ("address");
  955. lock (this) {
  956. SetBusy ();
  957. async = true;
  958. async_thread = new Thread (delegate (object state) {
  959. object [] args = (object []) state;
  960. try {
  961. string data = encoding.GetString (DownloadDataCore ((Uri) args [0], args [1]));
  962. OnDownloadStringCompleted (
  963. new DownloadStringCompletedEventArgs (data, null, false, args [1]));
  964. CompleteAsync ();
  965. } catch (ThreadInterruptedException){
  966. OnDownloadStringCompleted (
  967. new DownloadStringCompletedEventArgs (null, null, true, args [1]));
  968. }
  969. });
  970. object [] cb_args = new object [] {address, userToken};
  971. async_thread.Start (cb_args);
  972. }
  973. }
  974. // OpenReadAsync
  975. public void OpenReadAsync (Uri address)
  976. {
  977. OpenReadAsync (address, null);
  978. }
  979. public void OpenReadAsync (Uri address, object userToken)
  980. {
  981. if (address == null)
  982. throw new ArgumentNullException ("address");
  983. lock (this) {
  984. SetBusy ();
  985. async = true;
  986. async_thread = new Thread (delegate (object state) {
  987. object [] args = (object []) state;
  988. WebRequest request = null;
  989. try {
  990. request = SetupRequest ((Uri) args [0]);
  991. WebResponse response = request.GetResponse ();
  992. Stream stream = ProcessResponse (response);
  993. OnOpenReadCompleted (
  994. new OpenReadCompletedEventArgs (stream, null, false, args [1]));
  995. CompleteAsync ();
  996. } catch (ThreadInterruptedException){
  997. if (request != null)
  998. request.Abort ();
  999. OnOpenReadCompleted (new OpenReadCompletedEventArgs (null, null, true, args [1]));
  1000. }
  1001. } );
  1002. object [] cb_args = new object [] {address, userToken};
  1003. async_thread.Start (cb_args);
  1004. }
  1005. }
  1006. // OpenWriteAsync
  1007. public void OpenWriteAsync (Uri address)
  1008. {
  1009. OpenWriteAsync (address, null);
  1010. }
  1011. public void OpenWriteAsync (Uri address, string method)
  1012. {
  1013. OpenWriteAsync (address, method, null);
  1014. }
  1015. public void OpenWriteAsync (Uri address, string method, object userToken)
  1016. {
  1017. if (address == null)
  1018. throw new ArgumentNullException ("address");
  1019. if (method == null)
  1020. throw new ArgumentNullException ("method");
  1021. lock (this) {
  1022. SetBusy ();
  1023. async = true;
  1024. async_thread = new Thread (delegate (object state) {
  1025. object [] args = (object []) state;
  1026. WebRequest request = null;
  1027. try {
  1028. request = SetupRequest ((Uri) args [0], (string) args [1]);
  1029. Stream stream = request.GetRequestStream ();
  1030. OnOpenWriteCompleted (
  1031. new OpenWriteCompletedEventArgs (stream, null, false, args [2]));
  1032. CompleteAsync ();
  1033. } catch (ThreadInterruptedException){
  1034. if (request != null)
  1035. request.Abort ();
  1036. OnOpenWriteCompleted (
  1037. new OpenWriteCompletedEventArgs (null, null, true, args [2]));
  1038. }
  1039. });
  1040. object [] cb_args = new object [] {address, method, userToken};
  1041. async_thread.Start (cb_args);
  1042. }
  1043. }
  1044. // UploadDataAsync
  1045. public void UploadDataAsync (Uri address, byte [] data)
  1046. {
  1047. UploadDataAsync (address, null, data);
  1048. }
  1049. public void UploadDataAsync (Uri address, string method, byte [] data)
  1050. {
  1051. UploadDataAsync (address, method, data, null);
  1052. }
  1053. public void UploadDataAsync (Uri address, string method, byte [] data, object userToken)
  1054. {
  1055. if (address == null)
  1056. throw new ArgumentNullException ("address");
  1057. if (data == null)
  1058. throw new ArgumentNullException ("data");
  1059. lock (this) {
  1060. SetBusy ();
  1061. async = true;
  1062. async_thread = new Thread (delegate (object state) {
  1063. object [] args = (object []) state;
  1064. byte [] data2;
  1065. try {
  1066. data2 = UploadDataCore ((Uri) args [0], (string) args [1], (byte []) args [2], args [3]);
  1067. OnUploadDataCompleted (
  1068. new UploadDataCompletedEventArgs (data2, null, false, args [3]));
  1069. CompleteAsync ();
  1070. } catch (ThreadInterruptedException){
  1071. OnUploadDataCompleted (
  1072. new UploadDataCompletedEventArgs (null, null, true, args [3]));
  1073. }});
  1074. object [] cb_args = new object [] {address, method, data, userToken};
  1075. async_thread.Start (cb_args);
  1076. }
  1077. }
  1078. // UploadFileAsync
  1079. public void UploadFileAsync (Uri address, string fileName)
  1080. {
  1081. UploadFileAsync (address, null, fileName);
  1082. }
  1083. public void UploadFileAsync (Uri address, string method, string fileName)
  1084. {
  1085. UploadFileAsync (address, method, fileName, null);
  1086. }
  1087. public void UploadFileAsync (Uri address, string method, string fileName, object userToken)
  1088. {
  1089. if (address == null)
  1090. throw new ArgumentNullException ("address");
  1091. if (fileName == null)
  1092. throw new ArgumentNullException ("fileName");
  1093. lock (this) {
  1094. SetBusy ();
  1095. async = true;
  1096. async_thread = new Thread (delegate (object state) {
  1097. object [] args = (object []) state;
  1098. byte [] data;
  1099. try {
  1100. data = UploadFileCore ((Uri) args [0], (string) args [1], (string) args [2], args [3]);
  1101. OnUploadFileCompleted (
  1102. new UploadFileCompletedEventArgs (data, null, false, args [3]));
  1103. } catch (ThreadInterruptedException){
  1104. OnUploadFileCompleted (
  1105. new UploadFileCompletedEventArgs (null, null, true, args [3]));
  1106. }
  1107. });
  1108. object [] cb_args = new object [] {address, method, fileName, userToken};
  1109. async_thread.Start (cb_args);
  1110. }
  1111. }
  1112. // UploadStringAsync
  1113. public void UploadStringAsync (Uri address, string data)
  1114. {
  1115. UploadStringAsync (address, null, data);
  1116. }
  1117. public void UploadStringAsync (Uri address, string method, string data)
  1118. {
  1119. UploadStringAsync (address, method, data, null);
  1120. }
  1121. public void UploadStringAsync (Uri address, string method, string data, object userToken)
  1122. {
  1123. if (address == null)
  1124. throw new ArgumentNullException ("address");
  1125. if (data == null)
  1126. throw new ArgumentNullException ("data");
  1127. lock (this) {
  1128. SetBusy ();
  1129. async = true;
  1130. async_thread = new Thread (delegate (object state) {
  1131. object [] args = (object []) state;
  1132. try {
  1133. string data2 = UploadString ((Uri) args [0], (string) args [1], (string) args [2]);
  1134. OnUploadStringCompleted (
  1135. new UploadStringCompletedEventArgs (data2, null, false, args [3]));
  1136. CompleteAsync ();
  1137. } catch (ThreadInterruptedException){
  1138. OnUploadStringCompleted (
  1139. new UploadStringCompletedEventArgs (null, null, true, args [3]));
  1140. }
  1141. });
  1142. object [] cb_args = new object [] {address, method, data, userToken};
  1143. async_thread.Start (cb_args);
  1144. }
  1145. }
  1146. // UploadValuesAsync
  1147. public void UploadValuesAsync (Uri address, NameValueCollection values)
  1148. {
  1149. UploadValuesAsync (address, null, values);
  1150. }
  1151. public void UploadValuesAsync (Uri address, string method, NameValueCollection values)
  1152. {
  1153. UploadValuesAsync (address, method, values, null);
  1154. }
  1155. public void UploadValuesAsync (Uri address, string method, NameValueCollection values, object userToken)
  1156. {
  1157. if (address == null)
  1158. throw new ArgumentNullException ("address");
  1159. if (values == null)
  1160. throw new ArgumentNullException ("values");
  1161. lock (this) {
  1162. CheckBusy ();
  1163. async = true;
  1164. async_thread = new Thread (delegate (object state) {
  1165. object [] args = (object []) state;
  1166. try {
  1167. byte [] data = UploadValuesCore ((Uri) args [0], (string) args [1], (NameValueCollection) args [2], args [3]);
  1168. OnUploadValuesCompleted (
  1169. new UploadValuesCompletedEventArgs (data, null, false, args [3]));
  1170. CompleteAsync ();
  1171. } catch (ThreadInterruptedException){
  1172. OnUploadValuesCompleted (
  1173. new UploadValuesCompletedEventArgs (null, null, true, args [3]));
  1174. }
  1175. });
  1176. object [] cb_args = new object [] {address, method, values, userToken};
  1177. async_thread.Start (cb_args);
  1178. }
  1179. }
  1180. protected virtual void OnDownloadDataCompleted (DownloadDataCompletedEventArgs args)
  1181. {
  1182. if (DownloadDataCompleted != null)
  1183. DownloadDataCompleted (this, args);
  1184. }
  1185. protected virtual void OnDownloadFileCompleted (AsyncCompletedEventArgs args)
  1186. {
  1187. if (DownloadFileCompleted != null)
  1188. DownloadFileCompleted (this, args);
  1189. }
  1190. protected virtual void OnDownloadProgressChanged (DownloadProgressChangedEventArgs e)
  1191. {
  1192. if (DownloadProgressChanged != null)
  1193. DownloadProgressChanged (this, e);
  1194. }
  1195. protected virtual void OnDownloadStringCompleted (DownloadStringCompletedEventArgs args)
  1196. {
  1197. if (DownloadStringCompleted != null)
  1198. DownloadStringCompleted (this, args);
  1199. }
  1200. protected virtual void OnOpenReadCompleted (OpenReadCompletedEventArgs args)
  1201. {
  1202. if (OpenReadCompleted != null)
  1203. OpenReadCompleted (this, args);
  1204. }
  1205. protected virtual void OnOpenWriteCompleted (OpenWriteCompletedEventArgs args)
  1206. {
  1207. if (OpenWriteCompleted != null)
  1208. OpenWriteCompleted (this, args);
  1209. }
  1210. protected virtual void OnUploadDataCompleted (UploadDataCompletedEventArgs args)
  1211. {
  1212. if (UploadDataCompleted != null)
  1213. UploadDataCompleted (this, args);
  1214. }
  1215. protected virtual void OnUploadFileCompleted (UploadFileCompletedEventArgs args)
  1216. {
  1217. if (UploadFileCompleted != null)
  1218. UploadFileCompleted (this, args);
  1219. }
  1220. protected virtual void OnUploadProgressChanged (UploadProgressChangedEventArgs e)
  1221. {
  1222. if (UploadProgressChanged != null)
  1223. UploadProgressChanged (this, e);
  1224. }
  1225. protected virtual void OnUploadStringCompleted (UploadStringCompletedEventArgs args)
  1226. {
  1227. if (UploadStringCompleted != null)
  1228. UploadStringCompleted (this, args);
  1229. }
  1230. protected virtual void OnUploadValuesCompleted (UploadValuesCompletedEventArgs args)
  1231. {
  1232. if (UploadValuesCompleted != null)
  1233. UploadValuesCompleted (this, args);
  1234. }
  1235. [MonoNotSupported("")]
  1236. protected virtual WebRequest GetWebRequest (Uri address)
  1237. {
  1238. throw new NotImplementedException ();
  1239. }
  1240. protected virtual WebResponse GetWebResponse (WebRequest request)
  1241. {
  1242. return request.GetResponse ();
  1243. }
  1244. protected virtual WebResponse GetWebResponse (WebRequest request, IAsyncResult result)
  1245. {
  1246. return request.EndGetResponse (result);
  1247. }
  1248. #endif
  1249. }
  1250. }