//
using System;
+using System.Collections;
+using System.Globalization;
using System.IO;
using System.Net.Sockets;
using System.Runtime.Serialization;
string statusDescription;
long contentLength = -1;
string contentType;
+ CookieContainer cookieContainer;
bool disposed = false;
Stream stream;
// Constructors
- internal HttpWebResponse (Uri uri, string method, WebConnectionData data, bool cookiesSet)
+ internal HttpWebResponse (Uri uri, string method, WebConnectionData data, CookieContainer container)
{
this.uri = uri;
this.method = method;
statusCode = (HttpStatusCode) data.StatusCode;
statusDescription = data.StatusDescription;
stream = data.stream;
- if (cookiesSet) {
+ if (container != null) {
+ this.cookieContainer = container;
FillCookies ();
- } else if (webHeaders != null) {
- webHeaders.RemoveInternal ("Set-Cookie");
- webHeaders.RemoveInternal ("Set-Cookie2");
}
}
public string ContentEncoding {
get {
CheckDisposed ();
- return webHeaders ["Content-Encoding"];
+ string h = webHeaders ["Content-Encoding"];
+ return h != null ? h : "";
}
}
}
// Methods
-
+#if !NET_2_0
public override int GetHashCode ()
{
CheckDisposed ();
return base.GetHashCode ();
}
+#endif
public string GetResponseHeader (string headerName)
{
string value = webHeaders [headerName];
return (value != null) ? value : "";
}
-
+
+ internal void ReadAll ()
+ {
+ WebConnectionStream wce = stream as WebConnectionStream;
+ if (wce == null)
+ return;
+
+ try {
+ wce.ReadAll ();
+ } catch {}
+ }
+
public override Stream GetResponseStream ()
{
CheckDisposed ();
Dispose (true);
GC.SuppressFinalize (this);
}
-
- protected virtual void Dispose (bool disposing)
+
+#if !NET_2_0
+ protected virtual
+#endif
+ void Dispose (bool disposing)
{
if (this.disposed)
return;
// release unmanaged resources
Stream st = stream;
stream = null;
- if (st != null) {
- WebConnectionStream wce = st as WebConnectionStream;
- if (wce != null) {
- try {
- wce.ReadAll ();
- } catch {}
- }
+ if (st != null)
st.Close ();
- }
}
private void CheckDisposed ()
if (webHeaders == null)
return;
- string val = webHeaders ["Set-Cookie"];
- if (val != null && val.Trim () != "")
- SetCookie (val);
+ string [] values = webHeaders.GetValues ("Set-Cookie");
+ if (values != null) {
+ foreach (string va in values)
+ SetCookie (va);
+ }
- val = webHeaders ["Set-Cookie2"];
- if (val != null && val.Trim () != "")
- SetCookie2 (val);
- }
-
- static string [] SplitValue (string input)
- {
- string [] result = new string [2];
- int eq = input.IndexOf ('=');
- if (eq == -1) {
- result [0] = "invalid";
- } else {
- result [0] = input.Substring (0, eq).Trim ().ToUpper ();
- result [1] = input.Substring (eq + 1);
+ values = webHeaders.GetValues ("Set-Cookie2");
+ if (values != null) {
+ foreach (string va in values)
+ SetCookie2 (va);
}
-
- return result;
}
-
- [MonoTODO ("Parse dates")]
- void SetCookie (string cookie_str)
+
+ void SetCookie (string header)
{
- string[] parts = null;
- Collections.Queue options = null;
+ string name, val;
Cookie cookie = null;
+ CookieParser parser = new CookieParser (header);
- options = new Collections.Queue (cookie_str.Split (';'));
- parts = SplitValue ((string) options.Dequeue()); // NAME=VALUE must be first
+ while (parser.GetNextNameValue (out name, out val)) {
+ if ((name == null || name == "") && cookie == null)
+ continue;
- cookie = new Cookie (parts[0], parts[1]);
+ if (cookie == null) {
+ cookie = new Cookie (name, val);
+ continue;
+ }
- while (options.Count > 0) {
- parts = SplitValue ((string) options.Dequeue());
- switch (parts [0]) {
- case "COMMENT":
- if (cookie.Comment == null)
- cookie.Comment = parts[1];
+ name = name.ToUpper ();
+ switch (name) {
+ case "COMMENT":
+ if (cookie.Comment == null)
+ cookie.Comment = val;
break;
- case "COMMENTURL":
- if (cookie.CommentUri == null)
- cookie.CommentUri = new Uri(parts[1]);
+ case "COMMENTURL":
+ if (cookie.CommentUri == null)
+ cookie.CommentUri = new Uri (val);
break;
- case "DISCARD":
- cookie.Discard = true;
+ case "DISCARD":
+ cookie.Discard = true;
break;
- case "DOMAIN":
- if (cookie.Domain == "")
- cookie.Domain = parts[1];
+ case "DOMAIN":
+ if (cookie.Domain == "")
+ cookie.Domain = val;
break;
- case "MAX-AGE": // RFC Style Set-Cookie2
- if (cookie.Expires == DateTime.MinValue)
- cookie.Expires = cookie.TimeStamp.AddSeconds (Int32.Parse (parts[1]));
+ case "MAX-AGE": // RFC Style Set-Cookie2
+ if (cookie.Expires == DateTime.MinValue) {
+ try {
+ cookie.Expires = cookie.TimeStamp.AddSeconds (UInt32.Parse (val));
+ } catch {}
+ }
break;
- case "EXPIRES": // Netscape Style Set-Cookie
- if (cookie.Expires == DateTime.MinValue) {
- //FIXME: Does DateTime parse something like: "Sun, 17-Jan-2038 19:14:07 GMT"?
- //cookie.Expires = DateTime.ParseExact (parts[1]);
+ case "EXPIRES": // Netscape Style Set-Cookie
+ if (cookie.Expires != DateTime.MinValue)
+ break;
+ try {
+ cookie.Expires = DateTime.ParseExact (val, "r", CultureInfo.InvariantCulture);
+ } catch {
+ try {
+ cookie.Expires = DateTime.ParseExact (val,
+ "ddd, dd'-'MMM'-'yyyy HH':'mm':'ss 'GMT'",
+ CultureInfo.InvariantCulture);
+ } catch {
cookie.Expires = DateTime.Now.AddDays (1);
}
+ }
break;
- case "PATH":
- cookie.Path = parts[1];
+ case "PATH":
+ cookie.Path = val;
break;
- case "PORT":
- if (cookie.Port == null)
- cookie.Port = parts[1];
+ case "PORT":
+ if (cookie.Port == null)
+ cookie.Port = val;
break;
- case "SECURE":
- cookie.Secure = true;
+ case "SECURE":
+ cookie.Secure = true;
break;
- case "VERSION":
- cookie.Version = Int32.Parse (parts[1]);
+ case "VERSION":
+ try {
+ cookie.Version = (int) UInt32.Parse (val);
+ } catch {}
break;
- } // switch
- } // while
+ }
+ }
if (cookieCollection == null)
- cookieCollection = new CookieCollection();
+ cookieCollection = new CookieCollection ();
if (cookie.Domain == "")
cookie.Domain = uri.Host;
cookieCollection.Add (cookie);
+ if (cookieContainer != null)
+ cookieContainer.Add (uri, cookie);
}
void SetCookie2 (string cookies_str)
SetCookie (cookie_str);
}
}
+
+ class CookieParser {
+ string header;
+ int pos;
+ int length;
+
+ public CookieParser (string header) : this (header, 0)
+ {
+ }
+
+ public CookieParser (string header, int position)
+ {
+ this.header = header;
+ this.pos = position;
+ this.length = header.Length;
+ }
+
+ public bool GetNextNameValue (out string name, out string val)
+ {
+ name = null;
+ val = null;
+
+ if (pos >= length)
+ return false;
+
+ name = GetCookieName ();
+ if (pos < header.Length && header [pos] == '=') {
+ pos++;
+ val = GetCookieValue ();
+ }
+
+ if (pos < length && header [pos] == ';')
+ pos++;
+
+ return true;
+ }
+
+ string GetCookieName ()
+ {
+ int k = pos;
+ while (k < length && Char.IsWhiteSpace (header [k]))
+ k++;
+
+ int begin = k;
+ while (k < length && header [k] != ';' && header [k] != '=')
+ k++;
+
+ pos = k;
+ return header.Substring (begin, k - begin).Trim ();
+ }
+
+ string GetCookieValue ()
+ {
+ if (pos >= length)
+ return null;
+
+ int k = pos;
+ while (k < length && Char.IsWhiteSpace (header [k]))
+ k++;
+
+ int begin;
+ if (header [k] == '"'){
+ int j;
+ begin = ++k;
+
+ while (k < length && header [k] != '"')
+ k++;
+
+ for (j = k; j < length && header [j] != ';'; j++)
+ ;
+ pos = j;
+ } else {
+ begin = k;
+ while (k < length && header [k] != ';')
+ k++;
+ pos = k;
+ }
+
+ return header.Substring (begin, k - begin).Trim ();
+ }
+ }
}