-//
-// System.Web.HttpCookie
+//
+// System.Web.HttpCookie.cs
//
// Author:
-// Patrik Torstensson (Patrik.Torstensson@labs2.com)
+// Chris Toshok (toshok@novell.com)
//
+//
+// Copyright (C) 2005-2009 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// 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.Globalization;
+
using System.Text;
-using System.Web;
using System.Collections.Specialized;
+using System.Security.Permissions;
namespace System.Web
{
- public sealed class HttpCookie
- {
- string _Name;
- string _Value;
- string _Domain;
- DateTime _Expires;
- bool _ExpiresSet;
- string _Path;
- bool _Secure = false;
-
- HttpValueCollection _Values;
-
- internal HttpCookie ()
+ [Flags]
+ internal enum CookieFlags : byte {
+ Secure = 1,
+ HttpOnly = 2
+ }
+
+ // CAS - no InheritanceDemand here as the class is sealed
+ [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
+ public sealed class HttpCookie {
+
+ string path = "/";
+ string domain;
+ DateTime expires = DateTime.MinValue;
+ string name;
+ CookieFlags flags = 0;
+ NameValueCollection values;
+
+ [Obsolete]
+ internal HttpCookie (string name, string value, string path, DateTime expires)
{
- _Path = "/";
+ this.name = name;
+ this.values = new CookieNVC();
+ this.Value = value;
+ this.path = path;
+ this.expires = expires;
}
public HttpCookie (string name)
{
- _Path = "/";
- _Name = name;
+ this.name = name;
+ values = new CookieNVC();
+ Value = "";
}
public HttpCookie (string name, string value)
+ : this (name)
{
- _Name = name;
- _Value = value;
- _Path = "/";
+ Value = value;
}
- internal HttpCookie (string name, string value, string path, DateTime expires)
+ internal string GetCookieHeaderValue ()
{
- _Name = name;
- _Value = value;
- _Path = path;
- if (expires != DateTime.MinValue)
- Expires = expires;
- }
-
- internal HttpResponseHeader GetCookieHeader ()
- {
- StringBuilder oSetCookie = new StringBuilder ();
+ StringBuilder builder = new StringBuilder ();
- if (null != _Name && _Name.Length > 0) {
- oSetCookie.Append (_Name);
- oSetCookie.Append ("=");
- }
+ builder.Append (name);
+ builder.Append ("=");
+ builder.Append (Value);
- if (null != _Values) {
- oSetCookie.Append (_Values.ToString (false));
- } else if (null != _Value) {
- oSetCookie.Append (_Value);
+ if (domain != null) {
+ builder.Append ("; domain=");
+ builder.Append (domain);
}
-
- if (null != _Domain && _Domain.Length > 0) {
- oSetCookie.Append ("; domain=");
- oSetCookie.Append (_Domain);
+
+ if (path != null) {
+ builder.Append ("; path=");
+ builder.Append (path);
}
- if (null != _Path && Path.Length > 0) {
- oSetCookie.Append ("; path=");
- oSetCookie.Append (_Path);
+ if (expires != DateTime.MinValue) {
+ builder.Append ("; expires=");
+ builder.Append (expires.ToUniversalTime().ToString("r"));
}
- if (_ExpiresSet && _Expires != DateTime.MinValue) {
- oSetCookie.Append ("; expires=");
- DateTime ut = _Expires.ToUniversalTime ();
- oSetCookie.Append (ut.ToString ("ddd, dd-MMM-yyyy HH':'mm':'ss 'GMT'",
- DateTimeFormatInfo.InvariantInfo));
+ if ((flags & CookieFlags.Secure) != 0) {
+ builder.Append ("; secure");
}
- if (_Secure)
- oSetCookie.Append ("; secure");
+ if ((flags & CookieFlags.HttpOnly) != 0){
+ builder.Append ("; HttpOnly");
+ }
- return new HttpResponseHeader (HttpWorkerRequest.HeaderSetCookie, oSetCookie.ToString());
+ return builder.ToString ();
}
- public string Domain
- {
- get { return _Domain; }
- set { _Domain = value; }
+ public string Domain {
+ get {
+ return domain;
+ }
+ set {
+ domain = value;
+ }
}
- public DateTime Expires
- {
+ public DateTime Expires {
get {
- if (!_ExpiresSet)
- return DateTime.MinValue;
+ return expires;
+ }
+ set {
+ expires = value;
+ }
+ }
- return _Expires;
+ public bool HasKeys {
+ get {
+ return values.HasKeys();
}
+ }
+
+ public string this [ string key ] {
+ get {
+ return values [ key ];
+ }
set {
- _ExpiresSet = true;
- _Expires = value;
+ values [ key ] = value;
}
}
- public bool HasKeys
- {
+ public string Name {
get {
- return Values.HasKeys ();
+ return name;
+ }
+ set {
+ name = value;
}
}
- public string this [string key]
- {
- get { return Values [key]; }
- set { Values [key] = value; }
+ public string Path {
+ get {
+ return path;
+ }
+ set {
+ path = value;
+ }
}
- public string Name
- {
- get { return _Name; }
- set { _Name = value; }
+ public bool Secure {
+ get {
+ return (flags & CookieFlags.Secure) == CookieFlags.Secure;
+ }
+ set {
+ if (value)
+ flags |= CookieFlags.Secure;
+ else
+ flags &= ~CookieFlags.Secure;
+ }
}
- public string Path
- {
- get { return _Path; }
- set { _Path = value; }
+ public string Value {
+ get {
+ return HttpUtility.UrlDecode(values.ToString ());
+ }
+ set {
+ values.Clear ();
+
+ if (value != null && value != "") {
+ string [] components = value.Split ('&');
+ foreach (string kv in components){
+ int pos = kv.IndexOf ('=');
+ if (pos == -1){
+ values.Add (null, kv);
+ } else {
+ string key = kv.Substring (0, pos);
+ string val = kv.Substring (pos+1);
+
+ values.Add (key, val);
+ }
+ }
+ }
+ }
}
- public bool Secure
- {
- get { return _Secure; }
- set { _Secure = value; }
+ public NameValueCollection Values {
+ get {
+ return values;
+ }
}
- public string Value
- {
+ public bool HttpOnly {
get {
- if (null != _Values)
- return _Values.ToString (false);
-
- return _Value;
+ return (flags & CookieFlags.HttpOnly) == CookieFlags.HttpOnly;
}
set {
- if (null != _Values) {
- _Values.Reset ();
- _Values.Add (null, value);
- return;
- }
-
- _Value = value;
+ if (value)
+ flags |= CookieFlags.HttpOnly;
+ else
+ flags &= ~CookieFlags.HttpOnly;
}
}
- public NameValueCollection Values
+ /*
+ * simple utility class that just overrides ToString
+ * to get the desired behavior for
+ * HttpCookie.Values
+ */
+ [Serializable]
+ sealed class CookieNVC : NameValueCollection
{
- get {
- if (null == _Values) {
- _Values = new HttpValueCollection ();
- if (null != _Value) {
- // Do we have multiple keys
- if (_Value.IndexOf ("&") >= 0 || _Value.IndexOf ("=") >= 0) {
- _Values.FillFromCookieString (_Value);
- } else {
- _Values.Add (null, _Value);
- }
+ public CookieNVC ()
+ : base (StringComparer.OrdinalIgnoreCase)
+ {
+ }
+
+ public override string ToString ()
+ {
+ StringBuilder builder = new StringBuilder ("");
- _Value = null;
+ bool first_key = true;
+ foreach (string key in Keys) {
+ if (!first_key)
+ builder.Append ("&");
+
+ string[] vals = GetValues (key);
+ if(vals == null)
+ vals = new string[1] {String.Empty};
+
+ bool first_val = true;
+ foreach (string v in vals) {
+ if (!first_val)
+ builder.Append ("&");
+
+ if (key != null && key.Length > 0) {
+ builder.Append (HttpUtility.UrlEncode(key));
+ builder.Append ("=");
+ }
+ if(v != null && v.Length > 0)
+ builder.Append (HttpUtility.UrlEncode(v));
+
+ first_val = false;
}
+ first_key = false;
+ }
+
+ return builder.ToString();
+ }
+
+ /* MS's implementation has the interesting quirk that if you do:
+ * cookie.Values[null] = "foo"
+ * it clears out the rest of the values.
+ */
+ public override void Set (string name, string value)
+ {
+ if (this.IsReadOnly)
+ throw new NotSupportedException ("Collection is read-only");
+
+ if (name == null) {
+ Clear();
+ name = string.Empty;
}
+// if (value == null)
+// value = string.Empty;
- return _Values;
+ base.Set (name, value);
}
}
}
}
-