//
// System.Web.HttpCookie.cs
//
// Author:
// 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
// "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.Text;
using System.Collections.Specialized;
using System.Security.Permissions;
namespace System.Web{
[Flags]
internal enum CookieFlags : byte {
Secure = 1,
HttpOnly = 2
}
// CAS - no InheritanceDemand here as the class is sealed
[AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
#if TARGET_J2EE
// Cookies must be serializable to be saved in the session for J2EE portal
[Serializable]
#endif
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)
{
this.name = name;
this.values = new CookieNVC();
this.Value = value;
this.path = path;
this.expires = expires;
}
public HttpCookie (string name)
{
this.name = name;
values = new CookieNVC();
Value = "";
}
public HttpCookie (string name, string value)
: this (name)
{
Value = value;
}
internal string GetCookieHeaderValue ()
{
StringBuilder builder = new StringBuilder ();
builder.Append (name);
builder.Append ("=");
builder.Append (Value);
if (domain != null) {
builder.Append ("; domain=");
builder.Append (domain);
}
if (path != null) {
builder.Append ("; path=");
builder.Append (path);
}
if (expires != DateTime.MinValue) {
builder.Append ("; expires=");
builder.Append (expires.ToUniversalTime().ToString("r"));
}
if ((flags & CookieFlags.Secure) != 0) {
builder.Append ("; secure");
}
if ((flags & CookieFlags.HttpOnly) != 0){
builder.Append ("; HttpOnly");
}
return builder.ToString ();
}
public string Domain {
get {
return domain;
}
set {
domain = value;
}
}
public DateTime Expires {
get {
return expires;
}
set {
expires = value;
}
}
public bool HasKeys {
get {
return values.HasKeys();
}
}
public string this [ string key ] {
get {
return values [ key ];
}
set {
values [ key ] = value;
}
}
public string Name {
get {
return name;
}
set {
name = value;
}
}
public string Path {
get {
return path;
}
set {
path = value;
}
}
public bool Secure {
get {
return (flags & CookieFlags.Secure) == CookieFlags.Secure;
}
set {
if (value)
flags |= CookieFlags.Secure;
else
flags &= ~CookieFlags.Secure;
}
}
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 NameValueCollection Values {
get {
return values;
}
}
public bool HttpOnly {
get {
return (flags & CookieFlags.HttpOnly) == CookieFlags.HttpOnly;
}
set {
if (value)
flags |= CookieFlags.HttpOnly;
else
flags &= ~CookieFlags.HttpOnly;
}
}
/*
* simple utility class that just overrides ToString
* to get the desired behavior for
* HttpCookie.Values
*/
[Serializable]
sealed class CookieNVC : NameValueCollection
{
public CookieNVC ()
: base (StringComparer.OrdinalIgnoreCase)
{
}
public override string ToString ()
{
StringBuilder builder = new StringBuilder ("");
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;
base.Set (name, value);
}
}
}
}
|