1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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 package edu.internet2.middleware.grouperClientExt.org.apache.commons.httpclient.cookie;
47
48 import edu.internet2.middleware.grouperClientExt.org.apache.commons.httpclient.Cookie;
49 import edu.internet2.middleware.grouperClientExt.org.apache.commons.httpclient.NameValuePair;
50 import edu.internet2.middleware.grouperClientExt.org.apache.commons.httpclient.util.ParameterFormatter;
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69 public class RFC2109Spec extends CookieSpecBase {
70
71 private final ParameterFormatter formatter;
72
73
74
75
76
77 public final static String SET_COOKIE_KEY = "set-cookie";
78
79
80 public RFC2109Spec() {
81 super();
82 this.formatter = new ParameterFormatter();
83 this.formatter.setAlwaysUseQuotes(true);
84 }
85
86
87
88
89
90
91
92
93
94
95 public void parseAttribute(
96 final NameValuePair attribute, final Cookie cookie)
97 throws MalformedCookieException {
98
99 if (attribute == null) {
100 throw new IllegalArgumentException("Attribute may not be null.");
101 }
102 if (cookie == null) {
103 throw new IllegalArgumentException("Cookie may not be null.");
104 }
105 final String paramName = attribute.getName().toLowerCase();
106 final String paramValue = attribute.getValue();
107
108 if (paramName.equals("path")) {
109 if (paramValue == null) {
110 throw new MalformedCookieException(
111 "Missing value for path attribute");
112 }
113 if (paramValue.trim().equals("")) {
114 throw new MalformedCookieException(
115 "Blank value for path attribute");
116 }
117 cookie.setPath(paramValue);
118 cookie.setPathAttributeSpecified(true);
119 } else if (paramName.equals("version")) {
120
121 if (paramValue == null) {
122 throw new MalformedCookieException(
123 "Missing value for version attribute");
124 }
125 try {
126 cookie.setVersion(Integer.parseInt(paramValue));
127 } catch (NumberFormatException e) {
128 throw new MalformedCookieException("Invalid version: "
129 + e.getMessage());
130 }
131
132 } else {
133 super.parseAttribute(attribute, cookie);
134 }
135 }
136
137
138
139
140
141
142
143
144
145
146
147
148
149 public void validate(String host, int port, String path,
150 boolean secure, final Cookie cookie) throws MalformedCookieException {
151
152 LOG.trace("enter RFC2109Spec.validate(String, int, String, "
153 + "boolean, Cookie)");
154
155
156 super.validate(host, port, path, secure, cookie);
157
158
159 if (cookie.getName().indexOf(' ') != -1) {
160 throw new MalformedCookieException("Cookie name may not contain blanks");
161 }
162 if (cookie.getName().startsWith("$")) {
163 throw new MalformedCookieException("Cookie name may not start with $");
164 }
165
166 if (cookie.isDomainAttributeSpecified()
167 && (!cookie.getDomain().equals(host))) {
168
169
170 if (!cookie.getDomain().startsWith(".")) {
171 throw new MalformedCookieException("Domain attribute \""
172 + cookie.getDomain()
173 + "\" violates RFC 2109: domain must start with a dot");
174 }
175
176 int dotIndex = cookie.getDomain().indexOf('.', 1);
177 if (dotIndex < 0 || dotIndex == cookie.getDomain().length() - 1) {
178 throw new MalformedCookieException("Domain attribute \""
179 + cookie.getDomain()
180 + "\" violates RFC 2109: domain must contain an embedded dot");
181 }
182 host = host.toLowerCase();
183 if (!host.endsWith(cookie.getDomain())) {
184 throw new MalformedCookieException(
185 "Illegal domain attribute \"" + cookie.getDomain()
186 + "\". Domain of origin: \"" + host + "\"");
187 }
188
189 String hostWithoutDomain = host.substring(0, host.length()
190 - cookie.getDomain().length());
191 if (hostWithoutDomain.indexOf('.') != -1) {
192 throw new MalformedCookieException("Domain attribute \""
193 + cookie.getDomain()
194 + "\" violates RFC 2109: host minus domain may not contain any dots");
195 }
196 }
197 }
198
199
200
201
202
203
204
205
206
207 public boolean domainMatch(String host, String domain) {
208 boolean match = host.equals(domain)
209 || (domain.startsWith(".") && host.endsWith(domain));
210
211 return match;
212 }
213
214
215
216
217
218
219
220
221
222 private void formatParam(final StringBuffer buffer, final NameValuePair param, int version) {
223 if (version < 1) {
224 buffer.append(param.getName());
225 buffer.append("=");
226 if (param.getValue() != null) {
227 buffer.append(param.getValue());
228 }
229 } else {
230 this.formatter.format(buffer, param);
231 }
232 }
233
234
235
236
237
238
239
240
241 private void formatCookieAsVer(final StringBuffer buffer, final Cookie cookie, int version) {
242 String value = cookie.getValue();
243 if (value == null) {
244 value = "";
245 }
246 formatParam(buffer, new NameValuePair(cookie.getName(), value), version);
247 if ((cookie.getPath() != null) && cookie.isPathAttributeSpecified()) {
248 buffer.append("; ");
249 formatParam(buffer, new NameValuePair("$Path", cookie.getPath()), version);
250 }
251 if ((cookie.getDomain() != null)
252 && cookie.isDomainAttributeSpecified()) {
253 buffer.append("; ");
254 formatParam(buffer, new NameValuePair("$Domain", cookie.getDomain()), version);
255 }
256 }
257
258
259
260
261
262
263
264 public String formatCookie(Cookie cookie) {
265 LOG.trace("enter RFC2109Spec.formatCookie(Cookie)");
266 if (cookie == null) {
267 throw new IllegalArgumentException("Cookie may not be null");
268 }
269 int version = cookie.getVersion();
270 StringBuffer buffer = new StringBuffer();
271 formatParam(buffer,
272 new NameValuePair("$Version", Integer.toString(version)),
273 version);
274 buffer.append("; ");
275 formatCookieAsVer(buffer, cookie, version);
276 return buffer.toString();
277 }
278
279
280
281
282
283
284
285
286 public String formatCookies(Cookie[] cookies) {
287 LOG.trace("enter RFC2109Spec.formatCookieHeader(Cookie[])");
288 int version = Integer.MAX_VALUE;
289
290 for (int i = 0; i < cookies.length; i++) {
291 Cookie cookie = cookies[i];
292 if (cookie.getVersion() < version) {
293 version = cookie.getVersion();
294 }
295 }
296 final StringBuffer buffer = new StringBuffer();
297 formatParam(buffer,
298 new NameValuePair("$Version", Integer.toString(version)),
299 version);
300 for (int i = 0; i < cookies.length; i++) {
301 buffer.append("; ");
302 formatCookieAsVer(buffer, cookies[i], version);
303 }
304 return buffer.toString();
305 }
306
307 }