Add an option to strictly enforce cookie naming rules.
authormarkt <markt@13f79535-47bb-0310-9956-ffa450edef68>
Thu, 29 Oct 2009 19:26:52 +0000 (19:26 +0000)
committermarkt <markt@13f79535-47bb-0310-9956-ffa450edef68>
Thu, 29 Oct 2009 19:26:52 +0000 (19:26 +0000)
I'm not wild about the implementation but since we can't change the API, this was the best I could come up with. Suggestions for improvements welcome.

git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@831069 13f79535-47bb-0310-9956-ffa450edef68

java/javax/servlet/http/Cookie.java
webapps/docs/config/systemprops.xml

index f174ead..5b6f159 100644 (file)
@@ -17,6 +17,7 @@
 package javax.servlet.http;
 
 import java.text.MessageFormat;
+import java.util.Date;
 import java.util.ResourceBundle;
 
 /**
@@ -486,8 +487,56 @@ public class Cookie implements Cloneable {
     // private static final String tspecials = "()<>@,;:\\\"/[]?={} \t";
 
     private static final String tspecials = ",; ";
+    private static final String tspecials2 = "()<>@,;:\\\"/[]?={} \t";
+    private static final String tspecials2NoSlash = "()<>@,;:\\\"/[]?={} \t";
     
-    
+    /**
+     * If set to true, we parse cookies strictly according to the servlet,
+     * cookie and HTTP specs by default.
+     */
+    private static final boolean STRICT_SERVLET_COMPLIANCE;
+
+    /**
+     * If set to true, the <code>/</code> character will be treated as a
+     * separator. Default is usually false. If STRICT_SERVLET_COMPLIANCE==true
+     * then default is true. Explicitly setting always takes priority.
+     */
+    private static final boolean FWD_SLASH_IS_SEPARATOR;
+
+    /**
+     * If set to false, we don't use the IE6/7 Max-Age/Expires work around.
+     * Default is usually true. If STRICT_SERVLET_COMPLIANCE==true then default
+     * is false. Explicitly setting always takes priority.
+     */
+    private static final boolean STRICT_NAMING;
+
+
+    static {
+        STRICT_SERVLET_COMPLIANCE = Boolean.valueOf(System.getProperty(
+                "org.apache.catalina.STRICT_SERVLET_COMPLIANCE",
+                "false")).booleanValue();
+
+        String  fwdSlashIsSeparator = System.getProperty(
+                "org.apache.tomcat.util.http.ServerCookie.FWD_SLASH_IS_SEPARATOR");
+        if (fwdSlashIsSeparator == null) {
+            FWD_SLASH_IS_SEPARATOR = STRICT_SERVLET_COMPLIANCE;
+        } else {
+            FWD_SLASH_IS_SEPARATOR =
+                Boolean.valueOf(fwdSlashIsSeparator).booleanValue();
+        }
+
+        String strictNaming = System.getProperty(
+                "javax.servlet.http.Cookie.STRICT_NAMING");
+        if (strictNaming == null) {
+            STRICT_NAMING = STRICT_SERVLET_COMPLIANCE;
+        } else {
+            STRICT_NAMING =
+                Boolean.valueOf(strictNaming).booleanValue();
+        }
+
+    }
+
+
     
 
     /*
@@ -500,24 +549,27 @@ public class Cookie implements Cloneable {
      *                         a reserved token; <code>false</code>
      *                         if it is not                    
      */
-
     private boolean isToken(String value) {
-       int len = value.length();
-
-       for (int i = 0; i < len; i++) {
-           char c = value.charAt(i);
-
-           if (c < 0x20 || c >= 0x7f || tspecials.indexOf(c) != -1)
-               return false;
-       }
-       return true;
+        int len = value.length();
+
+        for (int i = 0; i < len; i++) {
+            char c = value.charAt(i);
+
+            if (c < 0x20 ||
+                    c >= 0x7f ||
+                    (!STRICT_NAMING && tspecials.indexOf(c) != -1) ||
+                    (STRICT_NAMING && !FWD_SLASH_IS_SEPARATOR &&
+                            tspecials2NoSlash.indexOf(c) != -1) ||
+                    (STRICT_NAMING && FWD_SLASH_IS_SEPARATOR &&
+                            tspecials2.indexOf(c) != -1)) {
+                return false;
+            }
+        }
+        return true;
     }
 
 
 
-
-
-
     /**
      *
      * Overrides the standard <code>java.lang.Object.clone</code> 
index 998b264..1834b67 100644 (file)
         The default value will be changed for
         <code>org.apache.tomcat.util.http.ServerCookie.ALWAYS_ADD_EXPIRES</code>.
         <code>org.apache.tomcat.util.http.ServerCookie.FWD_SLASH_IS_SEPARATOR</code>.
+        <code>org.apache.tomcat.util.http.ServerCookie.STRICT_NAMING</code>.
       </li>
       </ul>
       </p>
-      <p>Note that where setting this to <code>true</code> changes a default,
-      that can always be overridden by setting a system property explicitly.</p>
+      <p>Note that changing a number of the above defaults is likely to break
+      the majority of systems as a number of browsers are unable to correctly
+      handle the cookie headers that result from a strict adherence to the
+      specifications. Defaults, regardless of whether or not they have been
+      changed by setting
+      <code>org.apache.catalina.STRICT_SERVLET_COMPLIANCE</code> can always be
+      overridden by explicitly setting the appropriate system property.</p>
     </property>
 
     <property
       else the default value will be <code>false</code>.</p>
     </property>
 
+    <property
+    name="javax.servlet.http.Cookie. STRICT_NAMING">
+      <p> If this is true then the requirements of the Servlet specification
+      that Cookie names must adhere to RFC2109 (no use of separators) will be
+      enforced. If not specified, the default value will be used. If
+      <code>org.apache.catalina.STRICT_SERVLET_COMPLIANCE</code> is set to
+      <code>true</code>, the default of this setting will be <code>true</code>,
+      else the default value will be <code>false</code>.</p>
+    </property>
+
   </properties>
 
 </section>