Commit | Line | Data |
---|---|---|
141e5e3c FT |
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 { | |
d5dd6a2d | 9 | private final static Map<Request, MultiMap<String, Cookie>> cache = new WeakHashMap<Request, MultiMap<String, Cookie>>(); |
141e5e3c FT |
10 | public final static DateFormat datefmt; |
11 | static { | |
12 | datefmt = new SimpleDateFormat("EEE, dd-MMM-yyyy HH:mm:ss z", Locale.ENGLISH); | |
13 | datefmt.setCalendar(Calendar.getInstance(TimeZone.getTimeZone("UTC"))); | |
14 | } | |
15 | public final String name; | |
16 | public String value; | |
17 | public Date expires; | |
18 | public String domain, path; | |
19 | public boolean secure; | |
20 | ||
21 | public Cookie(String name, String value, Date expires, String domain, String path, boolean secure) { | |
22 | if(!Http.istoken(name)) | |
23 | throw(new RuntimeException("Invalid cookie name: `" + name + "'")); | |
24 | this.name = name; | |
25 | this.value = value; | |
26 | this.expires = expires; | |
27 | this.domain = domain; | |
28 | this.path = path; | |
29 | this.secure = secure; | |
30 | } | |
31 | ||
32 | public Cookie(String name) { | |
33 | this(name, null, null, null, null, false); | |
34 | } | |
35 | ||
36 | public Cookie(String name, String value) { | |
37 | this(name, value, null, null, null, false); | |
38 | } | |
39 | ||
40 | public String format() { | |
41 | StringBuilder buf = new StringBuilder(); | |
42 | buf.append(Http.tokenquote(name)); | |
43 | buf.append('='); | |
44 | buf.append(Http.tokenquote(value)); | |
45 | if(domain != null) | |
46 | buf.append("; Domain=" + Http.tokenquote(domain)); | |
47 | if(path != null) | |
48 | buf.append("; Path=" + Http.tokenquote(path)); | |
49 | if(expires != null) | |
50 | buf.append("; Expires=" + Http.tokenquote(datefmt.format(expires))); | |
51 | if(secure) | |
52 | buf.append("; Secure"); | |
53 | return(buf.toString()); | |
54 | } | |
55 | ||
56 | public void addto(Request req) { | |
57 | req.outheaders().add("Set-Cookie", format()); | |
58 | } | |
59 | ||
60 | public static MultiMap<String, Cookie> parse(Request req) { | |
61 | MultiMap<String, Cookie> ret = new WrappedMultiMap<String, Cookie>(new TreeMap<String, Collection<Cookie>>()); | |
62 | for(String in : req.inheaders().values("Cookie")) { | |
63 | try { | |
64 | StringReader r = new StringReader(in); | |
65 | Cookie c = null; | |
66 | while(true) { | |
67 | String k = Http.tokenunquote(r); | |
68 | String v = Http.tokenunquote(r); | |
69 | if(k == null) | |
70 | break; | |
71 | if(k.equals("$Version")) { | |
72 | if(Integer.parseInt(v) != 1) | |
73 | throw(new Http.EncodingException("Unknown cookie format version")); | |
74 | } else if(k.equals("$Path")) { | |
75 | if(c != null) | |
76 | c.path = v; | |
77 | } else if(k.equals("$Domain")) { | |
78 | if(c != null) | |
79 | c.domain = v; | |
80 | } else { | |
81 | c = new Cookie(k, v); | |
82 | ret.add(k, c); | |
83 | } | |
84 | } | |
85 | } catch(IOException e) { | |
86 | throw(new Error(e)); | |
87 | } | |
88 | } | |
89 | return(ret); | |
90 | } | |
91 | ||
d5dd6a2d FT |
92 | public static MultiMap<String, Cookie> get(Request req) { |
93 | synchronized(cache) { | |
94 | MultiMap<String, Cookie> ret = cache.get(req); | |
95 | if(ret == null) { | |
96 | ret = parse(req); | |
97 | cache.put(req, ret); | |
98 | } | |
99 | return(ret); | |
100 | } | |
101 | } | |
102 | ||
141e5e3c FT |
103 | public String toString() { |
104 | StringBuilder buf = new StringBuilder(); | |
105 | buf.append("Cookie("); | |
106 | buf.append(format()); | |
107 | buf.append(")"); | |
108 | return(buf.toString()); | |
109 | } | |
110 | } |