1 /* 2 * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/cookie/RFC2109Spec.java $ 3 * $Revision: 677240 $ 4 * $Date: 2008-07-16 04:25:47 -0700 (Wed, 16 Jul 2008) $ 5 * 6 * ==================================================================== 7 * Licensed to the Apache Software Foundation (ASF) under one 8 * or more contributor license agreements. See the NOTICE file 9 * distributed with this work for additional information 10 * regarding copyright ownership. The ASF licenses this file 11 * to you under the Apache License, Version 2.0 (the 12 * "License"); you may not use this file except in compliance 13 * with the License. You may obtain a copy of the License at 14 * 15 * http://www.apache.org/licenses/LICENSE-2.0 16 * 17 * Unless required by applicable law or agreed to in writing, 18 * software distributed under the License is distributed on an 19 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 20 * KIND, either express or implied. See the License for the 21 * specific language governing permissions and limitations 22 * under the License. 23 * ==================================================================== 24 * 25 * This software consists of voluntary contributions made by many 26 * individuals on behalf of the Apache Software Foundation. For more 27 * information on the Apache Software Foundation, please see 28 * <http://www.apache.org/>. 29 * 30 */ 31 32 package org.apache.http.impl.cookie; 33 34 import java.util.ArrayList; 35 import java.util.Collections; 36 import java.util.List; 37 38 import org.apache.http.Header; 39 import org.apache.http.HeaderElement; 40 import org.apache.http.cookie.ClientCookie; 41 import org.apache.http.cookie.Cookie; 42 import org.apache.http.cookie.CookieOrigin; 43 import org.apache.http.cookie.CookiePathComparator; 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 * RFC 2109 compliant cookie policy 51 * 52 * @author B.C. Holmes 53 * @author <a href="mailto:jericho@thinkfree.com">Park, Sung-Gu</a> 54 * @author <a href="mailto:dsale@us.britannica.com">Doug Sale</a> 55 * @author Rod Waldhoff 56 * @author dIon Gillard 57 * @author Sean C. Sullivan 58 * @author <a href="mailto:JEvans@Cyveillance.com">John Evans</a> 59 * @author Marc A. Saegesser 60 * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a> 61 * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a> 62 * 63 * @since 4.0 64 * 65 * @deprecated Please use {@link java.net.URL#openConnection} instead. 66 * Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a> 67 * for further details. 68 */ 69 70 @Deprecated 71 public class RFC2109Spec extends CookieSpecBase { 72 73 private final static CookiePathComparator PATH_COMPARATOR = new CookiePathComparator(); 74 75 private final static String[] DATE_PATTERNS = { 76 DateUtils.PATTERN_RFC1123, 77 DateUtils.PATTERN_RFC1036, 78 DateUtils.PATTERN_ASCTIME 79 }; 80 81 private final String[] datepatterns; 82 private final boolean oneHeader; 83 84 /** Default constructor */ RFC2109Spec(final String[] datepatterns, boolean oneHeader)85 public RFC2109Spec(final String[] datepatterns, boolean oneHeader) { 86 super(); 87 if (datepatterns != null) { 88 this.datepatterns = datepatterns.clone(); 89 } else { 90 this.datepatterns = DATE_PATTERNS; 91 } 92 this.oneHeader = oneHeader; 93 registerAttribHandler(ClientCookie.VERSION_ATTR, new RFC2109VersionHandler()); 94 registerAttribHandler(ClientCookie.PATH_ATTR, new BasicPathHandler()); 95 registerAttribHandler(ClientCookie.DOMAIN_ATTR, new RFC2109DomainHandler()); 96 registerAttribHandler(ClientCookie.MAX_AGE_ATTR, new BasicMaxAgeHandler()); 97 registerAttribHandler(ClientCookie.SECURE_ATTR, new BasicSecureHandler()); 98 registerAttribHandler(ClientCookie.COMMENT_ATTR, new BasicCommentHandler()); 99 registerAttribHandler(ClientCookie.EXPIRES_ATTR, new BasicExpiresHandler( 100 this.datepatterns)); 101 } 102 103 /** Default constructor */ RFC2109Spec()104 public RFC2109Spec() { 105 this(null, false); 106 } 107 parse(final Header header, final CookieOrigin origin)108 public List<Cookie> parse(final Header header, final CookieOrigin origin) 109 throws MalformedCookieException { 110 if (header == null) { 111 throw new IllegalArgumentException("Header may not be null"); 112 } 113 if (origin == null) { 114 throw new IllegalArgumentException("Cookie origin may not be null"); 115 } 116 HeaderElement[] elems = header.getElements(); 117 return parse(elems, origin); 118 } 119 120 @Override validate(final Cookie cookie, final CookieOrigin origin)121 public void validate(final Cookie cookie, final CookieOrigin origin) 122 throws MalformedCookieException { 123 if (cookie == null) { 124 throw new IllegalArgumentException("Cookie may not be null"); 125 } 126 String name = cookie.getName(); 127 if (name.indexOf(' ') != -1) { 128 throw new MalformedCookieException("Cookie name may not contain blanks"); 129 } 130 if (name.startsWith("$")) { 131 throw new MalformedCookieException("Cookie name may not start with $"); 132 } 133 super.validate(cookie, origin); 134 } 135 formatCookies(List<Cookie> cookies)136 public List<Header> formatCookies(List<Cookie> cookies) { 137 if (cookies == null) { 138 throw new IllegalArgumentException("List of cookies may not be null"); 139 } 140 if (cookies.isEmpty()) { 141 throw new IllegalArgumentException("List of cookies may not be empty"); 142 } 143 if (cookies.size() > 1) { 144 // Create a mutable copy and sort the copy. 145 cookies = new ArrayList<Cookie>(cookies); 146 Collections.sort(cookies, PATH_COMPARATOR); 147 } 148 if (this.oneHeader) { 149 return doFormatOneHeader(cookies); 150 } else { 151 return doFormatManyHeaders(cookies); 152 } 153 } 154 doFormatOneHeader(final List<Cookie> cookies)155 private List<Header> doFormatOneHeader(final List<Cookie> cookies) { 156 int version = Integer.MAX_VALUE; 157 // Pick the lowest common denominator 158 for (Cookie cookie : cookies) { 159 if (cookie.getVersion() < version) { 160 version = cookie.getVersion(); 161 } 162 } 163 CharArrayBuffer buffer = new CharArrayBuffer(40 * cookies.size()); 164 buffer.append(SM.COOKIE); 165 buffer.append(": "); 166 buffer.append("$Version="); 167 buffer.append(Integer.toString(version)); 168 for (Cookie cooky : cookies) { 169 buffer.append("; "); 170 Cookie cookie = cooky; 171 formatCookieAsVer(buffer, cookie, version); 172 } 173 List<Header> headers = new ArrayList<Header>(1); 174 headers.add(new BufferedHeader(buffer)); 175 return headers; 176 } 177 doFormatManyHeaders(final List<Cookie> cookies)178 private List<Header> doFormatManyHeaders(final List<Cookie> cookies) { 179 List<Header> headers = new ArrayList<Header>(cookies.size()); 180 for (Cookie cookie : cookies) { 181 int version = cookie.getVersion(); 182 CharArrayBuffer buffer = new CharArrayBuffer(40); 183 buffer.append("Cookie: "); 184 buffer.append("$Version="); 185 buffer.append(Integer.toString(version)); 186 buffer.append("; "); 187 formatCookieAsVer(buffer, cookie, version); 188 headers.add(new BufferedHeader(buffer)); 189 } 190 return headers; 191 } 192 193 /** 194 * Return a name/value string suitable for sending in a <tt>"Cookie"</tt> 195 * header as defined in RFC 2109 for backward compatibility with cookie 196 * version 0 197 * @param buffer The char array buffer to use for output 198 * @param name The cookie name 199 * @param value The cookie value 200 * @param version The cookie version 201 */ formatParamAsVer(final CharArrayBuffer buffer, final String name, final String value, int version)202 protected void formatParamAsVer(final CharArrayBuffer buffer, 203 final String name, final String value, int version) { 204 buffer.append(name); 205 buffer.append("="); 206 if (value != null) { 207 if (version > 0) { 208 buffer.append('\"'); 209 buffer.append(value); 210 buffer.append('\"'); 211 } else { 212 buffer.append(value); 213 } 214 } 215 } 216 217 /** 218 * Return a string suitable for sending in a <tt>"Cookie"</tt> header 219 * as defined in RFC 2109 for backward compatibility with cookie version 0 220 * @param buffer The char array buffer to use for output 221 * @param cookie The {@link Cookie} to be formatted as string 222 * @param version The version to use. 223 */ formatCookieAsVer(final CharArrayBuffer buffer, final Cookie cookie, int version)224 protected void formatCookieAsVer(final CharArrayBuffer buffer, 225 final Cookie cookie, int version) { 226 formatParamAsVer(buffer, cookie.getName(), cookie.getValue(), version); 227 if (cookie.getPath() != null) { 228 if (cookie instanceof ClientCookie 229 && ((ClientCookie) cookie).containsAttribute(ClientCookie.PATH_ATTR)) { 230 buffer.append("; "); 231 formatParamAsVer(buffer, "$Path", cookie.getPath(), version); 232 } 233 } 234 if (cookie.getDomain() != null) { 235 if (cookie instanceof ClientCookie 236 && ((ClientCookie) cookie).containsAttribute(ClientCookie.DOMAIN_ATTR)) { 237 buffer.append("; "); 238 formatParamAsVer(buffer, "$Domain", cookie.getDomain(), version); 239 } 240 } 241 } 242 getVersion()243 public int getVersion() { 244 return 1; 245 } 246 getVersionHeader()247 public Header getVersionHeader() { 248 return null; 249 } 250 251 } 252