You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2021/11/23 08:42:48 UTC
[tomcat] branch main updated: Cookie updates for Servlet 6.0. Only support RFC 6265. Remove others.
This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/main by this push:
new d78c719 Cookie updates for Servlet 6.0. Only support RFC 6265. Remove others.
d78c719 is described below
commit d78c7193f171fa4e75f2503b3c0173b7e37d0cee
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Mon Nov 22 09:52:45 2021 +0000
Cookie updates for Servlet 6.0. Only support RFC 6265. Remove others.
---
java/jakarta/servlet/SessionCookieConfig.java | 14 +-
java/jakarta/servlet/http/Cookie.java | 167 +---
java/org/apache/catalina/connector/Request.java | 9 -
java/org/apache/catalina/connector/Response.java | 3 -
.../core/ApplicationSessionCookieConfig.java | 4 +-
.../tomcat/util/http/LegacyCookieProcessor.java | 845 ---------------------
java/org/apache/tomcat/util/http/ServerCookie.java | 43 +-
.../org/apache/tomcat/util/http/parser/Cookie.java | 391 +---------
test/jakarta/servlet/http/TestCookie.java | 12 +-
.../servlet/http/TestCookieRFC2109Validator.java | 37 -
test/jakarta/servlet/http/TestCookieStrict.java | 44 --
.../core/TestApplicationSessionCookieConfig.java | 2 +-
.../valves/TestLoadBalancerDrainingValve.java | 4 +-
.../apache/tomcat/util/http/CookiesBaseTest.java | 95 ---
test/org/apache/tomcat/util/http/TestBug49158.java | 84 --
.../apache/tomcat/util/http/TestCookieParsing.java | 118 +--
.../util/http/TestCookieProcessorGeneration.java | 266 ++-----
test/org/apache/tomcat/util/http/TestCookies.java | 394 ++--------
.../util/http/TestCookiesDefaultSysProps.java | 69 --
.../util/http/TestCookiesNoFwdStrictSysProps.java | 62 --
.../http/TestCookiesNoStrictNamingSysProps.java | 62 --
.../util/http/TestCookiesStrictSysProps.java | 72 --
.../util/http/TestLegacyCookieProcessor.java | 56 --
.../tomcat/util/http/TesterCookiesPerformance.java | 14 +-
.../apache/tomcat/util/http/parser/TestCookie.java | 96 ---
webapps/docs/changelog.xml | 4 +
webapps/docs/config/cookie-processor.xml | 75 --
webapps/docs/config/systemprops.xml | 11 -
28 files changed, 207 insertions(+), 2846 deletions(-)
diff --git a/java/jakarta/servlet/SessionCookieConfig.java b/java/jakarta/servlet/SessionCookieConfig.java
index 6246d02..7d03bd2 100644
--- a/java/jakarta/servlet/SessionCookieConfig.java
+++ b/java/jakarta/servlet/SessionCookieConfig.java
@@ -79,20 +79,26 @@ public interface SessionCookieConfig {
public String getPath();
/**
- * Sets the comment for the session cookie
+ * If called, this method has no effect.
*
- * @param comment The session cookie comment
+ * @param comment Ignore
*
* @throws IllegalStateException if the associated ServletContext has
* already been initialised
+ *
+ * @deprecated This is no longer required with RFC 6265
*/
+ @Deprecated(since = "Servlet 6.0", forRemoval = true)
public void setComment(String comment);
/**
- * Obtain the comment to use for session cookies.
+ * With the adoption of support for RFC 6265, this method should no longer be used.
+ *
+ * @return always {@code null}
*
- * @return the comment to use for session cookies.
+ * @deprecated This is no longer required with RFC 6265
*/
+ @Deprecated(since = "Servlet 6.0", forRemoval = true)
public String getComment();
/**
diff --git a/java/jakarta/servlet/http/Cookie.java b/java/jakarta/servlet/http/Cookie.java
index 2e7bb98..49b7d5f 100644
--- a/java/jakarta/servlet/http/Cookie.java
+++ b/java/jakarta/servlet/http/Cookie.java
@@ -17,8 +17,6 @@
package jakarta.servlet.http;
import java.io.Serializable;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
import java.text.MessageFormat;
import java.util.BitSet;
import java.util.Collections;
@@ -53,60 +51,14 @@ import java.util.TreeMap;
* cache pages that use cookies created with this class. This class does not
* support the cache control defined with HTTP 1.1.
* <p>
- * This class supports both the RFC 2109 and the RFC 6265 specifications.
- * By default, cookies are created using RFC 6265.
+ * This class supports both the RFC 6265 specification.
*/
public class Cookie implements Cloneable, Serializable {
private static final String LSTRING_FILE = "jakarta.servlet.http.LocalStrings";
private static final ResourceBundle LSTRINGS = ResourceBundle.getBundle(LSTRING_FILE);
- private static final CookieNameValidator validation;
-
- static {
- boolean strictServletCompliance;
- boolean strictNaming;
- boolean allowSlash;
- String propStrictNaming;
- String propFwdSlashIsSeparator;
-
- if (System.getSecurityManager() == null) {
- strictServletCompliance = Boolean.getBoolean(
- "org.apache.catalina.STRICT_SERVLET_COMPLIANCE");
- propStrictNaming = System.getProperty(
- "org.apache.tomcat.util.http.ServerCookie.STRICT_NAMING");
- propFwdSlashIsSeparator = System.getProperty(
- "org.apache.tomcat.util.http.ServerCookie.FWD_SLASH_IS_SEPARATOR");
- } else {
- strictServletCompliance = AccessController.doPrivileged(
- (PrivilegedAction<Boolean>) () -> Boolean.valueOf(System.getProperty(
- "org.apache.catalina.STRICT_SERVLET_COMPLIANCE"))).booleanValue();
- propStrictNaming = AccessController.doPrivileged(
- (PrivilegedAction<String>) () -> System.getProperty(
- "org.apache.tomcat.util.http.ServerCookie.STRICT_NAMING"));
- propFwdSlashIsSeparator = AccessController.doPrivileged(
- (PrivilegedAction<String>) () -> System.getProperty(
- "org.apache.tomcat.util.http.ServerCookie.FWD_SLASH_IS_SEPARATOR"));
- }
-
- if (propStrictNaming == null) {
- strictNaming = strictServletCompliance;
- } else {
- strictNaming = Boolean.parseBoolean(propStrictNaming);
- }
-
- if (propFwdSlashIsSeparator == null) {
- allowSlash = !strictServletCompliance;
- } else {
- allowSlash = !Boolean.parseBoolean(propFwdSlashIsSeparator);
- }
-
- if (strictNaming) {
- validation = new RFC2109Validator(allowSlash);
- } else {
- validation = new RFC6265Validator();
- }
- }
+ private static final CookieNameValidator validation = new RFC6265Validator();
private static final long serialVersionUID = 2L;
@@ -121,16 +73,10 @@ public class Cookie implements Cloneable, Serializable {
private String value;
/**
- * Cookie version value. {@code ;Version=1 ...} means RFC 2109 style.
- */
- private int version = 0;
-
- /**
* Attributes encoded in the header's cookie fields.
*/
private volatile Map<String,String> attributes;
- private static final String COMMENT = "Comment";
private static final String DOMAIN = "Domain";
private static final String MAX_AGE = "Max-Age";
private static final String PATH = "Path";
@@ -140,29 +86,19 @@ public class Cookie implements Cloneable, Serializable {
/**
* Constructs a cookie with a specified name and value.
* <p>
- * The name must conform to RFC 2109. That means it can contain only ASCII
- * alphanumeric characters and cannot contain commas, semicolons, or white
- * space or begin with a $ character. The cookie's name cannot be changed
- * after creation.
+ * The cookie's name cannot be changed after creation.
* <p>
* The value can be anything the server chooses to send. Its value is
* probably of interest only to the server. The cookie's value can be
* changed after creation with the <code>setValue</code> method.
- * <p>
- * By default, cookies are created according to the Netscape cookie
- * specification. The version can be changed with the
- * <code>setVersion</code> method.
*
* @param name
* a <code>String</code> specifying the name of the cookie
* @param value
* a <code>String</code> specifying the value of the cookie
* @throws IllegalArgumentException
- * if the cookie name contains illegal characters (for example,
- * a comma, space, or semicolon) or it is one of the tokens
- * reserved for use by the cookie protocol
+ * if the cookie name contains illegal characters
* @see #setValue
- * @see #setVersion
*/
public Cookie(String name, String value) {
validation.validate(name);
@@ -172,45 +108,43 @@ public class Cookie implements Cloneable, Serializable {
/**
- * Specifies a comment that describes a cookie's purpose. The comment is
- * useful if the browser presents the cookie to the user. Comments are not
- * supported by Netscape Version 0 cookies.
+ * If called, this method has no effect.
+ *
+ * @param purpose ignored
*
- * @param purpose
- * a <code>String</code> specifying the comment to display to the
- * user
* @see #getComment
+ *
+ * @deprecated This is no longer required with RFC 6265
*/
+ @Deprecated(since = "Servlet 6.0", forRemoval = true)
public void setComment(String purpose) {
- setAttributeInternal(COMMENT, purpose);
+ // NO-OP
}
/**
- * Returns the comment describing the purpose of this cookie, or
- * <code>null</code> if the cookie has no comment.
+ * With the adoption of support for RFC 6265, this method should no longer be used.
+ *
+ * @return always {@code null}
*
- * @return a <code>String</code> containing the comment, or
- * <code>null</code> if none
* @see #setComment
+ *
+ * @deprecated This is no longer required with RFC 6265
*/
+ @Deprecated(since = "Servlet 6.0", forRemoval = true)
public String getComment() {
- return getAttribute(COMMENT);
+ return null;
}
/**
* Specifies the domain within which this cookie should be presented.
* <p>
- * The form of the domain name is specified by RFC 2109. A domain name
- * begins with a dot (<code>.foo.com</code>) and means that the cookie is
- * visible to servers in a specified Domain Name System (DNS) zone (for
- * example, <code>www.foo.com</code>, but not <code>a.b.foo.com</code>). By
- * default, cookies are only returned to the server that sent them.
+ * By default, cookies are only returned to the server that sent them.
*
* @param pattern
* a <code>String</code> containing the domain name within which
- * this cookie is visible; form is according to RFC 2109
+ * this cookie is visible
* @see #getDomain
*/
public void setDomain(String pattern) {
@@ -224,8 +158,7 @@ public class Cookie implements Cloneable, Serializable {
/**
- * Returns the domain name set for this cookie. The form of the domain name
- * is set by RFC 2109.
+ * Returns the domain name set for this cookie.
*
* @return a <code>String</code> containing the domain name
* @see #setDomain
@@ -285,9 +218,6 @@ public class Cookie implements Cloneable, Serializable {
* include the servlet that set the cookie, for example, <i>/catalog</i>,
* which makes the cookie visible to all directories on the server under
* <i>/catalog</i>.
- * <p>
- * Consult RFC 2109 (available on the Internet) for more information on
- * setting path names for cookies.
*
* @param uri
* a <code>String</code> specifying a path
@@ -385,35 +315,32 @@ public class Cookie implements Cloneable, Serializable {
/**
- * Returns the version of the protocol this cookie complies with. Version 1
- * complies with RFC 2109, and version 0 complies with the original cookie
- * specification drafted by Netscape. Cookies provided by a browser use and
- * identify the browser's cookie version.
+ * With the adoption of support for RFC 6265, this method should no longer be used.
+ *
+ * @return Always zero
*
- * @return 0 if the cookie complies with the original Netscape specification;
- * 1 if the cookie complies with RFC 2109
* @see #setVersion
+ *
+ * @deprecated This is no longer required with RFC 6265
*/
+ @Deprecated(since = "Servlet 6.0", forRemoval = true)
public int getVersion() {
- return version;
+ return 0;
}
/**
- * Sets the version of the cookie protocol this cookie complies with.
- * Version 0 complies with the original Netscape cookie specification.
- * Version 1 complies with RFC 2109.
- * <p>
- * Since RFC 2109 is still somewhat new, consider version 1 as experimental;
- * do not use it yet on production sites.
+ * If called, this method has no effect.
+ *
+ * @param v Ignored
*
- * @param v
- * 0 if the cookie should comply with the original Netscape
- * specification; 1 if the cookie should comply with RFC 2109
* @see #getVersion
+ *
+ * @deprecated This is no longer required with RFC 6265
*/
+ @Deprecated(since = "Servlet 6.0", forRemoval = true)
public void setVersion(int v) {
- version = v;
+ // NO-OP
}
@@ -553,7 +480,6 @@ public class Cookie implements Cloneable, Serializable {
result = prime * result + ((attributes == null) ? 0 : attributes.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((value == null) ? 0 : value.hashCode());
- result = prime * result + version;
return result;
}
@@ -591,9 +517,6 @@ public class Cookie implements Cloneable, Serializable {
} else if (!value.equals(other.value)) {
return false;
}
- if (version != other.version) {
- return false;
- }
return true;
}
}
@@ -643,22 +566,4 @@ class RFC6265Validator extends CookieNameValidator {
RFC6265Validator() {
super(RFC2616_SEPARATORS);
}
-}
-
-class RFC2109Validator extends RFC6265Validator {
- RFC2109Validator(boolean allowSlash) {
- // special treatment to allow for FWD_SLASH_IS_SEPARATOR property
- if (allowSlash) {
- allowed.set('/');
- }
- }
-
- @Override
- void validate(String name) {
- super.validate(name);
- if (name.charAt(0) == '$') {
- String errMsg = lStrings.getString("err.cookie_name_is_token");
- throw new IllegalArgumentException(MessageFormat.format(errMsg, name));
- }
- }
-}
+}
\ No newline at end of file
diff --git a/java/org/apache/catalina/connector/Request.java b/java/org/apache/catalina/connector/Request.java
index d591bcf..1e9c93d 100644
--- a/java/org/apache/catalina/connector/Request.java
+++ b/java/org/apache/catalina/connector/Request.java
@@ -3126,17 +3126,8 @@ public class Request implements HttpServletRequest {
try {
// We must unescape the '\\' escape character
Cookie cookie = new Cookie(scookie.getName().toString(),null);
- int version = scookie.getVersion();
- cookie.setVersion(version);
scookie.getValue().getByteChunk().setCharset(cookieProcessor.getCharset());
cookie.setValue(unescape(scookie.getValue().toString()));
- cookie.setPath(unescape(scookie.getPath().toString()));
- String domain = scookie.getDomain().toString();
- if (domain!=null) {
- cookie.setDomain(unescape(domain));//avoid NPE
- }
- String comment = scookie.getComment().toString();
- cookie.setComment(version==1?unescape(comment):null);
cookies[idx++] = cookie;
} catch(IllegalArgumentException e) {
// Ignore bad cookie
diff --git a/java/org/apache/catalina/connector/Response.java b/java/org/apache/catalina/connector/Response.java
index 6096d02..677ae41 100644
--- a/java/org/apache/catalina/connector/Response.java
+++ b/java/org/apache/catalina/connector/Response.java
@@ -927,9 +927,6 @@ public class Response implements HttpServletResponse {
String header = generateCookieString(cookie);
//if we reached here, no exception, cookie is valid
- // the header name is Set-Cookie for both "old" and v.1 ( RFC2109 )
- // RFC2965 is not supported by browsers and the Servlet spec
- // asks for 2109.
addHeader("Set-Cookie", header, getContext().getCookieProcessor().getCharset());
}
diff --git a/java/org/apache/catalina/core/ApplicationSessionCookieConfig.java b/java/org/apache/catalina/core/ApplicationSessionCookieConfig.java
index aaf7a13..ae876f7 100644
--- a/java/org/apache/catalina/core/ApplicationSessionCookieConfig.java
+++ b/java/org/apache/catalina/core/ApplicationSessionCookieConfig.java
@@ -51,7 +51,7 @@ public class ApplicationSessionCookieConfig implements SessionCookieConfig {
@Override
public String getComment() {
- return getAttribute(Constants.COOKIE_COMMENT_ATTR);
+ return null;
}
@Override
@@ -103,7 +103,6 @@ public class ApplicationSessionCookieConfig implements SessionCookieConfig {
"applicationSessionCookieConfig.ise", "comment",
context.getPath()));
}
- setAttribute(Constants.COOKIE_COMMENT_ATTR, comment);
}
@Override
@@ -208,7 +207,6 @@ public class ApplicationSessionCookieConfig implements SessionCookieConfig {
// Just apply the defaults.
cookie.setMaxAge(scc.getMaxAge());
- cookie.setComment(scc.getComment());
if (context.getSessionCookieDomain() == null) {
// Avoid possible NPE
diff --git a/java/org/apache/tomcat/util/http/LegacyCookieProcessor.java b/java/org/apache/tomcat/util/http/LegacyCookieProcessor.java
deleted file mode 100644
index 5867d50..0000000
--- a/java/org/apache/tomcat/util/http/LegacyCookieProcessor.java
+++ /dev/null
@@ -1,845 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.tomcat.util.http;
-
-import java.nio.charset.Charset;
-import java.nio.charset.StandardCharsets;
-import java.text.FieldPosition;
-import java.util.BitSet;
-import java.util.Date;
-import java.util.Map;
-
-import jakarta.servlet.http.Cookie;
-import jakarta.servlet.http.HttpServletRequest;
-
-import org.apache.juli.logging.Log;
-import org.apache.juli.logging.LogFactory;
-import org.apache.tomcat.util.buf.ByteChunk;
-import org.apache.tomcat.util.buf.MessageBytes;
-import org.apache.tomcat.util.descriptor.web.Constants;
-import org.apache.tomcat.util.log.UserDataHelper;
-import org.apache.tomcat.util.res.StringManager;
-
-/**
- * The legacy (up to early Tomcat 8 releases) cookie parser based on RFC6265,
- * RFC2109 and RFC2616.
- *
- * This class is not thread-safe.
- *
- * @author Costin Manolache
- * @author kevin seguin
- */
-public final class LegacyCookieProcessor extends CookieProcessorBase {
-
- private static final Log log = LogFactory.getLog(LegacyCookieProcessor.class);
-
- private static final UserDataHelper userDataLog = new UserDataHelper(log);
-
- private static final StringManager sm =
- StringManager.getManager("org.apache.tomcat.util.http");
-
- private static final char[] V0_SEPARATORS = {',', ';', ' ', '\t'};
- private static final BitSet V0_SEPARATOR_FLAGS = new BitSet(128);
-
- // Excludes '/' since configuration controls whether or not to treat '/' as
- // a separator
- private static final char[] HTTP_SEPARATORS = new char[] {
- '\t', ' ', '\"', '(', ')', ',', ':', ';', '<', '=', '>', '?', '@',
- '[', '\\', ']', '{', '}' };
-
- static {
- for (char c : V0_SEPARATORS) {
- V0_SEPARATOR_FLAGS.set(c);
- }
- }
-
- private final boolean STRICT_SERVLET_COMPLIANCE =
- Boolean.getBoolean("org.apache.catalina.STRICT_SERVLET_COMPLIANCE");
-
- private boolean allowEqualsInValue = false;
-
- private boolean allowNameOnly = false;
-
- private boolean allowHttpSepsInV0 = false;
-
- private boolean alwaysAddExpires = !STRICT_SERVLET_COMPLIANCE;
-
- private final BitSet httpSeparatorFlags = new BitSet(128);
-
- private final BitSet allowedWithoutQuotes = new BitSet(128);
-
- public LegacyCookieProcessor() {
- // BitSet elements will default to false
- for (char c : HTTP_SEPARATORS) {
- httpSeparatorFlags.set(c);
- }
- boolean b = STRICT_SERVLET_COMPLIANCE;
- if (b) {
- httpSeparatorFlags.set('/');
- }
-
- String separators;
- if (getAllowHttpSepsInV0()) {
- // comma, semi-colon and space as defined by netscape
- separators = ",; ";
- } else {
- // separators as defined by RFC2616
- separators = "()<>@,;:\\\"/[]?={} \t";
- }
-
- // all CHARs except CTLs or separators are allowed without quoting
- allowedWithoutQuotes.set(0x20, 0x7f);
- for (char ch : separators.toCharArray()) {
- allowedWithoutQuotes.clear(ch);
- }
-
- /**
- * Some browsers (e.g. IE6 and IE7) do not handle quoted Path values even
- * when Version is set to 1. To allow for this, we support a property
- * FWD_SLASH_IS_SEPARATOR which, when false, means a '/' character will not
- * be treated as a separator, potentially avoiding quoting and the ensuing
- * side effect of having the cookie upgraded to version 1.
- *
- * For now, we apply this rule globally rather than just to the Path attribute.
- */
- if (!getAllowHttpSepsInV0() && !getForwardSlashIsSeparator()) {
- allowedWithoutQuotes.set('/');
- }
- }
-
-
- public boolean getAllowEqualsInValue() {
- return allowEqualsInValue;
- }
-
-
- public void setAllowEqualsInValue(boolean allowEqualsInValue) {
- this.allowEqualsInValue = allowEqualsInValue;
- }
-
-
- public boolean getAllowNameOnly() {
- return allowNameOnly;
- }
-
-
- public void setAllowNameOnly(boolean allowNameOnly) {
- this.allowNameOnly = allowNameOnly;
- }
-
-
- public boolean getAllowHttpSepsInV0() {
- return allowHttpSepsInV0;
- }
-
-
- public void setAllowHttpSepsInV0(boolean allowHttpSepsInV0) {
- this.allowHttpSepsInV0 = allowHttpSepsInV0;
- // HTTP separators less comma, semicolon and space since the Netscape
- // spec defines those as separators too.
- // '/' is also treated as a special case
- char[] seps = "()<>@:\\\"[]?={}\t".toCharArray();
- for (char sep : seps) {
- if (allowHttpSepsInV0) {
- allowedWithoutQuotes.set(sep);
- } else {
- allowedWithoutQuotes.clear(sep);
- }
- }
- if (getForwardSlashIsSeparator() && !allowHttpSepsInV0) {
- allowedWithoutQuotes.clear('/');
- } else {
- allowedWithoutQuotes.set('/');
- }
- }
-
-
- public boolean getForwardSlashIsSeparator() {
- return httpSeparatorFlags.get('/');
- }
-
-
- public void setForwardSlashIsSeparator(boolean forwardSlashIsSeparator) {
- if (forwardSlashIsSeparator) {
- httpSeparatorFlags.set('/');
- } else {
- httpSeparatorFlags.clear('/');
- }
- if (forwardSlashIsSeparator && !getAllowHttpSepsInV0()) {
- allowedWithoutQuotes.clear('/');
- } else {
- allowedWithoutQuotes.set('/');
- }
- }
-
-
- public boolean getAlwaysAddExpires() {
- return alwaysAddExpires;
- }
-
-
- public void setAlwaysAddExpires(boolean alwaysAddExpires) {
- this.alwaysAddExpires = alwaysAddExpires;
- }
-
-
- @Override
- public Charset getCharset() {
- return StandardCharsets.ISO_8859_1;
- }
-
-
- @Override
- public void parseCookieHeader(MimeHeaders headers, ServerCookies serverCookies) {
-
- if (headers == null) {
- // nothing to process
- return;
- }
- // process each "cookie" header
- int pos = headers.findHeader("Cookie", 0);
- while (pos >= 0) {
- MessageBytes cookieValue = headers.getValue(pos);
-
- if (cookieValue != null && !cookieValue.isNull() ) {
- if (cookieValue.getType() != MessageBytes.T_BYTES ) {
- Exception e = new Exception();
- // TODO: Review this in light of HTTP/2
- log.debug("Cookies: Parsing cookie as String. Expected bytes.", e);
- cookieValue.toBytes();
- }
- if (log.isDebugEnabled()) {
- log.debug("Cookies: Parsing b[]: " + cookieValue.toString());
- }
- ByteChunk bc = cookieValue.getByteChunk();
- processCookieHeader(bc.getBytes(), bc.getOffset(), bc.getLength(), serverCookies);
- }
-
- // search from the next position
- pos = headers.findHeader("Cookie", ++pos);
- }
- }
-
-
- @Override
- public String generateHeader(Cookie cookie, HttpServletRequest request) {
-
- /*
- * The spec allows some latitude on when to send the version attribute
- * with a Set-Cookie header. To be nice to clients, we'll make sure the
- * version attribute is first. That means checking the various things
- * that can cause us to switch to a v1 cookie first.
- *
- * Note that by checking for tokens we will also throw an exception if a
- * control character is encountered.
- */
- int version = cookie.getVersion();
- String value = cookie.getValue();
- String path = cookie.getPath();
- String domain = cookie.getDomain();
- String comment = cookie.getComment();
-
- if (version == 0) {
- // Check for the things that require a v1 cookie
- if (needsQuotes(value, 0) || comment != null || needsQuotes(path, 0) || needsQuotes(domain, 0)) {
- version = 1;
- }
- }
-
- // Now build the cookie header
- StringBuffer buf = new StringBuffer(); // can't use StringBuilder due to DateFormat
-
- // Just use the name supplied in the Cookie
- buf.append(cookie.getName());
- buf.append('=');
-
- // Value
- maybeQuote(buf, value, version);
-
- // Add version 1 specific information
- if (version == 1) {
- // Version=1 ... required
- buf.append ("; Version=1");
-
- // Comment=comment
- if (comment != null) {
- buf.append ("; Comment=");
- maybeQuote(buf, comment, version);
- }
- }
-
- // Add domain information, if present
- if (domain != null) {
- buf.append("; Domain=");
- maybeQuote(buf, domain, version);
- }
-
- // Max-Age=secs ... or use old "Expires" format
- int maxAge = cookie.getMaxAge();
- if (maxAge >= 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 || getAlwaysAddExpires()) {
- // 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( ANCIENT_DATE );
- } else {
- COOKIE_DATE_FORMAT.get().format(
- new Date(System.currentTimeMillis() + maxAge * 1000L),
- buf,
- new FieldPosition(0));
- }
- }
- }
-
- // Path=path
- if (path!=null) {
- buf.append ("; Path=");
- maybeQuote(buf, path, version);
- }
-
- // Secure
- if (cookie.getSecure()) {
- buf.append ("; Secure");
- }
-
- // HttpOnly
- if (cookie.isHttpOnly()) {
- buf.append("; HttpOnly");
- }
-
- String cookieSameSite = cookie.getAttribute(Constants.COOKIE_SAME_SITE_ATTR);
- if (cookieSameSite == null) {
- // Use processor config
- SameSiteCookies sameSiteCookiesValue = getSameSiteCookies();
- if (!sameSiteCookiesValue.equals(SameSiteCookies.UNSET)) {
- buf.append("; SameSite=");
- buf.append(sameSiteCookiesValue.getValue());
- }
- } else {
- // Use explict config
- buf.append("; SameSite=");
- buf.append(cookieSameSite);
- }
-
- // Add the remaining attributes
- for (Map.Entry<String,String> entry : cookie.getAttributes().entrySet()) {
- switch (entry.getKey()) {
- case Constants.COOKIE_COMMENT_ATTR:
- case Constants.COOKIE_DOMAIN_ATTR:
- case Constants.COOKIE_MAX_AGE_ATTR:
- case Constants.COOKIE_PATH_ATTR:
- case Constants.COOKIE_SECURE_ATTR:
- case Constants.COOKIE_HTTP_ONLY_ATTR:
- case Constants.COOKIE_SAME_SITE_ATTR:
- // Handled above so NO-OP
- break;
- default: {
- buf.append("; ");
- buf.append(entry.getKey());
- buf.append('=');
- maybeQuote(buf, entry.getValue(), version);
- }
- }
- }
-
- return buf.toString();
- }
-
-
- private void maybeQuote(StringBuffer buf, String value, int version) {
- if (value == null || value.length() == 0) {
- buf.append("\"\"");
- } else if (alreadyQuoted(value)) {
- buf.append('"');
- escapeDoubleQuotes(buf, value,1,value.length()-1);
- buf.append('"');
- } else if (needsQuotes(value, version)) {
- buf.append('"');
- escapeDoubleQuotes(buf, value,0,value.length());
- buf.append('"');
- } else {
- buf.append(value);
- }
- }
-
-
- private static void escapeDoubleQuotes(StringBuffer b, String s, int beginIndex, int endIndex) {
- if (s.indexOf('"') == -1 && s.indexOf('\\') == -1) {
- b.append(s);
- return;
- }
-
- for (int i = beginIndex; i < endIndex; i++) {
- char c = s.charAt(i);
- if (c == '\\' ) {
- b.append('\\').append('\\');
- } else if (c == '"') {
- b.append('\\').append('"');
- } else {
- b.append(c);
- }
- }
- }
-
-
- private boolean needsQuotes(String value, int version) {
- if (value == null) {
- return false;
- }
-
- int i = 0;
- int len = value.length();
-
- if (alreadyQuoted(value)) {
- i++;
- len--;
- }
-
- for (; i < len; i++) {
- char c = value.charAt(i);
- if ((c < 0x20 && c != '\t') || c >= 0x7f) {
- throw new IllegalArgumentException(
- "Control character in cookie value or attribute.");
- }
- if (version == 0 && !allowedWithoutQuotes.get(c) ||
- version == 1 && isHttpSeparator(c)) {
- return true;
- }
- }
- return false;
- }
-
-
- private static boolean alreadyQuoted (String value) {
- return value.length() >= 2 &&
- value.charAt(0) == '\"' &&
- value.charAt(value.length() - 1) == '\"';
- }
-
-
- /**
- * Parses a cookie header after the initial "Cookie:"
- * [WS][$]token[WS]=[WS](token|QV)[;|,]
- * RFC 2965 / RFC 2109
- * JVK
- */
- private final void processCookieHeader(byte bytes[], int off, int len,
- ServerCookies serverCookies) {
-
- if (len <= 0 || bytes == null) {
- return;
- }
- int end = off + len;
- int pos = off;
- int nameStart = 0;
- int nameEnd = 0;
- int valueStart = 0;
- int valueEnd = 0;
- int version = 0;
- ServerCookie sc = null;
- boolean isSpecial;
- boolean isQuoted;
-
- while (pos < end) {
- isSpecial = false;
- isQuoted = false;
-
- // Skip whitespace and non-token characters (separators)
- while (pos < end &&
- (isHttpSeparator((char) bytes[pos]) &&
- !getAllowHttpSepsInV0() ||
- isV0Separator((char) bytes[pos]) ||
- isWhiteSpace(bytes[pos])))
- {pos++; }
-
- if (pos >= end) {
- return;
- }
-
- // Detect Special cookies
- if (bytes[pos] == '$') {
- isSpecial = true;
- pos++;
- }
-
- // Get the cookie/attribute name. This must be a token
- valueEnd = valueStart = nameStart = pos;
- pos = nameEnd = getTokenEndPosition(bytes,pos,end,version,true);
-
- // Skip whitespace
- while (pos < end && isWhiteSpace(bytes[pos])) {pos++; }
-
-
- // Check for an '=' -- This could also be a name-only
- // cookie at the end of the cookie header, so if we
- // are past the end of the header, but we have a name
- // skip to the name-only part.
- if (pos < (end - 1) && bytes[pos] == '=') {
-
- // Skip whitespace
- do {
- pos++;
- } while (pos < end && isWhiteSpace(bytes[pos]));
-
- if (pos >= end) {
- return;
- }
-
- // Determine what type of value this is, quoted value,
- // token, name-only with an '=', or other (bad)
- switch (bytes[pos]) {
- case '"': // Quoted Value
- isQuoted = true;
- valueStart = pos + 1; // strip "
- // getQuotedValue returns the position before
- // at the last quote. This must be dealt with
- // when the bytes are copied into the cookie
- valueEnd = getQuotedValueEndPosition(bytes, valueStart, end);
- // We need pos to advance
- pos = valueEnd;
- // Handles cases where the quoted value is
- // unterminated and at the end of the header,
- // e.g. [myname="value]
- if (pos >= end) {
- return;
- }
- break;
- case ';':
- case ',':
- // Name-only cookie with an '=' after the name token
- // This may not be RFC compliant
- valueStart = valueEnd = -1;
- // The position is OK (On a delimiter)
- break;
- default:
- if (version == 0 &&
- !isV0Separator((char)bytes[pos]) &&
- getAllowHttpSepsInV0() ||
- !isHttpSeparator((char)bytes[pos]) ||
- bytes[pos] == '=') {
- // Token
- valueStart = pos;
- // getToken returns the position at the delimiter
- // or other non-token character
- valueEnd = getTokenEndPosition(bytes, valueStart, end, version, false);
- // We need pos to advance
- pos = valueEnd;
- // Edge case. If value starts with '=' but this is not
- // allowed in a value make sure we treat this as no
- // value being present
- if (valueStart == valueEnd) {
- valueStart = -1;
- valueEnd = -1;
- }
- } else {
- // INVALID COOKIE, advance to next delimiter
- // The starting character of the cookie value was
- // not valid.
- UserDataHelper.Mode logMode = userDataLog.getNextMode();
- if (logMode != null) {
- String message = sm.getString(
- "cookies.invalidCookieToken");
- switch (logMode) {
- case INFO_THEN_DEBUG:
- message += sm.getString(
- "cookies.fallToDebug");
- //$FALL-THROUGH$
- case INFO:
- log.info(message);
- break;
- case DEBUG:
- log.debug(message);
- }
- }
- while (pos < end && bytes[pos] != ';' &&
- bytes[pos] != ',')
- {pos++; }
- pos++;
- // Make sure no special avpairs can be attributed to
- // the previous cookie by setting the current cookie
- // to null
- sc = null;
- continue;
- }
- }
- } else {
- // Name only cookie
- valueStart = valueEnd = -1;
- pos = nameEnd;
-
- }
-
- // We should have an avpair or name-only cookie at this
- // point. Perform some basic checks to make sure we are
- // in a good state.
-
- // Skip whitespace
- while (pos < end && isWhiteSpace(bytes[pos])) {pos++; }
-
-
- // Make sure that after the cookie we have a separator. This
- // is only important if this is not the last cookie pair
- while (pos < end && bytes[pos] != ';' && bytes[pos] != ',') {
- pos++;
- }
-
- pos++;
-
- // All checks passed. Add the cookie, start with the
- // special avpairs first
- if (isSpecial) {
- isSpecial = false;
- // $Version must be the first avpair in the cookie header
- // (sc must be null)
- if (equals( "Version", bytes, nameStart, nameEnd) &&
- sc == null) {
- // Set version
- if( bytes[valueStart] =='1' && valueEnd == (valueStart+1)) {
- version=1;
- } else {
- // unknown version (Versioning is not very strict)
- }
- continue;
- }
-
- // We need an active cookie for Path/Port/etc.
- if (sc == null) {
- continue;
- }
-
- // Domain is more common, so it goes first
- if (equals( "Domain", bytes, nameStart, nameEnd)) {
- sc.getDomain().setBytes( bytes,
- valueStart,
- valueEnd-valueStart);
- continue;
- }
-
- if (equals( "Path", bytes, nameStart, nameEnd)) {
- sc.getPath().setBytes( bytes,
- valueStart,
- valueEnd-valueStart);
- continue;
- }
-
- // v2 cookie attributes - skip them
- if (equals( "Port", bytes, nameStart, nameEnd)) {
- continue;
- }
- if (equals( "CommentURL", bytes, nameStart, nameEnd)) {
- continue;
- }
-
- // Unknown cookie, complain
- UserDataHelper.Mode logMode = userDataLog.getNextMode();
- if (logMode != null) {
- String message = sm.getString("cookies.invalidSpecial");
- switch (logMode) {
- case INFO_THEN_DEBUG:
- message += sm.getString("cookies.fallToDebug");
- //$FALL-THROUGH$
- case INFO:
- log.info(message);
- break;
- case DEBUG:
- log.debug(message);
- }
- }
- } else { // Normal Cookie
- if (valueStart == -1 && !getAllowNameOnly()) {
- // Skip name only cookies if not supported
- continue;
- }
-
- sc = serverCookies.addCookie();
- sc.setVersion( version );
- sc.getName().setBytes( bytes, nameStart,
- nameEnd-nameStart);
-
- if (valueStart != -1) { // Normal AVPair
- sc.getValue().setBytes( bytes, valueStart,
- valueEnd-valueStart);
- if (isQuoted) {
- // We know this is a byte value so this is safe
- unescapeDoubleQuotes(sc.getValue().getByteChunk());
- }
- } else {
- // Name Only
- sc.getValue().setString("");
- }
- continue;
- }
- }
- }
-
-
- /**
- * Given the starting position of a token, this gets the end of the
- * token, with no separator characters in between.
- * JVK
- */
- private final int getTokenEndPosition(byte bytes[], int off, int end,
- int version, boolean isName){
- int pos = off;
- while (pos < end &&
- (!isHttpSeparator((char)bytes[pos]) ||
- version == 0 && getAllowHttpSepsInV0() && bytes[pos] != '=' &&
- !isV0Separator((char)bytes[pos]) ||
- !isName && bytes[pos] == '=' && getAllowEqualsInValue())) {
- pos++;
- }
-
- if (pos > end) {
- return end;
- }
- return pos;
- }
-
-
- private boolean isHttpSeparator(final char c) {
- if (c < 0x20 || c >= 0x7f) {
- if (c != 0x09) {
- throw new IllegalArgumentException(
- "Control character in cookie value or attribute.");
- }
- }
-
- return httpSeparatorFlags.get(c);
- }
-
-
- /**
- * Returns true if the byte is a separator as defined by V0 of the cookie
- * spec.
- */
- private static boolean isV0Separator(final char c) {
- if (c < 0x20 || c >= 0x7f) {
- if (c != 0x09) {
- throw new IllegalArgumentException(
- "Control character in cookie value or attribute.");
- }
- }
-
- return V0_SEPARATOR_FLAGS.get(c);
- }
-
-
- /**
- * Given a starting position after an initial quote character, this gets
- * the position of the end quote. This escapes anything after a '\' char
- * JVK RFC 2616
- */
- private static final int getQuotedValueEndPosition(byte bytes[], int off, int end){
- int pos = off;
- while (pos < end) {
- if (bytes[pos] == '"') {
- return pos;
- } else if (bytes[pos] == '\\' && pos < (end - 1)) {
- pos+=2;
- } else {
- pos++;
- }
- }
- // Error, we have reached the end of the header w/o a end quote
- return end;
- }
-
-
- private static final boolean equals(String s, byte b[], int start, int end) {
- int blen = end-start;
- if (b == null || blen != s.length()) {
- return false;
- }
- int boff = start;
- for (int i = 0; i < blen; i++) {
- if (b[boff++] != s.charAt(i)) {
- return false;
- }
- }
- return true;
- }
-
-
- /**
- * Returns true if the byte is a whitespace character as
- * defined in RFC2619
- * JVK
- */
- private static final boolean isWhiteSpace(final byte c) {
- // This switch statement is slightly slower
- // for my vm than the if statement.
- // Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_07-164)
- /*
- switch (c) {
- case ' ':;
- case '\t':;
- case '\n':;
- case '\r':;
- case '\f':;
- return true;
- default:;
- return false;
- }
- */
- if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f') {
- return true;
- } else {
- return false;
- }
- }
-
-
- /**
- * Unescapes any double quotes in the given cookie value.
- *
- * @param bc The cookie value to modify
- */
- private static final void unescapeDoubleQuotes(ByteChunk bc) {
-
- if (bc == null || bc.getLength() == 0 || bc.indexOf('"', 0) == -1) {
- return;
- }
-
- // Take a copy of the buffer so the original cookie header is not
- // modified by this unescaping.
- byte[] original = bc.getBuffer();
- int len = bc.getLength();
-
- byte[] copy = new byte[len];
- System.arraycopy(original, bc.getStart(), copy, 0, len);
-
- int src = 0;
- int dest = 0;
-
- while (src < len) {
- if (copy[src] == '\\' && src < len && copy[src+1] == '"') {
- src++;
- }
- copy[dest] = copy[src];
- dest ++;
- src ++;
- }
- bc.setBytes(copy, 0, dest);
- }
-}
diff --git a/java/org/apache/tomcat/util/http/ServerCookie.java b/java/org/apache/tomcat/util/http/ServerCookie.java
index 5ae7f0d..157b76a 100644
--- a/java/org/apache/tomcat/util/http/ServerCookie.java
+++ b/java/org/apache/tomcat/util/http/ServerCookie.java
@@ -34,23 +34,9 @@ public class ServerCookie implements Serializable {
private static final long serialVersionUID = 1L;
- // Version 0 (Netscape) attributes
+ // RFC 6265
private final MessageBytes name=MessageBytes.newInstance();
private final MessageBytes value=MessageBytes.newInstance();
- // Expires - Not stored explicitly. Generated from Max-Age (see V1)
- private final MessageBytes path=MessageBytes.newInstance();
- private final MessageBytes domain=MessageBytes.newInstance();
-
- // Version 1 (RFC2109) attributes
- private final MessageBytes comment=MessageBytes.newInstance();
- private int version = 0;
-
- // Note: Servlet Spec =< 3.0 only refers to Netscape and RFC2109, not RFC2965
-
- // Version 2 (RFC2965) attributes that would need to be added to support v2 cookies
- // CommentURL
- // Discard - implied by maxAge <0
- // Port
public ServerCookie() {
// NOOP
@@ -59,22 +45,6 @@ public class ServerCookie implements Serializable {
public void recycle() {
name.recycle();
value.recycle();
- comment.recycle();
- path.recycle();
- domain.recycle();
- version=0;
- }
-
- public MessageBytes getComment() {
- return comment;
- }
-
- public MessageBytes getDomain() {
- return domain;
- }
-
- public MessageBytes getPath() {
- return path;
}
public MessageBytes getName() {
@@ -85,21 +55,12 @@ public class ServerCookie implements Serializable {
return value;
}
- public int getVersion() {
- return version;
- }
-
- public void setVersion(int v) {
- version = v;
- }
-
// -------------------- utils --------------------
@Override
public String toString() {
- return "Cookie " + getName() + "=" + getValue() + " ; "
- + getVersion() + " " + getPath() + " " + getDomain();
+ return "Cookie " + getName() + "=" + getValue();
}
}
diff --git a/java/org/apache/tomcat/util/http/parser/Cookie.java b/java/org/apache/tomcat/util/http/parser/Cookie.java
index 24c33b2..9a321bf 100644
--- a/java/org/apache/tomcat/util/http/parser/Cookie.java
+++ b/java/org/apache/tomcat/util/http/parser/Cookie.java
@@ -27,7 +27,7 @@ import org.apache.tomcat.util.res.StringManager;
/**
- * <p>Cookie header parser based on RFC6265 and RFC2109.</p>
+ * <p>Cookie header parser based on RFC6265</p>
* <p>The parsing of cookies using RFC6265 is more relaxed that the
* specification in the following ways:</p>
* <ul>
@@ -36,38 +36,26 @@ import org.apache.tomcat.util.res.StringManager;
* <li>For cookies without a value, the '=' is not required after the name as
* some browsers do not sent it.</li>
* </ul>
- * <p>The parsing of cookies using RFC2109 is more relaxed that the
- * specification in the following ways:</p>
- * <ul>
- * <li>Values for the path attribute that contain a / character do not have to
- * be quoted even though / is not permitted in a token.</li>
- * </ul>
*
* <p>Implementation note:<br>
- * This class has been carefully tuned to ensure that it has equal or better
- * performance than the original Netscape/RFC2109 cookie parser. Before
- * committing and changes, ensure that the TesterCookiePerformance unit test
- * continues to give results within 1% for the old and new parsers.</p>
+ * This class has been carefully tuned. Before committing any changes, ensure
+ * that the TesterCookiePerformance unit test continues to give results within
+ * 1% for the old and new parsers.</p>
*/
public class Cookie {
private static final Log log = LogFactory.getLog(Cookie.class);
- private static final UserDataHelper invalidCookieVersionLog = new UserDataHelper(log);
private static final UserDataHelper invalidCookieLog = new UserDataHelper(log);
private static final StringManager sm =
StringManager.getManager("org.apache.tomcat.util.http.parser");
private static final boolean isCookieOctet[] = new boolean[256];
private static final boolean isText[] = new boolean[256];
- private static final byte[] VERSION_BYTES = "$Version".getBytes(StandardCharsets.ISO_8859_1);
- private static final byte[] PATH_BYTES = "$Path".getBytes(StandardCharsets.ISO_8859_1);
- private static final byte[] DOMAIN_BYTES = "$Domain".getBytes(StandardCharsets.ISO_8859_1);
private static final byte[] EMPTY_BYTES = new byte[0];
private static final byte TAB_BYTE = (byte) 0x09;
private static final byte SPACE_BYTE = (byte) 0x20;
private static final byte QUOTE_BYTE = (byte) 0x22;
private static final byte COMMA_BYTE = (byte) 0x2C;
- private static final byte FORWARDSLASH_BYTE = (byte) 0x2F;
private static final byte SEMICOLON_BYTE = (byte) 0x3B;
private static final byte EQUALS_BYTE = (byte) 0x3D;
private static final byte SLASH_BYTE = (byte) 0x5C;
@@ -107,93 +95,6 @@ public class Cookie {
// and position information to be easily passed between parsing methods
ByteBuffer bb = new ByteBuffer(bytes, offset, len);
- // Using RFC6265 parsing rules, check to see if the header starts with a
- // version marker. An RFC2109 version marker may be read using RFC6265
- // parsing rules. If version 1, use RFC2109. Else use RFC6265.
-
- skipLWS(bb);
-
- // Record position in case we need to return.
- int mark = bb.position();
-
- SkipResult skipResult = skipBytes(bb, VERSION_BYTES);
- if (skipResult != SkipResult.FOUND) {
- // No need to reset position since skipBytes() will have done it
- parseCookieRfc6265(bb, serverCookies);
- return;
- }
-
- skipLWS(bb);
-
- skipResult = skipByte(bb, EQUALS_BYTE);
- if (skipResult != SkipResult.FOUND) {
- // Need to reset position as skipByte() will only have reset to
- // position before it was called
- bb.position(mark);
- parseCookieRfc6265(bb, serverCookies);
- return;
- }
-
- skipLWS(bb);
-
- ByteBuffer value = readCookieValue(bb);
- if (value != null && value.remaining() == 1) {
- int version = value.get() - '0';
- if (version == 1 || version == 0) {
- // $Version=1 -> RFC2109
- // $Version=0 -> RFC2109
- skipLWS(bb);
- byte b = bb.get();
- if (b == SEMICOLON_BYTE || b == COMMA_BYTE) {
- parseCookieRfc2109(bb, serverCookies, version);
- }
- } else {
- // Unrecognised version.
- // Ignore this header.
- value.rewind();
- logInvalidVersion(value);
- }
- } else {
- // Unrecognised version.
- // Ignore this header.
- logInvalidVersion(value);
- }
- }
-
-
- public static String unescapeCookieValueRfc2109(String input) {
- if (input == null || input.length() < 2) {
- return input;
- }
- if (input.charAt(0) != '"' && input.charAt(input.length() - 1) != '"') {
- return input;
- }
-
- StringBuilder sb = new StringBuilder(input.length());
- char[] chars = input.toCharArray();
- boolean escaped = false;
-
- for (int i = 1; i < input.length() - 1; i++) {
- if (chars[i] == '\\') {
- escaped = true;
- } else if (escaped) {
- escaped = false;
- if (chars[i] < 128) {
- sb.append(chars[i]);
- } else {
- sb.append('\\');
- sb.append(chars[i]);
- }
- } else {
- sb.append(chars[i]);
- }
- }
- return sb.toString();
- }
-
-
- private static void parseCookieRfc6265(ByteBuffer bb, ServerCookies serverCookies) {
-
boolean moreToProcess = true;
while (moreToProcess) {
@@ -243,139 +144,6 @@ public class Cookie {
}
- private static void parseCookieRfc2109(ByteBuffer bb, ServerCookies serverCookies,
- int version) {
-
- boolean moreToProcess = true;
-
- while (moreToProcess) {
- skipLWS(bb);
-
- boolean parseAttributes = true;
-
- ByteBuffer name = readToken(bb);
- ByteBuffer value = null;
- ByteBuffer path = null;
- ByteBuffer domain = null;
-
- skipLWS(bb);
-
- SkipResult skipResult = skipByte(bb, EQUALS_BYTE);
- if (skipResult == SkipResult.FOUND) {
- skipLWS(bb);
- value = readCookieValueRfc2109(bb, false);
- if (value == null) {
- skipInvalidCookie(bb);
- continue;
- }
- skipLWS(bb);
- }
-
- skipResult = skipByte(bb, COMMA_BYTE);
- if (skipResult == SkipResult.FOUND) {
- parseAttributes = false;
- } else {
- skipResult = skipByte(bb, SEMICOLON_BYTE);
- }
- if (skipResult == SkipResult.EOF) {
- parseAttributes = false;
- moreToProcess = false;
- } else if (skipResult == SkipResult.NOT_FOUND) {
- skipInvalidCookie(bb);
- continue;
- }
-
- if (parseAttributes) {
- skipLWS(bb);
- skipResult = skipBytes(bb, PATH_BYTES);
- if (skipResult == SkipResult.FOUND) {
- skipLWS(bb);
- skipResult = skipByte(bb, EQUALS_BYTE);
- if (skipResult != SkipResult.FOUND) {
- skipInvalidCookie(bb);
- continue;
- }
- skipLWS(bb);
- path = readCookieValueRfc2109(bb, true);
- if (path == null) {
- skipInvalidCookie(bb);
- continue;
- }
- skipLWS(bb);
-
- skipResult = skipByte(bb, COMMA_BYTE);
- if (skipResult == SkipResult.FOUND) {
- parseAttributes = false;
- } else {
- skipResult = skipByte(bb, SEMICOLON_BYTE);
- }
- if (skipResult == SkipResult.EOF) {
- parseAttributes = false;
- moreToProcess = false;
- } else if (skipResult == SkipResult.NOT_FOUND) {
- skipInvalidCookie(bb);
- continue;
- }
- }
- }
-
- if (parseAttributes) {
- skipLWS(bb);
- skipResult = skipBytes(bb, DOMAIN_BYTES);
- if (skipResult == SkipResult.FOUND) {
- skipLWS(bb);
- skipResult = skipByte(bb, EQUALS_BYTE);
- if (skipResult != SkipResult.FOUND) {
- skipInvalidCookie(bb);
- continue;
- }
- skipLWS(bb);
- domain = readCookieValueRfc2109(bb, false);
- if (domain == null) {
- skipInvalidCookie(bb);
- continue;
- }
- skipLWS(bb);
-
- skipResult = skipByte(bb, COMMA_BYTE);
- if (skipResult == SkipResult.FOUND) {
- parseAttributes = false;
- } else {
- skipResult = skipByte(bb, SEMICOLON_BYTE);
- }
- if (skipResult == SkipResult.EOF) {
- parseAttributes = false;
- moreToProcess = false;
- } else if (skipResult == SkipResult.NOT_FOUND) {
- skipInvalidCookie(bb);
- continue;
- }
- }
- }
-
- if (name.hasRemaining() && value != null && value.hasRemaining()) {
- ServerCookie sc = serverCookies.addCookie();
- sc.setVersion(version);
- sc.getName().setBytes(name.array(), name.position(), name.remaining());
- sc.getValue().setBytes(value.array(), value.position(), value.remaining());
- if (domain != null) {
- sc.getDomain().setBytes(domain.array(), domain.position(), domain.remaining());
- }
- if (path != null) {
- sc.getPath().setBytes(path.array(), path.position(), path.remaining());
- }
- }
- }
- }
-
-
- private static void skipInvalidCookie(ByteBuffer bb) {
- logInvalidHeader(bb);
- // Invalid cookie value. Skip to the next semi-colon
- skipUntilSemiColonOrComma(bb);
- }
-
-
private static void skipLWS(ByteBuffer bb) {
while(bb.hasRemaining()) {
byte b = bb.get();
@@ -396,16 +164,6 @@ public class Cookie {
}
- private static void skipUntilSemiColonOrComma(ByteBuffer bb) {
- while(bb.hasRemaining()) {
- byte b = bb.get();
- if (b == SEMICOLON_BYTE || b == COMMA_BYTE) {
- break;
- }
- }
- }
-
-
private static SkipResult skipByte(ByteBuffer bb, byte target) {
if (!bb.hasRemaining()) {
@@ -420,59 +178,6 @@ public class Cookie {
}
- private static SkipResult skipBytes(ByteBuffer bb, byte[] target) {
- int mark = bb.position();
-
- for (byte b : target) {
- if (!bb.hasRemaining()) {
- bb.position(mark);
- return SkipResult.EOF;
- }
- if (bb.get() != b) {
- bb.position(mark);
- return SkipResult.NOT_FOUND;
- }
- }
- return SkipResult.FOUND;
- }
-
-
- /**
- * Similar to readCookieValueRfc6265() but also allows a comma to terminate
- * the value (as permitted by RFC2109).
- */
- private static ByteBuffer readCookieValue(ByteBuffer bb) {
- boolean quoted = false;
- if (bb.hasRemaining()) {
- if (bb.get() == QUOTE_BYTE) {
- quoted = true;
- } else {
- bb.rewind();
- }
- }
- int start = bb.position();
- int end = bb.limit();
- while (bb.hasRemaining()) {
- byte b = bb.get();
- if (isCookieOctet[(b & 0xFF)]) {
- // NO-OP
- } else if (b == SEMICOLON_BYTE || b == COMMA_BYTE || b == SPACE_BYTE || b == TAB_BYTE) {
- end = bb.position() - 1;
- bb.position(end);
- break;
- } else if (quoted && b == QUOTE_BYTE) {
- end = bb.position() - 1;
- break;
- } else {
- // Invalid cookie
- return null;
- }
- }
-
- return new ByteBuffer(bb.bytes, start, end - start);
- }
-
-
/**
* Similar to readCookieValue() but treats a comma as part of an invalid
* value.
@@ -509,23 +214,6 @@ public class Cookie {
}
- private static ByteBuffer readCookieValueRfc2109(ByteBuffer bb, boolean allowForwardSlash) {
- if (!bb.hasRemaining()) {
- return null;
- }
-
- if (bb.peek() == QUOTE_BYTE) {
- return readQuotedString(bb);
- } else {
- if (allowForwardSlash) {
- return readTokenAllowForwardSlash(bb);
- } else {
- return readToken(bb);
- }
- }
- }
-
-
private static ByteBuffer readToken(ByteBuffer bb) {
final int start = bb.position();
int end = bb.limit();
@@ -541,48 +229,6 @@ public class Cookie {
}
- private static ByteBuffer readTokenAllowForwardSlash(ByteBuffer bb) {
- final int start = bb.position();
- int end = bb.limit();
- while (bb.hasRemaining()) {
- byte b = bb.get();
- if (b != FORWARDSLASH_BYTE && !HttpParser.isToken(b)) {
- end = bb.position() - 1;
- bb.position(end);
- break;
- }
- }
-
- return new ByteBuffer(bb.bytes, start, end - start);
- }
-
-
- private static ByteBuffer readQuotedString(ByteBuffer bb) {
- int start = bb.position();
-
- // Read the opening quote
- bb.get();
- boolean escaped = false;
- while (bb.hasRemaining()) {
- byte b = bb.get();
- if (b == SLASH_BYTE) {
- // Escaping another character
- escaped = true;
- } else if (escaped && b > (byte) -1) {
- escaped = false;
- } else if (b == QUOTE_BYTE) {
- return new ByteBuffer(bb.bytes, start, bb.position() - start);
- } else if (isText[b & 0xFF]) {
- escaped = false;
- } else {
- return null;
- }
- }
-
- return null;
- }
-
-
private static void logInvalidHeader(ByteBuffer bb) {
UserDataHelper.Mode logMode = invalidCookieLog.getNextMode();
if (logMode != null) {
@@ -603,31 +249,6 @@ public class Cookie {
}
- private static void logInvalidVersion(ByteBuffer value) {
- UserDataHelper.Mode logMode = invalidCookieVersionLog.getNextMode();
- if (logMode != null) {
- String version;
- if (value == null) {
- version = sm.getString("cookie.valueNotPresent");
- } else {
- version = new String(value.bytes, value.position(),
- value.limit() - value.position(), StandardCharsets.UTF_8);
- }
- String message = sm.getString("cookie.invalidCookieVersion", version);
- switch (logMode) {
- case INFO_THEN_DEBUG:
- message += sm.getString("cookie.fallToDebug");
- //$FALL-THROUGH$
- case INFO:
- log.info(message);
- break;
- case DEBUG:
- log.debug(message);
- }
- }
- }
-
-
/**
* Custom implementation that skips many of the safety checks in
* {@link java.nio.ByteBuffer}.
@@ -668,10 +289,6 @@ public class Cookie {
return bytes[position++];
}
- public byte peek() {
- return bytes[position];
- }
-
public void rewind() {
position--;
}
diff --git a/test/jakarta/servlet/http/TestCookie.java b/test/jakarta/servlet/http/TestCookie.java
index fa1d6da..27268be 100644
--- a/test/jakarta/servlet/http/TestCookie.java
+++ b/test/jakarta/servlet/http/TestCookie.java
@@ -49,6 +49,7 @@ public class TestCookie {
TOKEN.andNot(SEPARATORS); // or separators
}
+ @SuppressWarnings("removal")
@Test
public void testDefaults() {
Cookie cookie = new Cookie("foo", null);
@@ -58,6 +59,7 @@ public class TestCookie {
Assert.assertEquals(-1, cookie.getMaxAge());
}
+ @SuppressWarnings("removal")
@Test
public void testInitialValue() {
Cookie cookie = new Cookie("foo", "bar");
@@ -68,7 +70,6 @@ public class TestCookie {
@Test
public void defaultImpliesNetscape() {
- // $Foo is allowed by Netscape but not by RFC2109
Cookie cookie = new Cookie("$Foo", null);
Assert.assertEquals("$Foo", cookie.getName());
}
@@ -128,13 +129,6 @@ public class TestCookie {
}
@Test
- public void strictNamingImpliesRFC2109() {
- // Needs to be something RFC6265 allows, but strict naming does not.
- @SuppressWarnings("unused")
- Cookie cookie = new Cookie("$Foo", null);
- }
-
- @Test
public void testGetAttributes01() {
Cookie cookie = new Cookie("name", "value");
Assert.assertEquals(0, cookie.getAttributes().size());
@@ -183,7 +177,6 @@ public class TestCookie {
@Test
public void testClone() {
Cookie a = new Cookie("a","a");
- a.setComment("comment");
a.setDomain("domain");
a.setHttpOnly(true);
a.setMaxAge(123);
@@ -194,7 +187,6 @@ public class TestCookie {
Assert.assertEquals("a", b.getName());
Assert.assertEquals("a", b.getValue());
- Assert.assertEquals("comment", b.getComment());
Assert.assertEquals("domain", b.getDomain());
Assert.assertTrue(b.isHttpOnly());
Assert.assertEquals(123, b.getMaxAge());
diff --git a/test/jakarta/servlet/http/TestCookieRFC2109Validator.java b/test/jakarta/servlet/http/TestCookieRFC2109Validator.java
deleted file mode 100644
index 5879224..0000000
--- a/test/jakarta/servlet/http/TestCookieRFC2109Validator.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package jakarta.servlet.http;
-
-import org.junit.Test;
-
-/**
- * Basic tests for Cookie in default configuration.
- */
-public class TestCookieRFC2109Validator {
-
- private RFC2109Validator validator = new RFC2109Validator(false);
-
- @Test
- public void actualCharactersAllowedInName() {
- TestCookie.checkCharInName(validator, TestCookie.TOKEN);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void leadingDollar() {
- validator.validate("$Version");
- }
-}
diff --git a/test/jakarta/servlet/http/TestCookieStrict.java b/test/jakarta/servlet/http/TestCookieStrict.java
deleted file mode 100644
index aa3f7a0..0000000
--- a/test/jakarta/servlet/http/TestCookieStrict.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package jakarta.servlet.http;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-/**
- * Basic tests for Cookie in STRICT_SERVLET_COMPLIANCE configuration.
- */
-public class TestCookieStrict {
- static {
- System.setProperty("org.apache.tomcat.util.http.ServerCookie.STRICT_NAMING", "true");
- }
-
- @Test
- public void testDefaults() {
- Cookie cookie = new Cookie("strict", null);
- Assert.assertEquals("strict", cookie.getName());
- Assert.assertNull(cookie.getValue());
- Assert.assertEquals(0, cookie.getVersion());
- Assert.assertEquals(-1, cookie.getMaxAge());
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void strictNamingImpliesRFC2109() {
- @SuppressWarnings("unused")
- Cookie cookie = new Cookie("@Foo", null);
- }
-}
diff --git a/test/org/apache/catalina/core/TestApplicationSessionCookieConfig.java b/test/org/apache/catalina/core/TestApplicationSessionCookieConfig.java
index e59a4a2..4203901 100644
--- a/test/org/apache/catalina/core/TestApplicationSessionCookieConfig.java
+++ b/test/org/apache/catalina/core/TestApplicationSessionCookieConfig.java
@@ -36,7 +36,7 @@ public class TestApplicationSessionCookieConfig {
public void testSetCommentInitPhase() {
context.setState(LifecycleState.STARTING_PREP);
applicationSessionCookieConfig.setComment("test");
- Assert.assertTrue(applicationSessionCookieConfig.getComment().equals("test"));
+ Assert.assertNull(applicationSessionCookieConfig.getComment());
}
@Test(expected = IllegalStateException.class)
diff --git a/test/org/apache/catalina/valves/TestLoadBalancerDrainingValve.java b/test/org/apache/catalina/valves/TestLoadBalancerDrainingValve.java
index 1e13ed2..390f8d9 100644
--- a/test/org/apache/catalina/valves/TestLoadBalancerDrainingValve.java
+++ b/test/org/apache/catalina/valves/TestLoadBalancerDrainingValve.java
@@ -224,11 +224,11 @@ public class TestLoadBalancerDrainingValve {
}
@Override
public String getComment() {
- return attributes.get(Constants.COOKIE_COMMENT_ATTR);
+ return null;
}
@Override
public void setComment(String comment) {
- attributes.put(Constants.COOKIE_COMMENT_ATTR, comment);
+ // NO-OP
}
@Override
public boolean isHttpOnly() {
diff --git a/test/org/apache/tomcat/util/http/CookiesBaseTest.java b/test/org/apache/tomcat/util/http/CookiesBaseTest.java
deleted file mode 100644
index 70c7692..0000000
--- a/test/org/apache/tomcat/util/http/CookiesBaseTest.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.tomcat.util.http;
-
-import java.io.IOException;
-
-import jakarta.servlet.http.Cookie;
-import jakarta.servlet.http.HttpServlet;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
-
-import org.apache.catalina.Context;
-import org.apache.catalina.startup.Tomcat;
-import org.apache.catalina.startup.TomcatBaseTest;
-
-/**
- * Base Test case for {@link LegacyCookieProcessor}. <b>Note</b> because of the
- * use of <code>static final</code> constants in {@link LegacyCookieProcessor},
- * each of these tests must be executed in a new JVM instance. The tests have
- * been place in separate classes to facilitate this when running the unit tests
- * via Ant.
- */
-public abstract class CookiesBaseTest extends TomcatBaseTest {
-
- /**
- * Servlet for cookie naming test.
- */
- public static class CookieServlet extends HttpServlet {
-
- private static final long serialVersionUID = 1L;
-
- private final String cookieName;
- private final String cookieValue;
-
- public CookieServlet(String cookieName, String cookieValue) {
- this.cookieName = cookieName;
- this.cookieValue = cookieValue;
- }
-
- @Override
- public void doGet(HttpServletRequest req, HttpServletResponse res)
- throws IOException {
- try {
- Cookie cookie = new Cookie(cookieName, cookieValue);
- res.addCookie(cookie);
- res.getWriter().write("Cookie name ok");
- } catch (IllegalArgumentException iae) {
- res.getWriter().write("Cookie name fail");
- }
- }
-
- }
-
-
- public static void addServlets(Tomcat tomcat) {
- // No file system docBase required
- Context ctx = tomcat.addContext("", null);
- ctx.setCookieProcessor(new LegacyCookieProcessor());
-
- Tomcat.addServlet(ctx, "invalid", new CookieServlet("na;me", "value"));
- ctx.addServletMappingDecoded("/invalid", "invalid");
- Tomcat.addServlet(ctx, "null", new CookieServlet(null, "value"));
- ctx.addServletMappingDecoded("/null", "null");
- Tomcat.addServlet(ctx, "blank", new CookieServlet("", "value"));
- ctx.addServletMappingDecoded("/blank", "blank");
- Tomcat.addServlet(ctx, "invalidFwd",
- new CookieServlet("na/me", "value"));
- ctx.addServletMappingDecoded("/invalidFwd", "invalidFwd");
- Tomcat.addServlet(ctx, "invalidStrict",
- new CookieServlet("$name", "value"));
- ctx.addServletMappingDecoded("/invalidStrict", "invalidStrict");
- Tomcat.addServlet(ctx, "valid", new CookieServlet("name", "value"));
- ctx.addServletMappingDecoded("/valid", "valid");
- Tomcat.addServlet(ctx, "switch", new CookieServlet("name", "val?ue"));
- ctx.addServletMappingDecoded("/switch", "switch");
-
- }
-
- public abstract void testCookiesInstance() throws Exception;
-
-}
diff --git a/test/org/apache/tomcat/util/http/TestBug49158.java b/test/org/apache/tomcat/util/http/TestBug49158.java
deleted file mode 100644
index 3fdd6d9..0000000
--- a/test/org/apache/tomcat/util/http/TestBug49158.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.tomcat.util.http;
-
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import jakarta.servlet.ServletException;
-import jakarta.servlet.http.HttpServlet;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
-import jakarta.servlet.http.HttpSession;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-import org.apache.catalina.Context;
-import org.apache.catalina.startup.Tomcat;
-import org.apache.tomcat.util.buf.ByteChunk;
-
-/**
- * Test case for {@link LegacyCookieProcessor}. <b>Note</b> because of the use of <code>final
- * static</code> constants in {@link LegacyCookieProcessor}, each of these tests must be
- * executed in a new JVM instance. The tests have been place in separate classes
- * to facilitate this when running the unit tests via Ant.
- */
-public class TestBug49158 extends CookiesBaseTest {
- public static final String path = "49158";
-
- @Override
- @Test
- public void testCookiesInstance() throws Exception {
- Tomcat tomcat = getTomcatInstance();
- addServlets(tomcat);
- tomcat.start();
- Map<String,List<String>> headers = new HashMap<>();
- ByteChunk res = new ByteChunk();
- getUrl("http://localhost:" + getPort() + "/"+path, res, headers);
- List<String> cookieHeaders = headers.get("Set-Cookie");
- Assert.assertEquals("There should only be one Set-Cookie header in this test",
- 1, cookieHeaders.size());
- }
-
- public static void addServlets(Tomcat tomcat) {
- // No file system docBase required
- Context ctx = tomcat.addContext("", null);
-
- Tomcat.addServlet(ctx, path, new TestBug49158Servlet());
- ctx.addServletMappingDecoded("/"+path, path);
- }
-
- public static class TestBug49158Servlet extends HttpServlet {
-
- private static final long serialVersionUID = 2725990508758127399L;
-
- @Override
- public void service(HttpServletRequest req, HttpServletResponse res)
- throws ServletException, IOException {
- HttpSession session = req.getSession();
- session.invalidate();
- session = req.getSession();
- session.invalidate();
- req.getSession();
- }
-
- }
-
-}
diff --git a/test/org/apache/tomcat/util/http/TestCookieParsing.java b/test/org/apache/tomcat/util/http/TestCookieParsing.java
index 134360b..2792310 100644
--- a/test/org/apache/tomcat/util/http/TestCookieParsing.java
+++ b/test/org/apache/tomcat/util/http/TestCookieParsing.java
@@ -38,7 +38,6 @@ public class TestCookieParsing extends TomcatBaseTest {
private static final String[] COOKIES_WITH_EQUALS = new String[] {
"name=equals=middle", "name==equalsstart", "name=equalsend=" };
- private static final String COOKIES_WITH_EQUALS_TRUNC = "name=equalsname=name=equalsend";
private static final String[] COOKIES_WITH_NAME_ONLY = new String[] {
"bob", "bob=" };
@@ -46,7 +45,6 @@ public class TestCookieParsing extends TomcatBaseTest {
private static final String[] COOKIES_WITH_SEPS = new String[] {
"name=val/ue" };
- private static final String COOKIES_WITH_SEPS_TRUNC = "name=val";
private static final String[] COOKIES_WITH_QUOTES = new String[] {
"name=\"val\\\"ue\"", "name=\"value\"" };
@@ -54,43 +52,12 @@ public class TestCookieParsing extends TomcatBaseTest {
private static final String[] COOKIES_V0 = new String[] {
"$Version=0;name=\"val ue\"", "$Version=0;name=\"val\tue\""};
- private static final String COOKIES_V0_CONCAT = "name=\"val ue\"name=\"val\tue\"";
+ private static final String COOKIES_V0_CONCAT = "$Version=0$Version=0";
private static final String[] COOKIES_V1 = new String[] {
"$Version=1;name=\"val ue\"", "$Version=1;name=\"val\tue\""};
- private static final String COOKIES_V1_CONCAT = "name=\"val ue\"name=\"val\tue\"";
-
-
- @Test
- public void testLegacyWithEquals() throws Exception {
- doTestLegacyEquals(true);
- }
-
-
- @Test
- public void testLegacyWithoutEquals() throws Exception {
- doTestLegacyEquals(false);
- }
-
-
- private void doTestLegacyEquals(boolean allowEquals) throws Exception {
- LegacyCookieProcessor legacyCookieProcessor = new LegacyCookieProcessor();
- legacyCookieProcessor.setAllowEqualsInValue(allowEquals);
- // Need to allow name only cookies to handle equals at the start of
- // the value
- legacyCookieProcessor.setAllowNameOnly(true);
-
- String expected;
- if (allowEquals) {
- expected = concat(COOKIES_WITH_EQUALS);
- } else {
- expected = COOKIES_WITH_EQUALS_TRUNC;
- }
- TestCookieParsingClient client = new TestCookieParsingClient(
- legacyCookieProcessor, COOKIES_WITH_EQUALS, expected);
- client.doRequest();
- }
+ private static final String COOKIES_V1_CONCAT = "$Version=1$Version=1";
@Test
@@ -103,34 +70,6 @@ public class TestCookieParsing extends TomcatBaseTest {
@Test
- public void testLegacyWithNameOnly() throws Exception {
- doTestLegacyNameOnly(true);
- }
-
-
- @Test
- public void testLegacyWithoutNameOnly() throws Exception {
- doTestLegacyNameOnly(false);
- }
-
-
- private void doTestLegacyNameOnly(boolean nameOnly) throws Exception {
- LegacyCookieProcessor legacyCookieProcessor = new LegacyCookieProcessor();
- legacyCookieProcessor.setAllowNameOnly(nameOnly);
-
- String expected;
- if (nameOnly) {
- expected = COOKIES_WITH_NAME_ONLY_CONCAT;
- } else {
- expected = "";
- }
- TestCookieParsingClient client = new TestCookieParsingClient(
- legacyCookieProcessor, COOKIES_WITH_NAME_ONLY, expected);
- client.doRequest();
- }
-
-
- @Test
public void testRfc6265NameOnly() throws Exception {
// Always allows equals
TestCookieParsingClient client = new TestCookieParsingClient(
@@ -157,47 +96,6 @@ public class TestCookieParsing extends TomcatBaseTest {
@Test
- public void testLegacyWithSeps() throws Exception {
- doTestLegacySeps(true, true);
- }
-
-
- @Test
- public void testLegacyWithoutSeps() throws Exception {
- doTestLegacySeps(false, true);
- }
-
-
- @Test
- public void testLegacyWithFwdSlash() throws Exception {
- doTestLegacySeps(true, false);
- }
-
-
- @Test
- public void testLegacyWithoutFwdSlash() throws Exception {
- doTestLegacySeps(false, false);
- }
-
-
- private void doTestLegacySeps(boolean seps, boolean fwdSlash) throws Exception {
- LegacyCookieProcessor legacyCookieProcessor = new LegacyCookieProcessor();
- legacyCookieProcessor.setAllowHttpSepsInV0(seps);
- legacyCookieProcessor.setForwardSlashIsSeparator(fwdSlash);
-
- String expected;
- if (!seps && fwdSlash) {
- expected = COOKIES_WITH_SEPS_TRUNC;
- } else {
- expected = concat(COOKIES_WITH_SEPS);
- }
- TestCookieParsingClient client = new TestCookieParsingClient(
- legacyCookieProcessor, COOKIES_WITH_SEPS, expected);
- client.doRequest();
- }
-
-
- @Test
public void testRfc6265Seps() throws Exception {
// Always allows equals
TestCookieParsingClient client = new TestCookieParsingClient(
@@ -207,18 +105,6 @@ public class TestCookieParsing extends TomcatBaseTest {
@Test
- public void testLegacyPreserveHeader() throws Exception {
- LegacyCookieProcessor legacyCookieProcessor = new LegacyCookieProcessor();
-
- String expected;
- expected = concat(COOKIES_WITH_QUOTES);
- TestCookieParsingClient client = new TestCookieParsingClient(
- legacyCookieProcessor, true, COOKIES_WITH_QUOTES, expected);
- client.doRequest();
- }
-
-
- @Test
public void testRfc6265PreserveHeader() throws Exception {
// Always allows equals
TestCookieParsingClient client = new TestCookieParsingClient(new Rfc6265CookieProcessor(),
diff --git a/test/org/apache/tomcat/util/http/TestCookieProcessorGeneration.java b/test/org/apache/tomcat/util/http/TestCookieProcessorGeneration.java
index 166be60..30ff103 100644
--- a/test/org/apache/tomcat/util/http/TestCookieProcessorGeneration.java
+++ b/test/org/apache/tomcat/util/http/TestCookieProcessorGeneration.java
@@ -24,332 +24,193 @@ import org.junit.Test;
public class TestCookieProcessorGeneration {
@Test
- public void v0SimpleCookie() {
+ public void SimpleCookie() {
doTest(new Cookie("foo", "bar"), "foo=bar");
}
@Test
- public void v0NullValue() {
- doTest(new Cookie("foo", null), "foo=\"\"", "foo=");
+ public void nullValue() {
+ doTest(new Cookie("foo", null), "foo=");
}
@Test
- public void v0QuotedValue() {
+ public void quotedValue() {
doTest(new Cookie("foo", "\"bar\""), "foo=\"bar\"");
}
@Test
- public void v0ValueContainsSemicolon() {
- doTest(new Cookie("foo", "a;b"), "foo=\"a;b\"; Version=1", null);
+ public void valueContainsSemicolon() {
+ doTest(new Cookie("foo", "a;b"), null);
}
@Test
- public void v0ValueContainsComma() {
- doTest(new Cookie("foo", "a,b"), "foo=\"a,b\"; Version=1", null);
+ public void valueContainsComma() {
+ doTest(new Cookie("foo", "a,b"), null);
}
@Test
- public void v0ValueContainsSpace() {
- doTest(new Cookie("foo", "a b"), "foo=\"a b\"; Version=1", null);
+ public void valueContainsSpace() {
+ doTest(new Cookie("foo", "a b"), null);
}
@Test
- public void v0ValueContainsEquals() {
- Cookie cookie = new Cookie("foo", "a=b");
- doTestDefaults(cookie, "foo=\"a=b\"; Version=1", "foo=a=b");
- doTestAllowSeparators(cookie, "foo=a=b", "foo=a=b");
+ public void valueContainsEquals() {
+ doTest(new Cookie("foo", "a=b"), "foo=a=b");
}
@Test
- public void v0ValueContainsQuote() {
+ public void valueContainsQuote() {
Cookie cookie = new Cookie("foo", "a\"b");
- doTestDefaults(cookie,"foo=\"a\\\"b\"; Version=1", null);
- doTestAllowSeparators(cookie,"foo=a\"b", null);
+ doTest(cookie, null);
}
@Test
- public void v0ValueContainsNonV0Separator() {
+ public void valueContainsNonV0Separator() {
Cookie cookie = new Cookie("foo", "a()<>@:\\\"/[]?={}b");
- doTestDefaults(cookie,"foo=\"a()<>@:\\\\\\\"/[]?={}b\"; Version=1", null);
- doTestAllowSeparators(cookie,"foo=a()<>@:\\\"/[]?={}b", null);
+ doTest(cookie, null);
}
@Test
- public void v0ValueContainsBackslash() {
+ public void valueContainsBackslash() {
Cookie cookie = new Cookie("foo", "a\\b");
- doTestDefaults(cookie, "foo=\"a\\\\b\"; Version=1", null);
- doTestAllowSeparators(cookie, "foo=a\\b", null);
+ doTest(cookie, null);
}
@Test
- public void v0ValueContainsBackslashAtEnd() {
+ public void valueContainsBackslashAtEnd() {
Cookie cookie = new Cookie("foo", "a\\");
- doTestDefaults(cookie, "foo=\"a\\\\\"; Version=1", null);
- doTestAllowSeparators(cookie, "foo=a\\", null);
+ doTest(cookie, null);
}
@Test
- public void v0ValueContainsBackslashAndQuote() {
+ public void valueContainsBackslashAndQuote() {
Cookie cookie = new Cookie("foo", "a\"b\\c");
- doTestDefaults(cookie, "foo=\"a\\\"b\\\\c\"; Version=1", null);
- doTestAllowSeparators(cookie, "foo=a\"b\\c", null);
+ doTest(cookie, null);
}
@Test
- public void v1simpleCookie() {
- Cookie cookie = new Cookie("foo", "bar");
- cookie.setVersion(1);
- doTest(cookie, "foo=bar; Version=1", "foo=bar");
- }
-
- @Test
- public void v1NullValue() {
- Cookie cookie = new Cookie("foo", null);
- cookie.setVersion(1);
- doTest(cookie, "foo=\"\"; Version=1", "foo=");
- }
-
- @Test
- public void v1QuotedValue() {
- Cookie cookie = new Cookie("foo", "\"bar\"");
- cookie.setVersion(1);
- doTest(cookie, "foo=\"bar\"; Version=1", "foo=\"bar\"");
- }
-
- @Test
- public void v1ValueContainsSemicolon() {
- Cookie cookie = new Cookie("foo", "a;b");
- cookie.setVersion(1);
- doTest(cookie, "foo=\"a;b\"; Version=1", null);
- }
-
- @Test
- public void v1ValueContainsComma() {
- Cookie cookie = new Cookie("foo", "a,b");
- cookie.setVersion(1);
- doTest(cookie, "foo=\"a,b\"; Version=1", null);
- }
-
- @Test
- public void v1ValueContainsSpace() {
- Cookie cookie = new Cookie("foo", "a b");
- cookie.setVersion(1);
- doTest(cookie, "foo=\"a b\"; Version=1", null);
- }
-
- @Test
- public void v1ValueContainsEquals() {
- Cookie cookie = new Cookie("foo", "a=b");
- cookie.setVersion(1);
- doTest(cookie, "foo=\"a=b\"; Version=1", "foo=a=b");
- }
-
- @Test
- public void v1ValueContainsQuote() {
- Cookie cookie = new Cookie("foo", "a\"b");
- cookie.setVersion(1);
- doTest(cookie, "foo=\"a\\\"b\"; Version=1", null);
- }
-
- @Test
- public void v1ValueContainsNonV0Separator() {
- Cookie cookie = new Cookie("foo", "a()<>@,;:\\\"/[]?={}b");
- cookie.setVersion(1);
- doTest(cookie, "foo=\"a()<>@,;:\\\\\\\"/[]?={}b\"; Version=1", null);
- }
-
- @Test
- public void v1ValueContainsBackslash() {
- Cookie cookie = new Cookie("foo", "a\\b");
- cookie.setVersion(1);
- doTest(cookie, "foo=\"a\\\\b\"; Version=1", null);
- }
-
- @Test
- public void v1ValueContainsBackslashAndQuote() {
- Cookie cookie = new Cookie("foo", "a\"b\\c");
- cookie.setVersion(1);
- doTest(cookie, "foo=\"a\\\"b\\\\c\"; Version=1", null);
- }
-
- @Test
- public void v1ValueUTF8() {
+ public void valueUTF8() {
String value = "\u2300";
Cookie cookie = new Cookie("foo", value);
- cookie.setVersion(1);
- doTest(cookie, (String) null, "foo=" + value);
+ doTest(cookie, "foo=" + value);
}
@Test
- public void v1TestMaxAgePositive() {
- doV1TestMaxAge(100, "foo=bar; Version=1; Max-Age=100", "foo=bar; Max-Age=100");
+ public void testMaxAgePositive() {
+ doTestMaxAge(100, "foo=bar; Max-Age=100");
}
@Test
- public void v1TestMaxAgeZero() {
- doV1TestMaxAge(0, "foo=bar; Version=1; Max-Age=0",
- "foo=bar; Max-Age=0; Expires=Thu, 01-Jan-1970 00:00:10 GMT");
+ public void testMaxAgeZero() {
+ doTestMaxAge(0, "foo=bar; Max-Age=0; Expires=Thu, 01-Jan-1970 00:00:10 GMT");
}
@Test
- public void v1TestMaxAgeNegative() {
- doV1TestMaxAge(-100, "foo=bar; Version=1", "foo=bar");
+ public void testMaxAgeNegative() {
+ doTestMaxAge(-100, "foo=bar");
}
@Test
- public void v1TestDomainValid01() {
- doV1TestDomain("example.com", "foo=bar; Version=1; Domain=example.com",
- "foo=bar; Domain=example.com");
+ public void testDomainValid01() {
+ doTestDomain("example.com", "foo=bar; Domain=example.com");
}
@Test
- public void v1TestDomainValid02() {
- doV1TestDomain("exa-mple.com", "foo=bar; Version=1; Domain=exa-mple.com",
- "foo=bar; Domain=exa-mple.com");
+ public void testDomainValid02() {
+ doTestDomain("exa-mple.com", "foo=bar; Domain=exa-mple.com");
}
@Test
- public void v1TestDomainInvalid01() {
- doV1TestDomain("example.com.", "foo=bar; Version=1; Domain=example.com.", null);
+ public void testDomainInvalid01() {
+ doTestDomain("example.com.", null);
}
@Test
- public void v1TestDomainInvalid02() {
- doV1TestDomain("example.com-", "foo=bar; Version=1; Domain=example.com-", null);
+ public void testDomainInvalid02() {
+ doTestDomain("example.com-", null);
}
@Test
- public void v1TestDomainInvalid03() {
- doV1TestDomain(".example.com.", "foo=bar; Version=1; Domain=.example.com.", null);
+ public void testDomainInvalid03() {
+ doTestDomain(".example.com.", null);
}
@Test
- public void v1TestDomainInvalid04() {
- doV1TestDomain("-example.com.", "foo=bar; Version=1; Domain=-example.com.", null);
+ public void testDomainInvalid04() {
+ doTestDomain("-example.com.", null);
}
@Test
- public void v1TestDomainInvalid05() {
- doV1TestDomain("example..com.", "foo=bar; Version=1; Domain=example..com.", null);
+ public void testDomainInvalid05() {
+ doTestDomain("example..com.", null);
}
@Test
- public void v1TestDomainInvalid06() {
- doV1TestDomain("example-.com.", "foo=bar; Version=1; Domain=example-.com.", null);
+ public void testDomainInvalid06() {
+ doTestDomain("example-.com.", null);
}
@Test
- public void v1TestDomainInvalid07() {
- doV1TestDomain("exam$ple.com.", "foo=bar; Version=1; Domain=exam$ple.com.", null);
+ public void testDomainInvalid07() {
+ doTestDomain("exam$ple.com.", null);
}
@Test
- public void v1TestPathValid() {
- doV1TestPath("/example", "foo=bar; Version=1; Path=/example",
- "foo=bar; Path=/example");
+ public void testPathValid() {
+ doTestPath("/example", "foo=bar; Path=/example");
}
@Test
- public void v1TestPathInvalid01() {
- doV1TestPath("exa\tmple", "foo=bar; Version=1; Path=\"exa\tmple\"", null);
+ public void testPathInvalid01() {
+ doTestPath("exa\tmple", null);
}
@Test
public void testSameSiteCookies() {
- LegacyCookieProcessor legacy = new LegacyCookieProcessor();
Rfc6265CookieProcessor rfc6265 = new Rfc6265CookieProcessor();
Cookie cookie = new Cookie("foo", "bar");
- Assert.assertEquals("foo=bar", legacy.generateHeader(cookie, null));
Assert.assertEquals("foo=bar", rfc6265.generateHeader(cookie, null));
- legacy.setSameSiteCookies("unset");
rfc6265.setSameSiteCookies("unset");
- Assert.assertEquals("foo=bar", legacy.generateHeader(cookie, null));
Assert.assertEquals("foo=bar", rfc6265.generateHeader(cookie, null));
- legacy.setSameSiteCookies("none");
rfc6265.setSameSiteCookies("none");
- Assert.assertEquals("foo=bar; SameSite=None", legacy.generateHeader(cookie, null));
Assert.assertEquals("foo=bar; SameSite=None", rfc6265.generateHeader(cookie, null));
- legacy.setSameSiteCookies("lax");
rfc6265.setSameSiteCookies("lax");
- Assert.assertEquals("foo=bar; SameSite=Lax", legacy.generateHeader(cookie, null));
Assert.assertEquals("foo=bar; SameSite=Lax", rfc6265.generateHeader(cookie, null));
- legacy.setSameSiteCookies("strict");
rfc6265.setSameSiteCookies("strict");
- Assert.assertEquals("foo=bar; SameSite=Strict", legacy.generateHeader(cookie, null));
Assert.assertEquals("foo=bar; SameSite=Strict", rfc6265.generateHeader(cookie, null));
cookie.setSecure(true);
cookie.setHttpOnly(true);
- legacy.setSameSiteCookies("unset");
rfc6265.setSameSiteCookies("unset");
- Assert.assertEquals("foo=bar; Secure; HttpOnly", legacy.generateHeader(cookie, null));
Assert.assertEquals("foo=bar; Secure; HttpOnly", rfc6265.generateHeader(cookie, null));
- legacy.setSameSiteCookies("none");
rfc6265.setSameSiteCookies("none");
- Assert.assertEquals("foo=bar; Secure; HttpOnly; SameSite=None", legacy.generateHeader(cookie, null));
Assert.assertEquals("foo=bar; Secure; HttpOnly; SameSite=None", rfc6265.generateHeader(cookie, null));
- legacy.setSameSiteCookies("lax");
rfc6265.setSameSiteCookies("lax");
- Assert.assertEquals("foo=bar; Secure; HttpOnly; SameSite=Lax", legacy.generateHeader(cookie, null));
Assert.assertEquals("foo=bar; Secure; HttpOnly; SameSite=Lax", rfc6265.generateHeader(cookie, null));
- legacy.setSameSiteCookies("strict");
rfc6265.setSameSiteCookies("strict");
- Assert.assertEquals("foo=bar; Secure; HttpOnly; SameSite=Strict", legacy.generateHeader(cookie, null));
Assert.assertEquals("foo=bar; Secure; HttpOnly; SameSite=Strict", rfc6265.generateHeader(cookie, null));
}
- private void doTest(Cookie cookie, String expected) {
- doTest(cookie, expected, expected);
- }
-
-
- private void doTest(Cookie cookie,
- String expectedLegacy, String expectedRfc6265) {
- doTestDefaults(cookie, expectedLegacy, expectedRfc6265);
- doTestAllowSeparators(cookie, expectedLegacy, expectedRfc6265);
- }
-
-
- private void doTestDefaults(Cookie cookie,
- String expectedLegacy, String expectedRfc6265) {
- CookieProcessor legacy = new LegacyCookieProcessor();
- CookieProcessor rfc6265 = new Rfc6265CookieProcessor();
- doTest(cookie, legacy, expectedLegacy, rfc6265, expectedRfc6265);
- }
-
-
- private void doTestAllowSeparators(Cookie cookie,
- String expectedLegacy, String expectedRfc6265) {
- LegacyCookieProcessor legacy = new LegacyCookieProcessor();
- legacy.setAllowHttpSepsInV0(true);
- legacy.setForwardSlashIsSeparator(true);
+ private void doTest(Cookie cookie, String expectedRfc6265) {
CookieProcessor rfc6265 = new Rfc6265CookieProcessor();
- doTest(cookie, legacy, expectedLegacy, rfc6265, expectedRfc6265);
- }
-
-
- private void doTest(Cookie cookie,
- CookieProcessor legacy, String expectedLegacy,
- CookieProcessor rfc6265, String expectedRfc6265) {
- doTest(cookie, legacy, expectedLegacy);
doTest(cookie, rfc6265, expectedRfc6265);
}
@@ -376,32 +237,23 @@ public class TestCookieProcessorGeneration {
}
- private void doV1TestMaxAge(int age, String expectedLegacy, String expectedRfc6265) {
- LegacyCookieProcessor legacy = new LegacyCookieProcessor();
- legacy.setAlwaysAddExpires(false);
+ private void doTestMaxAge(int age, String expectedRfc6265) {
Cookie cookie = new Cookie("foo", "bar");
- cookie.setVersion(1);
cookie.setMaxAge(age);
- doTest(cookie, legacy, expectedLegacy, new Rfc6265CookieProcessor(), expectedRfc6265);
+ doTest(cookie, new Rfc6265CookieProcessor(), expectedRfc6265);
}
- private void doV1TestDomain(String domain, String expectedLegacy, String expectedRfc6265) {
- LegacyCookieProcessor legacy = new LegacyCookieProcessor();
- legacy.setAlwaysAddExpires(false);
+ private void doTestDomain(String domain, String expectedRfc6265) {
Cookie cookie = new Cookie("foo", "bar");
- cookie.setVersion(1);
cookie.setDomain(domain);
- doTest(cookie, legacy, expectedLegacy, new Rfc6265CookieProcessor(), expectedRfc6265);
+ doTest(cookie, new Rfc6265CookieProcessor(), expectedRfc6265);
}
- private void doV1TestPath(String path, String expectedLegacy, String expectedRfc6265) {
- LegacyCookieProcessor legacy = new LegacyCookieProcessor();
- legacy.setAlwaysAddExpires(false);
+ private void doTestPath(String path, String expectedRfc6265) {
Cookie cookie = new Cookie("foo", "bar");
- cookie.setVersion(1);
cookie.setPath(path);
- doTest(cookie, legacy, expectedLegacy, new Rfc6265CookieProcessor(), expectedRfc6265);
+ doTest(cookie, new Rfc6265CookieProcessor(), expectedRfc6265);
}
}
diff --git a/test/org/apache/tomcat/util/http/TestCookies.java b/test/org/apache/tomcat/util/http/TestCookies.java
index 18753bd..2658017 100644
--- a/test/org/apache/tomcat/util/http/TestCookies.java
+++ b/test/org/apache/tomcat/util/http/TestCookies.java
@@ -34,478 +34,253 @@ public class TestCookies {
private final Cookie A = new Cookie("a", "b");
private final Cookie HASH_EMPTY = new Cookie("#", "");
private final Cookie $PORT = new Cookie("$Port", "8080");
-
- @Test
- public void testBasicCookieOld() {
- doTestBasicCookie(false);
- }
+ // RFC 2109 attributes are generally interpreted as additional cookies by
+ // RFC 6265
+ private final Cookie $VERSION_0 = new Cookie("$Version", "0");
+ private final Cookie $VERSION_1 = new Cookie("$Version", "1");
+ private final Cookie $DOMAIN_ASF = new Cookie("$Domain", "apache.org");
+ private final Cookie $DOMAIN_YAHOO = new Cookie("$Domain", "yahoo.com");
+ private final Cookie $PATH = new Cookie("$Path", "/examples");
@Test
public void testBasicCookieRfc6265() {
- doTestBasicCookie(true);
- }
-
- private void doTestBasicCookie(boolean useRfc6265) {
- test(useRfc6265, "foo=bar; a=b", FOO, A);
- test(useRfc6265, "foo=bar;a=b", FOO, A);
- test(useRfc6265, "foo=bar;a=b;", FOO, A);
- test(useRfc6265, "foo=bar;a=b; ", FOO, A);
- test(useRfc6265, "foo=bar;a=b; ;", FOO, A);
- }
-
- @Test
- public void testNameOnlyAreDroppedOld() {
- test(false, "foo=;a=b; ;", A);
- test(false, "foo;a=b; ;", A);
- test(false, "foo;a=b;bar", A);
- test(false, "foo;a=b;bar;", A);
- test(false, "foo;a=b;bar ", A);
- test(false, "foo;a=b;bar ;", A);
-
- // Bug 49000
- Cookie fred = new Cookie("fred", "1");
- Cookie jim = new Cookie("jim", "2");
- Cookie george = new Cookie("george", "3");
- test(false, "fred=1; jim=2; bob", fred, jim);
- test(false, "fred=1; jim=2; bob; george=3", fred, jim, george);
- test(false, "fred=1; jim=2; bob=; george=3", fred, jim, george);
- test(false, "fred=1; jim=2; bob=", fred, jim);
+ test("foo=bar; a=b", FOO, A);
+ test("foo=bar;a=b", FOO, A);
+ test("foo=bar;a=b;", FOO, A);
+ test("foo=bar;a=b; ", FOO, A);
+ test("foo=bar;a=b; ;", FOO, A);
}
@Test
public void testNameOnlyAreDroppedRfc6265() {
// Name only cookies are not dropped in RFC6265
- test(true, "foo=;a=b; ;", FOO_EMPTY, A);
- test(true, "foo;a=b; ;", FOO_EMPTY, A);
- test(true, "foo;a=b;bar", FOO_EMPTY, A, BAR_EMPTY);
- test(true, "foo;a=b;bar;", FOO_EMPTY, A, BAR_EMPTY);
- test(true, "foo;a=b;bar ", FOO_EMPTY, A, BAR_EMPTY);
- test(true, "foo;a=b;bar ;", FOO_EMPTY, A, BAR_EMPTY);
+ test("foo=;a=b; ;", FOO_EMPTY, A);
+ test("foo;a=b; ;", FOO_EMPTY, A);
+ test("foo;a=b;bar", FOO_EMPTY, A, BAR_EMPTY);
+ test("foo;a=b;bar;", FOO_EMPTY, A, BAR_EMPTY);
+ test("foo;a=b;bar ", FOO_EMPTY, A, BAR_EMPTY);
+ test("foo;a=b;bar ;", FOO_EMPTY, A, BAR_EMPTY);
// Bug 49000
Cookie fred = new Cookie("fred", "1");
Cookie jim = new Cookie("jim", "2");
Cookie bobEmpty = new Cookie("bob", "");
Cookie george = new Cookie("george", "3");
- test(true, "fred=1; jim=2; bob", fred, jim, bobEmpty);
- test(true, "fred=1; jim=2; bob; george=3", fred, jim, bobEmpty, george);
- test(true, "fred=1; jim=2; bob=; george=3", fred, jim, bobEmpty, george);
- test(true, "fred=1; jim=2; bob=", fred, jim, bobEmpty);
- }
-
- @Test
- public void testQuotedValueOld() {
- doTestQuotedValue(false);
+ test("fred=1; jim=2; bob", fred, jim, bobEmpty);
+ test("fred=1; jim=2; bob; george=3", fred, jim, bobEmpty, george);
+ test("fred=1; jim=2; bob=; george=3", fred, jim, bobEmpty, george);
+ test("fred=1; jim=2; bob=", fred, jim, bobEmpty);
}
@Test
public void testQuotedValueRfc6265() {
- doTestQuotedValue(true);
- }
-
- private void doTestQuotedValue(boolean useRfc6265) {
- test(useRfc6265, "foo=bar;a=\"b\"", FOO, A);
- test(useRfc6265, "foo=bar;a=\"b\";", FOO, A);
- }
-
- @Test
- public void testEmptyPairsOld() {
- test(false, "foo;a=b; ;bar", A);
- test(false, "foo;a=b;;bar", A);
- test(false, "foo;a=b; ;;bar=rab", A, BAR);
- test(false, "foo;a=b;; ;bar=rab", A, BAR);
- test(false, "foo;a=b;;#;bar=rab", A, BAR);
- test(false, "foo;a=b;;\\;bar=rab", A, BAR);
+ test("foo=bar;a=\"b\"", FOO, A);
+ test("foo=bar;a=\"b\";", FOO, A);
}
@Test
public void testEmptyPairsRfc6265() {
- test(true, "foo;a=b; ;bar", FOO_EMPTY, A, BAR_EMPTY);
- test(true, "foo;a=b;;bar", FOO_EMPTY, A, BAR_EMPTY);
- test(true, "foo;a=b; ;;bar=rab", FOO_EMPTY, A, BAR);
- test(true, "foo;a=b;; ;bar=rab", FOO_EMPTY, A, BAR);
- test(true, "foo;a=b;;#;bar=rab", FOO_EMPTY, A, HASH_EMPTY, BAR);
- test(true, "foo;a=b;;\\;bar=rab", FOO_EMPTY, A, BAR);
- }
-
- @Test
- public void testSeparatorsInValueOld() {
- doTestSeparatorsInValue(false);
+ test("foo;a=b; ;bar", FOO_EMPTY, A, BAR_EMPTY);
+ test("foo;a=b;;bar", FOO_EMPTY, A, BAR_EMPTY);
+ test("foo;a=b; ;;bar=rab", FOO_EMPTY, A, BAR);
+ test("foo;a=b;; ;bar=rab", FOO_EMPTY, A, BAR);
+ test("foo;a=b;;#;bar=rab", FOO_EMPTY, A, HASH_EMPTY, BAR);
+ test("foo;a=b;;\\;bar=rab", FOO_EMPTY, A, BAR);
}
@Test
public void testSeparatorsInValueRfc6265() {
- doTestSeparatorsInValue(true);
- }
-
- private void doTestSeparatorsInValue(boolean useRfc6265) {
- test(useRfc6265, "a=()<>@:\\\"/[]?={}\t; foo=bar", FOO);
+ test("a=()<>@:\\\"/[]?={}\t; foo=bar", FOO);
}
@Test
- public void v1TokenValueOld() {
- doV1TokenValue(false);
- }
-
- @Test
public void v1TokenValueRfc6265() {
- doV1TokenValue(true);
- }
-
- private void doV1TokenValue(boolean useRfc6265) {
- FOO.setVersion(1);
- A.setVersion(1);
- test(useRfc6265, "$Version=1; foo=bar;a=b", FOO, A);
- test(useRfc6265, "$Version=1;foo=bar;a=b; ; ", FOO, A);
- }
-
- @Test
- public void v1NameOnlyIsDroppedOld() {
- doV1NameOnlyIsDropped(false);
- }
-
- @Test
- public void v1NameOnlyIsDroppedRfc6265() {
- doV1NameOnlyIsDropped(true);
- }
-
- private void doV1NameOnlyIsDropped(boolean useRfc6265) {
- A.setVersion(1);
- test(useRfc6265, "$Version=1;foo=;a=b; ; ", A);
- test(useRfc6265, "$Version=1;foo= ;a=b; ; ", A);
- test(useRfc6265, "$Version=1;foo;a=b; ; ", A);
+ test("$Version=1; foo=bar;a=b", $VERSION_1, FOO, A);
+ test("$Version=1;foo=bar;a=b; ; ", $VERSION_1, FOO, A);
}
@Test
- public void v1QuotedValueOld() {
- doV1QuotedValue(false);
+ public void v1NameOnlyRfc6265() {
+ test("$Version=1;foo=;a=b; ; ", $VERSION_1, FOO_EMPTY, A);
+ test("$Version=1;foo= ;a=b; ; ", $VERSION_1, FOO_EMPTY, A);
+ test("$Version=1;foo;a=b; ; ", $VERSION_1, FOO_EMPTY, A);
}
@Test
public void v1QuotedValueRfc6265() {
- doV1QuotedValue(true);
- }
-
- private void doV1QuotedValue(boolean useRfc6265) {
- FOO.setVersion(1);
- A.setVersion(1);
- // presumes quotes are removed
- test(useRfc6265, "$Version=1;foo=\"bar\";a=b; ; ", FOO, A);
- }
-
- @Test
- public void v1DQuoteInValueOld() {
- FOO.setValue("b");
- FOO.setVersion(1);
- A.setVersion(1);
- test(false, "$Version=1;foo=\"b\"ar\";a=b", FOO, A); // Incorrectly escaped.
+ test("$Version=1;foo=\"bar\";a=b; ; ", $VERSION_1, FOO, A);
}
@Test
public void v1DQuoteInValueRfc6265() {
- A.setVersion(1);
- test(true, "$Version=1;foo=\"b\"ar\";a=b", A); // Incorrectly escaped.
- }
-
- @Test
- public void v1QuoteInValueOld() {
- doV1QuoteInValue(false);
+ test("$Version=1;foo=\"b\"ar\";a=b", $VERSION_1, A); // Incorrectly escaped.
}
@Test
public void v1QuoteInValueRfc6265() {
- doV1QuoteInValue(true);
- }
-
- private void doV1QuoteInValue(boolean useRfc6265) {
FOO.setValue("b'ar");
- FOO.setVersion(1);
- A.setVersion(1);
- test(useRfc6265, "$Version=1;foo=b'ar;a=b", FOO, A);
+ test("$Version=1;foo=b'ar;a=b", $VERSION_1, FOO, A);
}
@Test
- public void v1QuoteInQuotedValueOld() {
- doV1QuoteInQuotedValue(false);
- }
-
- @Test
public void v1QuoteInQuotedValueRfc6265() {
- doV1QuoteInQuotedValue(true);
- }
-
- private void doV1QuoteInQuotedValue(boolean useRfc6265) {
FOO.setValue("b'ar");
- FOO.setVersion(1);
- A.setVersion(1);
- test(useRfc6265, "$Version=1;foo=\"b'ar\";a=b", FOO, A);
- }
-
- @Test
- public void v1EscapedDQuoteInValueOld() {
- doV1EscapedDQuoteInValue(false);
+ test("$Version=1;foo=\"b'ar\";a=b", $VERSION_1, FOO, A);
}
@Test
public void v1EscapedDQuoteInValueRfc6265() {
- doV1EscapedDQuoteInValue(true);
- }
-
- private void doV1EscapedDQuoteInValue(boolean useRfc6265) {
- FOO.setValue("b\"ar");
- FOO.setVersion(1);
- A.setVersion(1);
- test(useRfc6265, "$Version=1;foo=\"b\\\"ar\";a=b", FOO, A); // correctly escaped.
- }
-
- @Test
- public void v1QuotedValueEndsInBackslashOld() {
- doV1QuotedValueEndsInBackslash(false);
+ // RFC 2109 considers the 2nd cookie to be correctly escaped.
+ // RFC 6265 considers the 2nd cookie to be invalid
+ test("$Version=1;foo=\"b\\\"ar\";a=b", $VERSION_1, A);
}
@Test
public void v1QuotedValueEndsInBackslashRfc6265() {
- doV1QuotedValueEndsInBackslash(true);
- }
-
- private void doV1QuotedValueEndsInBackslash(boolean useRfc6265) {
- FOO.setVersion(1);
- test(useRfc6265, "$Version=1;foo=bar;a=\"b\\\"", FOO);
- }
-
- @Test
- public void v1MismatchedQuotesOld() {
- doV1MismatchedQuotes(false);
+ test("$Version=1;foo=bar;a=\"b\\\"", $VERSION_1, FOO);
}
@Test
public void v1MismatchedQuotesRfc6265() {
- doV1MismatchedQuotes(true);
- }
-
- private void doV1MismatchedQuotes(boolean useRfc6265) {
- FOO.setVersion(1);
- test(useRfc6265, "$Version=1;foo=bar;a=\"b\\", FOO);
- }
-
- @Test
- public void v1SingleQuotesAreValidTokenCharactersOld() {
- doV1SingleQuotesAreValidTokenCharacters(false);
+ test("$Version=1;foo=bar;a=\"b\\", $VERSION_1, FOO);
}
@Test
public void v1SingleQuotesAreValidTokenCharactersRfc6265() {
- doV1SingleQuotesAreValidTokenCharacters(true);
- }
-
- private void doV1SingleQuotesAreValidTokenCharacters(boolean useRfc6265) {
- FOO.setVersion(1);
FOO.setValue("'bar'");
- test(useRfc6265, "$Version=1; foo='bar'", FOO);
- }
-
- @Test
- public void v1DomainIsParsedOld() {
- doV1DomainIsParsed(false);
+ test("$Version=1; foo='bar'", $VERSION_1, FOO);
}
@Test
public void v1DomainIsParsedRfc6265() {
- doV1DomainIsParsed(true);
- }
-
- private void doV1DomainIsParsed(boolean useRfc6265) {
- FOO.setVersion(1);
FOO.setDomain("apache.org");
- A.setVersion(1);
A.setDomain("yahoo.com");
- test(useRfc6265, "$Version=1;foo=\"bar\";$Domain=apache.org;a=b;$Domain=yahoo.com", FOO, A);
- }
-
- @Test
- public void v1DomainOnlyAffectsPrecedingCookieOld() {
- doV1DomainOnlyAffectsPrecedingCookie(false);
+ test("$Version=1;foo=\"bar\";$Domain=apache.org;a=b;$Domain=yahoo.com",
+ $VERSION_1, FOO, $DOMAIN_ASF, A, $DOMAIN_YAHOO);
}
@Test
public void v1DomainOnlyAffectsPrecedingCookieRfc6265() {
- doV1DomainOnlyAffectsPrecedingCookie(true);
- }
-
- private void doV1DomainOnlyAffectsPrecedingCookie(boolean useRfc6265) {
- FOO.setVersion(1);
FOO.setDomain("apache.org");
- A.setVersion(1);
- test(useRfc6265, "$Version=1;foo=\"bar\";$Domain=apache.org;a=b", FOO, A);
- }
-
- @Test
- public void v1PortIsIgnoredOld() {
- FOO.setVersion(1);
- FOO.setDomain("apache.org");
- A.setVersion(1);
- test(false, "$Version=1;foo=\"bar\";$Domain=apache.org;$Port=8080;a=b", FOO, A);
+ test("$Version=1;foo=\"bar\";$Domain=apache.org;a=b", $VERSION_1, FOO, $DOMAIN_ASF, A);
}
@Test
public void v1PortIsIgnoredRfc6265() {
- FOO.setVersion(1);
FOO.setDomain("apache.org");
- $PORT.setVersion(1);
- A.setVersion(1);
- test(true, "$Version=1;foo=\"bar\";$Domain=apache.org;$Port=8080;a=b", FOO, $PORT, A);
- }
-
- @Test
- public void v1PathAffectsPrecedingCookieOld() {
- doV1PathAffectsPrecedingCookie(false);
+ test("$Version=1;foo=\"bar\";$Domain=apache.org;$Port=8080;a=b", $VERSION_1, FOO, $DOMAIN_ASF, $PORT, A);
}
@Test
public void v1PathAffectsPrecedingCookieRfc6265() {
- doV1PathAffectsPrecedingCookie(true);
- }
-
- private void doV1PathAffectsPrecedingCookie(boolean useRfc6265) {
- FOO.setVersion(1);
FOO.setPath("/examples");
- A.setVersion(1);
- test(useRfc6265, "$Version=1;foo=\"bar\";$Path=/examples;a=b; ; ", FOO, A);
- }
-
- @Test
- public void rfc2109Version0Old() {
- // rfc2109 semantically does not allow $Version to be 0 but it is valid syntax
- test(false, "$Version=0;foo=bar", FOO);
+ test("$Version=1;foo=\"bar\";$Path=/examples;a=b; ; ", $VERSION_1, FOO, $PATH, A);
}
@Test
public void rfc2109Version0Rfc6265() {
- // RFC6265 will parse explicit version 0 using RFC2109
- test(true, "$Version=0;foo=bar", FOO);
+ test("$Version=0;foo=bar", $VERSION_0, FOO);
}
@Test
public void disallow8bitInName() {
// Bug 55917
- test(true, "f\u00f6o=bar");
+ test("f\u00f6o=bar");
}
@Test
public void disallowControlInName() {
// Bug 55917
- test(true, "f\010o=bar");
+ test("f\010o=bar");
}
@Test
public void disallow8BitControlInName() {
// Bug 55917
- test(true, "f\210o=bar");
+ test("f\210o=bar");
}
@Test
public void allow8BitInV0Value() {
// Bug 55917
- test(true, "foo=b\u00e1r", FOO_CONTROL);
+ test("foo=b\u00e1r", FOO_CONTROL);
}
@Test
- public void disallow8bitInV1UnquotedValue() {
+ public void eightBitInV1UnquotedValue() {
// Bug 55917
- test(true, "$Version=1; foo=b\u00e1r");
+ // RFC 6265 considers this valid UTF-8
+ FOO.setValue("b\u00e1r");
+ test("$Version=1; foo=b\u00e1r", $VERSION_1, FOO);
}
@Test
public void allow8bitInV1QuotedValue() {
// Bug 55917
- FOO_CONTROL.setVersion(1);
- test(true, "$Version=1; foo=\"b\u00e1r\"", FOO_CONTROL);
+ test("$Version=1; foo=\"b\u00e1r\"", $VERSION_1, FOO_CONTROL);
}
@Test
public void disallowControlInV0Value() {
// Bug 55917
- test(true, "foo=b\010r");
+ test("foo=b\010r");
}
@Test
public void disallowControlInV1UnquotedValue() {
// Bug 55917
- test(true, "$Version=1; foo=b\010r");
+ test("$Version=1; foo=b\010r", $VERSION_1);
}
@Test
public void disallowControlInV1QuotedValue() {
// Bug 55917 / Bug 55918
- test(true, "$Version=1; foo=\"b\010r\"");
+ test("$Version=1; foo=\"b\u0008r\"", $VERSION_1);
}
@Test
- public void disallow8BitControlInV1UnquotedValue() {
+ public void eightBitControlInV1UnquotedValue() {
// Bug 55917
- test(true, "$Version=1; foo=b\210r");
+ // RFC 6265 considers this to be a valid UTF-8 value
+ test("$Version=1; foo=b\u0088r", $VERSION_1, new Cookie("foo", "b\u0088r"));
}
@Test
public void testJsonInV0() {
// Bug 55921
- test(true, "{\"a\":true, \"b\":false};a=b", A);
+ test("{\"a\":true, \"b\":false};a=b", A);
}
@Test
public void testJsonInV1() {
// Bug 55921
- A.setVersion(1);
- test(true, "$Version=1;{\"a\":true, \"b\":false};a=b", A);
+ test("$Version=1;{\"a\":true, \"b\":false};a=b", $VERSION_1, A);
}
@Test
public void testSkipSemicolonOrComma() {
- // V1 cookies can also use commas to separate cookies
- FOO.setVersion(1);
- A.setVersion(1);
- test(true, "$Version=1;x\tx=yyy,foo=bar;a=b", FOO, A);
+ // RFC 2109 cookies can also use commas to separate cookies
+ // RFC 6265 considers the second cookie invalid and skips it
+ test("$Version=1;x\tx=yyy,foo=bar;a=b", $VERSION_1, A);
}
@Test
public void testBug60788Rfc6265() {
- doTestBug60788(true);
- }
+ Cookie c1 = new Cookie("userId", "foo");
+ Cookie c2 = new Cookie("$Path", "/");
+ Cookie c3 = new Cookie("$Domain", "www.example.org");
- @Test
- public void testBug60788Rfc2109() {
- doTestBug60788(false);
+ test("$Version=\"1\"; userId=\"foo\";$Path=\"/\";$Domain=\"www.example.org\"",
+ $VERSION_1, c1, c2, c3);
}
- private void doTestBug60788(boolean useRfc6265) {
- Cookie expected = new Cookie("userId", "foo");
- expected.setVersion(1);
- if (useRfc6265) {
- expected.setDomain("\"www.example.org\"");
- expected.setPath("\"/\"");
- } else {
- // The legacy processor removes the quotes for domain and path
- expected.setDomain("www.example.org");
- expected.setPath("/");
- }
-
- test(useRfc6265, "$Version=\"1\"; userId=\"foo\";$Path=\"/\";$Domain=\"www.example.org\"",
- expected);
- }
-
- private void test(boolean useRfc6265, String header, Cookie... expected) {
+ private void test(String header, Cookie... expected) {
MimeHeaders mimeHeaders = new MimeHeaders();
ServerCookies serverCookies = new ServerCookies(4);
- CookieProcessor cookieProcessor;
-
- if (useRfc6265) {
- cookieProcessor = new Rfc6265CookieProcessor();
- } else {
- cookieProcessor = new LegacyCookieProcessor();
- }
+ CookieProcessor cookieProcessor = new Rfc6265CookieProcessor();
MessageBytes cookieHeaderValue = mimeHeaders.addValue("Cookie");
byte[] bytes = header.getBytes(StandardCharsets.UTF_8);
cookieHeaderValue.setBytes(bytes, 0, bytes.length);
@@ -514,16 +289,9 @@ public class TestCookies {
for (int i = 0; i < expected.length; i++) {
Cookie cookie = expected[i];
ServerCookie actual = serverCookies.getCookie(i);
- Assert.assertEquals(cookie.getVersion(), actual.getVersion());
Assert.assertEquals(cookie.getName(), actual.getName().toString());
actual.getValue().getByteChunk().setCharset(StandardCharsets.UTF_8);
- Assert.assertEquals(cookie.getValue(),
- org.apache.tomcat.util.http.parser.Cookie.unescapeCookieValueRfc2109(
- actual.getValue().toString()));
- if (cookie.getVersion() == 1) {
- Assert.assertEquals(cookie.getDomain(), actual.getDomain().toString());
- Assert.assertEquals(cookie.getPath(), actual.getPath().toString());
- }
+ Assert.assertEquals(cookie.getValue(), actual.getValue().toString());
}
}
}
diff --git a/test/org/apache/tomcat/util/http/TestCookiesDefaultSysProps.java b/test/org/apache/tomcat/util/http/TestCookiesDefaultSysProps.java
deleted file mode 100644
index a27882a..0000000
--- a/test/org/apache/tomcat/util/http/TestCookiesDefaultSysProps.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.tomcat.util.http;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-import org.apache.catalina.startup.Tomcat;
-import org.apache.tomcat.util.buf.ByteChunk;
-
-/**
- * Test case for {@link LegacyCookieProcessor}. <b>Note</b> because of the use
- * of <code>final static</code> constants in {@link jakarta.servlet.http.Cookie},
- * each of these tests must be executed in a new JVM instance. The tests have
- * been placed in separate classes to facilitate this when running the unit
- * tests via Ant.
- */
-public class TestCookiesDefaultSysProps extends CookiesBaseTest {
-
- @Override
- @Test
- public void testCookiesInstance() throws Exception {
-
- Tomcat tomcat = getTomcatInstance();
-
- addServlets(tomcat);
-
- tomcat.start();
-
- ByteChunk res = getUrl("http://localhost:" + getPort() + "/invalid");
- Assert.assertEquals("Cookie name fail", res.toString());
- res = getUrl("http://localhost:" + getPort() + "/null");
- Assert.assertEquals("Cookie name fail", res.toString());
- res = getUrl("http://localhost:" + getPort() + "/blank");
- Assert.assertEquals("Cookie name fail", res.toString());
- res = getUrl("http://localhost:" + getPort() + "/invalidFwd");
- Assert.assertEquals("Cookie name fail", res.toString());
- res = getUrl("http://localhost:" + getPort() + "/invalidStrict");
- Assert.assertEquals("Cookie name ok", res.toString());
- res = getUrl("http://localhost:" + getPort() + "/valid");
- Assert.assertEquals("Cookie name ok", res.toString());
-
- // Need to read response headers to test version switching
- Map<String,List<String>> headers = new HashMap<>();
- getUrl("http://localhost:" + getPort() + "/switch", res, headers);
- List<String> cookieHeaders = headers.get("Set-Cookie");
- for (String cookieHeader : cookieHeaders) {
- Assert.assertEquals("name=\"val?ue\"; Version=1", cookieHeader);
- }
- }
-}
diff --git a/test/org/apache/tomcat/util/http/TestCookiesNoFwdStrictSysProps.java b/test/org/apache/tomcat/util/http/TestCookiesNoFwdStrictSysProps.java
deleted file mode 100644
index 7099523..0000000
--- a/test/org/apache/tomcat/util/http/TestCookiesNoFwdStrictSysProps.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.tomcat.util.http;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-import org.apache.catalina.startup.Tomcat;
-import org.apache.tomcat.util.buf.ByteChunk;
-
-/**
- * Test case for {@link LegacyCookieProcessor}. <b>Note</b> because of the use
- * of <code>final static</code> constants in {@link jakarta.servlet.http.Cookie},
- * each of these tests must be executed in a new JVM instance. The tests have
- * been placed in separate classes to facilitate this when running the unit
- * tests via Ant.
- */
-public class TestCookiesNoFwdStrictSysProps extends CookiesBaseTest {
-
- @Override
- @Test
- public void testCookiesInstance() throws Exception {
-
- System.setProperty("org.apache.catalina.STRICT_SERVLET_COMPLIANCE",
- "true");
- System.setProperty("org.apache.tomcat.util.http.ServerCookie.FWD_SLASH_IS_SEPARATOR",
- "false");
-
- Tomcat tomcat = getTomcatInstance();
-
- addServlets(tomcat);
-
- tomcat.start();
-
- ByteChunk res = getUrl("http://localhost:" + getPort() + "/invalid");
- Assert.assertEquals("Cookie name fail", res.toString());
- res = getUrl("http://localhost:" + getPort() + "/null");
- Assert.assertEquals("Cookie name fail", res.toString());
- res = getUrl("http://localhost:" + getPort() + "/blank");
- Assert.assertEquals("Cookie name fail", res.toString());
- res = getUrl("http://localhost:" + getPort() + "/invalidFwd");
- Assert.assertEquals("Cookie name ok", res.toString());
- res = getUrl("http://localhost:" + getPort() + "/invalidStrict");
- Assert.assertEquals("Cookie name fail", res.toString());
- res = getUrl("http://localhost:" + getPort() + "/valid");
- Assert.assertEquals("Cookie name ok", res.toString());
- }
-}
diff --git a/test/org/apache/tomcat/util/http/TestCookiesNoStrictNamingSysProps.java b/test/org/apache/tomcat/util/http/TestCookiesNoStrictNamingSysProps.java
deleted file mode 100644
index d4374f4..0000000
--- a/test/org/apache/tomcat/util/http/TestCookiesNoStrictNamingSysProps.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.tomcat.util.http;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-import org.apache.catalina.startup.Tomcat;
-import org.apache.tomcat.util.buf.ByteChunk;
-
-/**
- * Test case for {@link LegacyCookieProcessor}. <b>Note</b> because of the use
- * of <code>final static</code> constants in {@link jakarta.servlet.http.Cookie},
- * each of these tests must be executed in a new JVM instance. The tests have
- * been placed in separate classes to facilitate this when running the unit
- * tests via Ant.
- */
-public class TestCookiesNoStrictNamingSysProps extends CookiesBaseTest {
-
- @Override
- @Test
- public void testCookiesInstance() throws Exception {
-
- System.setProperty("org.apache.catalina.STRICT_SERVLET_COMPLIANCE",
- "true");
- System.setProperty("org.apache.tomcat.util.http.ServerCookie.STRICT_NAMING",
- "false");
-
- Tomcat tomcat = getTomcatInstance();
-
- addServlets(tomcat);
-
- tomcat.start();
-
- ByteChunk res = getUrl("http://localhost:" + getPort() + "/invalid");
- Assert.assertEquals("Cookie name fail", res.toString());
- res = getUrl("http://localhost:" + getPort() + "/null");
- Assert.assertEquals("Cookie name fail", res.toString());
- res = getUrl("http://localhost:" + getPort() + "/blank");
- Assert.assertEquals("Cookie name fail", res.toString());
- res = getUrl("http://localhost:" + getPort() + "/invalidFwd");
- Assert.assertEquals("Cookie name fail", res.toString());
- res = getUrl("http://localhost:" + getPort() + "/invalidStrict");
- Assert.assertEquals("Cookie name ok", res.toString());
- res = getUrl("http://localhost:" + getPort() + "/valid");
- Assert.assertEquals("Cookie name ok", res.toString());
- }
-}
diff --git a/test/org/apache/tomcat/util/http/TestCookiesStrictSysProps.java b/test/org/apache/tomcat/util/http/TestCookiesStrictSysProps.java
deleted file mode 100644
index 20ded6d..0000000
--- a/test/org/apache/tomcat/util/http/TestCookiesStrictSysProps.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.tomcat.util.http;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-import org.apache.catalina.startup.Tomcat;
-import org.apache.tomcat.util.buf.ByteChunk;
-
-/**
- * Test case for {@link LegacyCookieProcessor}. <b>Note</b> because of the use
- * of <code>final static</code> constants in {@link jakarta.servlet.http.Cookie},
- * each of these tests must be executed in a new JVM instance. The tests have
- * been placed in separate classes to facilitate this when running the unit
- * tests via Ant.
- */
-public class TestCookiesStrictSysProps extends CookiesBaseTest {
-
- @Override
- @Test
- public void testCookiesInstance() throws Exception {
-
- System.setProperty("org.apache.catalina.STRICT_SERVLET_COMPLIANCE",
- "true");
-
- Tomcat tomcat = getTomcatInstance();
-
- addServlets(tomcat);
-
- tomcat.start();
-
- ByteChunk res = getUrl("http://localhost:" + getPort() + "/invalid");
- Assert.assertEquals("Cookie name fail", res.toString());
- res = getUrl("http://localhost:" + getPort() + "/null");
- Assert.assertEquals("Cookie name fail", res.toString());
- res = getUrl("http://localhost:" + getPort() + "/blank");
- Assert.assertEquals("Cookie name fail", res.toString());
- res = getUrl("http://localhost:" + getPort() + "/invalidFwd");
- Assert.assertEquals("Cookie name fail", res.toString());
- res = getUrl("http://localhost:" + getPort() + "/invalidStrict");
- Assert.assertEquals("Cookie name fail", res.toString());
- res = getUrl("http://localhost:" + getPort() + "/valid");
- Assert.assertEquals("Cookie name ok", res.toString());
-
- // Need to read response headers to test version switching
- Map<String,List<String>> headers = new HashMap<>();
- getUrl("http://localhost:" + getPort() + "/switch", res, headers);
- List<String> cookieHeaders = headers.get("Set-Cookie");
- for (String cookieHeader : cookieHeaders) {
- Assert.assertEquals("name=\"val?ue\"; Version=1", cookieHeader);
- }
- }
-}
diff --git a/test/org/apache/tomcat/util/http/TestLegacyCookieProcessor.java b/test/org/apache/tomcat/util/http/TestLegacyCookieProcessor.java
deleted file mode 100644
index d1ec3f0..0000000
--- a/test/org/apache/tomcat/util/http/TestLegacyCookieProcessor.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.tomcat.util.http;
-
-import java.nio.charset.StandardCharsets;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-import org.apache.tomcat.util.buf.MessageBytes;
-
-public class TestLegacyCookieProcessor {
-
- /*
- * https://bz.apache.org/bugzilla/show_bug.cgi?id=59925
- */
- @Test
- public void testV0WithPath() {
- LegacyCookieProcessor cp = new LegacyCookieProcessor();
- cp.setAllowHttpSepsInV0(true);
- cp.setForwardSlashIsSeparator(true);
-
- MimeHeaders mimeHeaders = new MimeHeaders();
- ServerCookies serverCookies = new ServerCookies(4);
-
- MessageBytes cookieHeaderValue = mimeHeaders.addValue("Cookie");
- byte[] bytes = "$Version=0;cname=cvalue;$Path=/example".getBytes(StandardCharsets.UTF_8);
- cookieHeaderValue.setBytes(bytes, 0, bytes.length);
- cp.parseCookieHeader(mimeHeaders, serverCookies);
- Assert.assertEquals(1, serverCookies.getCookieCount());
- for (int i = 0; i < 1; i++) {
- ServerCookie actual = serverCookies.getCookie(i);
- Assert.assertEquals(0, actual.getVersion());
- Assert.assertEquals("cname", actual.getName().toString());
- actual.getValue().getByteChunk().setCharset(StandardCharsets.UTF_8);
- Assert.assertEquals("cvalue",
- org.apache.tomcat.util.http.parser.Cookie.unescapeCookieValueRfc2109(
- actual.getValue().toString()));
- Assert.assertEquals("/example", actual.getPath().toString());
- }
- }
-}
diff --git a/test/org/apache/tomcat/util/http/TesterCookiesPerformance.java b/test/org/apache/tomcat/util/http/TesterCookiesPerformance.java
index 4f186c7..76c5d39 100644
--- a/test/org/apache/tomcat/util/http/TesterCookiesPerformance.java
+++ b/test/org/apache/tomcat/util/http/TesterCookiesPerformance.java
@@ -47,23 +47,14 @@ public class TesterCookiesPerformance {
headerValue.setBytes(cookieHeaderBytes, 0, cookieHeaderBytes.length);
ServerCookies serverCookies = new ServerCookies(4);
- LegacyCookieProcessor originalCookieProcessor = new LegacyCookieProcessor();
Rfc6265CookieProcessor rfc6265CookieProcessor = new Rfc6265CookieProcessor();
// warm up
for (int i = 0; i < parsingLoops; i++) {
- originalCookieProcessor.parseCookieHeader(mimeHeaders, serverCookies);
- Assert.assertEquals(cookieCount, serverCookies.getCookieCount());
- serverCookies.recycle();
- }
-
- long oldStart = System.nanoTime();
- for (int i = 0; i < parsingLoops; i++) {
- originalCookieProcessor.parseCookieHeader(mimeHeaders, serverCookies);
+ rfc6265CookieProcessor.parseCookieHeader(mimeHeaders, serverCookies);
Assert.assertEquals(cookieCount, serverCookies.getCookieCount());
serverCookies.recycle();
}
- long oldDuration = System.nanoTime() - oldStart;
long newStart = System.nanoTime();
for (int i = 0; i < parsingLoops; i++) {
@@ -73,7 +64,8 @@ public class TesterCookiesPerformance {
}
long newDuration = System.nanoTime() - newStart;
- System.out.println("Original duration: " + oldDuration);
System.out.println("RFC6265 duration: " + newDuration);
+
+ // As of November 2021 markt's desktop runs this test in 970ms to 1000ms
}
}
diff --git a/test/org/apache/tomcat/util/http/parser/TestCookie.java b/test/org/apache/tomcat/util/http/parser/TestCookie.java
deleted file mode 100644
index 0f8a1dd..0000000
--- a/test/org/apache/tomcat/util/http/parser/TestCookie.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.tomcat.util.http.parser;
-
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameter;
-
-import org.apache.tomcat.util.http.ServerCookies;
-
-@RunWith(Parameterized.class)
-public class TestCookie {
-
- @Parameterized.Parameters(name = "{index}: header[{0}]")
- public static Collection<Object[]> parameters() {
-
- List<Object[]> parameterSets = new ArrayList<>();
-
- String[] SEPS = new String[] { ",", ";" };
- String[] PATHS = new String[] { ";$Path=/foo", " ; $Path = /foo ", ""};
- String[] DOMAINS = new String[] { ";$Domain=bar.com", " ; $Domain = bar.com ", ""};
-
- for (String sep1 : SEPS) {
- for (String path1 : PATHS) {
- for (String domain1 : DOMAINS) {
- for (String sep2 : SEPS) {
- for (String path2 : PATHS) {
- for (String domain2 : DOMAINS) {
- for (String sep3 : SEPS) {
- for (String path3 : PATHS) {
- for (String domain3 : DOMAINS) {
- StringBuilder sb = new StringBuilder("$Version=1");
- sb.append(sep1);
- sb.append("first=1");
- sb.append(path1);
- sb.append(domain1);
- sb.append(sep2);
- sb.append("second=2");
- sb.append(path2);
- sb.append(domain2);
- sb.append(sep3);
- sb.append("third=3");
- sb.append(path3);
- sb.append(domain3);
-
- parameterSets.add(new Object[] { sb.toString() });
- }
- }
- }
- }
- }
- }
- }
- }
- }
- return parameterSets;
- }
-
- @Parameter(0)
- public String cookieHeader;
-
- @Test
- public void testParseThreeCookieHeader() {
- ServerCookies serverCookies = new ServerCookies(3);
- byte[] inputBytes = cookieHeader.getBytes(StandardCharsets.ISO_8859_1);
- Cookie.parseCookie(inputBytes, 0, inputBytes.length, serverCookies);
- Assert.assertEquals(3, serverCookies.getCookieCount());
- Assert.assertEquals("first", serverCookies.getCookie(0).getName().toString());
- Assert.assertEquals("1", serverCookies.getCookie(0).getValue().toString());
- Assert.assertEquals("second", serverCookies.getCookie(1).getName().toString());
- Assert.assertEquals("2", serverCookies.getCookie(1).getValue().toString());
- Assert.assertEquals("third", serverCookies.getCookie(2).getName().toString());
- Assert.assertEquals("3", serverCookies.getCookie(2).getValue().toString());
- }
-}
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 6a16393..fed3f83 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -123,6 +123,10 @@
Make SPNEGO authentication more robust for the case where the provided
credential has expired. (markt)
</fix>
+ <fix>
+ Limit cookie support to RFC 6265 to align with recent updates to the
+ Servlet specification. (markt)
+ </fix>
</changelog>
</subsection>
<subsection name="Coyote">
diff --git a/webapps/docs/config/cookie-processor.xml b/webapps/docs/config/cookie-processor.xml
index 4f32119..5e64cf2 100644
--- a/webapps/docs/config/cookie-processor.xml
+++ b/webapps/docs/config/cookie-processor.xml
@@ -119,81 +119,6 @@
</subsection>
- <subsection name="Legacy Cookie Processor - org.apache.tomcat.util.http.LegacyCookieProcessor">
-
- <p>This is the legacy cookie parser based on RFC6265, RFC2109 and RFC2616.
- It implements a strict interpretation of the cookie specifications. Due to
- various interoperability issues with browsers not all strict behaviours
- are enabled by default and additional options are available to further
- relax the behaviour of this cookie processor if required.</p>
-
- <attributes>
-
- <attribute name="allowEqualsInValue" required="false">
- <p>If this is <code>true</code> Tomcat will allow '<code>=</code>'
- characters when parsing unquoted cookie values. If <code>false</code>,
- cookie values containing '<code>=</code>' will be terminated when the
- '<code>=</code>' is encountered and the remainder of the cookie value
- will be dropped.</p>
- <p>If not set the specification compliant default value of
- <code>false</code> will be used.</p>
- </attribute>
-
- <attribute name="allowHttpSepsInV0" required="false">
- <p>If this is <code>true</code> Tomcat will allow HTTP separators in
- cookie names and values.</p>
- <p>If not specified, the default specification compliant value of
- <code>false</code> will be used.</p>
- </attribute>
-
- <attribute name="allowNameOnly" required="false">
- <p>If this is <code>true</code> Tomcat will allow name only cookies
- (with or without trailing '<code>=</code>') when parsing cookie headers.
- If <code>false</code>, name only cookies will be dropped.</p>
- <p>If not set the specification compliant default value of
- <code>false</code> will be used.</p>
- </attribute>
-
- <attribute name="alwaysAddExpires" required="false">
- <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 I
- to ignore the Max-Age parameter in a SetCookie header.</p>
- <p>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>
- </attribute>
-
- <attribute name="forwardSlashIsSeparator" required="false">
- <p>If this is <code>true</code> Tomcat will treat the forward slash
- character ('<code>/</code>') as an HTTP separator when processing cookie
- headers. 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>
- </attribute>
-
- <attribute name="sameSiteCookies" required="false">
- <p>Enables setting same-site cookie attribute.</p>
-
- <p>If value is <code>unset</code> then the same-site cookie attribute
- won't be set. This is the default value.</p>
-
- <p>If value is <code>none</code> then the same-site cookie attribute
- will be set and the cookie will always be sent in cross-site requests.</p>
-
- <p>If value is <code>lax</code> then the browser only sends the cookie
- in same-site requests and cross-site top level GET requests.</p>
-
- <p>If value is <code>strict</code> then the browser prevents sending the
- cookie in any cross-site request.</p>
- </attribute>
-
- </attributes>
-
- </subsection>
-
</section>
diff --git a/webapps/docs/config/systemprops.xml b/webapps/docs/config/systemprops.xml
index 349faab..8ec86a2 100644
--- a/webapps/docs/config/systemprops.xml
+++ b/webapps/docs/config/systemprops.xml
@@ -114,7 +114,6 @@
<p>If this is <code>true</code> the default values will be changed
to <code>true</code> instead of <code>false</code> for:</p>
<ul>
- <li><code>org.apache.tomcat.util.http.<br/>ServerCookie.STRICT_NAMING</code></li>
<li>The <code>alwaysAccessSession</code> attribute of any
<a href="context.html">Context</a> element.</li>
<li>The <code>contextGetResourceRequiresSlash</code> attribute of any
@@ -147,16 +146,6 @@
</ul>
</property>
- <property name="org.apache.tomcat.util.http. ServerCookie.STRICT_NAMING">
- <p> If this is <code>true</code> then the requirements of the Servlet specification
- that Cookie names must adhere to RFC2109 will be enforced. If this is
- <code>false</code> the naming rules specified in RFC6265 (allow the leading "$")
- will be used.</p>
- <p>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>
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org