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.Collections;
35 using System.Globalization;
37 using System.Net.Sockets;
38 using System.Runtime.Serialization;
44 public class HttpWebResponse : WebResponse, ISerializable, IDisposable
47 WebHeaderCollection webHeaders;
48 CookieCollection cookieCollection;
51 HttpStatusCode statusCode;
52 string statusDescription;
53 long contentLength = -1;
55 CookieContainer cookie_container;
57 bool disposed = false;
62 internal HttpWebResponse (Uri uri, string method, WebConnectionData data, CookieContainer container)
66 webHeaders = data.Headers;
67 version = data.Version;
68 statusCode = (HttpStatusCode) data.StatusCode;
69 statusDescription = data.StatusDescription;
71 if (container != null) {
72 this.cookie_container = container;
78 [Obsolete ("Serialization is obsoleted for this type", false)]
80 protected HttpWebResponse (SerializationInfo serializationInfo, StreamingContext streamingContext)
82 SerializationInfo info = serializationInfo;
84 uri = (Uri) info.GetValue ("uri", typeof (Uri));
85 contentLength = info.GetInt64 ("contentLength");
86 contentType = info.GetString ("contentType");
87 method = info.GetString ("method");
88 statusDescription = info.GetString ("statusDescription");
89 cookieCollection = (CookieCollection) info.GetValue ("cookieCollection", typeof (CookieCollection));
90 version = (Version) info.GetValue ("version", typeof (Version));
91 statusCode = (HttpStatusCode) info.GetValue ("statusCode", typeof (HttpStatusCode));
96 public string CharacterSet {
97 // Content-Type = "Content-Type" ":" media-type
98 // media-type = type "/" subtype *( ";" parameter )
99 // parameter = attribute "=" value
100 // 3.7.1. default is ISO-8859-1
103 string contentType = ContentType;
104 if (contentType == null)
106 string val = contentType.ToLower ();
107 int pos = val.IndexOf ("charset=");
111 int pos2 = val.IndexOf (';', pos);
113 ? contentType.Substring (pos)
114 : contentType.Substring (pos, pos2 - pos);
118 public string ContentEncoding {
121 string h = webHeaders ["Content-Encoding"];
122 return h != null ? h : "";
126 public override long ContentLength {
129 if (contentLength != -1)
130 return contentLength;
133 contentLength = (long) UInt64.Parse (webHeaders ["Content-Length"]);
134 } catch (Exception) {
138 return contentLength;
142 public override string ContentType {
145 if (contentType == null)
146 contentType = webHeaders ["Content-Type"];
152 public CookieCollection Cookies {
156 if (cookieCollection == null)
157 cookieCollection = new CookieCollection ();
158 return cookieCollection;
162 cookieCollection = value;
166 public override WebHeaderCollection Headers {
174 static Exception GetMustImplement ()
176 return new NotImplementedException ();
180 public override bool IsMutuallyAuthenticated
183 throw GetMustImplement ();
188 public DateTime LastModified {
192 string dtStr = webHeaders ["Last-Modified"];
193 return MonoHttpDate.Parse (dtStr);
194 } catch (Exception) {
200 public string Method {
207 public Version ProtocolVersion {
214 public override Uri ResponseUri {
221 public string Server {
224 return webHeaders ["Server"];
228 public HttpStatusCode StatusCode {
235 public string StatusDescription {
238 return statusDescription;
244 public override int GetHashCode ()
247 return base.GetHashCode ();
251 public string GetResponseHeader (string headerName)
254 string value = webHeaders [headerName];
255 return (value != null) ? value : "";
258 internal void ReadAll ()
260 WebConnectionStream wce = stream as WebConnectionStream;
269 public override Stream GetResponseStream ()
274 if (0 == String.Compare (method, "HEAD", true)) // see par 4.3 & 9.4
280 void ISerializable.GetObjectData (SerializationInfo serializationInfo,
281 StreamingContext streamingContext)
283 GetObjectData (serializationInfo, streamingContext);
289 void GetObjectData (SerializationInfo serializationInfo,
290 StreamingContext streamingContext)
292 SerializationInfo info = serializationInfo;
294 info.AddValue ("uri", uri);
295 info.AddValue ("contentLength", contentLength);
296 info.AddValue ("contentType", contentType);
297 info.AddValue ("method", method);
298 info.AddValue ("statusDescription", statusDescription);
299 info.AddValue ("cookieCollection", cookieCollection);
300 info.AddValue ("version", version);
301 info.AddValue ("statusCode", statusCode);
306 public override void Close ()
308 ((IDisposable) this).Dispose ();
311 void IDisposable.Dispose ()
314 GC.SuppressFinalize (this);
320 void Dispose (bool disposing)
324 this.disposed = true;
327 // release managed resources
330 cookieCollection = null;
333 statusDescription = null;
336 // release unmanaged resources
343 private void CheckDisposed ()
346 throw new ObjectDisposedException (GetType ().FullName);
351 if (webHeaders == null)
354 string [] values = webHeaders.GetValues ("Set-Cookie");
355 if (values != null) {
356 foreach (string va in values)
360 values = webHeaders.GetValues ("Set-Cookie2");
361 if (values != null) {
362 foreach (string va in values)
367 void SetCookie (string header)
370 Cookie cookie = null;
371 CookieParser parser = new CookieParser (header);
373 while (parser.GetNextNameValue (out name, out val)) {
374 if ((name == null || name == "") && cookie == null)
377 if (cookie == null) {
378 cookie = new Cookie (name, val);
382 name = name.ToUpper ();
385 if (cookie.Comment == null)
386 cookie.Comment = val;
389 if (cookie.CommentUri == null)
390 cookie.CommentUri = new Uri (val);
393 cookie.Discard = true;
396 if (cookie.Domain == "")
399 case "MAX-AGE": // RFC Style Set-Cookie2
400 if (cookie.Expires == DateTime.MinValue) {
402 cookie.Expires = cookie.TimeStamp.AddSeconds (UInt32.Parse (val));
406 case "EXPIRES": // Netscape Style Set-Cookie
407 if (cookie.Expires != DateTime.MinValue)
410 cookie.Expires = DateTime.ParseExact (val, "r", CultureInfo.InvariantCulture);
413 cookie.Expires = DateTime.ParseExact (val,
414 "ddd, dd'-'MMM'-'yyyy HH':'mm':'ss 'GMT'",
415 CultureInfo.InvariantCulture);
417 cookie.Expires = DateTime.Now.AddDays (1);
425 if (cookie.Port == null)
429 cookie.Secure = true;
433 cookie.Version = (int) UInt32.Parse (val);
439 if (cookieCollection == null)
440 cookieCollection = new CookieCollection ();
442 if (cookie.Domain == "")
443 cookie.Domain = uri.Host;
445 cookieCollection.Add (cookie);
446 if (cookie_container != null)
447 cookie_container.Add (uri, cookie);
450 void SetCookie2 (string cookies_str)
452 string [] cookies = cookies_str.Split (',');
454 foreach (string cookie_str in cookies)
455 SetCookie (cookie_str);
464 public CookieParser (string header) : this (header, 0)
468 public CookieParser (string header, int position)
470 this.header = header;
472 this.length = header.Length;
475 public bool GetNextNameValue (out string name, out string val)
483 name = GetCookieName ();
484 if (pos < header.Length && header [pos] == '=') {
486 val = GetCookieValue ();
489 if (pos < length && header [pos] == ';')
495 string GetCookieName ()
498 while (k < length && Char.IsWhiteSpace (header [k]))
502 while (k < length && header [k] != ';' && header [k] != '=')
506 return header.Substring (begin, k - begin).Trim ();
509 string GetCookieValue ()
515 while (k < length && Char.IsWhiteSpace (header [k]))
519 if (header [k] == '"'){
523 while (k < length && header [k] != '"')
526 for (j = k; j < length && header [j] != ';'; j++)
531 while (k < length && header [k] != ';')
536 return header.Substring (begin, k - begin).Trim ();