[jboss-remoting-commits] JBoss Remoting SVN: r4002 - remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie.

jboss-remoting-commits at lists.jboss.org jboss-remoting-commits at lists.jboss.org
Thu Apr 17 22:17:51 EDT 2008


Author: david.lloyd at jboss.com
Date: 2008-04-17 22:17:50 -0400 (Thu, 17 Apr 2008)
New Revision: 4002

Removed:
   remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/CookieDomain.java
Modified:
   remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/Cookie.java
   remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/CookieClientSession.java
   remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/CookieMatcher.java
   remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/CookieParser.java
   remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/CookieValidator.java
   remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/SimpleCookieMatcher.java
   remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/SimpleCookieParser.java
   remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/SimpleCookieValidator.java
Log:
Redo (and simplify) cookies

Modified: remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/Cookie.java
===================================================================
--- remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/Cookie.java	2008-04-17 03:03:00 UTC (rev 4001)
+++ remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/Cookie.java	2008-04-18 02:17:50 UTC (rev 4002)
@@ -12,12 +12,12 @@
     private final String value;
     private final String name;
     private final String path;
-    private final CookieDomain domain;
+    private final String domain;
     private final long expires;
     private final boolean secure;
     private final Key key;
 
-    public Cookie(final String name, final String value, final String path, final CookieDomain domain, final long expires, final boolean secure) {
+    public Cookie(final String name, final String value, final String path, final String domain, final long expires, final boolean secure) {
         this.expires = expires;
         if (name == null) {
             throw new NullPointerException("name is null");
@@ -34,7 +34,7 @@
         this.name = name;
         this.value = value;
         this.path = path;
-        this.domain = domain;
+        this.domain = domain.toLowerCase();
         this.secure = secure;
         key = new Key(name, path);
     }
@@ -51,7 +51,7 @@
         return path;
     }
 
-    public CookieDomain getDomain() {
+    public String getDomain() {
         return domain;
     }
 

Modified: remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/CookieClientSession.java
===================================================================
--- remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/CookieClientSession.java	2008-04-17 03:03:00 UTC (rev 4001)
+++ remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/CookieClientSession.java	2008-04-18 02:17:50 UTC (rev 4002)
@@ -41,10 +41,9 @@
      * @return the cookie header value
      */
     public String getCookieHeader(String domain, String path, boolean secureRequest) {
-        final CookieDomain cookieDomain = new CookieDomain(domain);
         final SortedMap<Cookie.Key, Cookie> sortedValidatedCookies = new TreeMap<Cookie.Key, Cookie>();
         for (final Cookie cookie : cookieMap.values()) {
-            if (cookieMatcher.matches(cookie, cookieDomain, path, secureRequest)) {
+            if (cookieMatcher.matches(cookie, domain, path, secureRequest)) {
                 sortedValidatedCookies.put(cookie.getKey(), cookie);
             }
         }
@@ -66,15 +65,12 @@
      * @param path the request path
      */
     public void handleSetCookieHeader(String headerValue, String domain, String path) {
-        final CookieDomain requestDomain = new CookieDomain(domain);
-        final Cookie[] cookies = cookieParser.parseSetCookie(headerValue, requestDomain, path);
-        for (Cookie cookie : cookies) {
-            if (! cookieValidator.isValid(cookie, requestDomain)) {
-                log.trace("Ignoring invalid cookie %s", cookie);
-            } else {
-                log.trace("Adding cookie '%s' from domain '%s'", cookie, requestDomain);
-                cookieMap.put(cookie.getKey(), cookie);
-            }
+        final Cookie cookie = cookieParser.parseSetCookie(headerValue, domain, path);
+        if (! cookieValidator.isValid(cookie, domain)) {
+            log.trace("Ignoring invalid cookie %s", cookie);
+        } else {
+            log.trace("Adding cookie '%s' from domain '%s'", cookie, domain);
+            cookieMap.put(cookie.getKey(), cookie);
         }
     }
 }

Deleted: remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/CookieDomain.java
===================================================================
--- remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/CookieDomain.java	2008-04-17 03:03:00 UTC (rev 4001)
+++ remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/CookieDomain.java	2008-04-18 02:17:50 UTC (rev 4002)
@@ -1,87 +0,0 @@
-package org.jboss.cx.remoting.http.cookie;
-
-import java.io.Serializable;
-import java.util.Arrays;
-import org.jboss.cx.remoting.util.CollectionUtil;
-import static org.jboss.cx.remoting.util.CollectionUtil.split;
-import static org.jboss.cx.remoting.util.CollectionUtil.toArrayReversed;
-
-/**
- *
- */
-public final class CookieDomain implements Serializable {
-
-    public static final CookieDomain LOCAL = new CookieDomain(".local");
-
-    private static final long serialVersionUID = 1L;
-
-    private final String[] parts;
-    private final boolean hostDomainName;
-
-    private CookieDomain(String[] parts, boolean hostDomainName) {
-        this.parts = parts;
-        this.hostDomainName = hostDomainName;
-    }
-
-    public CookieDomain(String domain) {
-        if (domain == null) {
-            throw new NullPointerException("domain is null");
-        }
-        if (domain.length() == 0) {
-            throw new IllegalArgumentException("domain is empty");
-        }
-        hostDomainName = domain.charAt(0) == '.';
-        final String baseDomain = hostDomainName ? domain.substring(1).toLowerCase() : domain.toLowerCase();
-        parts = toArrayReversed(split(".", baseDomain).iterator(), String.class);
-    }
-
-    public boolean equals(final CookieDomain other) {
-        return other != null && hostDomainName == other.hostDomainName && Arrays.equals(parts, other.parts);
-    }
-
-    public boolean equals(final Object other) {
-        return other instanceof CookieDomain && equals((CookieDomain)other);
-    }
-
-    public int hashCode() {
-        return Arrays.hashCode(parts) + (hostDomainName ? 1 : 0);
-    }
-
-    public String toString() {
-        final StringBuilder builder = new StringBuilder(40);
-        builder.append("Domain: ");
-        for (String x : parts) {
-            builder.append(x);
-            builder.append('/');
-        }
-        builder.setLength(builder.length() - 1);
-        return builder.toString();
-    }
-
-    public boolean matches(final CookieDomain other) {
-        // todo this doesn't quite match rfc 2965
-        return other.hostDomainName ? CollectionUtil.arrayStartsWith(parts, other.parts) : Arrays.equals(other.parts, parts); 
-    }
-
-    public int getPartCount() {
-        return parts.length;
-    }
-
-    public String getPart(int index) {
-        return parts[index];
-    }
-
-    public boolean hasParent() {
-        return parts.length > 1;
-    }
-
-    public boolean isHostDomainName() {
-        return hostDomainName;
-    }
-
-    public CookieDomain getParent() {
-        final String[] parentParts = new String[parts.length - 1];
-        System.arraycopy(parts, 0, parentParts, 0, parentParts.length);
-        return new CookieDomain(parentParts, false);
-    }
-}

Modified: remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/CookieMatcher.java
===================================================================
--- remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/CookieMatcher.java	2008-04-17 03:03:00 UTC (rev 4001)
+++ remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/CookieMatcher.java	2008-04-18 02:17:50 UTC (rev 4002)
@@ -14,5 +14,5 @@
      * @param secure whether the request is on a secure channel
      * @return {@code true} if the cookie should be sent
      */
-    boolean matches(Cookie cookie, CookieDomain requestDomain, String path, boolean secure);
+    boolean matches(Cookie cookie, String requestDomain, String path, boolean secure);
 }

Modified: remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/CookieParser.java
===================================================================
--- remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/CookieParser.java	2008-04-17 03:03:00 UTC (rev 4001)
+++ remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/CookieParser.java	2008-04-18 02:17:50 UTC (rev 4002)
@@ -4,5 +4,5 @@
  *
  */
 public interface CookieParser {
-    Cookie[] parseSetCookie(String setCookie, CookieDomain defaultDomain, String defaultPath);
+    Cookie parseSetCookie(String setCookie, String defaultDomain, String defaultPath);
 }

Modified: remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/CookieValidator.java
===================================================================
--- remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/CookieValidator.java	2008-04-17 03:03:00 UTC (rev 4001)
+++ remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/CookieValidator.java	2008-04-18 02:17:50 UTC (rev 4002)
@@ -9,8 +9,8 @@
      * Determine whether a cookie from a server is valid.
      *
      * @param cookie the cookie from the server
-     * @param fromDomain the actual domain that the request was sent to
+     * @param requestDomain the domain that the request was sent to
      * @return {@code true} if the cookie is valid
      */
-    boolean isValid(Cookie cookie, CookieDomain fromDomain);
+    boolean isValid(Cookie cookie, String requestDomain);
 }

Modified: remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/SimpleCookieMatcher.java
===================================================================
--- remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/SimpleCookieMatcher.java	2008-04-17 03:03:00 UTC (rev 4001)
+++ remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/SimpleCookieMatcher.java	2008-04-18 02:17:50 UTC (rev 4002)
@@ -5,12 +5,12 @@
  */
 public final class SimpleCookieMatcher implements CookieMatcher {
 
-    public boolean matches(final Cookie cookie, final CookieDomain requestDomain, final String path, final boolean secure) {
+    public boolean matches(final Cookie cookie, final String requestDomain, final String path, final boolean secure) {
         final boolean cookieSecure = cookie.isSecure();
         if (cookieSecure && ! secure) {
             return false;
         }
-        final CookieDomain cookieDomain = cookie.getDomain();
+        final String cookieDomain = cookie.getDomain();
         final String cookiePath = cookie.getPath();
         return requestDomain.matches(cookieDomain) && path.startsWith(cookiePath) && !cookie.isExpired();
     }

Modified: remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/SimpleCookieParser.java
===================================================================
--- remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/SimpleCookieParser.java	2008-04-17 03:03:00 UTC (rev 4001)
+++ remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/SimpleCookieParser.java	2008-04-18 02:17:50 UTC (rev 4002)
@@ -2,9 +2,9 @@
 
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
-import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 import org.jboss.cx.remoting.log.Logger;
-import org.jboss.cx.remoting.util.CollectionUtil;
 
 /**
  *
@@ -26,7 +26,10 @@
         }
     }
 
-    public Cookie[] parseSetCookie(final String setCookie, final CookieDomain defaultDomain, final String defaultPath) {
+    private static final String PAIR_PATTERN_STRING = "(\\s*+[^=;]*?)(?:\\s+=\\s*+([^;]*?)\\s+)(?:;|$)";
+    private static final Pattern PAIR_PATTERN = Pattern.compile(PAIR_PATTERN_STRING);
+
+    public Cookie parseSetCookie(final String setCookie, final String defaultDomain, final String defaultPath) {
         if (setCookie == null) {
             throw new NullPointerException("setCookie is null");
         }
@@ -36,48 +39,46 @@
         if (defaultPath == null) {
             throw new NullPointerException("defaultPath is null");
         }
+        final Matcher matcher = PAIR_PATTERN.matcher(setCookie);
+        if (! matcher.find()) {
+            return null; // no cookie!
+        }
+        final String name = matcher.group(1);
+        final String value = matcher.group(2);
+        if (name == null || value == null) {
+            return null; // no cookie!
+        }
         boolean secure = false;
         long expires = 0L;
-        CookieDomain domain = defaultDomain;
         String path = defaultPath;
-        List<Pair> pairs = CollectionUtil.arrayList();
-        for (final String s : CollectionUtil.split(";", setCookie)) {
-            final String assignment = s.trim();
-            final int equalsPos = assignment.indexOf('=');
-            if (equalsPos == -1) {
-                if (assignment.toLowerCase().equals("secure")) {
-                    secure = true;
-                    continue;
+        String domain = defaultDomain;
+        while (matcher.find()) {
+            final String attrName = matcher.group(1);
+            final String attrValue = matcher.group(2);
+            if ("secure".equalsIgnoreCase(attrName) && attrValue == null) {
+                secure = true;
+            } else if ("expires".equalsIgnoreCase(attrName) && attrValue != null) {
+                final int gmti = value.lastIndexOf(" GMT");
+                final String dateValue;
+                if (gmti != -1) {
+                    dateValue = attrValue.substring(0, gmti);
+                } else {
+                    dateValue = attrValue;
                 }
+                final SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT);
+                try {
+                    expires = dateFormat.parse(dateValue).getTime();
+                } catch (ParseException e) {
+                    log.trace("Invalid cookie expiration date '%s'", value);
+                }
+            } else if ("domain".equalsIgnoreCase(attrName) && attrValue != null) {
+                domain = attrValue;
+            } else if ("path".equalsIgnoreCase(attrName) && attrValue != null) {
+                path = attrValue;
             } else {
-                String name = assignment.substring(0, equalsPos).trim();
-                String lowerName = name.toLowerCase();
-                String value = assignment.substring(equalsPos + 1).trim();
-                if (lowerName.equals("expires")) {
-                    final int gmti = value.lastIndexOf(" GMT");
-                    if (gmti != -1) {
-                        value = value.substring(0, gmti);
-                    }
-                    final SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT);
-                    try {
-                        expires = dateFormat.parse(value).getTime();
-                    } catch (ParseException e) {
-                        log.trace("Invalid cookie expiration date '%s'", value);
-                    }
-                } else if (lowerName.equals("domain")) {
-                    domain = new CookieDomain(value);
-                } else if (lowerName.equals("path")) {
-                    path = value;
-                } else {
-                    pairs.add(new Pair(name, value));
-                }
+                log.trace("Unknown cookie attribute-value pair: \"%s\"=\"%s\"", attrName, attrValue);
             }
         }
-        Cookie[] cookies = new Cookie[pairs.size()];
-        int i = 0;
-        for (Pair pair : pairs) {
-            cookies[i++] = new Cookie(pair.name, pair.value, path, domain, expires, secure);
-        }
-        return cookies;
+        return new Cookie(name, value, path, domain, expires, secure);
     }
 }

Modified: remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/SimpleCookieValidator.java
===================================================================
--- remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/SimpleCookieValidator.java	2008-04-17 03:03:00 UTC (rev 4001)
+++ remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/SimpleCookieValidator.java	2008-04-18 02:17:50 UTC (rev 4002)
@@ -3,6 +3,8 @@
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.Set;
+import java.util.regex.Pattern;
+import org.jboss.cx.remoting.log.Logger;
 
 /**
  * Simple cookie validator.  Validates a cookie coming down from a server.  See
@@ -10,8 +12,13 @@
  * for more info.
  */
 public final class SimpleCookieValidator implements CookieValidator {
+    private static final String DOMAIN_PATTERN_STRING = "^(?:(?:[a-zA-Z0-9][a-zA-Z0-9]+)(?:-(?:[a-zA-Z0-9][a-zA-Z0-9]+))*(?:\\.(?:(?:[a-zA-Z0-9][a-zA-Z0-9]+)(?:-(?:[a-zA-Z0-9][a-zA-Z0-9]+))*)+$";
+    private static final Pattern DOMAIN_PATTERN = Pattern.compile(DOMAIN_PATTERN_STRING);
+
     private static final Set<String> TLD_SET;
 
+    private static final Logger log = Logger.getLogger(SimpleCookieValidator.class);
+
     static {
         final HashSet<String> tldSet = new HashSet<String>();
         tldSet.add("com");
@@ -24,29 +31,49 @@
         TLD_SET = Collections.unmodifiableSet(tldSet);
     }
 
-    public boolean isValid(final Cookie cookie, final CookieDomain requestDomain) {
-        final CookieDomain cookieDomain = cookie.getDomain();
-        for (int i = 0; i < cookieDomain.getPartCount(); i++) {
-            if (cookieDomain.getPart(i).length() == 0) {
-                return false;
-            }
+    private static void logReject(Cookie cookie, String requestDomain, String reason) {
+        log.trace("Rejecting cookie \"%s\" from request domain \"%s\": %s", cookie.getName(), requestDomain, reason);
+    }
+
+    public boolean isValid(final Cookie cookie, final String requestDomain) {
+
+        final String cookieDomain = cookie.getDomain();
+        final String matchDomain;
+        if (cookieDomain.length() == 0) {
+            logReject(cookie, requestDomain, "cookie domain length is zero");
+            return false;
         }
-        final int numParts = cookieDomain.getPartCount() + (cookieDomain.isHostDomainName() ? 1 : 0);
-        final String tld = numParts == 0 ? null : cookieDomain.getPart(0);
-        final int minSegments = TLD_SET.contains(tld) ? 3 : 4;
-        if (numParts < minSegments) {
-            // not valid: domain name is too short
+        if (cookieDomain.charAt(0) == '.') {
+            matchDomain = cookieDomain.substring(1);
+        } else {
+            matchDomain = cookieDomain;
+        }
+        if (! DOMAIN_PATTERN.matcher(matchDomain).matches()) {
+            logReject(cookie, requestDomain, "cookie has an invalid domain");
             return false;
         }
+        final String effectiveDomain;
+        if (matchDomain.indexOf('.') == -1) {
+            effectiveDomain = matchDomain + ".local";
+        } else {
+            effectiveDomain = matchDomain;
+        }
+        final String tld = effectiveDomain.substring(effectiveDomain.lastIndexOf('.') + 1);
+        final int minDots = TLD_SET.contains(tld) ? 1 : 2;
+        int dotCount = 0;
+        for (int p = effectiveDomain.indexOf('.', 0); p != -1; p = effectiveDomain.indexOf('.', p + 1)) {
+            dotCount ++;
+        }
+        if (dotCount < minDots) {
+            logReject(cookie, requestDomain, "cookie domain name is too short (see http://wp.netscape.com/newsref/std/cookie_spec.html)");
+            return false;
+        }
         final String path = cookie.getPath();
         if (path.length() == 0 || path.charAt(0) != '/') {
-            // not valid: bad or missing path
+            logReject(cookie, requestDomain, "cookie path is invalid");
             return false;
         }
-        if (! requestDomain.matches(cookieDomain)) {
-            // wrong domain
-            return false;
-        }
+        log.trace("Accepting cookie \"%s\" from request domain \"%s\"", cookie.getName(), requestDomain);
         return true;
     }
 }




More information about the jboss-remoting-commits mailing list