2 // System.Net.HttpWebResponse
5 // Lawrence Pit (loz@cable.a2000.nl)
6 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
8 // (c) 2002 Lawrence Pit
9 // (c) 2003 Ximian, Inc. (http://www.ximian.com)
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 using System.Globalization;
36 using System.Net.Sockets;
37 using System.Runtime.Serialization;
43 public class HttpWebResponse : WebResponse, ISerializable, IDisposable
46 WebHeaderCollection webHeaders;
47 CookieCollection cookieCollection;
50 HttpStatusCode statusCode;
51 string statusDescription;
52 long contentLength = -1;
55 bool disposed = false;
60 internal HttpWebResponse (Uri uri, string method, WebConnectionData data, bool cookiesSet)
64 webHeaders = data.Headers;
65 version = data.Version;
66 statusCode = (HttpStatusCode) data.StatusCode;
67 statusDescription = data.StatusDescription;
71 } else if (webHeaders != null) {
72 webHeaders.RemoveInternal ("Set-Cookie");
73 webHeaders.RemoveInternal ("Set-Cookie2");
77 protected HttpWebResponse (SerializationInfo serializationInfo, StreamingContext streamingContext)
79 SerializationInfo info = serializationInfo;
81 uri = (Uri) info.GetValue ("uri", typeof (Uri));
82 contentLength = info.GetInt64 ("contentLength");
83 contentType = info.GetString ("contentType");
84 method = info.GetString ("method");
85 statusDescription = info.GetString ("statusDescription");
86 cookieCollection = (CookieCollection) info.GetValue ("cookieCollection", typeof (CookieCollection));
87 version = (Version) info.GetValue ("version", typeof (Version));
88 statusCode = (HttpStatusCode) info.GetValue ("statusCode", typeof (HttpStatusCode));
93 public string CharacterSet {
94 // Content-Type = "Content-Type" ":" media-type
95 // media-type = type "/" subtype *( ";" parameter )
96 // parameter = attribute "=" value
97 // 3.7.1. default is ISO-8859-1
100 string contentType = ContentType;
101 if (contentType == null)
103 string val = contentType.ToLower ();
104 int pos = val.IndexOf ("charset=");
108 int pos2 = val.IndexOf (';', pos);
110 ? contentType.Substring (pos)
111 : contentType.Substring (pos, pos2 - pos);
115 public string ContentEncoding {
118 return webHeaders ["Content-Encoding"];
122 public override long ContentLength {
125 if (contentLength != -1)
126 return contentLength;
129 contentLength = (long) UInt64.Parse (webHeaders ["Content-Length"]);
130 } catch (Exception) {
134 return contentLength;
138 public override string ContentType {
141 if (contentType == null)
142 contentType = webHeaders ["Content-Type"];
148 public CookieCollection Cookies {
152 if (cookieCollection == null)
153 cookieCollection = new CookieCollection ();
154 return cookieCollection;
158 cookieCollection = value;
162 public override WebHeaderCollection Headers {
169 public DateTime LastModified {
173 string dtStr = webHeaders ["Last-Modified"];
174 return MonoHttpDate.Parse (dtStr);
175 } catch (Exception) {
181 public string Method {
188 public Version ProtocolVersion {
195 public override Uri ResponseUri {
202 public string Server {
205 return webHeaders ["Server"];
209 public HttpStatusCode StatusCode {
216 public string StatusDescription {
219 return statusDescription;
225 public override int GetHashCode ()
228 return base.GetHashCode ();
231 public string GetResponseHeader (string headerName)
234 string value = webHeaders [headerName];
235 return (value != null) ? value : "";
238 public override Stream GetResponseStream ()
243 if (0 == String.Compare (method, "HEAD", true)) // see par 4.3 & 9.4
249 void ISerializable.GetObjectData (SerializationInfo serializationInfo,
250 StreamingContext streamingContext)
252 SerializationInfo info = serializationInfo;
254 info.AddValue ("uri", uri);
255 info.AddValue ("contentLength", contentLength);
256 info.AddValue ("contentType", contentType);
257 info.AddValue ("method", method);
258 info.AddValue ("statusDescription", statusDescription);
259 info.AddValue ("cookieCollection", cookieCollection);
260 info.AddValue ("version", version);
261 info.AddValue ("statusCode", statusCode);
267 public override void Close ()
269 ((IDisposable) this).Dispose ();
272 void IDisposable.Dispose ()
275 GC.SuppressFinalize (this);
278 protected virtual void Dispose (bool disposing)
282 this.disposed = true;
285 // release managed resources
288 cookieCollection = null;
291 statusDescription = null;
294 // release unmanaged resources
298 WebConnectionStream wce = st as WebConnectionStream;
308 private void CheckDisposed ()
311 throw new ObjectDisposedException (GetType ().FullName);
316 if (webHeaders == null)
319 string [] values = webHeaders.GetValues ("Set-Cookie");
320 if (values != null) {
321 foreach (string va in values)
325 values = webHeaders.GetValues ("Set-Cookie2");
326 if (values != null) {
327 foreach (string va in values)
332 void SetCookie (string header)
334 string [] name_values = header.Trim ().Split (';');
335 int length = name_values.Length;
336 Cookie cookie = null;
338 for (int i = 0; i < length; i++) {
340 string name_value = name_values [i].Trim ();
341 if (name_value == "")
344 string name = GetCookieName (name_value, name_value.Length, ref pos);
345 string value = GetCookieValue (name_value, name_value.Length, ref pos);
346 if (cookie == null) {
347 cookie = new Cookie (name, value);
351 name = name.ToUpper ();
354 if (cookie.Comment == null)
355 cookie.Comment = value;
358 if (cookie.CommentUri == null)
359 cookie.CommentUri = new Uri (value);
362 cookie.Discard = true;
365 if (cookie.Domain == "")
366 cookie.Domain = value;
368 case "MAX-AGE": // RFC Style Set-Cookie2
369 if (cookie.Expires == DateTime.MinValue)
370 cookie.Expires = cookie.TimeStamp.AddSeconds (Int32.Parse (value));
372 case "EXPIRES": // Netscape Style Set-Cookie
373 if (cookie.Expires != DateTime.MinValue)
376 cookie.Expires = DateTime.ParseExact (value, "r", CultureInfo.InvariantCulture);
379 cookie.Expires = DateTime.ParseExact (value,
380 "ddd, dd'-'MMM'-'yyyy HH':'mm':'ss 'GMT'",
381 CultureInfo.InvariantCulture);
383 cookie.Expires = DateTime.Now.AddDays (1);
391 if (cookie.Port == null)
395 cookie.Secure = true;
398 cookie.Version = Int32.Parse (value);
403 if (cookieCollection == null)
404 cookieCollection = new CookieCollection ();
406 if (cookie.Domain == "")
407 cookie.Domain = uri.Host;
409 cookieCollection.Add (cookie);
412 void SetCookie2 (string cookies_str)
414 string [] cookies = cookies_str.Split (',');
416 foreach (string cookie_str in cookies)
417 SetCookie (cookie_str);
420 static string GetCookieValue (string str, int length, ref int i)
426 while (k < length && Char.IsWhiteSpace (str [k]))
430 while (k < length && str [k] != ';')
434 return str.Substring (begin, i - begin).Trim ();
437 static string GetCookieName (string str, int length, ref int i)
443 while (k < length && Char.IsWhiteSpace (str [k]))
447 while (k < length && str [k] != ';' && str [k] != '=')
451 return str.Substring (begin, k - begin).Trim ();