Add system property to control treatment of / as a separator when processing cookies
authormarkt <markt@13f79535-47bb-0310-9956-ffa450edef68>
Thu, 29 Oct 2009 18:36:49 +0000 (18:36 +0000)
committermarkt <markt@13f79535-47bb-0310-9956-ffa450edef68>
Thu, 29 Oct 2009 18:36:49 +0000 (18:36 +0000)
Modify ALWAYS_ADD_EXPIRES so STRICT_SERVLET_COMPLIANCE changes the default to a strict interpretation of the specs

Note: I'll refactor the common code into a Constants class once I am finished but I'm doing that last as the refactoring won't be proposed for back-port to 6.0.x/5.5.x

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

java/org/apache/tomcat/util/http/Cookies.java
java/org/apache/tomcat/util/http/ServerCookie.java
webapps/docs/config/systemprops.xml

index 60d52b3..e45b60d 100644 (file)
@@ -46,19 +46,54 @@ public final class Cookies { // extends MultiMap {
 
     MimeHeaders headers;
 
+    /**
+     * If set to true, we parse cookies strictly according to the servlet,
+     * cookie and HTTP specs by default.
+     */
+    public 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.
+     */
+    public static final boolean FWD_SLASH_IS_SEPARATOR;
+    
     /*
     List of Separator Characters (see isSeparator())
-    Excluding the '/' char violates the RFC, but 
-    it looks like a lot of people put '/'
-    in unquoted values: '/': ; //47 
-    '\t':9 ' ':32 '\"':34 '(':40 ')':41 ',':44 ':':58 ';':59 '<':60 
-    '=':61 '>':62 '?':63 '@':64 '[':91 '\\':92 ']':93 '{':123 '}':125
     */
-    public static final char SEPARATORS[] = { '\t', ' ', '\"', '(', ')', ',', 
-        ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '{', '}' };
+    public static final char SEPARATORS[];
 
     protected static final boolean separators[] = new boolean[128];
     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();
+        }
+
+        /*
+        Excluding the '/' char by default violates the RFC, but 
+        it looks like a lot of people put '/'
+        in unquoted values: '/': ; //47 
+        '\t':9 ' ':32 '\"':34 '(':40 ')':41 ',':44 ':':58 ';':59 '<':60 
+        '=':61 '>':62 '?':63 '@':64 '[':91 '\\':92 ']':93 '{':123 '}':125
+        */
+        if (FWD_SLASH_IS_SEPARATOR) {
+            SEPARATORS = new char[] { '\t', ' ', '\"', '(', ')', ',', '/', 
+                    ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '{', '}' };
+        } else {
+            SEPARATORS = new char[] { '\t', ' ', '\"', '(', ')', ',', 
+                    ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '{', '}' };
+        }
+        
         for (int i = 0; i < 128; i++) {
             separators[i] = false;
         }
index 8b1d258..e9cc851 100644 (file)
@@ -68,22 +68,53 @@ public class ServerCookie implements Serializable {
     };
     private static final String ancientDate;
 
-
-    static {
-        ancientDate = OLD_COOKIE_FORMAT.get().format(new Date(10000));
-    }
+    /**
+     * If set to true, we parse cookies strictly according to the servlet,
+     * cookie and HTTP specs by default.
+     */
+    public static final boolean STRICT_SERVLET_COMPLIANCE;
 
     /**
-     * If set to true, we parse cookies according to the servlet spec,
+     * 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.
      */
-    public static final boolean STRICT_SERVLET_COMPLIANCE =
-        Boolean.valueOf(System.getProperty("org.apache.catalina.STRICT_SERVLET_COMPLIANCE", "false")).booleanValue();
+    public static final boolean ALWAYS_ADD_EXPIRES;
 
     /**
-     * If set to false, we don't use the IE6/7 Max-Age/Expires work around
+     * 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.
      */
-    public static final boolean ALWAYS_ADD_EXPIRES =
-        Boolean.valueOf(System.getProperty("org.apache.tomcat.util.http.ServerCookie.ALWAYS_ADD_EXPIRES", "true")).booleanValue();
+    public static final boolean FWD_SLASH_IS_SEPARATOR;
+
+
+    static {
+        ancientDate = OLD_COOKIE_FORMAT.get().format(new Date(10000));
+        
+        STRICT_SERVLET_COMPLIANCE = Boolean.valueOf(System.getProperty(
+                "org.apache.catalina.STRICT_SERVLET_COMPLIANCE",
+                "false")).booleanValue();
+        
+
+        String alwaysAddExpires = System.getProperty(
+                "org.apache.tomcat.util.http.ServerCookie.ALWAYS_ADD_EXPIRES");
+        if (alwaysAddExpires == null) {
+            ALWAYS_ADD_EXPIRES = !STRICT_SERVLET_COMPLIANCE;
+        } else {
+            ALWAYS_ADD_EXPIRES =
+                Boolean.valueOf(alwaysAddExpires).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();
+        }
+    }
 
     // Note: Servlet Spec =< 2.5 only refers to Netscape and RFC2109,
     // not RFC2965
@@ -319,7 +350,13 @@ public class ServerCookie implements Serializable {
             if (version==0) {
                 maybeQuote2(version, buf, path);
             } else {
-                maybeQuote2(version, buf, path, ServerCookie.tspecials2NoSlash, false);
+                if (FWD_SLASH_IS_SEPARATOR) {
+                    maybeQuote2(version, buf, path, ServerCookie.tspecials,
+                            false);
+                } else {
+                    maybeQuote2(version, buf, path,
+                            ServerCookie.tspecials2NoSlash, false);
+                }
             }
         }
 
index ac83893..998b264 100644 (file)
         <code>ServletContext.getResource/getResourceAsStream</code> must start with "/"<br/>
         if set to false, code like <code>getResource("myfolder/myresource.txt")</code> will work
       </li>
+      <li>
+        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>.
+      </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>
     </property>
 
     <property
       <p>If this is <code>true</code> Tomcat will always add an expires
       parameter to a SetCookie header even for cookies with version greater than
       zero. This is to work around a known IE6 and IE7 bug that causes IE to
-      ignore the Max-Age parameter in a SetCookie header.If not specified, the
-      default value of <code>true</code> will be used.</p>
+      ignore the Max-Age parameter in a SetCookie header. 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>false</code>,
+      else the default value will be <code>true</code>.</p>
+    </property>
+
+    <property
+    name="org.apache.tomcat.util.http. ServerCookie.FWD_SLASH_IS_SEPARATOR">
+      <p> If this is true then the <code>/</code> (forward slash) character will
+      be treated as a separator. Note that this character is frequently used in
+      cookie path attributes and some browsers will fail to process a cookie if
+      the path attribute is quoted as is required by a strict adherence to the
+      specifications. 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>