marcsaeg 02/02/22 11:13:51 Modified: httpclient/src/java/org/apache/commons/httpclient Cookie.java Log: 1) Added better support for Netscape cookies. 2) Fixed cookie sorting problem. The previous implementation used a set and the compare() method made cookies with identical paths compre as equals which prevented them from being added. Revision Changes Path 1.14 +97 -26 jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/Cookie.java Index: Cookie.java =================================================================== RCS file: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/Cookie.java,v retrieving revision 1.13 retrieving revision 1.14 diff -u -r1.13 -r1.14 --- Cookie.java 19 Feb 2002 00:15:18 -0000 1.13 +++ Cookie.java 22 Feb 2002 19:13:51 -0000 1.14 @@ -1,7 +1,7 @@ /* - * $Header: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/Cookie.java,v 1.13 2002/02/19 00:15:18 dion Exp $ - * $Revision: 1.13 $ - * $Date: 2002/02/19 00:15:18 $ + * $Header: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/Cookie.java,v 1.14 2002/02/22 19:13:51 marcsaeg Exp $ + * $Revision: 1.14 $ + * $Date: 2002/02/22 19:13:51 $ * ==================================================================== * * The Apache Software License, Version 1.1 @@ -68,8 +68,9 @@ import java.util.Enumeration; import java.util.Vector; import java.util.Locale; -import java.util.Set; -import java.util.TreeSet; +import java.util.StringTokenizer; +import java.util.List; +import java.util.LinkedList; import java.util.Comparator; import java.util.Iterator; import java.text.RuleBasedCollator; @@ -87,7 +88,7 @@ * @author Rod Waldhoff * @author dIon Gillard * @author <a href="mailto:[EMAIL PROTECTED]">John Evans</a> - * @version $Revision: 1.13 $ $Date: 2002/02/19 00:15:18 $ + * @version $Revision: 1.14 $ $Date: 2002/02/22 19:13:51 $ */ public class Cookie extends NameValuePair implements Serializable, Comparator { @@ -350,11 +351,11 @@ StringBuffer buf = new StringBuffer(); buf.append(getName()).append("=").append(getValue()); if (_path != null) { - buf.append(";$Path="); + buf.append("; $Path="); buf.append(_path); } if (_domain != null) { - buf.append(";$Domain="); + buf.append("; $Domain="); buf.append(_domain); } return buf.toString(); @@ -473,20 +474,18 @@ if (cookies.length <= 0) { return null; } - Set addedCookies = new TreeSet(cookies[0]); + List addedCookies = new LinkedList(); for(int i=0;i<cookies.length;i++) { if(cookies[i].matches(domain,port,path,secure,now)) { - addedCookies.add(cookies[i]); + addInPathOrder(addedCookies, cookies[i]); added = true; } } if (added) { for (Iterator itr = addedCookies.iterator(); itr.hasNext(); ) { Cookie cookie = (Cookie)itr.next(); - if (cookie.matches(domain,port,path,secure,now)) { - value.append(";"); - value.append(cookie.toExternalForm()); - } + value.append("; "); + value.append(cookie.toExternalForm()); } return new Header("Cookie", value.toString()); @@ -728,7 +727,7 @@ } // check version - if (cookie.getVersion() != 1) { + if (cookie.getVersion() < 0 || cookie.getVersion() > 1) { if(log.isInfoEnabled()) { log.info("Cookie.parse(): Rejecting set cookie header \"" + setCookie.getValue() + "\" because it has an unrecognized version attribute (" + cookie.getVersion() + ")."); } @@ -756,16 +755,41 @@ " Illegal domain attribute" + cookie.getDomain()); } - // host minus domain may not contain any dots - if (domain.substring(0, - domain.length() - - cookie.getDomain().length()).indexOf('.') != -1) { - if(log.isInfoEnabled()) { - log.info("Cookie.parse(): Rejecting set cookie header \"" + setCookie.getValue() + "\" because \"" + cookie.getName() + "\" has an illegal domain attribute (\"" + cookie.getDomain() + "\") for the given domain \"" + domain + "\"."); + if(cookie.getVersion() == 0){ + // Validate domain using Netscape cookie specification + int domainParts = new StringTokenizer(domain, ".").countTokens(); + if(isSpecialDomain(domain)){ + if(domainParts < 2){ + if(log.isInfoEnabled()) { + log.info("Cookie.parse(): Rejecting set cookie header \"" + setCookie.getValue() + "\" because \"" + cookie.getName() + "\" has an illegal domain attribute (\"" + cookie.getDomain() + "\") for the given domain \"" + domain + "\". It violoates the Netscape cookie specification for special TLDs."); + } + throw new HttpException( + "Bad Set-Cookie header: " + setCookie.getValue() + + " Illegal domain attribute " + cookie.getDomain()); + } + }else{ + if(domainParts < 3){ + if(log.isInfoEnabled()) { + log.info("Cookie.parse(): Rejecting set cookie header \"" + setCookie.getValue() + "\" because \"" + cookie.getName() + "\" has an illegal domain attribute (\"" + cookie.getDomain() + "\") for the given domain \"" + domain + "\". It violoates the Netscape cookie specification for non-special TLDs."); + } + throw new HttpException( + "Bad Set-Cookie header: " + setCookie.getValue() + + " Illegal domain attribute " + cookie.getDomain()); + } + + } + }else{ + // host minus domain may not contain any dots + if (domain.substring(0, + domain.length() - + cookie.getDomain().length()).indexOf('.') != -1) { + if(log.isInfoEnabled()) { + log.info("Cookie.parse(): Rejecting set cookie header \"" + setCookie.getValue() + "\" because \"" + cookie.getName() + "\" has an illegal domain attribute (\"" + cookie.getDomain() + "\") for the given domain \"" + domain + "\"."); + } + throw new HttpException( + "Bad Set-Cookie header: " + setCookie.getValue() + + " Illegal domain attribute " + cookie.getDomain()); } - throw new HttpException( - "Bad Set-Cookie header: " + setCookie.getValue() + - " Illegal domain attribute " + cookie.getDomain()); } } @@ -815,6 +839,49 @@ return cookies; } + /** + * Checks if the given domain is in one of the seven special + * top level domains defined by the Netscape cookie specification. + */ + private static boolean isSpecialDomain(String domain) + { + 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; + + } + + /** + * Adds the given cookie into the given in descending path order. That is, + * more specific path to least specific paths. This may not be the fastest + * algorythm, but it'll work OK for the small number of cookies we're + * generally dealing with. + * + * @param list - the list to add the cookie to + * @param addCookie - the Cookie to add to list + */ + private static void addInPathOrder(List list, Cookie addCookie) + { + int i = 0; + + for(i=0;i<list.size();i++){ + Cookie c = (Cookie)list.get(i); + if(addCookie.compare(addCookie, c) > 0){ + break; + } + } + list.add(i, addCookie); + } + // ----------------------------------------------------- Instance Variables /** My comment. */ @@ -833,12 +900,12 @@ private boolean _secure; /** The version of the cookie specification I was created from. */ - private int _version = 1; + private int _version = 0; // -------------------------------------------------------------- Constants /** List of valid date formats for the "expires" cookie attribute. */ - private static final DateFormat[] expiryFormats = new DateFormat[4]; + private static final DateFormat[] expiryFormats = new DateFormat[6]; /** Collator for Cookie comparisons. Could be replaced with references to specific Locales. */ private static final RuleBasedCollator stringCollator = @@ -855,6 +922,10 @@ expiryFormats[2] = new SimpleDateFormat("EEE dd-MMM-yy HH:mm:ss z", Locale.US); expiryFormats[3] = new SimpleDateFormat("EEE dd-MMM-yyyy HH:mm:ss z", + Locale.US); + expiryFormats[4] = new SimpleDateFormat("EEE dd MMM yy HH:mm:ss z", + Locale.US); + expiryFormats[5] = new SimpleDateFormat("EEE dd MMM yyyy HH:mm:ss z", Locale.US); }
-- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>