This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 9.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 064f124300871005ad032717d333a4c97b658c1b Author: Mark Thomas <ma...@apache.org> AuthorDate: Tue Aug 20 11:53:37 2024 +0100 Add noEqualsCookie option with unchanged default --- .../tomcat/util/http/CookieProcessorBase.java | 17 +++++ .../tomcat/util/http/LocalStrings.properties | 2 + .../tomcat/util/http/LocalStrings_fr.properties | 2 + .../tomcat/util/http/LocalStrings_ko.properties | 2 + .../tomcat/util/http/LocalStrings_zh_CN.properties | 2 + .../apache/tomcat/util/http/NoEqualsCookie.java | 60 ++++++++++++++++ .../tomcat/util/http/Rfc6265CookieProcessor.java | 3 +- .../org/apache/tomcat/util/http/parser/Cookie.java | 50 +++++++++++-- .../apache/tomcat/util/http/TestCookieParsing.java | 43 ++++++++--- test/org/apache/tomcat/util/http/TestCookies.java | 84 +++++++++++++++++++++- .../apache/tomcat/util/http/parser/TestCookie.java | 3 +- webapps/docs/changelog.xml | 5 ++ webapps/docs/config/cookie-processor.xml | 9 +++ 13 files changed, 262 insertions(+), 20 deletions(-) diff --git a/java/org/apache/tomcat/util/http/CookieProcessorBase.java b/java/org/apache/tomcat/util/http/CookieProcessorBase.java index 5815ca4cd4..54cb7de5f4 100644 --- a/java/org/apache/tomcat/util/http/CookieProcessorBase.java +++ b/java/org/apache/tomcat/util/http/CookieProcessorBase.java @@ -42,6 +42,23 @@ public abstract class CookieProcessorBase implements CookieProcessor { private boolean partitioned = false; + private NoEqualsCookie noEqualsCookie = NoEqualsCookie.NAME; + + + public String getNoEqualsCookie() { + return noEqualsCookie.getValue(); + } + + + protected NoEqualsCookie getNoEqualsCookieInternal() { + return noEqualsCookie; + } + + + public void setNoEqualsCookie(String noEqualsCookie) { + this.noEqualsCookie = NoEqualsCookie.fromString(noEqualsCookie); + } + public SameSiteCookies getSameSiteCookies() { return sameSiteCookies; diff --git a/java/org/apache/tomcat/util/http/LocalStrings.properties b/java/org/apache/tomcat/util/http/LocalStrings.properties index 3a1fb8d1fd..0b44e2fc52 100644 --- a/java/org/apache/tomcat/util/http/LocalStrings.properties +++ b/java/org/apache/tomcat/util/http/LocalStrings.properties @@ -22,6 +22,8 @@ cookies.maxCountFail=More than the maximum allowed number of cookies, [{0}], wer headers.maxCountFail=More than the maximum allowed number of headers, [{0}], were detected. +noEqualsCookie.invalid=The value [{0}] is not recognised + parameters.bytes=Start processing with input [{0}] parameters.copyFail=Failed to create copy of original parameter values for debug logging purposes parameters.decodeFail.debug=Character decoding failed. Parameter [{0}] with value [{1}] has been ignored. diff --git a/java/org/apache/tomcat/util/http/LocalStrings_fr.properties b/java/org/apache/tomcat/util/http/LocalStrings_fr.properties index 2f2df95655..6f9d17a1eb 100644 --- a/java/org/apache/tomcat/util/http/LocalStrings_fr.properties +++ b/java/org/apache/tomcat/util/http/LocalStrings_fr.properties @@ -22,6 +22,8 @@ cookies.maxCountFail=Le nombre maximum de cookies [{0}] est dépassé headers.maxCountFail=Le nombre d''en-têtes [{0}] dépasse le maximum autorisé +noEqualsCookie.invalid=La valeur [{0}] n''est pas reconnue + parameters.bytes=Début du traitement avec les données [{0}] parameters.copyFail=Echec de la copie des valeurs de paramètres originaux pour raisons de journalisation du déboguage parameters.decodeFail.debug=Echec de décodage de caractère, le paramètre [{0}] de valeur [{1}] a été ignoré diff --git a/java/org/apache/tomcat/util/http/LocalStrings_ko.properties b/java/org/apache/tomcat/util/http/LocalStrings_ko.properties index 9ceb6f88ff..a0bc692b4e 100644 --- a/java/org/apache/tomcat/util/http/LocalStrings_ko.properties +++ b/java/org/apache/tomcat/util/http/LocalStrings_ko.properties @@ -22,6 +22,8 @@ cookies.maxCountFail=허용된 최대 쿠키 개수 [{0}]을(를) 초과한 쿠 headers.maxCountFail=최대 허용 헤더 개수 [{0}]보다 더 많은 헤더들이 탐지되었습니다. +noEqualsCookie.invalid=해당 값 [{0}]은(는) 인식되지 않습니다. + parameters.bytes=입력 [{0}]을(를) 사용하여 처리를 시작합니다. parameters.copyFail=디버그 로그를 위한 원래의 파라미터 값들을 복사하지 못했습니다. parameters.decodeFail.debug=문자 디코딩 실패. 값 [{1}](으)로 설정된 파라미터 [{0}]은(는) 무시됩니다. diff --git a/java/org/apache/tomcat/util/http/LocalStrings_zh_CN.properties b/java/org/apache/tomcat/util/http/LocalStrings_zh_CN.properties index cea40f524b..e0087a87d4 100644 --- a/java/org/apache/tomcat/util/http/LocalStrings_zh_CN.properties +++ b/java/org/apache/tomcat/util/http/LocalStrings_zh_CN.properties @@ -22,6 +22,8 @@ cookies.maxCountFail=检测到超过Cookie最大允许的数量[{0}] headers.maxCountFail=检测到超过了允许设置的最大header 数[{0}] +noEqualsCookie.invalid=值[{0}]未识别 + parameters.bytes=开始处理输入[{0}] parameters.copyFail=无法创建以调试日志记录为目的的原始参数值的副本 parameters.decodeFail.debug=字符解码失败.参数 [{0}]和值 [{1}]被忽略 diff --git a/java/org/apache/tomcat/util/http/NoEqualsCookie.java b/java/org/apache/tomcat/util/http/NoEqualsCookie.java new file mode 100644 index 0000000000..8d47102b95 --- /dev/null +++ b/java/org/apache/tomcat/util/http/NoEqualsCookie.java @@ -0,0 +1,60 @@ +/* + * 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.Locale; + +import org.apache.tomcat.util.res.StringManager; + +public enum NoEqualsCookie { + IGNORE("ignore"), + NAME("name"); + /* + * There is no VALUE option since the Servlet specification does not permit the creation of a Cookie with a name + * that is either null or the zero length string. + * + * The historical intention (from the user agent perspective) of using a name-value-pair without an equals sign has + * been to indicate a cookie with a name but no value. Tomcat has done the opposite. The current RFC6265bis text + * treats a name-value-pair without an equals sign as a cookie with a value but no name. Supporting this will + * require changes to the Servlet specifcation. + */ + + + private static final StringManager sm = StringManager.getManager(NoEqualsCookie.class); + + private final String value; + + NoEqualsCookie(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + + public static NoEqualsCookie fromString(String from) { + String trimmedLower = from.trim().toLowerCase(Locale.ENGLISH); + + for (NoEqualsCookie value : values()) { + if (value.getValue().equals(trimmedLower)) { + return value; + } + } + + throw new IllegalStateException(sm.getString("noEqualsCookie.invalid", from)); + } +} diff --git a/java/org/apache/tomcat/util/http/Rfc6265CookieProcessor.java b/java/org/apache/tomcat/util/http/Rfc6265CookieProcessor.java index 990d531d3e..bd239e1571 100644 --- a/java/org/apache/tomcat/util/http/Rfc6265CookieProcessor.java +++ b/java/org/apache/tomcat/util/http/Rfc6265CookieProcessor.java @@ -88,7 +88,8 @@ public class Rfc6265CookieProcessor extends CookieProcessorBase { } ByteChunk bc = cookieValue.getByteChunk(); - Cookie.parseCookie(bc.getBytes(), bc.getStart(), bc.getLength(), serverCookies); + Cookie.parseCookie(bc.getBytes(), bc.getStart(), bc.getLength(), serverCookies, + getNoEqualsCookieInternal()); } // search from the next position diff --git a/java/org/apache/tomcat/util/http/parser/Cookie.java b/java/org/apache/tomcat/util/http/parser/Cookie.java index 932698823a..75d8dd574d 100644 --- a/java/org/apache/tomcat/util/http/parser/Cookie.java +++ b/java/org/apache/tomcat/util/http/parser/Cookie.java @@ -20,6 +20,7 @@ import java.nio.charset.StandardCharsets; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; +import org.apache.tomcat.util.http.NoEqualsCookie; import org.apache.tomcat.util.http.ServerCookie; import org.apache.tomcat.util.http.ServerCookies; import org.apache.tomcat.util.log.UserDataHelper; @@ -102,7 +103,33 @@ public class Cookie { } + /** + * Parse byte array as cookie header. + * + * @param bytes Source + * @param offset Start point in array + * @param len Number of bytes to read + * @param serverCookies Structure to store results + * + * @deprecated Unused. This method will be removed in Tomcat 11 onwards. + */ + @Deprecated public static void parseCookie(byte[] bytes, int offset, int len, ServerCookies serverCookies) { + parseCookie(bytes, offset, len, serverCookies, NoEqualsCookie.NAME); + } + + + /** + * Parse byte array as cookie header. + * + * @param bytes Source + * @param offset Start point in array + * @param len Number of bytes to read + * @param serverCookies Structure to store results + * @param noEqualsCookie How to handle a cookie name-value-pair that does not contain an equals character + */ + public static void parseCookie(byte[] bytes, int offset, int len, ServerCookies serverCookies, + NoEqualsCookie noEqualsCookie) { // ByteBuffer is used throughout this parser as it allows the byte[] // and position information to be easily passed between parsing methods @@ -120,7 +147,7 @@ public class Cookie { SkipResult skipResult = skipBytes(bb, VERSION_BYTES); if (skipResult != SkipResult.FOUND) { // No need to reset position since skipBytes() will have done it - parseCookieRfc6265(bb, serverCookies); + parseCookieRfc6265(bb, serverCookies, noEqualsCookie); return; } @@ -131,7 +158,7 @@ public class Cookie { // Need to reset position as skipByte() will only have reset to // position before it was called bb.position(mark); - parseCookieRfc6265(bb, serverCookies); + parseCookieRfc6265(bb, serverCookies, noEqualsCookie); return; } @@ -193,7 +220,7 @@ public class Cookie { } - private static void parseCookieRfc6265(ByteBuffer bb, ServerCookies serverCookies) { + private static void parseCookieRfc6265(ByteBuffer bb, ServerCookies serverCookies,NoEqualsCookie noEqualsCookie) { boolean moreToProcess = true; @@ -233,11 +260,22 @@ public class Cookie { } if (name.hasRemaining()) { - ServerCookie sc = serverCookies.addCookie(); - sc.getName().setBytes(name.array(), name.position(), name.remaining()); if (value == null) { - sc.getValue().setBytes(EMPTY_BYTES, 0, EMPTY_BYTES.length); + switch (noEqualsCookie) { + case IGNORE: { + // This name-value-pair is a NO-OP + break; + } + case NAME: { + ServerCookie sc = serverCookies.addCookie(); + sc.getName().setBytes(name.array(), name.position(), name.remaining()); + sc.getValue().setBytes(EMPTY_BYTES, 0, EMPTY_BYTES.length); + break; + } + } } else { + ServerCookie sc = serverCookies.addCookie(); + sc.getName().setBytes(name.array(), name.position(), name.remaining()); sc.getValue().setBytes(value.array(), value.position(), value.remaining()); } } diff --git a/test/org/apache/tomcat/util/http/TestCookieParsing.java b/test/org/apache/tomcat/util/http/TestCookieParsing.java index b5e072bbd6..cd50bf3470 100644 --- a/test/org/apache/tomcat/util/http/TestCookieParsing.java +++ b/test/org/apache/tomcat/util/http/TestCookieParsing.java @@ -40,9 +40,13 @@ public class TestCookieParsing extends TomcatBaseTest { "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=" }; - private static final String COOKIES_WITH_NAME_ONLY_CONCAT = "bob=bob="; + private static final String[] COOKIES_WITH_NAME_OR_VALUE_ONLY = new String[] { "bob=", "bob", "=bob" }; + + // First two are treated as name and no value, third is invalid (therefore ignored) + private static final String COOKIES_WITH_NAME_OR_VALUE_ONLY_NAME_CONCAT = "bob=bob="; + + // First is treated as name and no value, second is ignored and third is invalid (therefore ignored) + private static final String COOKIES_WITH_NAME_OR_VALUE_ONLY_IGNORE_CONCAT = "bob="; private static final String[] COOKIES_WITH_SEPS = new String[] { "name=val/ue" }; @@ -120,22 +124,41 @@ public class TestCookieParsing extends TomcatBaseTest { String expected; if (nameOnly) { - expected = COOKIES_WITH_NAME_ONLY_CONCAT; + /* + * The legacy cookie processor skips all white space and non-token characters when looking for the cookie + * name. This means "=bob" is parsed as a cookie with name bob. This behaviour was exposed when adding the + * tests for the noEqualsCookie option. When adding the noEqualsCookie option the intention was not to + * change the existing behaviour. Therefore this potentially unintended behaviour has been left unchanged. + */ + expected = COOKIES_WITH_NAME_OR_VALUE_ONLY_NAME_CONCAT + "bob="; } else { expected = ""; } TestCookieParsingClient client = new TestCookieParsingClient( - legacyCookieProcessor, COOKIES_WITH_NAME_ONLY, expected); + legacyCookieProcessor, COOKIES_WITH_NAME_OR_VALUE_ONLY, expected); client.doRequest(); } @Test - public void testRfc6265NameOnly() throws Exception { - // Always allows equals - TestCookieParsingClient client = new TestCookieParsingClient( - new Rfc6265CookieProcessor(), COOKIES_WITH_NAME_ONLY, - COOKIES_WITH_NAME_ONLY_CONCAT); + public void testRfc6265NameOrValueOnlyIgnore() throws Exception { + doTestRfc6265NoEquals("ignore", COOKIES_WITH_NAME_OR_VALUE_ONLY_IGNORE_CONCAT); + } + + + @Test + public void testRfc6265NameOrValueOnlyDefault() throws Exception { + doTestRfc6265NoEquals(null, COOKIES_WITH_NAME_OR_VALUE_ONLY_NAME_CONCAT); + } + + + private void doTestRfc6265NoEquals(String cookieNoEquals, String expected) throws Exception { + Rfc6265CookieProcessor cookieProcessor = new Rfc6265CookieProcessor(); + if (cookieNoEquals != null) { + cookieProcessor.setNoEqualsCookie(cookieNoEquals); + } + TestCookieParsingClient client = new TestCookieParsingClient(cookieProcessor, COOKIES_WITH_NAME_OR_VALUE_ONLY, + expected); client.doRequest(); } diff --git a/test/org/apache/tomcat/util/http/TestCookies.java b/test/org/apache/tomcat/util/http/TestCookies.java index 63b3176d33..af9b0c418b 100644 --- a/test/org/apache/tomcat/util/http/TestCookies.java +++ b/test/org/apache/tomcat/util/http/TestCookies.java @@ -26,6 +26,9 @@ import org.junit.Test; import org.apache.tomcat.util.buf.MessageBytes; public class TestCookies { + private static final String NAME = "NAME"; + private static final String IGNORE = "IGNORE"; + private final Cookie FOO = new Cookie("foo", "bar"); private final Cookie FOO_EMPTY = new Cookie("foo", ""); private final Cookie FOO_CONTROL = new Cookie("foo", "b\u00e1r"); @@ -72,8 +75,53 @@ public class TestCookies { test(false, "fred=1; jim=2; bob=", fred, jim); } + + @Test + public void testNameOnlyAreDroppedRfc6265NoEqualsName() { + // Name only cookies are not dropped in RFC6265 + test(true, "foo=;a=b; ;", NAME, FOO_EMPTY, A); + test(true, "foo;a=b; ;", NAME, FOO_EMPTY, A); + test(true, "foo;a=b;bar", NAME, FOO_EMPTY, A, BAR_EMPTY); + test(true, "foo;a=b;bar;", NAME, FOO_EMPTY, A, BAR_EMPTY); + test(true, "foo;a=b;bar ", NAME, FOO_EMPTY, A, BAR_EMPTY); + test(true, "foo;a=b;bar ;", NAME, 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", NAME, fred, jim, bobEmpty); + test(true, "fred=1; jim=2; bob; george=3", NAME, fred, jim, bobEmpty, george); + test(true, "fred=1; jim=2; bob=; george=3", NAME, fred, jim, bobEmpty, george); + test(true, "fred=1; jim=2; bob=", NAME, fred, jim, bobEmpty); + } + + + @Test + public void testNameOnlyAreDroppedRfc6265NoEqualsIgnore() { + // Name only cookies are not dropped in RFC6265 + test(true, "foo=;a=b; ;", IGNORE, FOO_EMPTY, A); + test(true, "foo;a=b; ;", IGNORE, A); + test(true, "foo;a=b;bar", IGNORE, A); + test(true, "foo;a=b;bar;", IGNORE, A); + test(true, "foo;a=b;bar ", IGNORE, A); + test(true, "foo;a=b;bar ;", IGNORE, A); + + // 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", IGNORE, fred, jim); + test(true, "fred=1; jim=2; bob; george=3", IGNORE, fred, jim, george); + test(true, "fred=1; jim=2; bob=; george=3", IGNORE, fred, jim, bobEmpty, george); + test(true, "fred=1; jim=2; bob=", IGNORE, fred, jim, bobEmpty); + } + + @Test - public void testNameOnlyAreDroppedRfc6265() { + public void testNameOnlyAreDroppedRfc6265NoEqualsDefault() { // Name only cookies are not dropped in RFC6265 test(true, "foo=;a=b; ;", FOO_EMPTY, A); test(true, "foo;a=b; ;", FOO_EMPTY, A); @@ -98,6 +146,7 @@ public class TestCookies { doTestQuotedValue(false); } + @Test public void testQuotedValueRfc6265() { doTestQuotedValue(true); @@ -119,7 +168,29 @@ public class TestCookies { } @Test - public void testEmptyPairsRfc6265() { + public void testEmptyPairsRfc6265CookieNoEqualsName() { + test(true, "foo;a=b; ;bar", NAME, FOO_EMPTY, A, BAR_EMPTY); + test(true, "foo;a=b;;bar", NAME, FOO_EMPTY, A, BAR_EMPTY); + test(true, "foo;a=b; ;;bar=rab", NAME, FOO_EMPTY, A, BAR); + test(true, "foo;a=b;; ;bar=rab", NAME, FOO_EMPTY, A, BAR); + test(true, "foo;a=b;;#;bar=rab", NAME, FOO_EMPTY, A, HASH_EMPTY, BAR); + test(true, "foo;a=b;;\\;bar=rab", NAME, FOO_EMPTY, A, BAR); + } + + + @Test + public void testEmptyPairsRfc6265CookieNoEqualsIgnore() { + test(true, "foo;a=b; ;bar", IGNORE, A); + test(true, "foo;a=b;;bar", IGNORE, A); + test(true, "foo;a=b; ;;bar=rab", IGNORE, A, BAR); + test(true, "foo;a=b;; ;bar=rab", IGNORE, A, BAR); + test(true, "foo;a=b;;#;bar=rab", IGNORE, A, BAR); + test(true, "foo;a=b;;\\;bar=rab", IGNORE,A, BAR); + } + + + @Test + public void testEmptyPairsRfc6265CookieNoEqualsDefault() { 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); @@ -133,6 +204,7 @@ public class TestCookies { doTestSeparatorsInValue(false); } + @Test public void testSeparatorsInValueRfc6265() { doTestSeparatorsInValue(true); @@ -497,12 +569,20 @@ public class TestCookies { private void test(boolean useRfc6265, String header, Cookie... expected) { + test(useRfc6265, header, null, expected); + } + + + private void test(boolean useRfc6265, String header, String cookieNoEquals, Cookie... expected) { MimeHeaders mimeHeaders = new MimeHeaders(); ServerCookies serverCookies = new ServerCookies(4); CookieProcessor cookieProcessor; if (useRfc6265) { cookieProcessor = new Rfc6265CookieProcessor(); + if (cookieNoEquals != null) { + ((Rfc6265CookieProcessor) cookieProcessor).setNoEqualsCookie(cookieNoEquals); + } } else { cookieProcessor = new LegacyCookieProcessor(); } diff --git a/test/org/apache/tomcat/util/http/parser/TestCookie.java b/test/org/apache/tomcat/util/http/parser/TestCookie.java index 0f8a1dd9e3..51fa4e4307 100644 --- a/test/org/apache/tomcat/util/http/parser/TestCookie.java +++ b/test/org/apache/tomcat/util/http/parser/TestCookie.java @@ -27,6 +27,7 @@ import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameter; +import org.apache.tomcat.util.http.NoEqualsCookie; import org.apache.tomcat.util.http.ServerCookies; @RunWith(Parameterized.class) @@ -84,7 +85,7 @@ public class TestCookie { public void testParseThreeCookieHeader() { ServerCookies serverCookies = new ServerCookies(3); byte[] inputBytes = cookieHeader.getBytes(StandardCharsets.ISO_8859_1); - Cookie.parseCookie(inputBytes, 0, inputBytes.length, serverCookies); + Cookie.parseCookie(inputBytes, 0, inputBytes.length, serverCookies, NoEqualsCookie.NAME); Assert.assertEquals(3, serverCookies.getCookieCount()); Assert.assertEquals("first", serverCookies.getCookie(0).getName().toString()); Assert.assertEquals("1", serverCookies.getCookie(0).getValue().toString()); diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index ce55fa406c..27bd44816e 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -114,6 +114,11 @@ circumstances this could cause a blocking read to block waiting for more data rather than return the data it had already received. (markt) </fix> + <add> + Add a new attribute <code>noEqualsCookie</code> to the + <code>Rfc6265CookieProcessor</code>. The default behaviour is unchanged. + (markt) + </add> </changelog> </subsection> <subsection name="Jasper"> diff --git a/webapps/docs/config/cookie-processor.xml b/webapps/docs/config/cookie-processor.xml index 54590577bf..11c9c30fd8 100644 --- a/webapps/docs/config/cookie-processor.xml +++ b/webapps/docs/config/cookie-processor.xml @@ -99,6 +99,15 @@ <attributes> + <attribute name="noEqualsCookie" required="false"> + <p>Determines how a cookie received from a user agent should be + interpreted when the name value pair does not contain an equals sign. + The default value is <code>name</code> which means that the cookie will + be treated as a cookie with a name but no value. The other option is + <code>ignore</code> which means the cookie will be ignored. From Tomcat + 12 onwards the default will be <code>ignore</code>.</p> + </attribute> + <attribute name="partitioned" required="false"> <p>Should the Partitioned flag be set on cookies? Defaults to <code>false</code>.</p> <p>Note: The name of the attribute used to indicate a partitioned cookie as part of --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org