KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > HTTPClient > Cookie2


1 /*
2  * @(#)Cookie2.java 0.3-2 18/06/1999
3  *
4  * This file is part of the HTTPClient package
5  * Copyright (C) 1996-1999 Ronald Tschalär
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free
19  * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20  * MA 02111-1307, USA
21  *
22  * For questions, suggestions, bug-reports, enhancement-requests etc.
23  * I may be contacted at:
24  *
25  * ronald@innovation.ch
26  *
27  */

28
29 package HTTPClient;
30
31 import java.io.File JavaDoc;
32 import java.net.ProtocolException JavaDoc;
33 import java.util.Date JavaDoc;
34 import java.util.Vector JavaDoc;
35 import java.util.Hashtable JavaDoc;
36 import java.util.Enumeration JavaDoc;
37 import java.util.StringTokenizer JavaDoc;
38
39
40 /**
41  * This class represents an http cookie as specified in the
42  * <A HREF="ftp://ds.internic.net/internet-drafts/draft-ietf-http-state-man-mec-10.txt">
43  * HTTP State Management Mechanism spec</A> (also known as a version 1 cookie).
44  *
45  * @version 0.3-2 18/06/1999
46  * @author Ronald Tschalär
47  * @since V0.3
48  */

49
50 public class Cookie2 extends Cookie
51 {
52     protected int version;
53     protected boolean discard;
54     protected String JavaDoc comment;
55     protected URI comment_url;
56     protected int[] port_list;
57     protected String JavaDoc port_list_str;
58
59     protected boolean path_set;
60     protected boolean port_set;
61     protected boolean domain_set;
62
63
64     /**
65      * Create a cookie.
66      *
67      * @param name the cookie name
68      * @param value the cookie value
69      * @param domain the host this cookie will be sent to
70      * @param port_list an array of allowed server ports for this cookie,
71      * or null if the the cookie may be sent to any port
72      * @param path the path prefix for which this cookie will be sent
73      * @param epxires the Date this cookie expires, or null if never
74      * @param discard if true then the cookie will be discarded at the
75      * end of the session regardless of expiry
76      * @param secure if true this cookie will only be over secure connections
77      * @param comment the comment associated with this cookie, or null if none
78      * @param comment_url the comment URL associated with this cookie, or null
79      * if none
80      * @exception NullPointerException if <var>name</var>, <var>value</var>,
81      * <var>domain</var>, or <var>path</var>
82      * is null
83      */

84     public Cookie2(String JavaDoc name, String JavaDoc value, String JavaDoc domain, int[] port_list,
85            String JavaDoc path, Date JavaDoc expires, boolean discard, boolean secure,
86            String JavaDoc comment, URI comment_url)
87     {
88     super(name, value, domain, path, expires, secure);
89
90     this.discard = discard;
91     this.port_list = port_list;
92     this.comment = comment;
93     this.comment_url = comment_url;
94
95     path_set = true;
96     domain_set = true;
97
98     if (port_list != null && port_list.length > 0)
99     {
100         StringBuffer JavaDoc tmp = new StringBuffer JavaDoc();
101         tmp.append(port_list[0]);
102         for (int idx=1; idx<port_list.length; idx++)
103         {
104         tmp.append(',');
105         tmp.append(port_list[idx]);
106         }
107
108         port_list_str = tmp.toString();
109         port_set = true;
110     }
111
112     version = 1;
113     }
114
115
116     /**
117      * Use <code>parse()</code> to create cookies.
118      *
119      * @see #parse(java.lang.String, HTTPClient.RoRequest)
120      */

121     protected Cookie2(RoRequest req)
122     {
123     super(req);
124
125     int slash = path.lastIndexOf('/');
126     if (slash != -1) path = path.substring(0, slash+1);
127     if (domain.indexOf('.') == -1) domain += ".local";
128
129     version = -1;
130     discard = false;
131     comment = null;
132     comment_url = null;
133     port_list = null;
134     port_list_str = null;
135
136     path_set = false;
137     port_set = false;
138     domain_set = false;
139     }
140
141
142     /**
143      * Parses the Set-Cookie2 header into an array of Cookies.
144      *
145      * @param set_cookie the Set-Cookie header received from the server
146      * @param req the request used
147      * @return an array of Cookies as parsed from the Set-Cookie header
148      * @exception ProtocolException if an error occurs during parsing
149      */

150     protected static Cookie[] parse(String JavaDoc set_cookie, RoRequest req)
151         throws ProtocolException JavaDoc
152     {
153     Vector JavaDoc cookies;
154     try
155         { cookies = Util.parseHeader(set_cookie); }
156     catch (ParseException pe)
157         { throw new ProtocolException JavaDoc(pe.getMessage()); }
158
159         Cookie cookie_arr[] = new Cookie[cookies.size()];
160     int cidx=0;
161     for (int idx=0; idx<cookie_arr.length; idx++)
162     {
163         HttpHeaderElement c_elem =
164             (HttpHeaderElement) cookies.elementAt(idx);
165
166
167         // set NAME and VALUE
168

169         if (c_elem.getValue() == null)
170         throw new ProtocolException JavaDoc("Bad Set-Cookie2 header: " +
171                         set_cookie + "\nMissing value " +
172                         "for cookie '" + c_elem.getName() +
173                         "'");
174         Cookie2 curr = new Cookie2(req);
175         curr.name = c_elem.getName();
176         curr.value = c_elem.getValue();
177
178
179         // set all params
180

181         NVPair[] params = c_elem.getParams();
182         boolean discard_set = false, secure_set = false;
183         for (int idx2=0; idx2<params.length; idx2++)
184         {
185         String JavaDoc name = params[idx2].getName().toLowerCase();
186
187         // check for required value parts
188
if ((name.equals("version") || name.equals("max-age") ||
189              name.equals("domain") || name.equals("path") ||
190              name.equals("comment") || name.equals("commenturl")) &&
191             params[idx2].getValue() == null)
192         {
193             throw new ProtocolException JavaDoc("Bad Set-Cookie2 header: " +
194                         set_cookie + "\nMissing value "+
195                         "for " + params[idx2].getName()+
196                         " attribute in cookie '" +
197                         c_elem.getName() + "'");
198         }
199
200
201         if (name.equals("version")) // Version
202
{
203             if (curr.version != -1) continue;
204             try
205             {
206             curr.version =
207                 Integer.parseInt(params[idx2].getValue());
208             }
209             catch (NumberFormatException JavaDoc nfe)
210             {
211             throw new ProtocolException JavaDoc("Bad Set-Cookie2 header: " +
212                             set_cookie + "\nVersion '" +
213                             params[idx2].getValue() +
214                             "' not a number");
215             }
216         }
217         else if (name.equals("path")) // Path
218
{
219             if (curr.path_set) continue;
220             curr.path = params[idx2].getValue();
221             curr.path_set = true;
222         }
223         else if (name.equals("domain")) // Domain
224
{
225             if (curr.domain_set) continue;
226             String JavaDoc d = params[idx2].getValue().toLowerCase();
227
228             // add leading dot if not present and if domain is
229
// not the full host name
230
if (d.charAt(0) != '.' && !d.equals(curr.domain))
231             curr.domain = "." + d;
232             else
233             curr.domain = d;
234             curr.domain_set = true;
235         }
236         else if (name.equals("max-age")) // Max-Age
237
{
238             if (curr.expires != null) continue;
239             int age;
240             try
241             { age = Integer.parseInt(params[idx2].getValue()); }
242             catch (NumberFormatException JavaDoc nfe)
243             {
244             throw new ProtocolException JavaDoc("Bad Set-Cookie2 header: " +
245                         set_cookie + "\nMax-Age '" +
246                         params[idx2].getValue() +
247                         "' not a number");
248             }
249             curr.expires =
250                 new Date JavaDoc(System.currentTimeMillis() + age*1000L);
251         }
252         else if (name.equals("port")) // Port
253
{
254             if (curr.port_set) continue;
255
256             if (params[idx2].getValue() == null)
257             {
258             curr.port_list = new int[1];
259             curr.port_list[0] = req.getConnection().getPort();
260             curr.port_set = true;
261             continue;
262             }
263
264             curr.port_list_str = params[idx2].getValue();
265             StringTokenizer JavaDoc tok =
266                 new StringTokenizer JavaDoc(params[idx2].getValue(), ",");
267             curr.port_list = new int[tok.countTokens()];
268             for (int idx3=0; idx3<curr.port_list.length; idx3++)
269             {
270             String JavaDoc port = tok.nextToken().trim();
271             try
272                 { curr.port_list[idx3] = Integer.parseInt(port); }
273             catch (NumberFormatException JavaDoc nfe)
274             {
275                 throw new ProtocolException JavaDoc("Bad Set-Cookie2 header: " +
276                             set_cookie + "\nPort '" +
277                             port + "' not a number");
278             }
279             }
280             curr.port_set = true;
281         }
282         else if (name.equals("discard")) // Domain
283
{
284             if (discard_set) continue;
285             curr.discard = true;
286             discard_set = true;
287         }
288         else if (name.equals("secure")) // Secure
289
{
290             if (secure_set) continue;
291             curr.secure = true;
292             secure_set = true;
293         }
294         else if (name.equals("comment")) // Comment
295
{
296             if (curr.comment != null) continue;
297             curr.comment = params[idx2].getValue();
298         }
299         else if (name.equals("commenturl")) // CommentURL
300
{
301             if (curr.comment_url != null) continue;
302             try
303             { curr.comment_url = new URI(params[idx2].getValue()); }
304             catch (ParseException pe)
305             {
306             throw new ProtocolException JavaDoc("Bad Set-Cookie2 header: " +
307                         set_cookie + "\nCommentURL '" +
308                         params[idx2].getValue() +
309                         "' not a valid URL");
310             }
311         }
312         // ignore unknown element
313
}
314
315
316         // check version
317

318         if (curr.version == -1)
319         throw new ProtocolException JavaDoc("Bad Set-Cookie2 header: " +
320                         set_cookie + "\nMissing Version " +
321                         "attribute");
322         if (curr.version != 1) continue; // ignore unknown version
323

324
325         // setup defaults
326

327         if (curr.expires == null) curr.discard = true;
328
329
330         // check validity
331

332         // path attribute must be a prefix of the request-URI
333
if (!Util.getPath(req.getRequestURI()).startsWith(curr.path))
334         continue;
335
336         // if host name is simple (i.e w/o a domain) then append .local
337
String JavaDoc eff_host = req.getConnection().getHost();
338         if (eff_host.indexOf('.') == -1) eff_host += ".local";
339
340         // domain must be either .local or must contain at least two dots
341
if (!curr.domain.equals(".local") &&
342         curr.domain.indexOf('.', 1) == -1) continue;
343
344         // domain must domain match host
345
if (!eff_host.endsWith(curr.domain)) continue;
346
347         // host minus domain may not contain any dots
348
if (eff_host.substring(0, eff_host.length()-curr.domain.length()).
349         indexOf('.') != -1) continue;
350
351         // if a port list is given it must include the current port
352
if (curr.port_set)
353         {
354         int idx2=0;
355         for (idx2=0; idx2<curr.port_list.length; idx2++)
356             if (curr.port_list[idx2] == req.getConnection().getPort())
357             break;
358         if (idx2 == curr.port_list.length) continue;
359         }
360
361
362         // looks ok
363

364         cookie_arr[cidx++] = curr;
365     }
366
367     if (cidx < cookie_arr.length)
368         cookie_arr = Util.resizeArray(cookie_arr, cidx);
369
370     return cookie_arr;
371     }
372
373
374     /**
375      * @return the version as an int
376      */

377     public int getVersion()
378     {
379     return version;
380     }
381
382  
383     /**
384      * @return the comment string, or null if none was set
385      */

386     public String JavaDoc getComment()
387     {
388     return comment;
389     }
390
391  
392     /**
393      * @return the comment url
394      */

395     public URI getCommentURL()
396     {
397     return comment_url;
398     }
399
400  
401     /**
402      * @return the array of ports
403      */

404     public int[] getPorts()
405     {
406     return port_list;
407     }
408
409  
410     /**
411      * @return true if the cookie should be discarded at the end of the
412      * session; false otherwise
413      */

414     public boolean discard()
415     {
416     return discard;
417     }
418  
419
420     /**
421      * @param req the request to be sent
422      * @return true if this cookie should be sent with the request
423      */

424     protected boolean sendWith(RoRequest req)
425     {
426     HTTPConnection con = req.getConnection();
427
428     boolean port_match = !port_set;
429     if (port_set)
430         for (int idx=0; idx<port_list.length; idx++)
431         if (port_list[idx] == con.getPort())
432         {
433             port_match = true;
434             break;
435         }
436
437     String JavaDoc eff_host = con.getHost();
438     if (eff_host.indexOf('.') == -1) eff_host += ".local";
439
440     return ((domain.charAt(0) == '.' && eff_host.endsWith(domain) ||
441          domain.charAt(0) != '.' && eff_host.equals(domain)) &&
442         port_match &&
443         Util.getPath(req.getRequestURI()).startsWith(path) &&
444         (!secure || con.getProtocol().equals("https") ||
445          con.getProtocol().equals("shttp")));
446     }
447  
448
449     protected String JavaDoc toExternalForm()
450     {
451     StringBuffer JavaDoc cookie = new StringBuffer JavaDoc();
452
453     if (version == 1)
454     {
455         /*
456         cookie.append("$Version=");
457         cookie.append(version);
458         cookie.append("; ");
459         */

460
461         cookie.append(name);
462         cookie.append("=");
463         cookie.append(value);
464
465         if (path_set)
466         {
467         cookie.append("; ");
468         cookie.append("$Path=");
469         cookie.append(path);
470         }
471
472         if (domain_set)
473         {
474         cookie.append("; ");
475         cookie.append("$Domain=");
476         cookie.append(domain);
477         }
478
479         if (port_set)
480         {
481         cookie.append("; ");
482         cookie.append("$Port");
483         if (port_list_str != null)
484         {
485             cookie.append("=\"");
486             cookie.append(port_list_str);
487             cookie.append('\"');
488         }
489         }
490     }
491     else
492         throw new Error JavaDoc("Internal Error: unknown version " + version);
493
494     return cookie.toString();
495     }
496
497
498     /**
499      * Create a string containing all the cookie fields. The format is that
500      * used in the Set-Cookie header.
501      */

502     public String JavaDoc toString()
503     {
504     String JavaDoc string = name + "=" + value;
505
506     if (version == 1)
507     {
508         string += "; Version=" + version;
509         string += "; Path=" + path;
510         string += "; Domain=" + domain;
511         if (port_set)
512         {
513         string += "; Port=\"" + port_list[0];
514         for (int idx=1; idx<port_list.length; idx++)
515             string += "," + port_list[idx];
516         string += "\"";
517         }
518         if (expires != null) string += "; Max-Age=" +
519             ((expires.getTime() - new Date JavaDoc().getTime()) / 1000L);
520         if (discard) string += "; Discard";
521         if (secure) string += "; Secure";
522         if (comment != null) string += "; Comment=\"" + comment + "\"";
523         if (comment_url != null) string += "; CommentURL=\"" + comment_url + "\"";
524     }
525     else
526         throw new Error JavaDoc("Internal Error: unknown version " + version);
527
528     return string;
529     }
530 }
531
532
Popular Tags