WebRequest.cs 11 KB

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