HttpWebResponse.cs 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. //
  2. // System.Net.HttpWebResponse
  3. //
  4. // Authors:
  5. // Lawrence Pit ([email protected])
  6. // Gonzalo Paniagua Javier ([email protected])
  7. // Daniel Nauck (dna(at)mono-project(dot)de)
  8. //
  9. // (c) 2002 Lawrence Pit
  10. // (c) 2003 Ximian, Inc. (http://www.ximian.com)
  11. // (c) 2008 Daniel Nauck
  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;
  35. using System.Globalization;
  36. using System.IO;
  37. using System.IO.Compression;
  38. using System.Net.Sockets;
  39. using System.Runtime.Serialization;
  40. using System.Text;
  41. namespace System.Net
  42. {
  43. #if MOONLIGHT
  44. internal class HttpWebResponse : WebResponse, ISerializable, IDisposable {
  45. #else
  46. [Serializable]
  47. public class HttpWebResponse : WebResponse, ISerializable, IDisposable {
  48. #endif
  49. Uri uri;
  50. WebHeaderCollection webHeaders;
  51. CookieCollection cookieCollection;
  52. string method;
  53. Version version;
  54. HttpStatusCode statusCode;
  55. string statusDescription;
  56. long contentLength;
  57. string contentType;
  58. CookieContainer cookie_container;
  59. bool disposed;
  60. Stream stream;
  61. // Constructors
  62. internal HttpWebResponse (Uri uri, string method, WebConnectionData data, CookieContainer container)
  63. {
  64. this.uri = uri;
  65. this.method = method;
  66. webHeaders = data.Headers;
  67. version = data.Version;
  68. statusCode = (HttpStatusCode) data.StatusCode;
  69. statusDescription = data.StatusDescription;
  70. stream = data.stream;
  71. contentLength = -1;
  72. try {
  73. string cl = webHeaders ["Content-Length"];
  74. if (String.IsNullOrEmpty (cl) || !Int64.TryParse (cl, out contentLength))
  75. contentLength = -1;
  76. } catch (Exception) {
  77. contentLength = -1;
  78. }
  79. if (container != null) {
  80. this.cookie_container = container;
  81. FillCookies ();
  82. }
  83. string content_encoding = webHeaders ["Content-Encoding"];
  84. if (content_encoding == "gzip" && (data.request.AutomaticDecompression & DecompressionMethods.GZip) != 0)
  85. stream = new GZipStream (stream, CompressionMode.Decompress);
  86. else if (content_encoding == "deflate" && (data.request.AutomaticDecompression & DecompressionMethods.Deflate) != 0)
  87. stream = new DeflateStream (stream, CompressionMode.Decompress);
  88. }
  89. [Obsolete ("Serialization is obsoleted for this type", false)]
  90. protected HttpWebResponse (SerializationInfo serializationInfo, StreamingContext streamingContext)
  91. {
  92. SerializationInfo info = serializationInfo;
  93. uri = (Uri) info.GetValue ("uri", typeof (Uri));
  94. contentLength = info.GetInt64 ("contentLength");
  95. contentType = info.GetString ("contentType");
  96. method = info.GetString ("method");
  97. statusDescription = info.GetString ("statusDescription");
  98. cookieCollection = (CookieCollection) info.GetValue ("cookieCollection", typeof (CookieCollection));
  99. version = (Version) info.GetValue ("version", typeof (Version));
  100. statusCode = (HttpStatusCode) info.GetValue ("statusCode", typeof (HttpStatusCode));
  101. }
  102. // Properties
  103. public string CharacterSet {
  104. // Content-Type = "Content-Type" ":" media-type
  105. // media-type = type "/" subtype *( ";" parameter )
  106. // parameter = attribute "=" value
  107. // 3.7.1. default is ISO-8859-1
  108. get {
  109. string contentType = ContentType;
  110. if (contentType == null)
  111. return "ISO-8859-1";
  112. string val = contentType.ToLower ();
  113. int pos = val.IndexOf ("charset=", StringComparison.Ordinal);
  114. if (pos == -1)
  115. return "ISO-8859-1";
  116. pos += 8;
  117. int pos2 = val.IndexOf (';', pos);
  118. return (pos2 == -1)
  119. ? contentType.Substring (pos)
  120. : contentType.Substring (pos, pos2 - pos);
  121. }
  122. }
  123. public string ContentEncoding {
  124. get {
  125. CheckDisposed ();
  126. string h = webHeaders ["Content-Encoding"];
  127. return h != null ? h : "";
  128. }
  129. }
  130. public override long ContentLength {
  131. get {
  132. return contentLength;
  133. }
  134. }
  135. public override string ContentType {
  136. get {
  137. CheckDisposed ();
  138. if (contentType == null)
  139. contentType = webHeaders ["Content-Type"];
  140. return contentType;
  141. }
  142. }
  143. public CookieCollection Cookies {
  144. get {
  145. CheckDisposed ();
  146. if (cookieCollection == null)
  147. cookieCollection = new CookieCollection ();
  148. return cookieCollection;
  149. }
  150. set {
  151. CheckDisposed ();
  152. cookieCollection = value;
  153. }
  154. }
  155. public override WebHeaderCollection Headers {
  156. get {
  157. return webHeaders;
  158. }
  159. }
  160. static Exception GetMustImplement ()
  161. {
  162. return new NotImplementedException ();
  163. }
  164. [MonoTODO]
  165. public override bool IsMutuallyAuthenticated
  166. {
  167. get {
  168. throw GetMustImplement ();
  169. }
  170. }
  171. public DateTime LastModified {
  172. get {
  173. CheckDisposed ();
  174. try {
  175. string dtStr = webHeaders ["Last-Modified"];
  176. return MonoHttpDate.Parse (dtStr);
  177. } catch (Exception) {
  178. return DateTime.Now;
  179. }
  180. }
  181. }
  182. public string Method {
  183. get {
  184. CheckDisposed ();
  185. return method;
  186. }
  187. }
  188. public Version ProtocolVersion {
  189. get {
  190. CheckDisposed ();
  191. return version;
  192. }
  193. }
  194. public override Uri ResponseUri {
  195. get {
  196. CheckDisposed ();
  197. return uri;
  198. }
  199. }
  200. public string Server {
  201. get {
  202. CheckDisposed ();
  203. return webHeaders ["Server"];
  204. }
  205. }
  206. public HttpStatusCode StatusCode {
  207. get {
  208. return statusCode;
  209. }
  210. }
  211. public string StatusDescription {
  212. get {
  213. CheckDisposed ();
  214. return statusDescription;
  215. }
  216. }
  217. // Methods
  218. public string GetResponseHeader (string headerName)
  219. {
  220. CheckDisposed ();
  221. string value = webHeaders [headerName];
  222. return (value != null) ? value : "";
  223. }
  224. internal void ReadAll ()
  225. {
  226. WebConnectionStream wce = stream as WebConnectionStream;
  227. if (wce == null)
  228. return;
  229. try {
  230. wce.ReadAll ();
  231. } catch {}
  232. }
  233. public override Stream GetResponseStream ()
  234. {
  235. CheckDisposed ();
  236. if (stream == null)
  237. return Stream.Null;
  238. if (0 == String.Compare (method, "HEAD", true)) // see par 4.3 & 9.4
  239. return Stream.Null;
  240. return stream;
  241. }
  242. void ISerializable.GetObjectData (SerializationInfo serializationInfo,
  243. StreamingContext streamingContext)
  244. {
  245. GetObjectData (serializationInfo, streamingContext);
  246. }
  247. protected override void GetObjectData (SerializationInfo serializationInfo,
  248. StreamingContext streamingContext)
  249. {
  250. SerializationInfo info = serializationInfo;
  251. info.AddValue ("uri", uri);
  252. info.AddValue ("contentLength", contentLength);
  253. info.AddValue ("contentType", contentType);
  254. info.AddValue ("method", method);
  255. info.AddValue ("statusDescription", statusDescription);
  256. info.AddValue ("cookieCollection", cookieCollection);
  257. info.AddValue ("version", version);
  258. info.AddValue ("statusCode", statusCode);
  259. }
  260. // Cleaning up stuff
  261. public override void Close ()
  262. {
  263. if (stream != null) {
  264. Stream st = stream;
  265. stream = null;
  266. if (st != null)
  267. st.Close ();
  268. }
  269. }
  270. void IDisposable.Dispose ()
  271. {
  272. Dispose (true);
  273. GC.SuppressFinalize (this);
  274. }
  275. void Dispose (bool disposing)
  276. {
  277. this.disposed = true;
  278. if (disposing)
  279. Close ();
  280. }
  281. private void CheckDisposed ()
  282. {
  283. if (disposed)
  284. throw new ObjectDisposedException (GetType ().FullName);
  285. }
  286. void FillCookies ()
  287. {
  288. if (webHeaders == null)
  289. return;
  290. string value = webHeaders.Get ("Set-Cookie");
  291. if (value != null) {
  292. SetCookie (value);
  293. }
  294. value = webHeaders.Get ("Set-Cookie2");
  295. if (value != null) {
  296. SetCookie (value);
  297. }
  298. }
  299. void SetCookie (string header)
  300. {
  301. if (cookieCollection == null)
  302. cookieCollection = new CookieCollection ();
  303. var parser = new CookieParser (header);
  304. foreach (var cookie in parser.Parse ()) {
  305. if (cookie.Domain == "") {
  306. cookie.Domain = uri.Host;
  307. cookie.HasDomain = false;
  308. }
  309. if (cookie.HasDomain &&
  310. !CookieContainer.CheckSameOrigin (uri, cookie.Domain))
  311. continue;
  312. cookieCollection.Add (cookie);
  313. if (cookie_container != null)
  314. cookie_container.Add (uri, cookie);
  315. }
  316. }
  317. }
  318. }