2 // System.Web.HttpCookie.cs
5 // Chris Toshok (toshok@novell.com)
6 // Katharina Bogad (bogad@cs.tum.edu)
10 // Copyright (C) 2005-2009 Novell, Inc (http://www.novell.com)
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 using System
.Collections
.Specialized
;
34 using System
.Security
.Permissions
;
35 using System
.Web
.Configuration
;
40 internal enum CookieFlags
: byte {
45 // CAS - no InheritanceDemand here as the class is sealed
46 [AspNetHostingPermission (SecurityAction
.LinkDemand
, Level
= AspNetHostingPermissionLevel
.Minimal
)]
47 public sealed class HttpCookie
{
51 DateTime expires
= DateTime
.MinValue
;
53 CookieFlags flags
= 0;
54 NameValueCollection values
;
57 internal HttpCookie (string name
, string value, string path
, DateTime expires
)
60 this.values
= new CookieNVC();
63 this.expires
= expires
;
66 public HttpCookie (string name
)
69 values
= new CookieNVC();
72 HttpCookiesSection cookieConfig
= (HttpCookiesSection
) WebConfigurationManager
.GetSection ("system.web/httpCookies");
74 if(!string.IsNullOrWhiteSpace(cookieConfig
.Domain
))
75 domain
= cookieConfig
.Domain
;
77 if(cookieConfig
.HttpOnlyCookies
)
78 flags
|= CookieFlags
.HttpOnly
;
80 if(cookieConfig
.RequireSSL
)
81 flags
|= CookieFlags
.Secure
;
84 public HttpCookie (string name
, string value)
90 internal string GetCookieHeaderValue ()
92 StringBuilder builder
= new StringBuilder ();
94 builder
.Append (name
);
96 builder
.Append (Value
);
99 builder
.Append ("; domain=");
100 builder
.Append (domain
);
104 builder
.Append ("; path=");
105 builder
.Append (path
);
108 if (expires
!= DateTime
.MinValue
) {
109 builder
.Append ("; expires=");
110 builder
.Append (expires
.ToUniversalTime().ToString("r"));
113 if ((flags
& CookieFlags
.Secure
) != 0) {
114 builder
.Append ("; secure");
117 if ((flags
& CookieFlags
.HttpOnly
) != 0){
118 builder
.Append ("; HttpOnly");
121 return builder
.ToString ();
124 public string Domain
{
133 public DateTime Expires
{
142 public bool HasKeys
{
144 return values
.HasKeys();
149 public string this [ string key
] {
151 return values
[ key
];
154 values
[ key
] = value;
178 return (flags
& CookieFlags
.Secure
) == CookieFlags
.Secure
;
182 flags
|= CookieFlags
.Secure
;
184 flags
&= ~CookieFlags
.Secure
;
188 public string Value
{
190 return HttpUtility
.UrlDecode(values
.ToString ());
195 if (value != null && value != "") {
196 string [] components
= value.Split ('&');
197 foreach (string kv
in components
){
198 int pos
= kv
.IndexOf ('=');
200 values
.Add (null, kv
);
202 string key
= kv
.Substring (0, pos
);
203 string val
= kv
.Substring (pos
+1);
205 values
.Add (key
, val
);
212 public NameValueCollection Values
{
218 public bool HttpOnly
{
220 return (flags
& CookieFlags
.HttpOnly
) == CookieFlags
.HttpOnly
;
225 flags
|= CookieFlags
.HttpOnly
;
227 flags
&= ~CookieFlags
.HttpOnly
;
232 * simple utility class that just overrides ToString
233 * to get the desired behavior for
237 sealed class CookieNVC
: NameValueCollection
240 : base (StringComparer
.OrdinalIgnoreCase
)
244 public override string ToString ()
246 StringBuilder builder
= new StringBuilder ("");
248 bool first_key
= true;
249 foreach (string key
in Keys
) {
251 builder
.Append ("&");
253 string[] vals
= GetValues (key
);
255 vals
= new string[1] {String.Empty}
;
257 bool first_val
= true;
258 foreach (string v
in vals
) {
260 builder
.Append ("&");
262 if (key
!= null && key
.Length
> 0) {
263 builder
.Append (HttpUtility
.UrlEncode(key
));
264 builder
.Append ("=");
266 if(v
!= null && v
.Length
> 0)
267 builder
.Append (HttpUtility
.UrlEncode(v
));
274 return builder
.ToString();
277 /* MS's implementation has the interesting quirk that if you do:
278 * cookie.Values[null] = "foo"
279 * it clears out the rest of the values.
281 public override void Set (string name
, string value)
284 throw new NotSupportedException ("Collection is read-only");
290 // if (value == null)
291 // value = string.Empty;
293 base.Set (name
, value);