1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.jboss.netty.handler.codec.http;
17
18 import java.util.Date;
19 import java.util.Set;
20 import java.util.TreeSet;
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50 public class CookieEncoder {
51
52 private final Set<Cookie> cookies = new TreeSet<Cookie>();
53 private final boolean server;
54
55
56
57
58
59
60
61
62 public CookieEncoder(boolean server) {
63 this.server = server;
64 }
65
66
67
68
69
70 public void addCookie(String name, String value) {
71 cookies.add(new DefaultCookie(name, value));
72 }
73
74
75
76
77 public void addCookie(Cookie cookie) {
78 cookies.add(cookie);
79 }
80
81
82
83
84
85
86
87
88 public String encode() {
89 String answer;
90 if (server) {
91 answer = encodeServerSide();
92 } else {
93 answer = encodeClientSide();
94 }
95 cookies.clear();
96 return answer;
97 }
98
99 private String encodeServerSide() {
100 if (cookies.size() > 1) {
101 throw new IllegalStateException(
102 "encode() can encode only one cookie on server mode: " + cookies.size() + " cookies added");
103 }
104
105 StringBuilder sb = new StringBuilder();
106
107 for (Cookie cookie: cookies) {
108 add(sb, cookie.getName(), cookie.getValue());
109
110 if (cookie.getMaxAge() != Integer.MIN_VALUE) {
111 if (cookie.getVersion() == 0) {
112 addUnquoted(sb, CookieHeaderNames.EXPIRES,
113 new CookieDateFormat().format(
114 new Date(System.currentTimeMillis() +
115 cookie.getMaxAge() * 1000L)));
116 } else {
117 add(sb, CookieHeaderNames.MAX_AGE, cookie.getMaxAge());
118 }
119 }
120
121 if (cookie.getPath() != null) {
122 if (cookie.getVersion() > 0) {
123 add(sb, CookieHeaderNames.PATH, cookie.getPath());
124 } else {
125 addUnquoted(sb, CookieHeaderNames.PATH, cookie.getPath());
126 }
127 }
128
129 if (cookie.getDomain() != null) {
130 if (cookie.getVersion() > 0) {
131 add(sb, CookieHeaderNames.DOMAIN, cookie.getDomain());
132 } else {
133 addUnquoted(sb, CookieHeaderNames.DOMAIN, cookie.getDomain());
134 }
135 }
136 if (cookie.isSecure()) {
137 sb.append(CookieHeaderNames.SECURE);
138 sb.append((char) HttpConstants.SEMICOLON);
139 sb.append((char) HttpConstants.SP);
140 }
141 if (cookie.isHttpOnly()) {
142 sb.append(CookieHeaderNames.HTTPONLY);
143 sb.append((char) HttpConstants.SEMICOLON);
144 sb.append((char) HttpConstants.SP);
145 }
146 if (cookie.getVersion() >= 1) {
147 if (cookie.getComment() != null) {
148 add(sb, CookieHeaderNames.COMMENT, cookie.getComment());
149 }
150
151 add(sb, CookieHeaderNames.VERSION, 1);
152
153 if (cookie.getCommentUrl() != null) {
154 addQuoted(sb, CookieHeaderNames.COMMENTURL, cookie.getCommentUrl());
155 }
156
157 if (!cookie.getPorts().isEmpty()) {
158 sb.append(CookieHeaderNames.PORT);
159 sb.append((char) HttpConstants.EQUALS);
160 sb.append((char) HttpConstants.DOUBLE_QUOTE);
161 for (int port: cookie.getPorts()) {
162 sb.append(port);
163 sb.append((char) HttpConstants.COMMA);
164 }
165 sb.setCharAt(sb.length() - 1, (char) HttpConstants.DOUBLE_QUOTE);
166 sb.append((char) HttpConstants.SEMICOLON);
167 sb.append((char) HttpConstants.SP);
168
169 }
170 if (cookie.isDiscard()) {
171 sb.append(CookieHeaderNames.DISCARD);
172 sb.append((char) HttpConstants.SEMICOLON);
173 sb.append((char) HttpConstants.SP);
174 }
175 }
176 }
177
178 if (sb.length() > 0) {
179 sb.setLength(sb.length() - 2);
180 }
181
182 return sb.toString();
183 }
184
185 private String encodeClientSide() {
186 StringBuilder sb = new StringBuilder();
187
188 for (Cookie cookie: cookies) {
189 if (cookie.getVersion() >= 1) {
190 add(sb, '$' + CookieHeaderNames.VERSION, 1);
191 }
192
193 add(sb, cookie.getName(), cookie.getValue());
194
195 if (cookie.getPath() != null) {
196 add(sb, '$' + CookieHeaderNames.PATH, cookie.getPath());
197 }
198
199 if (cookie.getDomain() != null) {
200 add(sb, '$' + CookieHeaderNames.DOMAIN, cookie.getDomain());
201 }
202
203 if (cookie.getVersion() >= 1) {
204 if (!cookie.getPorts().isEmpty()) {
205 sb.append('$');
206 sb.append(CookieHeaderNames.PORT);
207 sb.append((char) HttpConstants.EQUALS);
208 sb.append((char) HttpConstants.DOUBLE_QUOTE);
209 for (int port: cookie.getPorts()) {
210 sb.append(port);
211 sb.append((char) HttpConstants.COMMA);
212 }
213 sb.setCharAt(sb.length() - 1, (char) HttpConstants.DOUBLE_QUOTE);
214 sb.append((char) HttpConstants.SEMICOLON);
215 sb.append((char) HttpConstants.SP);
216 }
217 }
218 }
219
220 if (sb.length() > 0) {
221 sb.setLength(sb.length() - 2);
222 }
223 return sb.toString();
224 }
225
226 private static void add(StringBuilder sb, String name, String val) {
227 if (val == null) {
228 addQuoted(sb, name, "");
229 return;
230 }
231
232 for (int i = 0; i < val.length(); i ++) {
233 char c = val.charAt(i);
234 switch (c) {
235 case '\t': case ' ': case '"': case '(': case ')': case ',':
236 case '/': case ':': case ';': case '<': case '=': case '>':
237 case '?': case '@': case '[': case '\\': case ']':
238 case '{': case '}':
239 addQuoted(sb, name, val);
240 return;
241 }
242 }
243
244 addUnquoted(sb, name, val);
245 }
246
247 private static void addUnquoted(StringBuilder sb, String name, String val) {
248 sb.append(name);
249 sb.append((char) HttpConstants.EQUALS);
250 sb.append(val);
251 sb.append((char) HttpConstants.SEMICOLON);
252 sb.append((char) HttpConstants.SP);
253 }
254
255 private static void addQuoted(StringBuilder sb, String name, String val) {
256 if (val == null) {
257 val = "";
258 }
259
260 sb.append(name);
261 sb.append((char) HttpConstants.EQUALS);
262 sb.append((char) HttpConstants.DOUBLE_QUOTE);
263 sb.append(val.replace("\\", "\\\\").replace("\"", "\\\""));
264 sb.append((char) HttpConstants.DOUBLE_QUOTE);
265 sb.append((char) HttpConstants.SEMICOLON);
266 sb.append((char) HttpConstants.SP);
267
268 }
269
270 private static void add(StringBuilder sb, String name, int val) {
271 sb.append(name);
272 sb.append((char) HttpConstants.EQUALS);
273 sb.append(val);
274 sb.append((char) HttpConstants.SEMICOLON);
275 sb.append((char) HttpConstants.SP);
276 }
277 }