001/* 002 * ==================================================================== 003 * Licensed to the Apache Software Foundation (ASF) under one 004 * or more contributor license agreements. See the NOTICE file 005 * distributed with this work for additional information 006 * regarding copyright ownership. The ASF licenses this file 007 * to you under the Apache License, Version 2.0 (the 008 * "License"); you may not use this file except in compliance 009 * with the License. You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, 014 * software distributed under the License is distributed on an 015 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 016 * KIND, either express or implied. See the License for the 017 * specific language governing permissions and limitations 018 * under the License. 019 * ==================================================================== 020 * 021 * This software consists of voluntary contributions made by many 022 * individuals on behalf of the Apache Software Foundation. For more 023 * information on the Apache Software Foundation, please see 024 * <http://www.apache.org/>. 025 * 026 */ 027 028package org.apache.http.impl.cookie; 029 030import java.util.ArrayList; 031import java.util.List; 032 033import org.apache.http.FormattedHeader; 034import org.apache.http.Header; 035import org.apache.http.HeaderElement; 036import org.apache.http.annotation.Contract; 037import org.apache.http.annotation.Obsolete; 038import org.apache.http.annotation.ThreadingBehavior; 039import org.apache.http.cookie.CommonCookieAttributeHandler; 040import org.apache.http.cookie.Cookie; 041import org.apache.http.cookie.CookieOrigin; 042import org.apache.http.cookie.MalformedCookieException; 043import org.apache.http.cookie.SM; 044import org.apache.http.message.BufferedHeader; 045import org.apache.http.message.ParserCursor; 046import org.apache.http.util.Args; 047import org.apache.http.util.CharArrayBuffer; 048 049/** 050 * This {@link org.apache.http.cookie.CookieSpec} implementation conforms to 051 * the original draft specification published by Netscape Communications. 052 * It should be avoided unless absolutely necessary for compatibility with 053 * legacy applications. 054 * <p> 055 * Rendered obsolete by {@link org.apache.http.impl.cookie.RFC6265LaxSpec}. 056 * 057 * @since 4.0 058 * @see org.apache.http.impl.cookie.RFC6265LaxSpec 059 */ 060@Obsolete 061@Contract(threading = ThreadingBehavior.SAFE) 062public class NetscapeDraftSpec extends CookieSpecBase { 063 064 protected static final String EXPIRES_PATTERN = "EEE, dd-MMM-yy HH:mm:ss z"; 065 066 /** Default constructor */ 067 public NetscapeDraftSpec(final String[] datepatterns) { 068 super(new BasicPathHandler(), 069 new NetscapeDomainHandler(), 070 new BasicSecureHandler(), 071 new BasicCommentHandler(), 072 new BasicExpiresHandler( 073 datepatterns != null ? datepatterns.clone() : new String[]{EXPIRES_PATTERN})); 074 } 075 076 NetscapeDraftSpec(final CommonCookieAttributeHandler... handlers) { 077 super(handlers); 078 } 079 080 public NetscapeDraftSpec() { 081 this((String[]) null); 082 } 083 084 /** 085 * Parses the Set-Cookie value into an array of {@code Cookie}s. 086 * 087 * <p>Syntax of the Set-Cookie HTTP Response Header:</p> 088 * 089 * <p>This is the format a CGI script would use to add to 090 * the HTTP headers a new piece of data which is to be stored by 091 * the client for later retrieval.</p> 092 * 093 * <PRE> 094 * Set-Cookie: NAME=VALUE; expires=DATE; path=PATH; domain=DOMAIN_NAME; secure 095 * </PRE> 096 * 097 * <p>Please note that the Netscape draft specification does not fully conform to the HTTP 098 * header format. Comma character if present in {@code Set-Cookie} will not be treated 099 * as a header element separator</p> 100 * 101 * @see <a href="http://web.archive.org/web/20020803110822/http://wp.netscape.com/newsref/std/cookie_spec.html"> 102 * The Cookie Spec.</a> 103 * 104 * @param header the {@code Set-Cookie} received from the server 105 * @return an array of {@code Cookie}s parsed from the Set-Cookie value 106 * @throws MalformedCookieException if an exception occurs during parsing 107 */ 108 @Override 109 public List<Cookie> parse(final Header header, final CookieOrigin origin) 110 throws MalformedCookieException { 111 Args.notNull(header, "Header"); 112 Args.notNull(origin, "Cookie origin"); 113 if (!header.getName().equalsIgnoreCase(SM.SET_COOKIE)) { 114 throw new MalformedCookieException("Unrecognized cookie header '" 115 + header.toString() + "'"); 116 } 117 final NetscapeDraftHeaderParser parser = NetscapeDraftHeaderParser.DEFAULT; 118 final CharArrayBuffer buffer; 119 final ParserCursor cursor; 120 if (header instanceof FormattedHeader) { 121 buffer = ((FormattedHeader) header).getBuffer(); 122 cursor = new ParserCursor( 123 ((FormattedHeader) header).getValuePos(), 124 buffer.length()); 125 } else { 126 final String s = header.getValue(); 127 if (s == null) { 128 throw new MalformedCookieException("Header value is null"); 129 } 130 buffer = new CharArrayBuffer(s.length()); 131 buffer.append(s); 132 cursor = new ParserCursor(0, buffer.length()); 133 } 134 return parse(new HeaderElement[] { parser.parseHeader(buffer, cursor) }, origin); 135 } 136 137 @Override 138 public List<Header> formatCookies(final List<Cookie> cookies) { 139 Args.notEmpty(cookies, "List of cookies"); 140 final CharArrayBuffer buffer = new CharArrayBuffer(20 * cookies.size()); 141 buffer.append(SM.COOKIE); 142 buffer.append(": "); 143 for (int i = 0; i < cookies.size(); i++) { 144 final Cookie cookie = cookies.get(i); 145 if (i > 0) { 146 buffer.append("; "); 147 } 148 buffer.append(cookie.getName()); 149 final String s = cookie.getValue(); 150 if (s != null) { 151 buffer.append("="); 152 buffer.append(s); 153 } 154 } 155 final List<Header> headers = new ArrayList<Header>(1); 156 headers.add(new BufferedHeader(buffer)); 157 return headers; 158 } 159 160 @Override 161 public int getVersion() { 162 return 0; 163 } 164 165 @Override 166 public Header getVersionHeader() { 167 return null; 168 } 169 170 @Override 171 public String toString() { 172 return "netscape"; 173 } 174 175}