- /*
- * $Header: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/cookie/NetscapeDraftSpec.java,v 1.11 2004/05/13 04:02:00 mbecke Exp $
- * $Revision: 1.11 $
- * $Date: 2004/05/13 04:02:00 $
- *
- * ====================================================================
- *
- * Copyright 2002-2004 The Apache Software Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- */
-
- package org.apache.commons.httpclient.cookie;
-
- import java.util.StringTokenizer;
- import java.util.Date;
- import java.util.Locale;
- import java.text.DateFormat;
- import java.text.SimpleDateFormat;
- import java.text.ParseException;
-
- import org.apache.commons.httpclient.HeaderElement;
- import org.apache.commons.httpclient.NameValuePair;
- import org.apache.commons.httpclient.Cookie;
-
- /**
- * <P>Netscape cookie draft specific cookie management functions
- *
- * @author B.C. Holmes
- * @author <a href="mailto:jericho@thinkfree.com">Park, Sung-Gu</a>
- * @author <a href="mailto:dsale@us.britannica.com">Doug Sale</a>
- * @author Rod Waldhoff
- * @author dIon Gillard
- * @author Sean C. Sullivan
- * @author <a href="mailto:JEvans@Cyveillance.com">John Evans</a>
- * @author Marc A. Saegesser
- * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
- * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
- *
- * @since 2.0
- */
-
- public class NetscapeDraftSpec extends CookieSpecBase {
-
- /** Default constructor */
- public NetscapeDraftSpec() {
- super();
- }
-
- /**
- * Parses the Set-Cookie value into an array of <tt>Cookie</tt>s.
- *
- * <p>Syntax of the Set-Cookie HTTP Response Header:</p>
- *
- * <p>This is the format a CGI script would use to add to
- * the HTTP headers a new piece of data which is to be stored by
- * the client for later retrieval.</p>
- *
- * <PRE>
- * Set-Cookie: NAME=VALUE; expires=DATE; path=PATH; domain=DOMAIN_NAME; secure
- * </PRE>
- *
- * <p>Please note that Netscape draft specification does not fully
- * conform to the HTTP header format. Netscape draft does not specify
- * whether multiple cookies may be sent in one header. Hence, comma
- * character may be present in unquoted cookie value or unquoted
- * parameter value.</p>
- *
- * @link http://wp.netscape.com/newsref/std/cookie_spec.html
- *
- * @param host the host from which the <tt>Set-Cookie</tt> value was
- * received
- * @param port the port from which the <tt>Set-Cookie</tt> value was
- * received
- * @param path the path from which the <tt>Set-Cookie</tt> value was
- * received
- * @param secure <tt>true</tt> when the <tt>Set-Cookie</tt> value was
- * received over secure conection
- * @param header the <tt>Set-Cookie</tt> received from the server
- * @return an array of <tt>Cookie</tt>s parsed from the Set-Cookie value
- * @throws MalformedCookieException if an exception occurs during parsing
- *
- * @since 3.0
- */
- public Cookie[] parse(String host, int port, String path,
- boolean secure, final String header)
- throws MalformedCookieException {
-
- LOG.trace("enter NetscapeDraftSpec.parse(String, port, path, boolean, Header)");
-
- if (host == null) {
- throw new IllegalArgumentException("Host of origin may not be null");
- }
- if (host.trim().equals("")) {
- throw new IllegalArgumentException("Host of origin may not be blank");
- }
- if (port < 0) {
- throw new IllegalArgumentException("Invalid port: " + port);
- }
- if (path == null) {
- throw new IllegalArgumentException("Path of origin may not be null.");
- }
- if (header == null) {
- throw new IllegalArgumentException("Header may not be null.");
- }
-
- if (path.trim().equals("")) {
- path = PATH_DELIM;
- }
- host = host.toLowerCase();
-
- String defaultPath = path;
- int lastSlashIndex = defaultPath.lastIndexOf(PATH_DELIM);
- if (lastSlashIndex >= 0) {
- if (lastSlashIndex == 0) {
- //Do not remove the very first slash
- lastSlashIndex = 1;
- }
- defaultPath = defaultPath.substring(0, lastSlashIndex);
- }
- HeaderElement headerelement = new HeaderElement(header.toCharArray());
- Cookie cookie = new Cookie(host,
- headerelement.getName(),
- headerelement.getValue(),
- defaultPath,
- null,
- false);
- // cycle through the parameters
- NameValuePair[] parameters = headerelement.getParameters();
- // could be null. In case only a header element and no parameters.
- if (parameters != null) {
- for (int j = 0; j < parameters.length; j++) {
- parseAttribute(parameters[j], cookie);
- }
- }
- return new Cookie[] {cookie};
- }
-
-
- /**
- * Parse the cookie attribute and update the corresponsing {@link Cookie}
- * properties as defined by the Netscape draft specification
- *
- * @param attribute {@link NameValuePair} cookie attribute from the
- * <tt>Set- Cookie</tt>
- * @param cookie {@link Cookie} to be updated
- * @throws MalformedCookieException if an exception occurs during parsing
- */
- public void parseAttribute(
- final NameValuePair attribute, final Cookie cookie)
- throws MalformedCookieException {
-
- if (attribute == null) {
- throw new IllegalArgumentException("Attribute may not be null.");
- }
- if (cookie == null) {
- throw new IllegalArgumentException("Cookie may not be null.");
- }
- final String paramName = attribute.getName().toLowerCase();
- final String paramValue = attribute.getValue();
-
- if (paramName.equals("expires")) {
-
- if (paramValue == null) {
- throw new MalformedCookieException(
- "Missing value for expires attribute");
- }
- try {
- DateFormat expiryFormat = new SimpleDateFormat(
- "EEE, dd-MMM-yyyy HH:mm:ss z", Locale.US);
- Date date = expiryFormat.parse(paramValue);
- cookie.setExpiryDate(date);
- } catch (ParseException e) {
- throw new MalformedCookieException("Invalid expires "
- + "attribute: " + e.getMessage());
- }
- } else {
- super.parseAttribute(attribute, cookie);
- }
- }
-
- /**
- * Performs Netscape draft compliant {@link Cookie} validation
- *
- * @param host the host from which the {@link Cookie} was received
- * @param port the port from which the {@link Cookie} was received
- * @param path the path from which the {@link Cookie} was received
- * @param secure <tt>true</tt> when the {@link Cookie} was received
- * using a secure connection
- * @param cookie The cookie to validate.
- * @throws MalformedCookieException if an exception occurs during
- * validation
- */
- public void validate(String host, int port, String path,
- boolean secure, final Cookie cookie)
- throws MalformedCookieException {
-
- LOG.trace("enterNetscapeDraftCookieProcessor "
- + "RCF2109CookieProcessor.validate(Cookie)");
- // Perform generic validation
- super.validate(host, port, path, secure, cookie);
- // Perform Netscape Cookie draft specific validation
- if (host.indexOf(".") >= 0) {
- int domainParts = new StringTokenizer(cookie.getDomain(), ".")
- .countTokens();
-
- if (isSpecialDomain(cookie.getDomain())) {
- if (domainParts < 2) {
- throw new MalformedCookieException("Domain attribute \""
- + cookie.getDomain()
- + "\" violates the Netscape cookie specification for "
- + "special domains");
- }
- } else {
- if (domainParts < 3) {
- throw new MalformedCookieException("Domain attribute \""
- + cookie.getDomain()
- + "\" violates the Netscape cookie specification");
- }
- }
- }
- }
-
- /**
- * Checks if the given domain is in one of the seven special
- * top level domains defined by the Netscape cookie specification.
- * @param domain The domain.
- * @return True if the specified domain is "special"
- */
- private static boolean isSpecialDomain(final String domain) {
- final String ucDomain = domain.toUpperCase();
- if (ucDomain.endsWith(".COM")
- || ucDomain.endsWith(".EDU")
- || ucDomain.endsWith(".NET")
- || ucDomain.endsWith(".GOV")
- || ucDomain.endsWith(".MIL")
- || ucDomain.endsWith(".ORG")
- || ucDomain.endsWith(".INT")) {
- return true;
- }
- return false;
- }
- }