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 package org.apache.http.impl.cookie;
29
30 import java.util.ArrayList;
31 import java.util.Collections;
32 import java.util.List;
33
34 import org.apache.http.annotation.NotThreadSafe;
35
36 import org.apache.http.Header;
37 import org.apache.http.HeaderElement;
38 import org.apache.http.cookie.ClientCookie;
39 import org.apache.http.cookie.Cookie;
40 import org.apache.http.cookie.CookieOrigin;
41 import org.apache.http.cookie.CookiePathComparator;
42 import org.apache.http.cookie.CookieRestrictionViolationException;
43 import org.apache.http.cookie.CookieSpec;
44 import org.apache.http.cookie.MalformedCookieException;
45 import org.apache.http.cookie.SM;
46 import org.apache.http.message.BufferedHeader;
47 import org.apache.http.util.CharArrayBuffer;
48
49
50
51
52
53
54
55
56
57
58 @NotThreadSafe
59 public class RFC2109Spec extends CookieSpecBase {
60
61 private final static CookiePathComparator PATH_COMPARATOR = new CookiePathComparator();
62
63 private final static String[] DATE_PATTERNS = {
64 DateUtils.PATTERN_RFC1123,
65 DateUtils.PATTERN_RFC1036,
66 DateUtils.PATTERN_ASCTIME
67 };
68
69 private final String[] datepatterns;
70 private final boolean oneHeader;
71
72
73 public RFC2109Spec(final String[] datepatterns, boolean oneHeader) {
74 super();
75 if (datepatterns != null) {
76 this.datepatterns = datepatterns.clone();
77 } else {
78 this.datepatterns = DATE_PATTERNS;
79 }
80 this.oneHeader = oneHeader;
81 registerAttribHandler(ClientCookie.VERSION_ATTR, new RFC2109VersionHandler());
82 registerAttribHandler(ClientCookie.PATH_ATTR, new BasicPathHandler());
83 registerAttribHandler(ClientCookie.DOMAIN_ATTR, new RFC2109DomainHandler());
84 registerAttribHandler(ClientCookie.MAX_AGE_ATTR, new BasicMaxAgeHandler());
85 registerAttribHandler(ClientCookie.SECURE_ATTR, new BasicSecureHandler());
86 registerAttribHandler(ClientCookie.COMMENT_ATTR, new BasicCommentHandler());
87 registerAttribHandler(ClientCookie.EXPIRES_ATTR, new BasicExpiresHandler(
88 this.datepatterns));
89 }
90
91
92 public RFC2109Spec() {
93 this(null, false);
94 }
95
96 public List<Cookie> parse(final Header header, final CookieOrigin origin)
97 throws MalformedCookieException {
98 if (header == null) {
99 throw new IllegalArgumentException("Header may not be null");
100 }
101 if (origin == null) {
102 throw new IllegalArgumentException("Cookie origin may not be null");
103 }
104 if (!header.getName().equalsIgnoreCase(SM.SET_COOKIE)) {
105 throw new MalformedCookieException("Unrecognized cookie header '"
106 + header.toString() + "'");
107 }
108 HeaderElement[] elems = header.getElements();
109 return parse(elems, origin);
110 }
111
112 @Override
113 public void validate(final Cookie cookie, final CookieOrigin origin)
114 throws MalformedCookieException {
115 if (cookie == null) {
116 throw new IllegalArgumentException("Cookie may not be null");
117 }
118 String name = cookie.getName();
119 if (name.indexOf(' ') != -1) {
120 throw new CookieRestrictionViolationException("Cookie name may not contain blanks");
121 }
122 if (name.startsWith("$")) {
123 throw new CookieRestrictionViolationException("Cookie name may not start with $");
124 }
125 super.validate(cookie, origin);
126 }
127
128 public List<Header> formatCookies(List<Cookie> cookies) {
129 if (cookies == null) {
130 throw new IllegalArgumentException("List of cookies may not be null");
131 }
132 if (cookies.isEmpty()) {
133 throw new IllegalArgumentException("List of cookies may not be empty");
134 }
135 if (cookies.size() > 1) {
136
137 cookies = new ArrayList<Cookie>(cookies);
138 Collections.sort(cookies, PATH_COMPARATOR);
139 }
140 if (this.oneHeader) {
141 return doFormatOneHeader(cookies);
142 } else {
143 return doFormatManyHeaders(cookies);
144 }
145 }
146
147 private List<Header> doFormatOneHeader(final List<Cookie> cookies) {
148 int version = Integer.MAX_VALUE;
149
150 for (Cookie cookie : cookies) {
151 if (cookie.getVersion() < version) {
152 version = cookie.getVersion();
153 }
154 }
155 CharArrayBuffer buffer = new CharArrayBuffer(40 * cookies.size());
156 buffer.append(SM.COOKIE);
157 buffer.append(": ");
158 buffer.append("$Version=");
159 buffer.append(Integer.toString(version));
160 for (Cookie cooky : cookies) {
161 buffer.append("; ");
162 Cookie cookie = cooky;
163 formatCookieAsVer(buffer, cookie, version);
164 }
165 List<Header> headers = new ArrayList<Header>(1);
166 headers.add(new BufferedHeader(buffer));
167 return headers;
168 }
169
170 private List<Header> doFormatManyHeaders(final List<Cookie> cookies) {
171 List<Header> headers = new ArrayList<Header>(cookies.size());
172 for (Cookie cookie : cookies) {
173 int version = cookie.getVersion();
174 CharArrayBuffer buffer = new CharArrayBuffer(40);
175 buffer.append("Cookie: ");
176 buffer.append("$Version=");
177 buffer.append(Integer.toString(version));
178 buffer.append("; ");
179 formatCookieAsVer(buffer, cookie, version);
180 headers.add(new BufferedHeader(buffer));
181 }
182 return headers;
183 }
184
185
186
187
188
189
190
191
192
193
194 protected void formatParamAsVer(final CharArrayBuffer buffer,
195 final String name, final String value, int version) {
196 buffer.append(name);
197 buffer.append("=");
198 if (value != null) {
199 if (version > 0) {
200 buffer.append('\"');
201 buffer.append(value);
202 buffer.append('\"');
203 } else {
204 buffer.append(value);
205 }
206 }
207 }
208
209
210
211
212
213
214
215
216 protected void formatCookieAsVer(final CharArrayBuffer buffer,
217 final Cookie cookie, int version) {
218 formatParamAsVer(buffer, cookie.getName(), cookie.getValue(), version);
219 if (cookie.getPath() != null) {
220 if (cookie instanceof ClientCookie
221 && ((ClientCookie) cookie).containsAttribute(ClientCookie.PATH_ATTR)) {
222 buffer.append("; ");
223 formatParamAsVer(buffer, "$Path", cookie.getPath(), version);
224 }
225 }
226 if (cookie.getDomain() != null) {
227 if (cookie instanceof ClientCookie
228 && ((ClientCookie) cookie).containsAttribute(ClientCookie.DOMAIN_ATTR)) {
229 buffer.append("; ");
230 formatParamAsVer(buffer, "$Domain", cookie.getDomain(), version);
231 }
232 }
233 }
234
235 public int getVersion() {
236 return 1;
237 }
238
239 public Header getVersionHeader() {
240 return null;
241 }
242
243 @Override
244 public String toString() {
245 return "rfc2109";
246 }
247
248 }