From 9fad75a35301d5fab65d7c1482ed9bc598caf0db Mon Sep 17 00:00:00 2001 From: Mark Thomas Date: Thu, 18 Nov 2021 17:47:14 +0000 Subject: [PATCH] Fix #37 - update Cookie class for RFC 6265 In summary: - setVersion() is NO-OP, getVersion() is hard-coded to 0 - Restrictions on cookie name relaxed to 'must be non-null, non-empty token' --- .../java/jakarta/servlet/http/Cookie.java | 54 ++++++++----------- .../java/jakarta/servlet/http/CookieTest.java | 11 ++-- 2 files changed, 27 insertions(+), 38 deletions(-) diff --git a/api/src/main/java/jakarta/servlet/http/Cookie.java b/api/src/main/java/jakarta/servlet/http/Cookie.java index 0a282facd..08d8ace24 100644 --- a/api/src/main/java/jakarta/servlet/http/Cookie.java +++ b/api/src/main/java/jakarta/servlet/http/Cookie.java @@ -55,8 +55,7 @@ * with this class. This class does not support the cache control defined with HTTP 1.1. * *

- * This class supports both the Version 0 (by Netscape) and Version 1 (by RFC 2109) cookie specifications. By default, - * cookies are created using Version 0 to ensure the best interoperability. + * This class supports cookies as defined by RFC 6265. * * @author Various */ @@ -96,7 +95,6 @@ public Boolean run() { // private final String name; // NAME= ... "$Name" style is reserved private String value; // value of NAME - private int version = 0; // ;Version=1 ... means RFC 2109++ style // // Attributes encoded in the header's cookie fields. @@ -107,7 +105,7 @@ public Boolean run() { * Constructs a cookie with the specified name and value. * *

- * The name must conform to RFC 2109. However, vendors may provide a configuration option that allows cookie names + * The name must conform to RFC 6265. However, vendors may provide a configuration option that allows cookie names * conforming to the original Netscape Cookie Specification to be accepted. * *

@@ -136,16 +134,7 @@ public Cookie(String name, String value) { throw new IllegalArgumentException(createErrorMessage("err.cookie_name_blank")); } - if (hasReservedCharacters(name) || name.startsWith("$") - || name.equalsIgnoreCase(COMMENT) // rfc2109 - || name.equalsIgnoreCase("Discard") // 2109++ - || name.equalsIgnoreCase(DOMAIN) - || name.equalsIgnoreCase("Expires") // (old cookies) - || name.equalsIgnoreCase(MAX_AGE) // rfc2109 - || name.equalsIgnoreCase(PATH) - || name.equalsIgnoreCase(SECURE) - || name.equalsIgnoreCase("Version") - || name.equalsIgnoreCase(HTTP_ONLY)) { + if (hasReservedCharacters(name)) { throw new IllegalArgumentException(createErrorMessage("err.cookie_name_invalid", name)); } @@ -181,12 +170,12 @@ public String getComment() { * Specifies the domain within which this cookie should be presented. * *

- * The form of the domain name is specified by RFC 2109. A domain name begins with a dot (.foo.com) and + * The form of the domain name is specified by RFC 6265. A domain name begins with a dot (.foo.com) and * means that the cookie is visible to servers in a specified Domain Name System (DNS) zone (for example, * www.foo.com, but not a.b.foo.com). By default, cookies are only returned to the server that * sent them. * - * @param domain the domain name within which this cookie is visible; form is according to RFC 2109 + * @param domain the domain name within which this cookie is visible; form is according to RFC 6265 * * @see #getDomain */ @@ -198,7 +187,7 @@ public void setDomain(String domain) { * Gets the domain name of this Cookie. * *

- * Domain names are formatted according to RFC 2109. + * Domain names are formatted according to RFC 6265. * * @return the domain name of this Cookie * @@ -253,7 +242,8 @@ public int getMaxAge() { * makes the cookie visible to all directories on the server under /catalog. * *

- * Consult RFC 2109 (available on the Internet) for more information on setting path names for cookies. + * Consult RFC 6265 for more information on setting path names for + * cookies. * * * @param uri a String specifying a path @@ -343,31 +333,33 @@ public String getValue() { } /** - * 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 0 if the cookie complies with the original Netscape specification; 1 if the cookie complies with RFC 2109 + * @return Always 0 * * @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 that this Cookie complies with. - * + * With the adoption of support for RFC 6265, this method should no longer be used. *

- * Version 0 complies with the original Netscape cookie specification. Version 1 complies with RFC 2109. + * If called, this method has no effect. * - * @param v 0 if the cookie should comply with the original Netscape specification; 1 if the cookie should comply with - * RFC 2109 + * @param v This parameter is ignored * * @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 } /* @@ -526,7 +518,7 @@ public Map getAttributes() { @Override public int hashCode() { - return Objects.hash(name, value, attributes) + version; + return Objects.hash(name, value, attributes); } @Override @@ -543,6 +535,6 @@ public boolean equals(Object obj) { @Override public String toString() { - return String.format("%s{%s=%s,%d,%s}", super.toString(), name, value, version, attributes); + return String.format("%s{%s=%s,%s}", super.toString(), name, value, attributes); } } diff --git a/api/src/test/java/jakarta/servlet/http/CookieTest.java b/api/src/test/java/jakarta/servlet/http/CookieTest.java index 7634c2134..0fb78d373 100644 --- a/api/src/test/java/jakarta/servlet/http/CookieTest.java +++ b/api/src/test/java/jakarta/servlet/http/CookieTest.java @@ -30,6 +30,7 @@ import org.junit.jupiter.params.provider.ValueSource; public class CookieTest { + @SuppressWarnings("removal") @Test public void testCookie() { Cookie cookie = new Cookie("name", "value"); @@ -51,9 +52,6 @@ public void testCookie() { "=", " ", "name=value", - "$name", - "comment", - "domain", "\377", }) public void testBadCookie(String name) { @@ -160,15 +158,16 @@ public void testValue() { assertThat(cookie.getValue(), nullValue()); } + @SuppressWarnings("removal") @Test public void testVersion() { Cookie cookie = new Cookie("name", "value"); assertThat(cookie.getVersion(), is(0)); cookie.setVersion(1); - assertThat(cookie.getVersion(), is(1)); + assertThat(cookie.getVersion(), is(0)); assertThat(cookie.getAttributes().size(), is(0)); cookie.setVersion(Integer.MAX_VALUE); - assertThat(cookie.getVersion(), is(Integer.MAX_VALUE)); + assertThat(cookie.getVersion(), is(0)); assertThat(cookie.getAttributes().size(), is(0)); } @@ -239,7 +238,6 @@ public void testCloneHashEquals() { cookie.setMaxAge(10); cookie.setPath("/path"); cookie.setSecure(false); - cookie.setVersion(2); cookie.setAttribute("A0", "V0"); Cookie clone = (Cookie) cookie.clone(); @@ -253,7 +251,6 @@ public void testCloneHashEquals() { assertThat(clone.getPath(), is("/path")); assertThat(clone.getSecure(), is(false)); assertThat(clone.isHttpOnly(), is(true)); - assertThat(clone.getVersion(), is(2)); assertThat(clone.getAttributes().size(), is(cookie.getAttributes().size())); assertEquals(cookie, clone);