**** Merged from MCS ****
[mono-project.git] / mcs / class / System / System.Net / CookieContainer.cs
blob70267856a55abbe0377b8cc83891e3764931fd7f
1 //
2 // System.Net.CookieContainer
3 //
4 // Authors:
5 // Lawrence Pit (loz@cable.a2000.nl)
6 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 //
8 // (c) 2003 Ximian, Inc. (http://www.ximian.com)
9 //
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:
19 //
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 //
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.
32 using System;
33 using System.Collections;
34 using System.Runtime.Serialization;
35 using System.Text;
37 namespace System.Net
39 [Serializable]
40 public class CookieContainer
42 public const int DefaultCookieLengthLimit = 4096;
43 public const int DefaultCookieLimit = 300;
44 public const int DefaultPerDomainCookieLimit = 20;
46 int count;
47 int capacity = DefaultCookieLimit;
48 int perDomainCapacity = DefaultPerDomainCookieLimit;
49 int maxCookieSize = DefaultCookieLengthLimit;
50 CookieCollection cookies;
52 // ctors
53 public CookieContainer ()
57 public CookieContainer (int capacity)
59 if (capacity <= 0)
60 throw new ArgumentException ("Must be greater than zero", "capacity");
62 this.capacity = capacity;
65 public CookieContainer (int capacity, int perDomainCapacity, int maxCookieSize)
66 : this (capacity)
68 if (perDomainCapacity <= 0 || perDomainCapacity < capacity)
69 throw new ArgumentException ("Invalid value", "perDomaniCapacity");
71 if (maxCookieSize <= 0)
72 throw new ArgumentException ("Must be greater than zero", "maxCookieSize");
74 this.perDomainCapacity = perDomainCapacity;
75 this.maxCookieSize = maxCookieSize;
78 // properties
80 public int Count {
81 get { return count; }
84 public int Capacity {
85 get { return capacity; }
86 set {
87 if ((value <= 0) ||
88 (value < perDomainCapacity && perDomainCapacity != Int32.MaxValue))
89 throw new ArgumentOutOfRangeException ("value");
90 if (value < maxCookieSize)
91 maxCookieSize = value;
92 capacity = value;
96 public int MaxCookieSize {
97 get { return maxCookieSize; }
98 set {
99 if (value <= 0)
100 throw new ArgumentOutOfRangeException ("value");
101 maxCookieSize = value;
105 public int PerDomainCapacity {
106 get { return perDomainCapacity; }
107 set {
108 if ((value <= 0) ||
109 (value > DefaultCookieLimit && value != Int32.MaxValue))
110 throw new ArgumentOutOfRangeException ("value");
111 if (value < perDomainCapacity)
112 perDomainCapacity = value;
113 perDomainCapacity = value;
117 public void Add (Cookie cookie)
119 if (cookie == null)
120 throw new ArgumentNullException ("cookie");
122 if (cookie.Domain == null && cookie.Domain == "")
123 throw new ArgumentException ("Cookie domain not set.", "cookie");
125 if (cookie.Value.ToString ().Length > maxCookieSize)
126 throw new CookieException ("Cookie size too big");
128 AddCookie (cookie);
131 void AddCookie (Cookie cookie)
133 lock (this) {
134 if (cookies == null)
135 cookies = new CookieCollection ();
137 if (count + 1 > capacity)
138 throw new CookieException ("Capacity exceeded");
140 cookies.Add (cookie);
141 count++;
145 public void Add (CookieCollection cookies)
147 if (cookies == null)
148 throw new ArgumentNullException ("cookies");
150 foreach (Cookie cookie in cookies)
151 Add (cookie);
154 [MonoTODO ("Uri")]
155 public void Add (Uri uri, Cookie cookie)
157 if (uri == null)
158 throw new ArgumentNullException ("uri");
160 Add (cookie);
163 [MonoTODO("Uri")]
164 public void Add (Uri uri, CookieCollection cookies)
166 if (uri == null)
167 throw new ArgumentNullException ("uri");
169 Add (cookies);
172 [MonoTODO("Uri")]
173 public string GetCookieHeader (Uri uri)
175 if (uri == null)
176 throw new ArgumentNullException ("uri");
178 if (cookies == null)
179 return "";
181 StringBuilder result = new StringBuilder ();
182 bool notfirst = false;
183 foreach (Cookie cookie in cookies) {
184 if (notfirst)
185 result.Append (';');
187 result.Append (cookie.ToString ());
188 notfirst = true;
190 return result.ToString ();
193 [MonoTODO("Uri")]
194 public CookieCollection GetCookies (Uri uri)
196 if (uri == null)
197 throw new ArgumentNullException ("uri");
199 CookieCollection coll = new CookieCollection ();
200 if (cookies == null)
201 return coll;
203 foreach (Cookie cookie in cookies)
204 coll.Add (cookie);
206 return coll;
209 public void SetCookies (Uri uri, string cookieHeader)
211 if (uri == null)
212 throw new ArgumentNullException ("uri");
214 if (cookieHeader == null)
215 throw new ArgumentNullException ("cookieHeader");
217 ParseAndAddCookies (cookieHeader);
220 // GetCookieValue, GetCookieName and ParseAndAddCookies copied from HttpRequest.cs
221 static string GetCookieValue (string str, int length, ref int i)
223 if (i >= length)
224 return null;
226 int k = i;
227 while (k < length && Char.IsWhiteSpace (str [k]))
228 k++;
230 int begin = k;
231 while (k < length && str [k] != ';')
232 k++;
234 i = k;
235 return str.Substring (begin, i - begin).Trim ();
238 static string GetCookieName (string str, int length, ref int i)
240 if (i >= length)
241 return null;
243 int k = i;
244 while (k < length && Char.IsWhiteSpace (str [k]))
245 k++;
247 int begin = k;
248 while (k < length && str [k] != ';' && str [k] != '=')
249 k++;
251 i = k + 1;
252 return str.Substring (begin, k - begin).Trim ();
256 void ParseAndAddCookies (string header)
258 if (header.Length == 0)
259 return;
261 /* RFC 2109
262 * cookie = "Cookie:" cookie-version
263 * 1*((";" | ",") cookie-value)
264 * cookie-value = NAME "=" VALUE [";" path] [";" domain]
265 * cookie-version = "$Version" "=" value
266 * NAME = attr
267 * VALUE = value
268 * path = "$Path" "=" value
269 * domain = "$Domain" "=" value
271 * MS ignores $Version!
272 * ',' as a separator produces errors.
275 string [] name_values = header.Trim ().Split (';');
276 int length = name_values.Length;
277 Cookie cookie = null;
278 int pos;
279 for (int i = 0; i < length; i++) {
280 pos = 0;
281 string name_value = name_values [i].Trim ();
282 string name = GetCookieName (name_value, name_value.Length, ref pos);
283 string value = GetCookieValue (name_value, name_value.Length, ref pos);
284 if (cookie != null) {
285 if (name == "$Path") {
286 cookie.Path = value;
287 continue;
288 } else if (name == "$Domain") {
289 cookie.Domain = value;
290 continue;
291 } else {
292 Add (cookie);
293 cookie = null;
296 cookie = new Cookie (name, value);
299 if (cookie != null)
300 Add (cookie);
303 } // CookieContainer
305 } // System.Net