1 /* 2 * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/cookie/NetscapeDraftSpec.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.List; 36 37 import org.apache.http.FormattedHeader; 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.MalformedCookieException; 44 import org.apache.http.cookie.SM; 45 import org.apache.http.message.BufferedHeader; 46 import org.apache.http.message.ParserCursor; 47 import org.apache.http.util.CharArrayBuffer; 48 49 /** 50 * Netscape cookie draft 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@ural.ru">Oleg Kalnichevski</a> 61 * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a> 62 * 63 * @since 4.0 64 */ 65 public class NetscapeDraftSpec extends CookieSpecBase { 66 67 protected static final String EXPIRES_PATTERN = "EEE, dd-MMM-yyyy HH:mm:ss z"; 68 69 private final String[] datepatterns; 70 71 /** Default constructor */ NetscapeDraftSpec(final String[] datepatterns)72 public NetscapeDraftSpec(final String[] datepatterns) { 73 super(); 74 if (datepatterns != null) { 75 this.datepatterns = datepatterns.clone(); 76 } else { 77 this.datepatterns = new String[] { EXPIRES_PATTERN }; 78 } 79 registerAttribHandler(ClientCookie.PATH_ATTR, new BasicPathHandler()); 80 registerAttribHandler(ClientCookie.DOMAIN_ATTR, new NetscapeDomainHandler()); 81 registerAttribHandler(ClientCookie.MAX_AGE_ATTR, new BasicMaxAgeHandler()); 82 registerAttribHandler(ClientCookie.SECURE_ATTR, new BasicSecureHandler()); 83 registerAttribHandler(ClientCookie.COMMENT_ATTR, new BasicCommentHandler()); 84 registerAttribHandler(ClientCookie.EXPIRES_ATTR, new BasicExpiresHandler( 85 this.datepatterns)); 86 } 87 88 /** Default constructor */ NetscapeDraftSpec()89 public NetscapeDraftSpec() { 90 this(null); 91 } 92 93 /** 94 * Parses the Set-Cookie value into an array of <tt>Cookie</tt>s. 95 * 96 * <p>Syntax of the Set-Cookie HTTP Response Header:</p> 97 * 98 * <p>This is the format a CGI script would use to add to 99 * the HTTP headers a new piece of data which is to be stored by 100 * the client for later retrieval.</p> 101 * 102 * <PRE> 103 * Set-Cookie: NAME=VALUE; expires=DATE; path=PATH; domain=DOMAIN_NAME; secure 104 * </PRE> 105 * 106 * <p>Please note that Netscape draft specification does not fully 107 * conform to the HTTP header format. Netscape draft does not specify 108 * whether multiple cookies may be sent in one header. Hence, comma 109 * character may be present in unquoted cookie value or unquoted 110 * parameter value.</p> 111 * 112 * @see <a href="http://wp.netscape.com/newsref/std/cookie_spec.html"> 113 * The Cookie Spec.</a> 114 * 115 * @param header the <tt>Set-Cookie</tt> received from the server 116 * @return an array of <tt>Cookie</tt>s parsed from the Set-Cookie value 117 * @throws MalformedCookieException if an exception occurs during parsing 118 */ parse(final Header header, final CookieOrigin origin)119 public List<Cookie> parse(final Header header, final CookieOrigin origin) 120 throws MalformedCookieException { 121 if (header == null) { 122 throw new IllegalArgumentException("Header may not be null"); 123 } 124 if (origin == null) { 125 throw new IllegalArgumentException("Cookie origin may not be null"); 126 } 127 NetscapeDraftHeaderParser parser = NetscapeDraftHeaderParser.DEFAULT; 128 CharArrayBuffer buffer; 129 ParserCursor cursor; 130 if (header instanceof FormattedHeader) { 131 buffer = ((FormattedHeader) header).getBuffer(); 132 cursor = new ParserCursor( 133 ((FormattedHeader) header).getValuePos(), 134 buffer.length()); 135 } else { 136 String s = header.getValue(); 137 if (s == null) { 138 throw new MalformedCookieException("Header value is null"); 139 } 140 buffer = new CharArrayBuffer(s.length()); 141 buffer.append(s); 142 cursor = new ParserCursor(0, buffer.length()); 143 } 144 return parse(new HeaderElement[] { parser.parseHeader(buffer, cursor) }, origin); 145 } 146 formatCookies(final List<Cookie> cookies)147 public List<Header> formatCookies(final List<Cookie> cookies) { 148 if (cookies == null) { 149 throw new IllegalArgumentException("List of cookies may not be null"); 150 } 151 if (cookies.isEmpty()) { 152 throw new IllegalArgumentException("List of cookies may not be empty"); 153 } 154 CharArrayBuffer buffer = new CharArrayBuffer(20 * cookies.size()); 155 buffer.append(SM.COOKIE); 156 buffer.append(": "); 157 for (int i = 0; i < cookies.size(); i++) { 158 Cookie cookie = cookies.get(i); 159 if (i > 0) { 160 buffer.append("; "); 161 } 162 buffer.append(cookie.getName()); 163 String s = cookie.getValue(); 164 if (s != null) { 165 buffer.append("="); 166 buffer.append(s); 167 } 168 } 169 List<Header> headers = new ArrayList<Header>(1); 170 headers.add(new BufferedHeader(buffer)); 171 return headers; 172 } 173 getVersion()174 public int getVersion() { 175 return 0; 176 } 177 getVersionHeader()178 public Header getVersionHeader() { 179 return null; 180 } 181 182 } 183