WebRequest.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511
  1. //
  2. // System.Net.WebRequest
  3. //
  4. // Authors:
  5. // Lawrence Pit ([email protected])
  6. // Marek Safar ([email protected])
  7. //
  8. // Copyright 2011 Xamarin Inc.
  9. //
  10. // Permission is hereby granted, free of charge, to any person obtaining
  11. // a copy of this software and associated documentation files (the
  12. // "Software"), to deal in the Software without restriction, including
  13. // without limitation the rights to use, copy, modify, merge, publish,
  14. // distribute, sublicense, and/or sell copies of the Software, and to
  15. // permit persons to whom the Software is furnished to do so, subject to
  16. // the following conditions:
  17. //
  18. // The above copyright notice and this permission notice shall be
  19. // included in all copies or substantial portions of the Software.
  20. //
  21. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  22. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  23. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  24. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  25. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  26. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  27. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  28. //
  29. using System;
  30. using System.Collections;
  31. using System.Collections.Specialized;
  32. using System.Configuration;
  33. using System.IO;
  34. using System.Reflection;
  35. using System.Runtime.Serialization;
  36. using System.Globalization;
  37. using System.Net.Configuration;
  38. using System.Net.Security;
  39. using System.Net.Cache;
  40. using System.Security.Principal;
  41. #if NET_4_5
  42. using System.Threading.Tasks;
  43. #endif
  44. #if NET_2_1
  45. using ConfigurationException = System.ArgumentException;
  46. namespace System.Net.Configuration {
  47. class Dummy {}
  48. }
  49. #endif
  50. namespace System.Net
  51. {
  52. #if MOONLIGHT
  53. internal abstract class WebRequest : ISerializable {
  54. #else
  55. [Serializable]
  56. public abstract class WebRequest : MarshalByRefObject, ISerializable {
  57. #endif
  58. static HybridDictionary prefixes = new HybridDictionary ();
  59. static bool isDefaultWebProxySet;
  60. static IWebProxy defaultWebProxy;
  61. static RequestCachePolicy defaultCachePolicy;
  62. // Constructors
  63. static WebRequest ()
  64. {
  65. #if NET_2_1
  66. IWebRequestCreate http = new HttpRequestCreator ();
  67. RegisterPrefix ("http", http);
  68. RegisterPrefix ("https", http);
  69. #if MOBILE
  70. RegisterPrefix ("file", new FileWebRequestCreator ());
  71. RegisterPrefix ("ftp", new FtpRequestCreator ());
  72. #endif
  73. #else
  74. defaultCachePolicy = new HttpRequestCachePolicy (HttpRequestCacheLevel.NoCacheNoStore);
  75. #if CONFIGURATION_DEP
  76. object cfg = ConfigurationManager.GetSection ("system.net/webRequestModules");
  77. WebRequestModulesSection s = cfg as WebRequestModulesSection;
  78. if (s != null) {
  79. foreach (WebRequestModuleElement el in
  80. s.WebRequestModules)
  81. AddPrefix (el.Prefix, el.Type);
  82. return;
  83. }
  84. #endif
  85. ConfigurationSettings.GetConfig ("system.net/webRequestModules");
  86. #endif
  87. }
  88. protected WebRequest ()
  89. {
  90. }
  91. protected WebRequest (SerializationInfo serializationInfo, StreamingContext streamingContext)
  92. {
  93. }
  94. static Exception GetMustImplement ()
  95. {
  96. return new NotImplementedException ("This method must be implemented in derived classes");
  97. }
  98. // Properties
  99. private AuthenticationLevel authentication_level = AuthenticationLevel.MutualAuthRequested;
  100. public AuthenticationLevel AuthenticationLevel
  101. {
  102. get {
  103. return(authentication_level);
  104. }
  105. set {
  106. authentication_level = value;
  107. }
  108. }
  109. [MonoTODO ("Implement the caching system. Currently always returns a policy with the NoCacheNoStore level")]
  110. public virtual RequestCachePolicy CachePolicy
  111. {
  112. get { return DefaultCachePolicy; }
  113. set {
  114. }
  115. }
  116. public virtual string ConnectionGroupName {
  117. get { throw GetMustImplement (); }
  118. set { throw GetMustImplement (); }
  119. }
  120. public virtual long ContentLength {
  121. get { throw GetMustImplement (); }
  122. set { throw GetMustImplement (); }
  123. }
  124. public virtual string ContentType {
  125. get { throw GetMustImplement (); }
  126. set { throw GetMustImplement (); }
  127. }
  128. public virtual ICredentials Credentials {
  129. get { throw GetMustImplement (); }
  130. set { throw GetMustImplement (); }
  131. }
  132. public static RequestCachePolicy DefaultCachePolicy
  133. {
  134. get { return defaultCachePolicy; }
  135. set {
  136. throw GetMustImplement ();
  137. }
  138. }
  139. public virtual WebHeaderCollection Headers {
  140. get { throw GetMustImplement (); }
  141. set { throw GetMustImplement (); }
  142. }
  143. #if !MOONLIGHT
  144. public TokenImpersonationLevel ImpersonationLevel {
  145. get { throw GetMustImplement (); }
  146. set { throw GetMustImplement (); }
  147. }
  148. #endif
  149. public virtual string Method {
  150. get { throw GetMustImplement (); }
  151. set { throw GetMustImplement (); }
  152. }
  153. public virtual bool PreAuthenticate {
  154. get { throw GetMustImplement (); }
  155. set { throw GetMustImplement (); }
  156. }
  157. public virtual IWebProxy Proxy {
  158. get { throw GetMustImplement (); }
  159. set { throw GetMustImplement (); }
  160. }
  161. public virtual Uri RequestUri {
  162. get { throw GetMustImplement (); }
  163. }
  164. public virtual int Timeout {
  165. get { throw GetMustImplement (); }
  166. set { throw GetMustImplement (); }
  167. }
  168. public virtual bool UseDefaultCredentials
  169. {
  170. get {
  171. throw GetMustImplement ();
  172. }
  173. set {
  174. throw GetMustImplement ();
  175. }
  176. }
  177. // volatile static IWebProxy proxy;
  178. static readonly object lockobj = new object ();
  179. public static IWebProxy DefaultWebProxy {
  180. get {
  181. if (!isDefaultWebProxySet) {
  182. lock (lockobj) {
  183. if (defaultWebProxy == null)
  184. defaultWebProxy = GetDefaultWebProxy ();
  185. }
  186. }
  187. return defaultWebProxy;
  188. }
  189. set {
  190. /* MS documentation states that a null value would cause an ArgumentNullException
  191. * but that's not the way it behaves:
  192. * https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=304724
  193. */
  194. defaultWebProxy = value;
  195. isDefaultWebProxySet = true;
  196. }
  197. }
  198. [MonoTODO("Needs to respect Module, Proxy.AutoDetect, and Proxy.ScriptLocation config settings")]
  199. static IWebProxy GetDefaultWebProxy ()
  200. {
  201. #if CONFIGURATION_DEP
  202. DefaultProxySection sec = ConfigurationManager.GetSection ("system.net/defaultProxy") as DefaultProxySection;
  203. WebProxy p;
  204. if (sec == null)
  205. return GetSystemWebProxy ();
  206. ProxyElement pe = sec.Proxy;
  207. if ((pe.UseSystemDefault != ProxyElement.UseSystemDefaultValues.False) && (pe.ProxyAddress == null)) {
  208. IWebProxy proxy = GetSystemWebProxy ();
  209. if (!(proxy is WebProxy))
  210. return proxy;
  211. p = (WebProxy) proxy;
  212. } else
  213. p = new WebProxy ();
  214. if (pe.ProxyAddress != null)
  215. p.Address = pe.ProxyAddress;
  216. if (pe.BypassOnLocal != ProxyElement.BypassOnLocalValues.Unspecified)
  217. p.BypassProxyOnLocal = (pe.BypassOnLocal == ProxyElement.BypassOnLocalValues.True);
  218. foreach(BypassElement elem in sec.BypassList)
  219. p.BypassArrayList.Add(elem.Address);
  220. return p;
  221. #else
  222. return GetSystemWebProxy ();
  223. #endif
  224. }
  225. // Methods
  226. public virtual void Abort()
  227. {
  228. throw GetMustImplement ();
  229. }
  230. public virtual IAsyncResult BeginGetRequestStream (AsyncCallback callback, object state)
  231. {
  232. throw GetMustImplement ();
  233. }
  234. public virtual IAsyncResult BeginGetResponse (AsyncCallback callback, object state)
  235. {
  236. throw GetMustImplement ();
  237. }
  238. public static WebRequest Create (string requestUriString)
  239. {
  240. if (requestUriString == null)
  241. throw new ArgumentNullException ("requestUriString");
  242. return Create (new Uri (requestUriString));
  243. }
  244. public static WebRequest Create (Uri requestUri)
  245. {
  246. if (requestUri == null)
  247. throw new ArgumentNullException ("requestUri");
  248. return GetCreator (requestUri.AbsoluteUri).Create (requestUri);
  249. }
  250. public static WebRequest CreateDefault (Uri requestUri)
  251. {
  252. if (requestUri == null)
  253. throw new ArgumentNullException ("requestUri");
  254. return GetCreator (requestUri.Scheme).Create (requestUri);
  255. }
  256. public virtual Stream EndGetRequestStream (IAsyncResult asyncResult)
  257. {
  258. throw GetMustImplement ();
  259. }
  260. public virtual WebResponse EndGetResponse (IAsyncResult asyncResult)
  261. {
  262. throw GetMustImplement ();
  263. }
  264. public virtual Stream GetRequestStream()
  265. {
  266. throw GetMustImplement ();
  267. }
  268. public virtual WebResponse GetResponse()
  269. {
  270. throw GetMustImplement ();
  271. }
  272. [MonoTODO("Look in other places for proxy config info")]
  273. public static IWebProxy GetSystemWebProxy ()
  274. {
  275. #if !NET_2_1
  276. if (IsWindows ()) {
  277. int iProxyEnable = (int)Microsoft.Win32.Registry.GetValue ("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", "ProxyEnable", 0);
  278. if (iProxyEnable > 0) {
  279. string strHttpProxy = "";
  280. bool bBypassOnLocal = false;
  281. ArrayList al = new ArrayList ();
  282. string strProxyServer = (string)Microsoft.Win32.Registry.GetValue ("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", "ProxyServer", null);
  283. string strProxyOverrride = (string)Microsoft.Win32.Registry.GetValue ("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", "ProxyOverride", null);
  284. if (strProxyServer.Contains ("=")) {
  285. foreach (string strEntry in strProxyServer.Split (new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
  286. if (strEntry.StartsWith ("http=")) {
  287. strHttpProxy = strEntry.Substring (5);
  288. break;
  289. }
  290. } else strHttpProxy = strProxyServer;
  291. if (strProxyOverrride != null) {
  292. string[] bypassList = strProxyOverrride.Split (new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
  293. foreach (string str in bypassList) {
  294. if (str != "<local>")
  295. al.Add (str);
  296. else
  297. bBypassOnLocal = true;
  298. }
  299. }
  300. return new WebProxy (strHttpProxy, bBypassOnLocal, al.ToArray (typeof(string)) as string[]);
  301. }
  302. } else {
  303. #endif
  304. if (Platform.IsMacOS)
  305. return CFNetwork.GetDefaultProxy ();
  306. string address = Environment.GetEnvironmentVariable ("http_proxy");
  307. if (address == null)
  308. address = Environment.GetEnvironmentVariable ("HTTP_PROXY");
  309. if (address != null) {
  310. try {
  311. if (!address.StartsWith ("http://"))
  312. address = "http://" + address;
  313. Uri uri = new Uri (address);
  314. IPAddress ip;
  315. if (IPAddress.TryParse (uri.Host, out ip)) {
  316. if (IPAddress.Any.Equals (ip)) {
  317. UriBuilder builder = new UriBuilder (uri);
  318. builder.Host = "127.0.0.1";
  319. uri = builder.Uri;
  320. } else if (IPAddress.IPv6Any.Equals (ip)) {
  321. UriBuilder builder = new UriBuilder (uri);
  322. builder.Host = "[::1]";
  323. uri = builder.Uri;
  324. }
  325. }
  326. bool bBypassOnLocal = false;
  327. ArrayList al = new ArrayList ();
  328. string bypass = Environment.GetEnvironmentVariable ("no_proxy");
  329. if (bypass == null)
  330. bypass = Environment.GetEnvironmentVariable ("NO_PROXY");
  331. if (bypass != null) {
  332. string[] bypassList = bypass.Split (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
  333. foreach (string str in bypassList) {
  334. if (str != "*.local")
  335. al.Add (str);
  336. else
  337. bBypassOnLocal = true;
  338. }
  339. }
  340. return new WebProxy (uri, bBypassOnLocal, al.ToArray (typeof(string)) as string[]);
  341. } catch (UriFormatException) {
  342. }
  343. }
  344. #if !NET_2_1
  345. }
  346. #endif
  347. return new WebProxy ();
  348. }
  349. void ISerializable.GetObjectData (SerializationInfo serializationInfo, StreamingContext streamingContext)
  350. {
  351. throw new NotSupportedException ();
  352. }
  353. protected virtual void GetObjectData (SerializationInfo serializationInfo, StreamingContext streamingContext)
  354. {
  355. throw GetMustImplement ();
  356. }
  357. public static bool RegisterPrefix (string prefix, IWebRequestCreate creator)
  358. {
  359. if (prefix == null)
  360. throw new ArgumentNullException ("prefix");
  361. if (creator == null)
  362. throw new ArgumentNullException ("creator");
  363. lock (prefixes.SyncRoot) {
  364. string lowerCasePrefix = prefix.ToLower (CultureInfo.InvariantCulture);
  365. if (prefixes.Contains (lowerCasePrefix))
  366. return false;
  367. prefixes.Add (lowerCasePrefix, creator);
  368. }
  369. return true;
  370. }
  371. private static IWebRequestCreate GetCreator (string prefix)
  372. {
  373. int longestPrefix = -1;
  374. IWebRequestCreate creator = null;
  375. prefix = prefix.ToLower (CultureInfo.InvariantCulture);
  376. IDictionaryEnumerator e = prefixes.GetEnumerator ();
  377. while (e.MoveNext ()) {
  378. string key = e.Key as string;
  379. if (key.Length <= longestPrefix)
  380. continue;
  381. if (!prefix.StartsWith (key))
  382. continue;
  383. longestPrefix = key.Length;
  384. creator = (IWebRequestCreate) e.Value;
  385. }
  386. if (creator == null)
  387. throw new NotSupportedException (prefix);
  388. return creator;
  389. }
  390. internal static bool IsWindows ()
  391. {
  392. return (int) Environment.OSVersion.Platform < 4;
  393. }
  394. internal static void ClearPrefixes ()
  395. {
  396. prefixes.Clear ();
  397. }
  398. internal static void RemovePrefix (string prefix)
  399. {
  400. prefixes.Remove (prefix);
  401. }
  402. internal static void AddPrefix (string prefix, string typeName)
  403. {
  404. Type type = Type.GetType (typeName);
  405. if (type == null)
  406. throw new ConfigurationException (String.Format ("Type {0} not found", typeName));
  407. AddPrefix (prefix, type);
  408. }
  409. internal static void AddPrefix (string prefix, Type type)
  410. {
  411. object o = Activator.CreateInstance (type, true);
  412. prefixes [prefix] = o;
  413. }
  414. #if NET_4_5
  415. public virtual Task<Stream> GetRequestStreamAsync ()
  416. {
  417. return Task<Stream>.Factory.FromAsync (BeginGetRequestStream, EndGetRequestStream, null);
  418. }
  419. public virtual Task<WebResponse> GetResponseAsync ()
  420. {
  421. return Task<WebResponse>.Factory.FromAsync (BeginGetResponse, EndGetResponse, null);
  422. }
  423. #endif
  424. }
  425. }