-//\r
-// System.Net.Cookie.cs\r
-//\r
-// Author:\r
-// Lawrence Pit (loz@cable.a2000.nl)\r
-//\r
-\r
-using System;\r
-using System.Text;\r
-\r
-namespace System.Net {\r
-\r
- // Supported cookie formats are:\r
- // Netscape: http://home.netscape.com/newsref/std/cookie_spec.html\r
- // RFC 2109: http://www.ietf.org/rfc/rfc2109.txt\r
- // RFC 2965: http://www.ietf.org/rfc/rfc2965.txt\r
- [Serializable]\r
- public sealed class Cookie \r
- {\r
- private string comment;\r
- private Uri commentUri;\r
- private bool discard;\r
- private string domain;\r
- private bool expired;\r
- private DateTime expires;\r
- private string name;\r
- private string path;\r
- private string port;\r
- private int [] ports;\r
- private bool secure;\r
- private DateTime timestamp;\r
- private string val;\r
- private int version;\r
- \r
- private static char [] reservedCharsName = new char [] {' ', '=', ';', ',', '\n', '\r', '\t'};\r
- private static char [] reservedCharsValue = new char [] {';', ','};\r
- private static char [] portSeparators = new char [] {'"', ','};\r
- private static string tspecials = "()<>@,;:\\\"/[]?={} \t"; // from RFC 2965, 2068\r
- \r
- public Cookie () \r
- : this (String.Empty, String.Empty) {}\r
- \r
- public Cookie (string name, string value) \r
- {\r
- Name = name;\r
- Value = value;\r
- \r
- discard = false;\r
- expired = false;\r
- secure = false;\r
- expires = DateTime.MinValue;\r
- timestamp = DateTime.Now;\r
- version = 0; \r
- domain = "";\r
- } \r
- \r
- public Cookie (string name, string value, string path) \r
- : this (name, value) \r
- {\r
- Path = path;\r
- }\r
- \r
- public Cookie (string name, string value, string path, string domain)\r
- : this (name, value, path)\r
- {\r
- Domain = domain;\r
- }\r
- \r
- public string Comment {\r
- get { return comment; }\r
- set { comment = value == null ? String.Empty : value; }\r
- }\r
- \r
- public Uri CommentUri {\r
- get { return commentUri; }\r
- set { commentUri = value; }\r
- }\r
-\r
- public bool Discard {\r
- get { return discard; }\r
- set { discard = value; }\r
- }\r
- \r
- public string Domain {\r
- get { return domain; }\r
- set { domain = value == null ? String.Empty : value; }\r
- }\r
-\r
- public bool Expired {\r
- get { \r
- return expires <= DateTime.Now && \r
- expires != DateTime.MinValue;\r
- }\r
- set { \r
- expired = value; \r
- if (expired) {\r
- expires = DateTime.Now;\r
- }\r
- }\r
- }\r
-\r
- public DateTime Expires {\r
- get { return expires; }\r
- set { expires = value; }\r
- }\r
-\r
- public string Name {\r
- get { return name; }\r
- set { \r
- if (value == null || value.Length == 0) {\r
- throw new CookieException ("Name cannot be empty");\r
- } \r
- \r
- if (value [0] == '$' || value.IndexOfAny (reservedCharsName) != -1) {\r
- // see CookieTest, according to MS implementation\r
- // the name value changes even though it's incorrect\r
- name = String.Empty;\r
- throw new CookieException ("Name contains invalid characters");\r
- }\r
- \r
- name = value; \r
- }\r
- }\r
-\r
- public string Path {\r
- get { return (path == null) ? "/" : path; }\r
- set { path = (value == null) ? String.Empty : value; }\r
- }\r
-\r
- public string Port {\r
- get { return port; }\r
- set { \r
- if (value == null || value.Length == 0) {\r
- port = String.Empty;\r
- return;\r
- }\r
- if (value [0] != '"' || value [value.Length - 1] != '"') {\r
- throw new CookieException("The 'Port'='" + value + "' part of the cookie is invalid. Port must be enclosed by double quotes.");\r
- }\r
- port = value; \r
- string [] values = port.Split (portSeparators);\r
- ports = new int[values.Length];\r
- for (int i = 0; i < ports.Length; i++) {\r
- ports [i] = Int32.MinValue;\r
- if (values [i].Length == 0)\r
- continue;\r
- try { \r
- ports [i] = Int32.Parse (values [i]);\r
- } catch (Exception e) {\r
- throw new CookieException("The 'Port'='" + value + "' part of the cookie is invalid. Invalid value: " + values [i], e);\r
- }\r
- }\r
- }\r
- }\r
- \r
- int[] Ports {\r
- get { return ports; }\r
- }\r
-\r
- public bool Secure {\r
- get { return secure; }\r
- set { secure = value; }\r
- }\r
-\r
- public DateTime TimeStamp {\r
- get { return timestamp; }\r
- }\r
-\r
- public string Value {\r
- get { return val; }\r
- set { \r
- if (value == null) {\r
- val = String.Empty;\r
- return;\r
- }\r
- \r
- // LAMESPEC: According to .Net specs the Value property should not accept \r
- // the semicolon and comma characters, yet it does. For now we'll follow\r
- // the behaviour of MS.Net instead of the specs.\r
- /*\r
- if (value.IndexOfAny(reservedCharsValue) != -1)\r
- throw new CookieException("Invalid value. Value cannot contain semicolon or comma characters.");\r
- */\r
- \r
- val = value; \r
- }\r
- }\r
- \r
- public int Version {\r
- get { return version; }\r
- set { \r
- if ((value < 0) || (value > 10)) \r
- version = 0;\r
- else \r
- version = value; \r
- }\r
- }\r
- \r
- public override bool Equals (Object obj) \r
- {\r
- System.Net.Cookie c = obj as System.Net.Cookie; \r
- \r
- return c != null &&\r
- String.Compare (this.name, c.name, true) == 0 &&\r
- String.Compare (this.val, c.val, false) == 0 &&\r
- String.Compare (this.path, c.path, false) == 0 &&\r
- String.Compare (this.domain, c.domain, true) == 0 &&\r
- this.version == c.version;\r
- }\r
- \r
- public override int GetHashCode ()\r
- {\r
- return hash(name.ToLower ().GetHashCode (),\r
- val.GetHashCode (),\r
- path.GetHashCode (),\r
- domain.ToLower ().GetHashCode (),\r
- version);\r
- }\r
- \r
- private static int hash (int i, int j, int k, int l, int m) \r
- {\r
- return i ^ (j << 13 | j >> 19) ^ (k << 26 | k >> 6) ^ (l << 7 | l >> 25) ^ (m << 20 | m >> 12);\r
- }\r
- \r
- // returns a string that can be used to send a cookie to an Origin Server\r
- // i.e., only used for clients\r
- // see also para 3.3.4 of RFC 1965\r
- public override string ToString () \r
- {\r
- if (name.Length == 0) \r
- return String.Empty;\r
-\r
- StringBuilder result = new StringBuilder (64);\r
- \r
- if (version > 0) {\r
- result.Append ("$Version=").Append (version).Append (";");\r
- } \r
- \r
- result.Append (name).Append ("=").Append (val);\r
-\r
- // in the MS.Net implementation path and domain don't show up in\r
- // the result, I guess that's a bug in their implementation...\r
- if (path != null && path.Length != 0)\r
- result.Append (";$Path=").Append (QuotedString (path));\r
- \r
- if (domain != null && domain.Length != 0)\r
- result.Append (";$Domain=").Append (QuotedString (domain)); \r
- \r
- if (port != null && port.Length != 0)\r
- result.Append (";$Port=").Append (port); \r
- \r
- return result.ToString ();\r
- }\r
- \r
- // See par 3.6 of RFC 2616\r
- private string QuotedString (string value)\r
- {\r
- if (version == 0 || IsToken (value))\r
- return value;\r
- else \r
- return "\"" + value.Replace("\"", "\\\"") + "\"";\r
- } \r
-\r
- private bool IsToken (string value) \r
- {\r
- int len = value.Length;\r
- for (int i = 0; i < len; i++) {\r
- char c = value [i];\r
- if (c < 0x20 || c >= 0x7f || tspecials.IndexOf (c) != -1)\r
- return false;\r
- }\r
- return true;\r
- } \r
-\r
- }\r
-}\r
-\r
+//
+// System.Net.Cookie.cs
+//
+// Authors:
+// Lawrence Pit (loz@cable.a2000.nl)
+// Gonzalo Paniagua Javier (gonzalo@ximian.com)
+//
+// (c) Copyright 2004 Novell, Inc. (http://www.ximian.com)
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Text;
+using System.Globalization;
+
+namespace System.Net {
+
+ // Supported cookie formats are:
+ // Netscape: http://home.netscape.com/newsref/std/cookie_spec.html
+ // RFC 2109: http://www.ietf.org/rfc/rfc2109.txt
+ // RFC 2965: http://www.ietf.org/rfc/rfc2965.txt
+ [Serializable]
+ public sealed class Cookie
+ {
+ string comment;
+ Uri commentUri;
+ bool discard;
+ string domain;
+ bool expired;
+ DateTime expires;
+ string name;
+ string path;
+ string port;
+ int [] ports;
+ bool secure;
+ DateTime timestamp;
+ string val;
+ int version;
+
+ static char [] reservedCharsName = new char [] {' ', '=', ';', ',', '\n', '\r', '\t'};
+ static char [] portSeparators = new char [] {'"', ','};
+ static string tspecials = "()<>@,;:\\\"/[]?={} \t"; // from RFC 2965, 2068
+
+ public Cookie ()
+ {
+ expires = DateTime.MinValue;
+ timestamp = DateTime.Now;
+ domain = "";
+ name = "";
+ val = "";
+ comment = "";
+ domain = "";
+ port = "";
+ }
+
+ public Cookie (string name, string value)
+ : this ()
+ {
+ Name = name;
+ Value = value;
+ }
+
+ public Cookie (string name, string value, string path)
+ : this (name, value)
+ {
+ Path = path;
+ }
+
+ public Cookie (string name, string value, string path, string domain)
+ : this (name, value, path)
+ {
+ Domain = domain;
+ }
+
+ public string Comment {
+ get { return comment; }
+ set { comment = value == null ? String.Empty : value; }
+ }
+
+ public Uri CommentUri {
+ get { return commentUri; }
+ set { commentUri = value; }
+ }
+
+ public bool Discard {
+ get { return discard; }
+ set { discard = value; }
+ }
+
+ public string Domain {
+ get { return domain; }
+ set { domain = value == null ? String.Empty : value; }
+ }
+
+ public bool Expired {
+ get {
+ return expires <= DateTime.Now &&
+ expires != DateTime.MinValue;
+ }
+ set {
+ expired = value;
+ if (expired) {
+ expires = DateTime.Now;
+ }
+ }
+ }
+
+ public DateTime Expires {
+ get { return expires; }
+ set { expires = value; }
+ }
+
+ public string Name {
+ get { return name; }
+ set {
+ if (value == null || value.Length == 0) {
+ throw new CookieException ("Name cannot be empty");
+ }
+
+ if (value [0] == '$' || value.IndexOfAny (reservedCharsName) != -1) {
+ // see CookieTest, according to MS implementation
+ // the name value changes even though it's incorrect
+ name = String.Empty;
+ throw new CookieException ("Name contains invalid characters");
+ }
+
+ name = value;
+ }
+ }
+
+ public string Path {
+ get { return (path == null || path == "") ? "/" : path; }
+ set { path = (value == null) ? String.Empty : value; }
+ }
+
+ public string Port {
+ get { return port; }
+ set {
+ if (value == null || value.Length == 0) {
+ port = String.Empty;
+ return;
+ }
+ if (value [0] != '"' || value [value.Length - 1] != '"') {
+ throw new CookieException("The 'Port'='" + value + "' part of the cookie is invalid. Port must be enclosed by double quotes.");
+ }
+ port = value;
+ string [] values = port.Split (portSeparators);
+ ports = new int[values.Length];
+ for (int i = 0; i < ports.Length; i++) {
+ ports [i] = Int32.MinValue;
+ if (values [i].Length == 0)
+ continue;
+ try {
+ ports [i] = Int32.Parse (values [i]);
+ } catch (Exception e) {
+ throw new CookieException("The 'Port'='" + value + "' part of the cookie is invalid. Invalid value: " + values [i], e);
+ }
+ }
+ }
+ }
+
+ internal int [] Ports {
+ get { return ports; }
+ }
+
+ public bool Secure {
+ get { return secure; }
+ set { secure = value; }
+ }
+
+ public DateTime TimeStamp {
+ get { return timestamp; }
+ }
+
+ public string Value {
+ get { return val; }
+ set {
+ if (value == null) {
+ val = String.Empty;
+ return;
+ }
+
+ // LAMESPEC: According to .Net specs the Value property should not accept
+ // the semicolon and comma characters, yet it does. For now we'll follow
+ // the behaviour of MS.Net instead of the specs.
+ /*
+ if (value.IndexOfAny(reservedCharsValue) != -1)
+ throw new CookieException("Invalid value. Value cannot contain semicolon or comma characters.");
+ */
+
+ val = value;
+ }
+ }
+
+ public int Version {
+ get { return version; }
+ set {
+ if ((value < 0) || (value > 10))
+ version = 0;
+ else
+ version = value;
+ }
+ }
+
+ public override bool Equals (Object obj)
+ {
+ System.Net.Cookie c = obj as System.Net.Cookie;
+
+ return c != null &&
+ String.Compare (this.name, c.name, true, CultureInfo.InvariantCulture) == 0 &&
+ String.Compare (this.val, c.val, false, CultureInfo.InvariantCulture) == 0 &&
+ String.Compare (this.path, c.path, false, CultureInfo.InvariantCulture) == 0 &&
+ String.Compare (this.domain, c.domain, true, CultureInfo.InvariantCulture) == 0 &&
+ this.version == c.version;
+ }
+
+ public override int GetHashCode ()
+ {
+ return hash(name.ToLower ().GetHashCode (),
+ val.GetHashCode (),
+ path.GetHashCode (),
+ domain.ToLower ().GetHashCode (),
+ version);
+ }
+
+ private static int hash (int i, int j, int k, int l, int m)
+ {
+ return i ^ (j << 13 | j >> 19) ^ (k << 26 | k >> 6) ^ (l << 7 | l >> 25) ^ (m << 20 | m >> 12);
+ }
+
+ // returns a string that can be used to send a cookie to an Origin Server
+ // i.e., only used for clients
+ // see also para 3.3.4 of RFC 1965
+ public override string ToString ()
+ {
+ if (name.Length == 0)
+ return String.Empty;
+
+ StringBuilder result = new StringBuilder (64);
+
+ if (version > 0) {
+ result.Append ("$Version=").Append (version).Append (";");
+ }
+
+ result.Append (name).Append ("=").Append (val);
+
+ // in the MS.Net implementation path and domain don't show up in
+ // the result, I guess that's a bug in their implementation...
+ if (path != null && path.Length != 0)
+ result.Append (";$Path=").Append (QuotedString (path));
+
+ if (domain != null && domain.Length != 0)
+ result.Append (";$Domain=").Append (QuotedString (domain));
+
+ if (port != null && port.Length != 0)
+ result.Append (";$Port=").Append (port);
+
+ return result.ToString ();
+ }
+
+ // See par 3.6 of RFC 2616
+ string QuotedString (string value)
+ {
+ if (version == 0 || IsToken (value))
+ return value;
+ else
+ return "\"" + value.Replace("\"", "\\\"") + "\"";
+ }
+
+ bool IsToken (string value)
+ {
+ int len = value.Length;
+ for (int i = 0; i < len; i++) {
+ char c = value [i];
+ if (c < 0x20 || c >= 0x7f || tspecials.IndexOf (c) != -1)
+ return false;
+ }
+ return true;
+ }
+ }
+}
+