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 */
27
28 package org.apache.http.impl.cookie;
29
30 import java.util.ArrayList;
31 import java.util.List;
32
33 import org.apache.http.FormattedHeader;
34 import org.apache.http.Header;
35 import org.apache.http.HeaderElement;
36 import org.apache.http.annotation.Contract;
37 import org.apache.http.annotation.Obsolete;
38 import org.apache.http.annotation.ThreadingBehavior;
39 import org.apache.http.cookie.CommonCookieAttributeHandler;
40 import org.apache.http.cookie.Cookie;
41 import org.apache.http.cookie.CookieOrigin;
42 import org.apache.http.cookie.MalformedCookieException;
43 import org.apache.http.cookie.SM;
44 import org.apache.http.message.BufferedHeader;
45 import org.apache.http.message.ParserCursor;
46 import org.apache.http.util.Args;
47 import org.apache.http.util.CharArrayBuffer;
48
49 /**
50 * This {@link org.apache.http.cookie.CookieSpec} implementation conforms to
51 * the original draft specification published by Netscape Communications.
52 * It should be avoided unless absolutely necessary for compatibility with
53 * legacy applications.
54 * <p>
55 * Rendered obsolete by {@link org.apache.http.impl.cookie.RFC6265LaxSpec}.
56 *
57 * @since 4.0
58 * @see org.apache.http.impl.cookie.RFC6265LaxSpec
59 */
60 @Obsolete
61 @Contract(threading = ThreadingBehavior.SAFE)
62 public class NetscapeDraftSpec extends CookieSpecBase {
63
64 protected static final String EXPIRES_PATTERN = "EEE, dd-MMM-yy HH:mm:ss z";
65
66 /** Default constructor */
67 public NetscapeDraftSpec(final String[] datepatterns) {
68 super(new BasicPathHandler(),
69 new NetscapeDomainHandler(),
70 new BasicSecureHandler(),
71 new BasicCommentHandler(),
72 new BasicExpiresHandler(
73 datepatterns != null ? datepatterns.clone() : new String[]{EXPIRES_PATTERN}));
74 }
75
76 NetscapeDraftSpec(final CommonCookieAttributeHandler... handlers) {
77 super(handlers);
78 }
79
80 public NetscapeDraftSpec() {
81 this((String[]) null);
82 }
83
84 /**
85 * Parses the Set-Cookie value into an array of {@code Cookie}s.
86 *
87 * <p>Syntax of the Set-Cookie HTTP Response Header:</p>
88 *
89 * <p>This is the format a CGI script would use to add to
90 * the HTTP headers a new piece of data which is to be stored by
91 * the client for later retrieval.</p>
92 *
93 * <PRE>
94 * Set-Cookie: NAME=VALUE; expires=DATE; path=PATH; domain=DOMAIN_NAME; secure
95 * </PRE>
96 *
97 * <p>Please note that the Netscape draft specification does not fully conform to the HTTP
98 * header format. Comma character if present in {@code Set-Cookie} will not be treated
99 * 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 }
176