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.List;
31
32 import org.apache.http.FormattedHeader;
33 import org.apache.http.Header;
34 import org.apache.http.HeaderElement;
35 import org.apache.http.annotation.Contract;
36 import org.apache.http.annotation.ThreadingBehavior;
37 import org.apache.http.cookie.Cookie;
38 import org.apache.http.cookie.CookieOrigin;
39 import org.apache.http.cookie.CookieSpec;
40 import org.apache.http.cookie.MalformedCookieException;
41 import org.apache.http.cookie.SM;
42 import org.apache.http.cookie.SetCookie2;
43 import org.apache.http.message.ParserCursor;
44 import org.apache.http.util.Args;
45 import org.apache.http.util.CharArrayBuffer;
46
47
48
49
50
51
52
53 @Contract(threading = ThreadingBehavior.SAFE)
54 public class DefaultCookieSpec implements CookieSpec {
55
56 private final RFC2965Spec strict;
57 private final RFC2109Spec obsoleteStrict;
58 private final NetscapeDraftSpec netscapeDraft;
59
60 DefaultCookieSpec(
61 final RFC2965Spec strict,
62 final RFC2109Spec obsoleteStrict,
63 final NetscapeDraftSpec netscapeDraft) {
64 this.strict = strict;
65 this.obsoleteStrict = obsoleteStrict;
66 this.netscapeDraft = netscapeDraft;
67 }
68
69 public DefaultCookieSpec(
70 final String[] datepatterns,
71 final boolean oneHeader) {
72 this.strict = new RFC2965Spec(oneHeader,
73 new RFC2965VersionAttributeHandler(),
74 new BasicPathHandler(),
75 new RFC2965DomainAttributeHandler(),
76 new RFC2965PortAttributeHandler(),
77 new BasicMaxAgeHandler(),
78 new BasicSecureHandler(),
79 new BasicCommentHandler(),
80 new RFC2965CommentUrlAttributeHandler(),
81 new RFC2965DiscardAttributeHandler());
82 this.obsoleteStrict = new RFC2109Spec(oneHeader,
83 new RFC2109VersionHandler(),
84 new BasicPathHandler(),
85 new RFC2109DomainHandler(),
86 new BasicMaxAgeHandler(),
87 new BasicSecureHandler(),
88 new BasicCommentHandler());
89 this.netscapeDraft = new NetscapeDraftSpec(
90 new BasicDomainHandler(),
91 new BasicPathHandler(),
92 new BasicSecureHandler(),
93 new BasicCommentHandler(),
94 new BasicExpiresHandler(
95 datepatterns != null ? datepatterns.clone() : new String[]{NetscapeDraftSpec.EXPIRES_PATTERN}));
96 }
97
98 public DefaultCookieSpec() {
99 this(null, false);
100 }
101
102 @Override
103 public List<Cookie> parse(
104 final Header header,
105 final CookieOrigin origin) throws MalformedCookieException {
106 Args.notNull(header, "Header");
107 Args.notNull(origin, "Cookie origin");
108 HeaderElement[] hElems = header.getElements();
109 boolean versioned = false;
110 boolean netscape = false;
111 for (final HeaderElement hElem: hElems) {
112 if (hElem.getParameterByName("version") != null) {
113 versioned = true;
114 }
115 if (hElem.getParameterByName("expires") != null) {
116 netscape = true;
117 }
118 }
119 if (netscape || !versioned) {
120
121
122 final NetscapeDraftHeaderParser parser = NetscapeDraftHeaderParser.DEFAULT;
123 final CharArrayBuffer buffer;
124 final ParserCursor cursor;
125 if (header instanceof FormattedHeader) {
126 buffer = ((FormattedHeader) header).getBuffer();
127 cursor = new ParserCursor(
128 ((FormattedHeader) header).getValuePos(),
129 buffer.length());
130 } else {
131 final String hValue = header.getValue();
132 if (hValue == null) {
133 throw new MalformedCookieException("Header value is null");
134 }
135 buffer = new CharArrayBuffer(hValue.length());
136 buffer.append(hValue);
137 cursor = new ParserCursor(0, buffer.length());
138 }
139 hElems = new HeaderElement[] { parser.parseHeader(buffer, cursor) };
140 return netscapeDraft.parse(hElems, origin);
141 }
142 return SM.SET_COOKIE2.equals(header.getName())
143 ? strict.parse(hElems, origin)
144 : obsoleteStrict.parse(hElems, origin);
145 }
146
147 @Override
148 public void validate(
149 final Cookie cookie,
150 final CookieOrigin origin) throws MalformedCookieException {
151 Args.notNull(cookie, "Cookie");
152 Args.notNull(origin, "Cookie origin");
153 if (cookie.getVersion() > 0) {
154 if (cookie instanceof SetCookie2) {
155 strict.validate(cookie, origin);
156 } else {
157 obsoleteStrict.validate(cookie, origin);
158 }
159 } else {
160 netscapeDraft.validate(cookie, origin);
161 }
162 }
163
164 @Override
165 public boolean match(final Cookie cookie, final CookieOrigin origin) {
166 Args.notNull(cookie, "Cookie");
167 Args.notNull(origin, "Cookie origin");
168 if (cookie.getVersion() > 0) {
169 return cookie instanceof SetCookie2
170 ? strict.match(cookie, origin)
171 : obsoleteStrict.match(cookie, origin);
172 }
173 return netscapeDraft.match(cookie, origin);
174 }
175
176 @Override
177 public List<Header> formatCookies(final List<Cookie> cookies) {
178 Args.notNull(cookies, "List of cookies");
179 int version = Integer.MAX_VALUE;
180 boolean isSetCookie2 = true;
181 for (final Cookie cookie: cookies) {
182 if (!(cookie instanceof SetCookie2)) {
183 isSetCookie2 = false;
184 }
185 if (cookie.getVersion() < version) {
186 version = cookie.getVersion();
187 }
188 }
189 if (version > 0) {
190 return isSetCookie2
191 ? strict.formatCookies(cookies)
192 : obsoleteStrict.formatCookies(cookies);
193 }
194 return netscapeDraft.formatCookies(cookies);
195 }
196
197 @Override
198 public int getVersion() {
199 return strict.getVersion();
200 }
201
202 @Override
203 public Header getVersionHeader() {
204 return null;
205 }
206
207 @Override
208 public String toString() {
209 return "default";
210 }
211
212 }