Wed, 31 Dec 2014 07:22:50 +0100
Correct previous dual key logic pending first delivery installment.
1 /*
2 * ====================================================================
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 * ====================================================================
20 *
21 * This software consists of voluntary contributions made by many
22 * individuals on behalf of the Apache Software Foundation. For more
23 * information on the Apache Software Foundation, please see
24 * <http://www.apache.org/>.
25 *
26 */
28 package ch.boye.httpclientandroidlib.impl.cookie;
30 import java.util.ArrayList;
31 import java.util.List;
33 import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
35 import ch.boye.httpclientandroidlib.FormattedHeader;
36 import ch.boye.httpclientandroidlib.Header;
37 import ch.boye.httpclientandroidlib.HeaderElement;
38 import ch.boye.httpclientandroidlib.cookie.ClientCookie;
39 import ch.boye.httpclientandroidlib.cookie.Cookie;
40 import ch.boye.httpclientandroidlib.cookie.CookieOrigin;
41 import ch.boye.httpclientandroidlib.cookie.MalformedCookieException;
42 import ch.boye.httpclientandroidlib.cookie.SM;
43 import ch.boye.httpclientandroidlib.message.BufferedHeader;
44 import ch.boye.httpclientandroidlib.message.ParserCursor;
45 import ch.boye.httpclientandroidlib.util.CharArrayBuffer;
47 /**
48 * Cookie specification that strives to closely mimic (mis)behavior of
49 * common web browser applications such as Microsoft Internet Explorer
50 * and Mozilla FireFox.
51 *
52 *
53 * @since 4.0
54 */
55 @NotThreadSafe // superclass is @NotThreadSafe
56 public class BrowserCompatSpec extends CookieSpecBase {
58 @Deprecated
59 protected static final String[] DATE_PATTERNS = new String[] {
60 DateUtils.PATTERN_RFC1123,
61 DateUtils.PATTERN_RFC1036,
62 DateUtils.PATTERN_ASCTIME,
63 "EEE, dd-MMM-yyyy HH:mm:ss z",
64 "EEE, dd-MMM-yyyy HH-mm-ss z",
65 "EEE, dd MMM yy HH:mm:ss z",
66 "EEE dd-MMM-yyyy HH:mm:ss z",
67 "EEE dd MMM yyyy HH:mm:ss z",
68 "EEE dd-MMM-yyyy HH-mm-ss z",
69 "EEE dd-MMM-yy HH:mm:ss z",
70 "EEE dd MMM yy HH:mm:ss z",
71 "EEE,dd-MMM-yy HH:mm:ss z",
72 "EEE,dd-MMM-yyyy HH:mm:ss z",
73 "EEE, dd-MM-yyyy HH:mm:ss z",
74 };
76 private static final String[] DEFAULT_DATE_PATTERNS = new String[] {
77 DateUtils.PATTERN_RFC1123,
78 DateUtils.PATTERN_RFC1036,
79 DateUtils.PATTERN_ASCTIME,
80 "EEE, dd-MMM-yyyy HH:mm:ss z",
81 "EEE, dd-MMM-yyyy HH-mm-ss z",
82 "EEE, dd MMM yy HH:mm:ss z",
83 "EEE dd-MMM-yyyy HH:mm:ss z",
84 "EEE dd MMM yyyy HH:mm:ss z",
85 "EEE dd-MMM-yyyy HH-mm-ss z",
86 "EEE dd-MMM-yy HH:mm:ss z",
87 "EEE dd MMM yy HH:mm:ss z",
88 "EEE,dd-MMM-yy HH:mm:ss z",
89 "EEE,dd-MMM-yyyy HH:mm:ss z",
90 "EEE, dd-MM-yyyy HH:mm:ss z",
91 };
93 private final String[] datepatterns;
95 /** Default constructor */
96 public BrowserCompatSpec(final String[] datepatterns) {
97 super();
98 if (datepatterns != null) {
99 this.datepatterns = datepatterns.clone();
100 } else {
101 this.datepatterns = DEFAULT_DATE_PATTERNS;
102 }
103 registerAttribHandler(ClientCookie.PATH_ATTR, new BasicPathHandler());
104 registerAttribHandler(ClientCookie.DOMAIN_ATTR, new BasicDomainHandler());
105 registerAttribHandler(ClientCookie.MAX_AGE_ATTR, new BasicMaxAgeHandler());
106 registerAttribHandler(ClientCookie.SECURE_ATTR, new BasicSecureHandler());
107 registerAttribHandler(ClientCookie.COMMENT_ATTR, new BasicCommentHandler());
108 registerAttribHandler(ClientCookie.EXPIRES_ATTR, new BasicExpiresHandler(
109 this.datepatterns));
110 }
112 /** Default constructor */
113 public BrowserCompatSpec() {
114 this(null);
115 }
117 public List<Cookie> parse(final Header header, final CookieOrigin origin)
118 throws MalformedCookieException {
119 if (header == null) {
120 throw new IllegalArgumentException("Header may not be null");
121 }
122 if (origin == null) {
123 throw new IllegalArgumentException("Cookie origin may not be null");
124 }
125 String headername = header.getName();
126 if (!headername.equalsIgnoreCase(SM.SET_COOKIE)) {
127 throw new MalformedCookieException("Unrecognized cookie header '"
128 + header.toString() + "'");
129 }
130 HeaderElement[] helems = header.getElements();
131 boolean versioned = false;
132 boolean netscape = false;
133 for (HeaderElement helem: helems) {
134 if (helem.getParameterByName("version") != null) {
135 versioned = true;
136 }
137 if (helem.getParameterByName("expires") != null) {
138 netscape = true;
139 }
140 }
141 if (netscape || !versioned) {
142 // Need to parse the header again, because Netscape style cookies do not correctly
143 // support multiple header elements (comma cannot be treated as an element separator)
144 NetscapeDraftHeaderParser parser = NetscapeDraftHeaderParser.DEFAULT;
145 CharArrayBuffer buffer;
146 ParserCursor cursor;
147 if (header instanceof FormattedHeader) {
148 buffer = ((FormattedHeader) header).getBuffer();
149 cursor = new ParserCursor(
150 ((FormattedHeader) header).getValuePos(),
151 buffer.length());
152 } else {
153 String s = header.getValue();
154 if (s == null) {
155 throw new MalformedCookieException("Header value is null");
156 }
157 buffer = new CharArrayBuffer(s.length());
158 buffer.append(s);
159 cursor = new ParserCursor(0, buffer.length());
160 }
161 helems = new HeaderElement[] { parser.parseHeader(buffer, cursor) };
162 }
163 return parse(helems, origin);
164 }
166 public List<Header> formatCookies(final List<Cookie> cookies) {
167 if (cookies == null) {
168 throw new IllegalArgumentException("List of cookies may not be null");
169 }
170 if (cookies.isEmpty()) {
171 throw new IllegalArgumentException("List of cookies may not be empty");
172 }
173 CharArrayBuffer buffer = new CharArrayBuffer(20 * cookies.size());
174 buffer.append(SM.COOKIE);
175 buffer.append(": ");
176 for (int i = 0; i < cookies.size(); i++) {
177 Cookie cookie = cookies.get(i);
178 if (i > 0) {
179 buffer.append("; ");
180 }
181 buffer.append(cookie.getName());
182 buffer.append("=");
183 String s = cookie.getValue();
184 if (s != null) {
185 buffer.append(s);
186 }
187 }
188 List<Header> headers = new ArrayList<Header>(1);
189 headers.add(new BufferedHeader(buffer));
190 return headers;
191 }
193 public int getVersion() {
194 return 0;
195 }
197 public Header getVersionHeader() {
198 return null;
199 }
201 @Override
202 public String toString() {
203 return "compatibility";
204 }
206 }