svn path=/branches/mono-1-1-9/mcs/; revision=51207
[mono.git] / mcs / class / System.Web / System.Web / HttpCookie.cs
1 //
2 // System.Web.HttpCookie.cs 
3 //
4 // Author:
5 //      Chris Toshok (toshok@novell.com)
6 //
7
8 //
9 // Copyright (C) 2005 Novell, Inc (http://www.novell.com)
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30
31 using System.Text;
32 using System.Collections.Specialized;
33
34 namespace System.Web {
35
36         [Flags]
37         internal enum CookieFlags : byte {
38                 Secure = 1,
39                 HttpOnly = 2
40         }
41         
42         public sealed class HttpCookie {
43
44                 string path = "/";
45                 string domain;
46                 DateTime expires = DateTime.MinValue;
47                 string name;
48                 CookieFlags flags = 0;
49                 NameValueCollection values;
50
51                 [Obsolete]
52                 internal HttpCookie (string name, string value, string path, DateTime expires)
53                 {
54                         this.name = name;
55                         this.values = new CookieNVC();
56                         this.Value = value;
57                         this.path = path;
58                         this.expires = expires;
59                 }
60
61                 public HttpCookie (string name)
62                 {
63                         this.name = name;
64                         values = new CookieNVC();
65                         Value = "";
66                 }
67
68                 public HttpCookie (string name, string value)
69                   : this (name)
70                 {
71                         Value = value;
72                 }
73
74                 internal BaseResponseHeader GetCookieHeader ()
75                 {
76                         StringBuilder builder = new StringBuilder ("");
77
78                         builder.Append (name);
79                         builder.Append ("=");
80                         builder.Append (Value);
81
82                         if (domain != null) {
83                                 builder.Append ("; domain=");
84                                 builder.Append (domain);
85                         }
86                
87                         if (path != null) {
88                                 builder.Append ("; path=");
89                                 builder.Append (path);
90                         }
91
92                         if (expires != DateTime.MinValue) {
93                                 builder.Append ("; expires=");
94                                 builder.Append (expires.ToUniversalTime().ToString("r"));
95                         }
96
97                         if ((flags & CookieFlags.Secure) != 0) {
98                                 builder.Append ("; secure");
99                         }
100
101                         if ((flags & CookieFlags.HttpOnly) != 0){
102                                 builder.Append ("; HttpOnly");
103                         }
104
105                         return new UnknownResponseHeader ("Set-Cookie", builder.ToString());
106                 }
107
108                 public string Domain {
109                         get {
110                                 return domain;
111                         }
112                         set {
113                                 domain = value;
114                         }
115                 }
116
117                 public DateTime Expires {
118                         get {
119                                 return expires;
120                         }
121                         set {
122                                 expires = value;
123                         }
124                 }
125
126                 public bool HasKeys {
127                         get {
128                                 return values.HasKeys();
129                         }
130                 }
131
132
133                 public string this [ string key ] {
134                         get {
135                                 return values [ key ];
136                         }
137                         set {
138                                 values [ key ] = value;
139                         }
140                 }
141
142                 public string Name {
143                         get {
144                                 return name;
145                         }
146                         set {
147                                 name = value;
148                         }
149                 }
150
151                 public string Path {
152                         get {
153                                 return path;
154                         }
155                         set {
156                                 path = value;
157                         }
158                 }
159
160                 public bool Secure {
161                         get {
162                                 return (flags & CookieFlags.Secure) == CookieFlags.Secure;
163                         }
164                         set {
165                                 flags |= CookieFlags.Secure;
166                         }
167                 }
168
169                 public string Value {
170                         get {
171                                 return values.ToString ();
172                         }
173                         set {
174                                 values.Clear ();
175                                 
176                                 if (value != null && value != "") {
177                                         string [] components = value.Split ('&');
178                                         foreach (string kv in components){
179                                                 int pos = kv.IndexOf ('=');
180                                                 if (pos == -1){
181                                                         values.Add (null, kv);
182                                                 } else {
183                                                         string key = kv.Substring (0, pos);
184                                                         string val = kv.Substring (pos+1);
185                                                         
186                                                         values.Add (key, val);
187                                                 }
188                                         }
189                                 }
190                         }
191                 }
192
193                 public NameValueCollection Values {
194                         get {
195                                 return values;
196                         }
197                 }
198
199 #if NET_2_0
200                 public bool HttpOnly {
201                         get {
202                                 return (flags & CookieFlags.HttpOnly) == CookieFlags.HttpOnly;
203                         }
204
205                         set {
206                                 flags |= CookieFlags.HttpOnly;
207                         }
208                 }
209 #endif
210
211                 /*
212                  * simple utility class that just overrides ToString
213                  * to get the desired behavior for
214                  * HttpCookie.Values
215                  */
216                 class CookieNVC : NameValueCollection
217                 {
218                         public override string ToString ()
219                         {
220                                 StringBuilder builder = new StringBuilder ("");
221
222                                 bool first_key = true;
223                                 foreach (string key in Keys) {
224                                         if (!first_key)
225                                                 builder.Append ("&");
226
227                                         bool first_val = true;
228                                         foreach (string v in GetValues (key)) {
229                                                 if (!first_val)
230                                                         builder.Append ("&");
231
232                                                 if (key != null) {
233                                                         builder.Append (key);
234                                                         builder.Append ("=");
235                                                 }
236                                                 builder.Append (v);
237                                                 first_val = false;
238                                         }
239                                         first_key = false;
240                                 }
241
242                                 return builder.ToString();
243                         }
244
245                         /* MS's implementation has the interesting quirk that if you do:
246                          * cookie.Values[null] = "foo"
247                          * it clears out the rest of the values.
248                          */
249                         public override void Set (string name, string value)
250                         {
251                                 if (this.IsReadOnly)
252                                         throw new NotSupportedException ("Collection is read-only");
253
254                                 if (name == null)
255                                         Clear();
256
257                                 base.Set (name, value);
258                         }
259                 }
260         }
261
262 }