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/22 09:53:37 UTC
[tomcat] branch servlet-6-cookies created (now c2d3ec7)
This is an automated email from the ASF dual-hosted git repository.
markt pushed a change to branch servlet-6-cookies
in repository https://gitbox.apache.org/repos/asf/tomcat.git.
at c2d3ec7 Cookie updates for Servlet 6.0. Only support RFC 6265. Remove others.
This branch includes the following new commits:
new c2d3ec7 Cookie updates for Servlet 6.0. Only support RFC 6265. Remove others.
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
[tomcat] 01/01: Cookie updates for Servlet 6.0. Only support RFC 6265. Remove others.
Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch servlet-6-cookies
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit c2d3ec75a9f20cd35a2bf8aa6ef5a977bf642224
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..49a2afa 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 = "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 = "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..34df555 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 = "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 = "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 = "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 = "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 bc02c77..f39a21b 100644
--- a/java/org/apache/catalina/connector/Request.java
+++ b/java/org/apache/catalina/connector/Request.java
@@ -3124,17 +3124,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 2eb6c43..160ae87 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -119,6 +119,10 @@
<code>web.xml</code> file, a <code>web-fragment.xml</code> file nor
annotated with <code>WebListener</code>. (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