HttpWebResponse.cs 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. //
  2. // System.Net.HttpWebResponse
  3. //
  4. // Authors:
  5. // Lawrence Pit ([email protected])
  6. // Gonzalo Paniagua Javier ([email protected])
  7. //
  8. // (c) 2002 Lawrence Pit
  9. // (c) 2003 Ximian, Inc. (http://www.ximian.com)
  10. //
  11. using System;
  12. using System.IO;
  13. using System.Net.Sockets;
  14. using System.Runtime.Serialization;
  15. using System.Text;
  16. namespace System.Net
  17. {
  18. [Serializable]
  19. public class HttpWebResponse : WebResponse, ISerializable, IDisposable
  20. {
  21. Uri uri;
  22. WebHeaderCollection webHeaders;
  23. CookieCollection cookieCollection;
  24. string method;
  25. Version version;
  26. HttpStatusCode statusCode;
  27. string statusDescription;
  28. long contentLength = -1;
  29. string contentType;
  30. bool disposed = false;
  31. Stream stream;
  32. // Constructors
  33. internal HttpWebResponse (Uri uri, string method, WebConnectionData data, bool cookiesSet)
  34. {
  35. this.uri = uri;
  36. this.method = method;
  37. webHeaders = data.Headers;
  38. version = data.Version;
  39. statusCode = (HttpStatusCode) data.StatusCode;
  40. statusDescription = data.StatusDescription;
  41. stream = data.stream;
  42. if (cookiesSet) {
  43. FillCookies ();
  44. } else if (webHeaders != null) {
  45. webHeaders.RemoveInternal ("Set-Cookie");
  46. webHeaders.RemoveInternal ("Set-Cookie2");
  47. }
  48. }
  49. protected HttpWebResponse (SerializationInfo serializationInfo, StreamingContext streamingContext)
  50. {
  51. SerializationInfo info = serializationInfo;
  52. uri = (Uri) info.GetValue ("uri", typeof (Uri));
  53. contentLength = info.GetInt64 ("contentLength");
  54. contentType = info.GetString ("contentType");
  55. method = info.GetString ("method");
  56. statusDescription = info.GetString ("statusDescription");
  57. cookieCollection = (CookieCollection) info.GetValue ("cookieCollection", typeof (CookieCollection));
  58. version = (Version) info.GetValue ("version", typeof (Version));
  59. statusCode = (HttpStatusCode) info.GetValue ("statusCode", typeof (HttpStatusCode));
  60. }
  61. // Properties
  62. public string CharacterSet {
  63. // Content-Type = "Content-Type" ":" media-type
  64. // media-type = type "/" subtype *( ";" parameter )
  65. // parameter = attribute "=" value
  66. // 3.7.1. default is ISO-8859-1
  67. get {
  68. CheckDisposed ();
  69. string contentType = ContentType;
  70. if (contentType == null)
  71. return "ISO-8859-1";
  72. string val = contentType.ToLower ();
  73. int pos = val.IndexOf ("charset=");
  74. if (pos == -1)
  75. return "ISO-8859-1";
  76. pos += 8;
  77. int pos2 = val.IndexOf (';', pos);
  78. return (pos2 == -1)
  79. ? contentType.Substring (pos)
  80. : contentType.Substring (pos, pos2 - pos);
  81. }
  82. }
  83. public string ContentEncoding {
  84. get {
  85. CheckDisposed ();
  86. return webHeaders ["Content-Encoding"];
  87. }
  88. }
  89. public override long ContentLength {
  90. get {
  91. CheckDisposed ();
  92. if (contentLength != -1)
  93. return contentLength;
  94. try {
  95. contentLength = (long) UInt64.Parse (webHeaders ["Content-Length"]);
  96. } catch (Exception) {
  97. return -1;
  98. }
  99. return contentLength;
  100. }
  101. }
  102. public override string ContentType {
  103. get {
  104. CheckDisposed ();
  105. if (contentType == null)
  106. contentType = webHeaders ["Content-Type"];
  107. return contentType;
  108. }
  109. }
  110. public CookieCollection Cookies {
  111. get {
  112. CheckDisposed ();
  113. if (cookieCollection == null)
  114. cookieCollection = new CookieCollection ();
  115. return cookieCollection;
  116. }
  117. set {
  118. CheckDisposed ();
  119. cookieCollection = value;
  120. }
  121. }
  122. public override WebHeaderCollection Headers {
  123. get {
  124. CheckDisposed ();
  125. return webHeaders;
  126. }
  127. }
  128. public DateTime LastModified {
  129. get {
  130. CheckDisposed ();
  131. try {
  132. string dtStr = webHeaders ["Last-Modified"];
  133. return MonoHttpDate.Parse (dtStr);
  134. } catch (Exception) {
  135. return DateTime.Now;
  136. }
  137. }
  138. }
  139. public string Method {
  140. get {
  141. CheckDisposed ();
  142. return method;
  143. }
  144. }
  145. public Version ProtocolVersion {
  146. get {
  147. CheckDisposed ();
  148. return version;
  149. }
  150. }
  151. public override Uri ResponseUri {
  152. get {
  153. CheckDisposed ();
  154. return uri;
  155. }
  156. }
  157. public string Server {
  158. get {
  159. CheckDisposed ();
  160. return webHeaders ["Server"];
  161. }
  162. }
  163. public HttpStatusCode StatusCode {
  164. get {
  165. CheckDisposed ();
  166. return statusCode;
  167. }
  168. }
  169. public string StatusDescription {
  170. get {
  171. CheckDisposed ();
  172. return statusDescription;
  173. }
  174. }
  175. // Methods
  176. public override int GetHashCode ()
  177. {
  178. CheckDisposed ();
  179. return base.GetHashCode ();
  180. }
  181. public string GetResponseHeader (string headerName)
  182. {
  183. CheckDisposed ();
  184. string value = webHeaders [headerName];
  185. return (value != null) ? value : "";
  186. }
  187. public override Stream GetResponseStream ()
  188. {
  189. CheckDisposed ();
  190. if (stream == null)
  191. return Stream.Null;
  192. if (0 == String.Compare (method, "HEAD", true)) // see par 4.3 & 9.4
  193. return Stream.Null;
  194. return stream;
  195. }
  196. void ISerializable.GetObjectData (SerializationInfo serializationInfo,
  197. StreamingContext streamingContext)
  198. {
  199. SerializationInfo info = serializationInfo;
  200. info.AddValue ("uri", uri);
  201. info.AddValue ("contentLength", contentLength);
  202. info.AddValue ("contentType", contentType);
  203. info.AddValue ("method", method);
  204. info.AddValue ("statusDescription", statusDescription);
  205. info.AddValue ("cookieCollection", cookieCollection);
  206. info.AddValue ("version", version);
  207. info.AddValue ("statusCode", statusCode);
  208. }
  209. // Cleaning up stuff
  210. public override void Close ()
  211. {
  212. ((IDisposable) this).Dispose ();
  213. }
  214. void IDisposable.Dispose ()
  215. {
  216. Dispose (true);
  217. GC.SuppressFinalize (this);
  218. }
  219. protected virtual void Dispose (bool disposing)
  220. {
  221. if (this.disposed)
  222. return;
  223. this.disposed = true;
  224. if (disposing) {
  225. // release managed resources
  226. uri = null;
  227. webHeaders = null;
  228. cookieCollection = null;
  229. method = null;
  230. version = null;
  231. statusDescription = null;
  232. }
  233. // release unmanaged resources
  234. Stream st = stream;
  235. stream = null;
  236. if (st != null)
  237. st.Close ();
  238. }
  239. private void CheckDisposed ()
  240. {
  241. if (disposed)
  242. throw new ObjectDisposedException (GetType ().FullName);
  243. }
  244. void FillCookies ()
  245. {
  246. if (webHeaders == null)
  247. return;
  248. string val = webHeaders ["Set-Cookie"];
  249. if (val != null && val.Trim () != "")
  250. SetCookie (val);
  251. val = webHeaders ["Set-Cookie2"];
  252. if (val != null && val.Trim () != "")
  253. SetCookie2 (val);
  254. }
  255. static string [] SplitValue (string input)
  256. {
  257. string [] result = new string [2];
  258. int eq = input.IndexOf ('=');
  259. if (eq == -1) {
  260. result [0] = "invalid";
  261. } else {
  262. result [0] = input.Substring (0, eq).Trim ().ToUpper ();
  263. result [1] = input.Substring (eq + 1);
  264. }
  265. return result;
  266. }
  267. [MonoTODO ("Parse dates")]
  268. void SetCookie (string cookie_str)
  269. {
  270. string[] parts = null;
  271. Collections.Queue options = null;
  272. Cookie cookie = null;
  273. options = new Collections.Queue (cookie_str.Split (';'));
  274. parts = SplitValue ((string) options.Dequeue()); // NAME=VALUE must be first
  275. cookie = new Cookie (parts[0], parts[1]);
  276. while (options.Count > 0) {
  277. parts = SplitValue ((string) options.Dequeue());
  278. switch (parts [0]) {
  279. case "COMMENT":
  280. if (cookie.Comment == null)
  281. cookie.Comment = parts[1];
  282. break;
  283. case "COMMENTURL":
  284. if (cookie.CommentUri == null)
  285. cookie.CommentUri = new Uri(parts[1]);
  286. break;
  287. case "DISCARD":
  288. cookie.Discard = true;
  289. break;
  290. case "DOMAIN":
  291. if (cookie.Domain == "")
  292. cookie.Domain = parts[1];
  293. break;
  294. case "MAX-AGE": // RFC Style Set-Cookie2
  295. if (cookie.Expires == DateTime.MinValue)
  296. cookie.Expires = cookie.TimeStamp.AddSeconds (Int32.Parse (parts[1]));
  297. break;
  298. case "EXPIRES": // Netscape Style Set-Cookie
  299. if (cookie.Expires == DateTime.MinValue) {
  300. //FIXME: Does DateTime parse something like: "Sun, 17-Jan-2038 19:14:07 GMT"?
  301. //cookie.Expires = DateTime.ParseExact (parts[1]);
  302. cookie.Expires = DateTime.Now.AddDays (1);
  303. }
  304. break;
  305. case "PATH":
  306. cookie.Path = parts[1];
  307. break;
  308. case "PORT":
  309. if (cookie.Port == null)
  310. cookie.Port = parts[1];
  311. break;
  312. case "SECURE":
  313. cookie.Secure = true;
  314. break;
  315. case "VERSION":
  316. cookie.Version = Int32.Parse (parts[1]);
  317. break;
  318. } // switch
  319. } // while
  320. if (cookieCollection == null)
  321. cookieCollection = new CookieCollection();
  322. if (cookie.Domain == "")
  323. cookie.Domain = uri.Host;
  324. cookieCollection.Add (cookie);
  325. }
  326. void SetCookie2 (string cookies_str)
  327. {
  328. string [] cookies = cookies_str.Split (',');
  329. foreach (string cookie_str in cookies)
  330. SetCookie (cookie_str);
  331. }
  332. }
  333. }