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 HttpHeaderDateFormat.get().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 if (cookie.isDiscard()) {
170 sb.append(CookieHeaderNames.DISCARD);
171 sb.append((char) HttpConstants.SEMICOLON);
172 sb.append((char) HttpConstants.SP);
173 }
174 }
175 }
176
177 if (sb.length() > 0) {
178 sb.setLength(sb.length() - 2);
179 }
180
181 return sb.toString();
182 }
183
184 private String encodeClientSide() {
185 StringBuilder sb = new StringBuilder();
186
187 for (Cookie cookie: cookies) {
188 if (cookie.getVersion() >= 1) {
189 add(sb, '$' + CookieHeaderNames.VERSION, 1);
190 }
191
192 add(sb, cookie.getName(), cookie.getValue());
193
194 if (cookie.getPath() != null) {
195 add(sb, '$' + CookieHeaderNames.PATH, cookie.getPath());
196 }
197
198 if (cookie.getDomain() != null) {
199 add(sb, '$' + CookieHeaderNames.DOMAIN, cookie.getDomain());
200 }
201
202 if (cookie.getVersion() >= 1) {
203 if (!cookie.getPorts().isEmpty()) {
204 sb.append('$');
205 sb.append(CookieHeaderNames.PORT);
206 sb.append((char) HttpConstants.EQUALS);
207 sb.append((char) HttpConstants.DOUBLE_QUOTE);
208 for (int port: cookie.getPorts()) {
209 sb.append(port);
210 sb.append((char) HttpConstants.COMMA);
211 }
212 sb.setCharAt(sb.length() - 1, (char) HttpConstants.DOUBLE_QUOTE);
213 sb.append((char) HttpConstants.SEMICOLON);
214 sb.append((char) HttpConstants.SP);
215 }
216 }
217 }
218
219 if (sb.length() > 0) {
220 sb.setLength(sb.length() - 2);
221 }
222 return sb.toString();
223 }
224
225 private static void add(StringBuilder sb, String name, String val) {
226 if (val == null) {
227 addQuoted(sb, name, "");
228 return;
229 }
230
231 for (int i = 0; i < val.length(); i ++) {
232 char c = val.charAt(i);
233 switch (c) {
234 case '\t': case ' ': case '"': case '(': case ')': case ',':
235 case '/': case ':': case ';': case '<': case '=': case '>':
236 case '?': case '@': case '[': case '\\': case ']':
237 case '{': case '}':
238 addQuoted(sb, name, val);
239 return;
240 }
241 }
242
243 addUnquoted(sb, name, val);
244 }
245
246 private static void addUnquoted(StringBuilder sb, String name, String val) {
247 sb.append(name);
248 sb.append((char) HttpConstants.EQUALS);
249 sb.append(val);
250 sb.append((char) HttpConstants.SEMICOLON);
251 sb.append((char) HttpConstants.SP);
252 }
253
254 private static void addQuoted(StringBuilder sb, String name, String val) {
255 if (val == null) {
256 val = "";
257 }
258
259 sb.append(name);
260 sb.append((char) HttpConstants.EQUALS);
261 sb.append((char) HttpConstants.DOUBLE_QUOTE);
262 sb.append(val.replace("\\", "\\\\").replace("\"", "\\\""));
263 sb.append((char) HttpConstants.DOUBLE_QUOTE);
264 sb.append((char) HttpConstants.SEMICOLON);
265 sb.append((char) HttpConstants.SP);
266 }
267
268 private static void add(StringBuilder sb, String name, int val) {
269 sb.append(name);
270 sb.append((char) HttpConstants.EQUALS);
271 sb.append(val);
272 sb.append((char) HttpConstants.SEMICOLON);
273 sb.append((char) HttpConstants.SP);
274 }
275 }