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
51
52
53
54 public class CookieEncoder {
55
56 private final Set<Cookie> cookies = new TreeSet<Cookie>();
57 private final boolean server;
58
59
60
61
62
63
64
65
66 public CookieEncoder(boolean server) {
67 this.server = server;
68 }
69
70
71
72
73
74 public void addCookie(String name, String value) {
75 cookies.add(new DefaultCookie(name, value));
76 }
77
78
79
80
81 public void addCookie(Cookie cookie) {
82 cookies.add(cookie);
83 }
84
85
86
87
88
89
90 public String encode() {
91 String answer;
92 if (server) {
93 answer = encodeServerSide();
94 } else {
95 answer = encodeClientSide();
96 }
97 cookies.clear();
98 return answer;
99 }
100
101 private String encodeServerSide() {
102 StringBuilder sb = new StringBuilder();
103
104 for (Cookie cookie: cookies) {
105 add(sb, cookie.getName(), cookie.getValue());
106
107 if (cookie.getMaxAge() >= 0) {
108 if (cookie.getVersion() == 0) {
109 addUnquoted(sb, CookieHeaderNames.EXPIRES,
110 new CookieDateFormat().format(
111 new Date(System.currentTimeMillis() +
112 cookie.getMaxAge() * 1000L)));
113 } else {
114 add(sb, CookieHeaderNames.MAX_AGE, cookie.getMaxAge());
115 }
116 }
117
118 if (cookie.getPath() != null) {
119 if (cookie.getVersion() > 0) {
120 add(sb, CookieHeaderNames.PATH, cookie.getPath());
121 } else {
122 addUnquoted(sb, CookieHeaderNames.PATH, cookie.getPath());
123 }
124 }
125
126 if (cookie.getDomain() != null) {
127 if (cookie.getVersion() > 0) {
128 add(sb, CookieHeaderNames.DOMAIN, cookie.getDomain());
129 } else {
130 addUnquoted(sb, CookieHeaderNames.DOMAIN, cookie.getDomain());
131 }
132 }
133 if (cookie.isSecure()) {
134 sb.append(CookieHeaderNames.SECURE);
135 sb.append((char) HttpCodecUtil.SEMICOLON);
136 }
137 if (cookie.isHttpOnly()) {
138 sb.append(CookieHeaderNames.HTTPONLY);
139 sb.append((char) HttpCodecUtil.SEMICOLON);
140 }
141 if (cookie.getVersion() >= 1) {
142 if (cookie.getComment() != null) {
143 add(sb, CookieHeaderNames.COMMENT, cookie.getComment());
144 }
145
146 add(sb, CookieHeaderNames.VERSION, 1);
147
148 if (cookie.getCommentUrl() != null) {
149 addQuoted(sb, CookieHeaderNames.COMMENTURL, cookie.getCommentUrl());
150 }
151
152 if(!cookie.getPorts().isEmpty()) {
153 sb.append(CookieHeaderNames.PORT);
154 sb.append((char) HttpCodecUtil.EQUALS);
155 sb.append((char) HttpCodecUtil.DOUBLE_QUOTE);
156 for (int port: cookie.getPorts()) {
157 sb.append(port);
158 sb.append((char) HttpCodecUtil.COMMA);
159 }
160 sb.setCharAt(sb.length() - 1, (char) HttpCodecUtil.DOUBLE_QUOTE);
161 sb.append((char) HttpCodecUtil.SEMICOLON);
162 }
163 if (cookie.isDiscard()) {
164 sb.append(CookieHeaderNames.DISCARD);
165 sb.append((char) HttpCodecUtil.SEMICOLON);
166 }
167 }
168 }
169
170 if (sb.length() > 0) {
171 sb.setLength(sb.length() - 1);
172 }
173
174 return sb.toString();
175 }
176
177 private String encodeClientSide() {
178 StringBuilder sb = new StringBuilder();
179
180 for (Cookie cookie: cookies) {
181 if (cookie.getVersion() >= 1) {
182 add(sb, '$' + CookieHeaderNames.VERSION, 1);
183 }
184
185 add(sb, cookie.getName(), cookie.getValue());
186
187 if (cookie.getPath() != null) {
188 add(sb, '$' + CookieHeaderNames.PATH, cookie.getPath());
189 }
190
191 if (cookie.getDomain() != null) {
192 add(sb, '$' + CookieHeaderNames.DOMAIN, cookie.getDomain());
193 }
194
195 if (cookie.getVersion() >= 1) {
196 if(!cookie.getPorts().isEmpty()) {
197 sb.append('$');
198 sb.append(CookieHeaderNames.PORT);
199 sb.append((char) HttpCodecUtil.EQUALS);
200 sb.append((char) HttpCodecUtil.DOUBLE_QUOTE);
201 for (int port: cookie.getPorts()) {
202 sb.append(port);
203 sb.append((char) HttpCodecUtil.COMMA);
204 }
205 sb.setCharAt(sb.length() - 1, (char) HttpCodecUtil.DOUBLE_QUOTE);
206 sb.append((char) HttpCodecUtil.SEMICOLON);
207 }
208 }
209 }
210
211 if(sb.length() > 0)
212 sb.setLength(sb.length() - 1);
213 return sb.toString();
214 }
215
216 private static void add(StringBuilder sb, String name, String val) {
217 if (val == null) {
218 addQuoted(sb, name, "");
219 return;
220 }
221
222 for (int i = 0; i < val.length(); i ++) {
223 char c = val.charAt(i);
224 switch (c) {
225 case '\t': case ' ': case '"': case '(': case ')': case ',':
226 case '/': case ':': case ';': case '<': case '=': case '>':
227 case '?': case '@': case '[': case '\\': case ']':
228 case '{': case '}':
229 addQuoted(sb, name, val);
230 return;
231 }
232 }
233
234 addUnquoted(sb, name, val);
235 }
236
237 private static void addUnquoted(StringBuilder sb, String name, String val) {
238 sb.append(name);
239 sb.append((char) HttpCodecUtil.EQUALS);
240 sb.append(val);
241 sb.append((char) HttpCodecUtil.SEMICOLON);
242 }
243
244 private static void addQuoted(StringBuilder sb, String name, String val) {
245 if (val == null) {
246 val = "";
247 }
248
249 sb.append(name);
250 sb.append((char) HttpCodecUtil.EQUALS);
251 sb.append((char) HttpCodecUtil.DOUBLE_QUOTE);
252 sb.append(val.replace("\\", "\\\\").replace("\"", "\\\""));
253 sb.append((char) HttpCodecUtil.DOUBLE_QUOTE);
254 sb.append((char) HttpCodecUtil.SEMICOLON);
255 }
256
257 private static void add(StringBuilder sb, String name, int val) {
258 sb.append(name);
259 sb.append((char) HttpCodecUtil.EQUALS);
260 sb.append(val);
261 sb.append((char) HttpCodecUtil.SEMICOLON);
262 }
263 }