2004-01-27 Nick Drochak <ndrochak@ieee.org>
[mono.git] / mcs / class / System / System.Net / CookieContainer.cs
1 //\r
2 // System.Net.CookieContainer\r
3 //\r
4 // Authors:\r
5 //      Lawrence Pit (loz@cable.a2000.nl)\r
6 //      Gonzalo Paniagua Javier (gonzalo@ximian.com)\r
7 //\r
8 // (c) 2003 Ximian, Inc. (http://www.ximian.com)\r
9 //\r
10 \r
11 using System;\r
12 using System.Collections;\r
13 using System.Runtime.Serialization;\r
14 using System.Text;\r
15 \r
16 namespace System.Net \r
17 {\r
18         [Serializable]\r
19         public class CookieContainer\r
20         {\r
21                 public const int DefaultCookieLengthLimit = 4096;\r
22                 public const int DefaultCookieLimit = 300;\r
23                 public const int DefaultPerDomainCookieLimit = 20;\r
24 \r
25                 int count;\r
26                 int capacity = DefaultCookieLimit;\r
27                 int perDomainCapacity = DefaultPerDomainCookieLimit;\r
28                 int maxCookieSize = DefaultCookieLengthLimit;\r
29                 CookieCollection cookies;\r
30                                 \r
31                 // ctors\r
32                 public CookieContainer ()\r
33                 { \r
34                 } \r
35         \r
36                 public CookieContainer (int capacity)\r
37                 {\r
38                         if (capacity <= 0)\r
39                                 throw new ArgumentException ("Must be greater than zero", "capacity");\r
40 \r
41                         this.capacity = capacity;\r
42                 }\r
43                 \r
44                 public CookieContainer (int capacity, int perDomainCapacity, int maxCookieSize)\r
45                         : this (capacity)\r
46                 {\r
47                         if (perDomainCapacity <= 0 || perDomainCapacity < capacity)\r
48                                 throw new ArgumentException ("Invalid value", "perDomaniCapacity");\r
49 \r
50                         if (maxCookieSize <= 0)\r
51                                 throw new ArgumentException ("Must be greater than zero", "maxCookieSize");\r
52 \r
53                         this.perDomainCapacity = perDomainCapacity;\r
54                         this.maxCookieSize = maxCookieSize;\r
55                 }\r
56 \r
57                 // properties\r
58                 \r
59                 public int Count { \r
60                         get { return count; }\r
61                 }\r
62                 \r
63                 public int Capacity {\r
64                         get { return capacity; }\r
65                         set { \r
66                                 if ((value <= 0) ||\r
67                                     (value < perDomainCapacity && perDomainCapacity != Int32.MaxValue))\r
68                                         throw new ArgumentOutOfRangeException ("value");\r
69                                 if (value < maxCookieSize)\r
70                                         maxCookieSize = value;\r
71                                 capacity = value;                                                       \r
72                         }\r
73                 }\r
74                 \r
75                 public int MaxCookieSize {\r
76                         get { return maxCookieSize; }\r
77                         set {\r
78                                 if (value <= 0)\r
79                                         throw new ArgumentOutOfRangeException ("value");                                \r
80                                 maxCookieSize = value;\r
81                         }\r
82                 }\r
83                 \r
84                 public int PerDomainCapacity {\r
85                         get { return perDomainCapacity; }\r
86                         set {\r
87                                 if ((value <= 0) ||\r
88                                     (value > DefaultCookieLimit && value != Int32.MaxValue))\r
89                                         throw new ArgumentOutOfRangeException ("value");                                        \r
90                                 if (value < perDomainCapacity)\r
91                                         perDomainCapacity = value;\r
92                                 perDomainCapacity = value;\r
93                         }\r
94                 }\r
95                 \r
96                 public void Add (Cookie cookie) \r
97                 {\r
98                         if (cookie == null)\r
99                                 throw new ArgumentNullException ("cookie");\r
100 \r
101                         if (cookie.Domain == null && cookie.Domain == "")\r
102                                 throw new ArgumentException ("Cookie domain not set.", "cookie");\r
103 \r
104                         if (cookie.Value.ToString ().Length > maxCookieSize)\r
105                                 throw new CookieException ("Cookie size too big");\r
106 \r
107                         AddCookie (cookie);\r
108                 }\r
109 \r
110                 void AddCookie (Cookie cookie)\r
111                 {\r
112                         lock (this) {\r
113                                 if (cookies == null)\r
114                                         cookies = new CookieCollection ();\r
115 \r
116                                 if (count + 1 > capacity)\r
117                                         throw new CookieException ("Capacity exceeded");\r
118 \r
119                                 cookies.Add (cookie);\r
120                                 count++;\r
121                         }\r
122                 }\r
123 \r
124                 public void Add (CookieCollection cookies)\r
125                 {\r
126                         if (cookies == null)\r
127                                 throw new ArgumentNullException ("cookies");\r
128 \r
129                         foreach (Cookie cookie in cookies)\r
130                                 Add (cookie);\r
131                 }\r
132 \r
133                 [MonoTODO ("Uri")]\r
134                 public void Add (Uri uri, Cookie cookie)\r
135                 {\r
136                         if (uri == null)\r
137                                 throw new ArgumentNullException ("uri");\r
138                         \r
139                         Add (cookie);\r
140                 }\r
141 \r
142                 [MonoTODO("Uri")]\r
143                 public void Add (Uri uri, CookieCollection cookies)\r
144                 {\r
145                         if (uri == null)\r
146                                 throw new ArgumentNullException ("uri");\r
147                         \r
148                         Add (cookies);\r
149                 }               \r
150 \r
151                 [MonoTODO("Uri")]\r
152                 public string GetCookieHeader (Uri uri)\r
153                 {\r
154                         if (uri == null)\r
155                                 throw new ArgumentNullException ("uri");\r
156 \r
157                         if (cookies == null)\r
158                                 return "";\r
159 \r
160                         StringBuilder result = new StringBuilder ();\r
161                         bool notfirst = false;\r
162                         foreach (Cookie cookie in cookies) {\r
163                                 if (notfirst)\r
164                                         result.Append (';');\r
165 \r
166                                 result.Append (cookie.ToString ());\r
167                                 notfirst = true;\r
168                         }\r
169                         return result.ToString ();\r
170                 }\r
171 \r
172                 [MonoTODO("Uri")]\r
173                 public CookieCollection GetCookies (Uri uri)\r
174                 {\r
175                         if (uri == null)\r
176                                 throw new ArgumentNullException ("uri");\r
177                         \r
178                         CookieCollection coll = new CookieCollection ();\r
179                         if (cookies == null)\r
180                                 return coll;\r
181                         \r
182                         foreach (Cookie cookie in cookies)\r
183                                 coll.Add (cookie);\r
184                         \r
185                         return coll;\r
186                 }\r
187 \r
188                 public void SetCookies (Uri uri, string cookieHeader)\r
189                 {\r
190                         if (uri == null)\r
191                                 throw new ArgumentNullException ("uri");\r
192                         \r
193                         if (cookieHeader == null)\r
194                                 throw new ArgumentNullException ("cookieHeader");\r
195                         \r
196                         ParseAndAddCookies (cookieHeader);\r
197                 }\r
198 \r
199                 // GetCookieValue, GetCookieName and ParseAndAddCookies copied from HttpRequest.cs\r
200                 static string GetCookieValue (string str, int length, ref int i)\r
201                 {\r
202                         if (i >= length)\r
203                                 return null;\r
204 \r
205                         int k = i;\r
206                         while (k < length && Char.IsWhiteSpace (str [k]))\r
207                                 k++;\r
208 \r
209                         int begin = k;\r
210                         while (k < length && str [k] != ';')\r
211                                 k++;\r
212 \r
213                         i = k;\r
214                         return str.Substring (begin, i - begin).Trim ();\r
215                 }\r
216 \r
217                 static string GetCookieName (string str, int length, ref int i)\r
218                 {\r
219                         if (i >= length)\r
220                                 return null;\r
221 \r
222                         int k = i;\r
223                         while (k < length && Char.IsWhiteSpace (str [k]))\r
224                                 k++;\r
225 \r
226                         int begin = k;\r
227                         while (k < length && str [k] != ';' &&  str [k] != '=')\r
228                                 k++;\r
229 \r
230                         i = k + 1;\r
231                         return str.Substring (begin, k - begin).Trim ();\r
232                 }\r
233 \r
234 \r
235                 void ParseAndAddCookies (string header)\r
236                 {\r
237                         if (header.Length == 0)\r
238                                 return;\r
239 \r
240                         /* RFC 2109\r
241                          *      cookie          =       "Cookie:" cookie-version\r
242                          *                                 1*((";" | ",") cookie-value)\r
243                          *      cookie-value    =       NAME "=" VALUE [";" path] [";" domain]\r
244                          *      cookie-version  =       "$Version" "=" value\r
245                          *      NAME            =       attr\r
246                          *      VALUE           =       value\r
247                          *      path            =       "$Path" "=" value\r
248                          *      domain          =       "$Domain" "=" value\r
249                          *\r
250                          *      MS ignores $Version! \r
251                          *      ',' as a separator produces errors.\r
252                          */\r
253 \r
254                         string [] name_values = header.Trim ().Split (';');\r
255                         int length = name_values.Length;\r
256                         Cookie cookie = null;\r
257                         int pos;\r
258                         for (int i = 0; i < length; i++) {\r
259                                 pos = 0;\r
260                                 string name_value = name_values [i].Trim ();\r
261                                 string name = GetCookieName (name_value, name_value.Length, ref pos);\r
262                                 string value = GetCookieValue (name_value, name_value.Length, ref pos);\r
263                                 if (cookie != null) {\r
264                                         if (name == "$Path") {\r
265                                                 cookie.Path = value;\r
266                                                 continue;\r
267                                         } else if (name == "$Domain") {\r
268                                                 cookie.Domain = value;\r
269                                                 continue;\r
270                                         } else {\r
271                                                 Add (cookie);\r
272                                                 cookie = null;\r
273                                         }\r
274                                 }\r
275                                 cookie = new Cookie (name, value);\r
276                         }\r
277 \r
278                         if (cookie != null)\r
279                                 Add (cookie);\r
280                 }\r
281 \r
282         } // CookieContainer\r
283 \r
284 } // System.Net\r
285 \r