Author: markt
Date: Wed Apr 29 09:38:29 2009
New Revision: 769730
URL: http://svn.apache.org/viewvc?rev=769730&view=rev
Log:
Fix bug 46597. Port all the cookie handling changes from Tomcat 6.
Modified:
tomcat/connectors/trunk/util/java/org/apache/tomcat/util/http/ServerCookie.java
tomcat/container/tc5.5.x/webapps/docs/changelog.xml
tomcat/container/tc5.5.x/webapps/docs/config/systemprops.xml
Modified:
tomcat/connectors/trunk/util/java/org/apache/tomcat/util/http/ServerCookie.java
URL:
http://svn.apache.org/viewvc/tomcat/connectors/trunk/util/java/org/apache/tomcat/util/http/ServerCookie.java?rev=769730&r1=769729&r2=769730&view=diff
==============================================================================
---
tomcat/connectors/trunk/util/java/org/apache/tomcat/util/http/ServerCookie.java
(original)
+++
tomcat/connectors/trunk/util/java/org/apache/tomcat/util/http/ServerCookie.java
Wed Apr 29 09:38:29 2009
@@ -18,11 +18,14 @@
package org.apache.tomcat.util.http;
import java.io.Serializable;
+import java.text.DateFormat;
import java.text.FieldPosition;
+import java.text.SimpleDateFormat;
import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
import org.apache.tomcat.util.buf.ByteChunk;
-import org.apache.tomcat.util.buf.DateTool;
import org.apache.tomcat.util.buf.MessageBytes;
@@ -50,6 +53,37 @@
private int maxAge = -1;
private int version = 0;
+ // Other fields
+ private static final String OLD_COOKIE_PATTERN =
+ "EEE, dd-MMM-yyyy HH:mm:ss z";
+ private static final ThreadLocal<DateFormat> OLD_COOKIE_FORMAT =
+ new ThreadLocal<DateFormat>() {
+ protected DateFormat initialValue() {
+ DateFormat df =
+ new SimpleDateFormat(OLD_COOKIE_PATTERN, Locale.US);
+ df.setTimeZone(TimeZone.getTimeZone("GMT"));
+ return df;
+ }
+ };
+ private static final String ancientDate;
+
+
+ static {
+ ancientDate = OLD_COOKIE_FORMAT.get().format(new Date(10000));
+ }
+
+ /**
+ * If set to true, we parse cookies according to the servlet spec,
+ */
+ public static final boolean STRICT_SERVLET_COMPLIANCE =
+
Boolean.valueOf(System.getProperty("org.apache.catalina.STRICT_SERVLET_COMPLIANCE",
"false")).booleanValue();
+
+ /**
+ * If set to false, we don't use the IE6/7 Max-Age/Expires work around
+ */
+ public static final boolean ALWAYS_ADD_EXPIRES =
+
Boolean.valueOf(System.getProperty("org.apache.tomcat.util.http.ServerCookie.ALWAYS_ADD_EXPIRES",
"true")).booleanValue();
+
// Note: Servlet Spec =< 2.5 only refers to Netscape and RFC2109,
// not RFC2965
@@ -127,6 +161,7 @@
private static final String tspecials = ",; ";
private static final String tspecials2 = "()<>@,;:\\\"/[]?={} \t";
+ private static final String tspecials2NoSlash = "()<>@,;:\\\"[]?={} \t";
/*
* Tests a string and returns true if the string counts as a
@@ -139,6 +174,11 @@
* if it is not
*/
public static boolean isToken(String value) {
+ return isToken(value,null);
+ }
+
+ public static boolean isToken(String value, String literals) {
+ String tspecials = (literals==null?ServerCookie.tspecials:literals);
if( value==null) return true;
int len = value.length();
@@ -164,9 +204,13 @@
}
return false;
}
-
-
+
public static boolean isToken2(String value) {
+ return isToken2(value,null);
+ }
+
+ public static boolean isToken2(String value, String literals) {
+ String tspecials2 = (literals==null?ServerCookie.tspecials2:literals);
if( value==null) return true;
int len = value.length();
@@ -230,9 +274,6 @@
}
}
- private static final String ancientDate =
- DateTool.formatOldCookie(new Date(10000));
-
// TODO RFC2965 fields also need to be passed
public static void appendCookieValue( StringBuffer headerBuf,
int version,
@@ -250,7 +291,7 @@
buf.append("=");
// Servlet implementation does not check anything else
- maybeQuote2(version, buf, value);
+ version = maybeQuote2(version, buf, value,true);
// Add version 1 specific information
if (version == 1) {
@@ -273,28 +314,34 @@
// Max-Age=secs ... or use old "Expires" format
// TODO RFC2965 Discard
if (maxAge >= 0) {
- if (version == 0) {
+ if (version > 0) {
+ buf.append ("; Max-Age=");
+ buf.append (maxAge);
+ }
+ // IE6, IE7 and possibly other browsers don't understand Max-Age.
+ // They do understand Expires, even with V1 cookies!
+ if (version == 0 || ALWAYS_ADD_EXPIRES) {
// Wdy, DD-Mon-YY HH:MM:SS GMT ( Expires Netscape format )
buf.append ("; Expires=");
// To expire immediately we need to set the time in past
if (maxAge == 0)
buf.append( ancientDate );
else
- DateTool.formatOldCookie
- (new Date( System.currentTimeMillis() +
- maxAge *1000L), buf,
- new FieldPosition(0));
-
- } else {
- buf.append ("; Max-Age=");
- buf.append (maxAge);
+ OLD_COOKIE_FORMAT.get().format(
+ new Date(System.currentTimeMillis() +
+ maxAge*1000L),
+ buf, new FieldPosition(0));
}
}
// Path=path
if (path!=null) {
buf.append ("; Path=");
- maybeQuote2(version, buf, path);
+ if (version==0) {
+ maybeQuote2(version, buf, path);
+ } else {
+ maybeQuote2(version, buf, path,
ServerCookie.tspecials2NoSlash, false);
+ }
}
// Secure
@@ -332,27 +379,40 @@
* @param buf
* @param value
*/
- public static void maybeQuote2(int version, StringBuffer buf,
- String value) {
+ public static int maybeQuote2 (int version, StringBuffer buf, String
value) {
+ return maybeQuote2(version,buf,value,false);
+ }
+
+ public static int maybeQuote2 (int version, StringBuffer buf, String
value, boolean allowVersionSwitch) {
+ return maybeQuote2(version,buf,value,null,allowVersionSwitch);
+ }
+
+ public static int maybeQuote2 (int version, StringBuffer buf, String
value, String literals, boolean allowVersionSwitch) {
if (value==null || value.length()==0) {
buf.append("\"\"");
} else if (containsCTL(value,version))
throw new IllegalArgumentException("Control character in cookie
value, consider BASE64 encoding your value");
else if (alreadyQuoted(value)) {
buf.append('"');
- buf.append(escapeDoubleQuotes(value,1,value.length()-1));
buf.append('"');
+ buf.append(escapeDoubleQuotes(value,1,value.length()-1));
buf.append('"');
- } else if (version==0 && !isToken(value)) {
+ } else if (allowVersionSwitch && (!STRICT_SERVLET_COMPLIANCE) &&
version==0 && !isToken2(value, literals)) {
buf.append('"');
buf.append(escapeDoubleQuotes(value,0,value.length()));
buf.append('"');
- } else if (version==1 && !isToken2(value)) {
+ version = 1;
+ } else if (version==0 && !isToken(value,literals)) {
+ buf.append('"');
+ buf.append(escapeDoubleQuotes(value,0,value.length()));
+ buf.append('"');
+ } else if (version==1 && !isToken2(value,literals)) {
buf.append('"');
buf.append(escapeDoubleQuotes(value,0,value.length()));
buf.append('"');
} else {
buf.append(value);
}
+ return version;
}
/**
Modified: tomcat/container/tc5.5.x/webapps/docs/changelog.xml
URL:
http://svn.apache.org/viewvc/tomcat/container/tc5.5.x/webapps/docs/changelog.xml?rev=769730&r1=769729&r2=769730&view=diff
==============================================================================
--- tomcat/container/tc5.5.x/webapps/docs/changelog.xml (original)
+++ tomcat/container/tc5.5.x/webapps/docs/changelog.xml Wed Apr 29 09:38:29 2009
@@ -59,6 +59,10 @@
(markt)
</fix>
<fix>
+ <bug>46597</bug>: Port all cookie handling changes from Tomcat 6.0.x.
+ (markt)
+ </fix>
+ <fix>
<bug>45628</bug>: JARs that do not declare any dependencies should
always be considered as fulfilled. (markt)
</fix>
Modified: tomcat/container/tc5.5.x/webapps/docs/config/systemprops.xml
URL:
http://svn.apache.org/viewvc/tomcat/container/tc5.5.x/webapps/docs/config/systemprops.xml?rev=769730&r1=769729&r2=769730&view=diff
==============================================================================
--- tomcat/container/tc5.5.x/webapps/docs/config/systemprops.xml (original)
+++ tomcat/container/tc5.5.x/webapps/docs/config/systemprops.xml Wed Apr 29
09:38:29 2009
@@ -101,17 +101,32 @@
<property name="org.apache.catalina. STRICT_SERVLET_COMPLIANCE">
<p>If this is <code>true</code> the following actions will occur:
<ul>
- <li>any wrapped request or response object passed to an application
- dispatcher will be checked to ensure that it has wrapped the original
- request or response. (SRV.8.2 / SRV.14.2.5.1)
- </li>
- <li>when updating the access count for the session, the update will be
- synchronized.
- </li>
+ <li>any wrapped request or response object passed to an application
+ dispatcher will be checked to ensure that it has wrapped the original
+ request or response. (SRV.8.2 / SRV.14.2.5.1)
+ </li>
+ <li>when updating the access count for the session, the update will be
+ synchronized.
+ </li>
+ <li>
+ cookies will be parsed strictly, by default v0 cookies will not work
+ with any invalid characters.<br/>If set to false, any v0 cookie with
+ invalid character will be switched to a v1 cookie and the value will
+ be quoted.
+ </li>
</ul>
</p>
</property>
+ <property
+ name="org.apache.tomcat.util.http. ServerCookie.ALWAYS_ADD_EXPIRES">
+ <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>
+ </property>
+
</properties>
</section>
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]