using System.Collections;
using System.Globalization;
using System.IO;
+using System.IO.Compression;
using System.Net.Sockets;
using System.Runtime.Serialization;
using System.Text;
-#if NET_2_0
-using System.IO.Compression;
-#endif
namespace System.Net
{
[Serializable]
- public class HttpWebResponse : WebResponse, ISerializable, IDisposable
- {
+ public class HttpWebResponse : WebResponse, ISerializable, IDisposable {
Uri uri;
WebHeaderCollection webHeaders;
CookieCollection cookieCollection;
try {
string cl = webHeaders ["Content-Length"];
-#if NET_2_0
if (String.IsNullOrEmpty (cl) || !Int64.TryParse (cl, out contentLength))
contentLength = -1;
-#else
- if (cl != null && cl != String.Empty)
- contentLength = (long) UInt64.Parse (cl);
-#endif
} catch (Exception) {
contentLength = -1;
}
this.cookie_container = container;
FillCookies ();
}
-#if NET_2_0
+
string content_encoding = webHeaders ["Content-Encoding"];
if (content_encoding == "gzip" && (data.request.AutomaticDecompression & DecompressionMethods.GZip) != 0)
stream = new GZipStream (stream, CompressionMode.Decompress);
else if (content_encoding == "deflate" && (data.request.AutomaticDecompression & DecompressionMethods.Deflate) != 0)
stream = new DeflateStream (stream, CompressionMode.Decompress);
-#endif
}
-#if NET_2_0
[Obsolete ("Serialization is obsoleted for this type", false)]
-#endif
protected HttpWebResponse (SerializationInfo serializationInfo, StreamingContext streamingContext)
{
SerializationInfo info = serializationInfo;
if (contentType == null)
return "ISO-8859-1";
string val = contentType.ToLower ();
- int pos = val.IndexOf ("charset=");
+ int pos = val.IndexOf ("charset=", StringComparison.Ordinal);
if (pos == -1)
return "ISO-8859-1";
pos += 8;
}
}
+#if NET_4_5
+ virtual
+#endif
public CookieCollection Cookies {
get {
CheckDisposed ();
public override WebHeaderCollection Headers {
get {
-#if ONLY_1_1
- CheckDisposed ();
-#endif
return webHeaders;
}
}
-#if NET_2_0
static Exception GetMustImplement ()
{
return new NotImplementedException ();
throw GetMustImplement ();
}
}
-#endif
public DateTime LastModified {
get {
}
}
+#if NET_4_5
+ virtual
+#endif
public string Method {
get {
CheckDisposed ();
}
}
+#if NET_4_5
+ virtual
+#endif
public HttpStatusCode StatusCode {
get {
return statusCode;
}
}
+#if NET_4_5
+ virtual
+#endif
public string StatusDescription {
get {
CheckDisposed ();
}
// Methods
-#if !NET_2_0
- public override int GetHashCode ()
- {
- return base.GetHashCode ();
- }
-#endif
public string GetResponseHeader (string headerName)
{
CheckDisposed ();
if (stream == null)
return Stream.Null;
- if (0 == String.Compare (method, "HEAD", true)) // see par 4.3 & 9.4
+ if (string.Equals (method, "HEAD", StringComparison.OrdinalIgnoreCase)) // see par 4.3 & 9.4
return Stream.Null;
return stream;
GetObjectData (serializationInfo, streamingContext);
}
-#if NET_2_0
- protected override
-#endif
- void GetObjectData (SerializationInfo serializationInfo,
- StreamingContext streamingContext)
+ protected override void GetObjectData (SerializationInfo serializationInfo,
+ StreamingContext streamingContext)
{
SerializationInfo info = serializationInfo;
public override void Close ()
{
- ((IDisposable) this).Dispose ();
+ if (stream != null) {
+ Stream st = stream;
+ stream = null;
+ if (st != null)
+ st.Close ();
+ }
}
void IDisposable.Dispose ()
{
Dispose (true);
- GC.SuppressFinalize (this);
}
-
-#if !NET_2_0
- protected virtual
-#endif
+
+#if NET_4_0
+ protected override void Dispose (bool disposing)
+ {
+ this.disposed = true;
+ base.Dispose (true);
+ }
+#else
void Dispose (bool disposing)
{
- if (this.disposed)
- return;
this.disposed = true;
-
- if (disposing) {
- // release managed resources
- uri = null;
-#if !NET_2_0
- webHeaders = null;
-#endif
- cookieCollection = null;
- method = null;
- version = null;
- statusDescription = null;
- }
-
- // release unmanaged resources
- Stream st = stream;
- stream = null;
- if (st != null)
- st.Close ();
+ if (disposing)
+ Close ();
}
+#endif
private void CheckDisposed ()
{
if (webHeaders == null)
return;
- string [] values = webHeaders.GetValues ("Set-Cookie");
- if (values != null) {
- foreach (string va in values)
- SetCookie (va);
+ //
+ // Don't terminate response reading on bad cookie value
+ //
+ string value;
+ try {
+ value = webHeaders.Get ("Set-Cookie");
+ if (value != null && SetCookie (value))
+ return;
+ } catch {
}
- values = webHeaders.GetValues ("Set-Cookie2");
- if (values != null) {
- foreach (string va in values)
- SetCookie2 (va);
+ try {
+ value = webHeaders.Get ("Set-Cookie2");
+ if (value != null)
+ SetCookie (value);
+ } catch {
}
}
- void SetCookie (string header)
+ bool SetCookie (string header)
{
- string name, val;
- Cookie cookie = null;
- CookieParser parser = new CookieParser (header);
-
- while (parser.GetNextNameValue (out name, out val)) {
- if ((name == null || name == "") && cookie == null)
- continue;
-
- if (cookie == null) {
- cookie = new Cookie (name, val);
- continue;
- }
-
- 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 (val);
- break;
- case "DISCARD":
- cookie.Discard = true;
- break;
- case "DOMAIN":
- if (cookie.Domain == "")
- cookie.Domain = val;
- break;
-#if NET_2_0
- case "HTTPONLY":
- cookie.HttpOnly = true;
- break;
-#endif
- 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)
- break;
-
- cookie.Expires = TryParseCookieExpires (val);
- break;
- case "PATH":
- cookie.Path = val;
- break;
- case "PORT":
- if (cookie.Port == null)
- cookie.Port = val;
- break;
- case "SECURE":
- cookie.Secure = true;
- break;
- case "VERSION":
- try {
- cookie.Version = (int) UInt32.Parse (val);
- } catch {}
- break;
- }
- }
-
if (cookieCollection == null)
cookieCollection = new CookieCollection ();
- if (cookie.Domain == "")
- cookie.Domain = uri.Host;
-
- cookieCollection.Add (cookie);
- if (cookie_container != null)
- cookie_container.Add (uri, cookie);
- }
-
- void SetCookie2 (string cookies_str)
- {
- string [] cookies = cookies_str.Split (',');
-
- foreach (string cookie_str in cookies)
- SetCookie (cookie_str);
- }
-
- string[] cookieExpiresFormats =
- new string[] { "r",
- "ddd, dd'-'MMM'-'yyyy HH':'mm':'ss 'GMT'",
- "ddd, dd'-'MMM'-'yy HH':'mm':'ss 'GMT'" };
-
- DateTime TryParseCookieExpires (string value)
- {
- if (value == null || value.Length == 0)
- return DateTime.MinValue;
+ bool at_least_one_set = false;
+ var parser = new CookieParser (header);
+ foreach (var cookie in parser.Parse ()) {
+ if (cookie.Domain == "") {
+ cookie.Domain = uri.Host;
+ cookie.HasDomain = false;
+ }
- for (int i = 0; i < cookieExpiresFormats.Length; i++)
- {
- try {
- DateTime cookieExpiresUtc = DateTime.ParseExact (value, cookieExpiresFormats [i], CultureInfo.InvariantCulture);
+ if (cookie.HasDomain &&
+ !CookieContainer.CheckSameOrigin (uri, cookie.Domain))
+ continue;
- //convert UTC/GMT time to local time
-#if NET_2_0
- cookieExpiresUtc = DateTime.SpecifyKind (cookieExpiresUtc, DateTimeKind.Utc);
- return TimeZone.CurrentTimeZone.ToLocalTime (cookieExpiresUtc);
-#else
- //DateTime.Kind is only available on .NET 2.0, so do some calculation
- TimeSpan localOffset = TimeZone.CurrentTimeZone.GetUtcOffset (cookieExpiresUtc.Date);
- return cookieExpiresUtc.Add (localOffset);
-#endif
- } catch {}
+ cookieCollection.Add (cookie);
+ if (cookie_container != null) {
+ cookie_container.Add (uri, cookie);
+ at_least_one_set = true;
+ }
}
- //If we can't parse Expires, use cookie as session cookie (expires is DateTime.MinValue)
- return DateTime.MinValue;
+ return at_least_one_set;
}
}
-
- 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 ();
- }
- }
}