Added library functions for setting and parsing cookies.
[jsvc.git] / src / dolda / jsvc / util / Cookie.java
1 package dolda.jsvc.util;
2
3 import dolda.jsvc.*;
4 import java.util.*;
5 import java.text.*;
6 import java.io.*;
7
8 public class Cookie {
9     public final static DateFormat datefmt;
10     static {
11         datefmt = new SimpleDateFormat("EEE, dd-MMM-yyyy HH:mm:ss z", Locale.ENGLISH);
12         datefmt.setCalendar(Calendar.getInstance(TimeZone.getTimeZone("UTC")));
13     }
14     public final String name;
15     public String value;
16     public Date expires;
17     public String domain, path;
18     public boolean secure;
19     
20     public Cookie(String name, String value, Date expires, String domain, String path, boolean secure) {
21         if(!Http.istoken(name))
22             throw(new RuntimeException("Invalid cookie name: `" + name + "'"));
23         this.name = name;
24         this.value = value;
25         this.expires = expires;
26         this.domain = domain;
27         this.path = path;
28         this.secure = secure;
29     }
30     
31     public Cookie(String name) {
32         this(name, null, null, null, null, false);
33     }
34     
35     public Cookie(String name, String value) {
36         this(name, value, null, null, null, false);
37     }
38     
39     public String format() {
40         StringBuilder buf = new StringBuilder();
41         buf.append(Http.tokenquote(name));
42         buf.append('=');
43         buf.append(Http.tokenquote(value));
44         if(domain != null)
45             buf.append("; Domain=" + Http.tokenquote(domain));
46         if(path != null)
47             buf.append("; Path=" + Http.tokenquote(path));
48         if(expires != null)
49             buf.append("; Expires=" + Http.tokenquote(datefmt.format(expires)));
50         if(secure)
51             buf.append("; Secure");
52         return(buf.toString());
53     }
54
55     public void addto(Request req) {
56         req.outheaders().add("Set-Cookie", format());
57     }
58     
59     public static MultiMap<String, Cookie> parse(Request req) {
60         MultiMap<String, Cookie> ret = new WrappedMultiMap<String, Cookie>(new TreeMap<String, Collection<Cookie>>());
61         for(String in : req.inheaders().values("Cookie")) {
62             try {
63                 StringReader r = new StringReader(in);
64                 Cookie c = null;
65                 while(true) {
66                     String k = Http.tokenunquote(r);
67                     String v = Http.tokenunquote(r);
68                     if(k == null)
69                         break;
70                     if(k.equals("$Version")) {
71                         if(Integer.parseInt(v) != 1)
72                             throw(new Http.EncodingException("Unknown cookie format version"));
73                     } else if(k.equals("$Path")) {
74                         if(c != null)
75                             c.path = v;
76                     } else if(k.equals("$Domain")) {
77                         if(c != null)
78                             c.domain = v;
79                     } else {
80                         c = new Cookie(k, v);
81                         ret.add(k, c);
82                     }
83                 }
84             } catch(IOException e) {
85                 throw(new Error(e));
86             }
87         }
88         return(ret);
89     }
90     
91     public String toString() {
92         StringBuilder buf = new StringBuilder();
93         buf.append("Cookie(");
94         buf.append(format());
95         buf.append(")");
96         return(buf.toString());
97     }
98 }