svn path=/branches/mono-1-1-9/mcs/; revision=51206
[mono.git] / mcs / class / System / System.Net / Cookie.cs
index 125827e6375c63adc92e94a641c8f9d8daeac5d3..dcc56400a75b9ae4057a554af34c40006557b964 100644 (file)
-//\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;
+               }           
+       }
+}
+