Merge remote-tracking branch 'origin/jetty-10.0.x' into jetty-11.0.x
This commit is contained in:
commit
94d28e45f8
|
@ -373,7 +373,7 @@ public class XmlConfiguredJetty
|
||||||
public void load() throws Exception
|
public void load() throws Exception
|
||||||
{
|
{
|
||||||
this._server = loadConfigurations(_xmlConfigurations, _properties);
|
this._server = loadConfigurations(_xmlConfigurations, _properties);
|
||||||
this._server.setStopTimeout(10);
|
this._server.setStopTimeout(1000); //wait up to a second to stop
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeWebapp(String name)
|
public void removeWebapp(String name)
|
||||||
|
|
|
@ -94,7 +94,12 @@ public class CookieCompliance implements ComplianceViolation.Mode
|
||||||
/**
|
/**
|
||||||
* Whitespace was found around the cookie name and/or around the cookie value.
|
* Whitespace was found around the cookie name and/or around the cookie value.
|
||||||
*/
|
*/
|
||||||
OPTIONAL_WHITE_SPACE("https://www.rfc-editor.org/rfc/rfc6265#section-5.2", "White space around name/value");
|
OPTIONAL_WHITE_SPACE("https://www.rfc-editor.org/rfc/rfc6265#section-5.2", "White space around name/value"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow spaces within values without quotes.
|
||||||
|
*/
|
||||||
|
SPACE_IN_VALUES("https://www.rfc-editor.org/rfc/rfc6265#section-5.2", "Space in value");
|
||||||
|
|
||||||
private final String url;
|
private final String url;
|
||||||
private final String description;
|
private final String description;
|
||||||
|
@ -130,10 +135,11 @@ public class CookieCompliance implements ComplianceViolation.Mode
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>{@link Violation#INVALID_COOKIES}</li>
|
* <li>{@link Violation#INVALID_COOKIES}</li>
|
||||||
* <li>{@link Violation#OPTIONAL_WHITE_SPACE}</li>
|
* <li>{@link Violation#OPTIONAL_WHITE_SPACE}</li>
|
||||||
|
* <li>{@link Violation#SPACE_IN_VALUES}</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
public static final CookieCompliance RFC6265 = new CookieCompliance("RFC6265", of(
|
public static final CookieCompliance RFC6265 = new CookieCompliance("RFC6265", of(
|
||||||
Violation.INVALID_COOKIES, Violation.OPTIONAL_WHITE_SPACE)
|
Violation.INVALID_COOKIES, Violation.OPTIONAL_WHITE_SPACE, Violation.SPACE_IN_VALUES)
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -151,10 +157,11 @@ public class CookieCompliance implements ComplianceViolation.Mode
|
||||||
* <li>{@link Violation#INVALID_COOKIES}</li>
|
* <li>{@link Violation#INVALID_COOKIES}</li>
|
||||||
* <li>{@link Violation#OPTIONAL_WHITE_SPACE}</li>
|
* <li>{@link Violation#OPTIONAL_WHITE_SPACE}</li>
|
||||||
* <li>{@link Violation#SPECIAL_CHARS_IN_QUOTES}</li>
|
* <li>{@link Violation#SPECIAL_CHARS_IN_QUOTES}</li>
|
||||||
|
* <li>{@link Violation#SPACE_IN_VALUES}</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
public static final CookieCompliance RFC6265_LEGACY = new CookieCompliance("RFC6265_LEGACY", EnumSet.of(
|
public static final CookieCompliance RFC6265_LEGACY = new CookieCompliance("RFC6265_LEGACY", EnumSet.of(
|
||||||
Violation.ATTRIBUTES, Violation.BAD_QUOTES, Violation.ESCAPE_IN_QUOTES, Violation.INVALID_COOKIES, Violation.OPTIONAL_WHITE_SPACE, Violation.SPECIAL_CHARS_IN_QUOTES)
|
Violation.ATTRIBUTES, Violation.BAD_QUOTES, Violation.ESCAPE_IN_QUOTES, Violation.INVALID_COOKIES, Violation.OPTIONAL_WHITE_SPACE, Violation.SPECIAL_CHARS_IN_QUOTES, Violation.SPACE_IN_VALUES)
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -26,6 +26,7 @@ import static org.eclipse.jetty.http.CookieCompliance.Violation.COMMA_SEPARATOR;
|
||||||
import static org.eclipse.jetty.http.CookieCompliance.Violation.ESCAPE_IN_QUOTES;
|
import static org.eclipse.jetty.http.CookieCompliance.Violation.ESCAPE_IN_QUOTES;
|
||||||
import static org.eclipse.jetty.http.CookieCompliance.Violation.INVALID_COOKIES;
|
import static org.eclipse.jetty.http.CookieCompliance.Violation.INVALID_COOKIES;
|
||||||
import static org.eclipse.jetty.http.CookieCompliance.Violation.OPTIONAL_WHITE_SPACE;
|
import static org.eclipse.jetty.http.CookieCompliance.Violation.OPTIONAL_WHITE_SPACE;
|
||||||
|
import static org.eclipse.jetty.http.CookieCompliance.Violation.SPACE_IN_VALUES;
|
||||||
import static org.eclipse.jetty.http.CookieCompliance.Violation.SPECIAL_CHARS_IN_QUOTES;
|
import static org.eclipse.jetty.http.CookieCompliance.Violation.SPECIAL_CHARS_IN_QUOTES;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -53,6 +54,7 @@ public class RFC6265CookieParser implements CookieParser
|
||||||
AFTER_NAME,
|
AFTER_NAME,
|
||||||
VALUE,
|
VALUE,
|
||||||
IN_VALUE,
|
IN_VALUE,
|
||||||
|
SPACE_IN_VALUE,
|
||||||
IN_QUOTED_VALUE,
|
IN_QUOTED_VALUE,
|
||||||
ESCAPED_VALUE,
|
ESCAPED_VALUE,
|
||||||
AFTER_QUOTED_VALUE,
|
AFTER_QUOTED_VALUE,
|
||||||
|
@ -74,6 +76,7 @@ public class RFC6265CookieParser implements CookieParser
|
||||||
String cookieComment = null;
|
String cookieComment = null;
|
||||||
int cookieVersion = 0;
|
int cookieVersion = 0;
|
||||||
boolean cookieInvalid = false;
|
boolean cookieInvalid = false;
|
||||||
|
int spaces = 0;
|
||||||
|
|
||||||
int length = field.length();
|
int length = field.length();
|
||||||
StringBuilder string = new StringBuilder();
|
StringBuilder string = new StringBuilder();
|
||||||
|
@ -220,7 +223,13 @@ public class RFC6265CookieParser implements CookieParser
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IN_VALUE:
|
case IN_VALUE:
|
||||||
if (c == ';' || c == ',' || c == ' ' || c == '\t')
|
if (c == ' ' && _complianceMode.allows(SPACE_IN_VALUES))
|
||||||
|
{
|
||||||
|
reportComplianceViolation(SPACE_IN_VALUES, field);
|
||||||
|
spaces = 1;
|
||||||
|
state = State.SPACE_IN_VALUE;
|
||||||
|
}
|
||||||
|
else if (c == ' ' || c == ';' || c == ',' || c == '\t')
|
||||||
{
|
{
|
||||||
value = string.toString();
|
value = string.toString();
|
||||||
i--;
|
i--;
|
||||||
|
@ -241,6 +250,33 @@ public class RFC6265CookieParser implements CookieParser
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SPACE_IN_VALUE:
|
||||||
|
if (c == ' ')
|
||||||
|
{
|
||||||
|
spaces++;
|
||||||
|
}
|
||||||
|
else if (c == ';' || c == ',' || c == '\t')
|
||||||
|
{
|
||||||
|
value = string.toString();
|
||||||
|
i--;
|
||||||
|
state = State.END;
|
||||||
|
}
|
||||||
|
else if (token.isRfc6265CookieOctet())
|
||||||
|
{
|
||||||
|
string.append(" ".repeat(spaces)).append(c);
|
||||||
|
state = State.IN_VALUE;
|
||||||
|
}
|
||||||
|
else if (_complianceMode.allows(INVALID_COOKIES))
|
||||||
|
{
|
||||||
|
reportComplianceViolation(INVALID_COOKIES, field);
|
||||||
|
state = State.INVALID_COOKIE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new InvalidCookieException("Bad Cookie value");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case IN_QUOTED_VALUE:
|
case IN_QUOTED_VALUE:
|
||||||
if (c == '"')
|
if (c == '"')
|
||||||
{
|
{
|
||||||
|
@ -265,6 +301,11 @@ public class RFC6265CookieParser implements CookieParser
|
||||||
reportComplianceViolation(COMMA_NOT_VALID_OCTET, field);
|
reportComplianceViolation(COMMA_NOT_VALID_OCTET, field);
|
||||||
string.append(c);
|
string.append(c);
|
||||||
}
|
}
|
||||||
|
else if (c == ' ' && _complianceMode.allows(SPACE_IN_VALUES))
|
||||||
|
{
|
||||||
|
reportComplianceViolation(SPACE_IN_VALUES, field);
|
||||||
|
string.append(c);
|
||||||
|
}
|
||||||
else if (_complianceMode.allows(INVALID_COOKIES))
|
else if (_complianceMode.allows(INVALID_COOKIES))
|
||||||
{
|
{
|
||||||
string.append(c);
|
string.append(c);
|
||||||
|
|
|
@ -22,6 +22,7 @@ import org.junit.jupiter.params.provider.Arguments;
|
||||||
import org.junit.jupiter.params.provider.MethodSource;
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
|
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
import static org.hamcrest.Matchers.is;
|
import static org.hamcrest.Matchers.is;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -34,8 +35,8 @@ public class RFC6265CookieParserLenientTest
|
||||||
{
|
{
|
||||||
return Stream.of(
|
return Stream.of(
|
||||||
// Simple test to verify behavior
|
// Simple test to verify behavior
|
||||||
Arguments.of("x=y", "x", "y"),
|
Arguments.of("x=y", new String[]{"x", "y"}),
|
||||||
Arguments.of("key=value", "key", "value"),
|
Arguments.of("key=value", new String[]{"key", "value"}),
|
||||||
|
|
||||||
// Tests that conform to RFC2109
|
// Tests that conform to RFC2109
|
||||||
// RFC2109 - token values
|
// RFC2109 - token values
|
||||||
|
@ -49,75 +50,83 @@ public class RFC6265CookieParserLenientTest
|
||||||
// | "," | ";" | ":" | "\" | <">
|
// | "," | ";" | ":" | "\" | <">
|
||||||
// | "/" | "[" | "]" | "?" | "="
|
// | "/" | "[" | "]" | "?" | "="
|
||||||
// | "{" | "}" | SP | HT
|
// | "{" | "}" | SP | HT
|
||||||
Arguments.of("abc=xyz", "abc", "xyz"),
|
Arguments.of("abc=xyz", new String[]{"abc", "xyz"}),
|
||||||
Arguments.of("abc=!bar", "abc", "!bar"),
|
Arguments.of("abc=!bar", new String[]{"abc", "!bar"}),
|
||||||
Arguments.of("abc=#hash", "abc", "#hash"),
|
Arguments.of("abc=#hash", new String[]{"abc", "#hash"}),
|
||||||
Arguments.of("abc=#hash", "abc", "#hash"),
|
Arguments.of("abc=#hash", new String[]{"abc", "#hash"}),
|
||||||
// RFC2109 - quoted-string values
|
// RFC2109 - quoted-string values
|
||||||
// quoted-string = ( <"> *(qdtext) <"> )
|
// quoted-string = ( <"> *(qdtext) <"> )
|
||||||
// qdtext = <any TEXT except <">>
|
// qdtext = <any TEXT except <">>
|
||||||
|
|
||||||
// rejected, as name cannot be DQUOTED
|
// rejected, as name cannot be DQUOTED
|
||||||
Arguments.of("\"a\"=bcd", null, null),
|
Arguments.of("\"a\"=bcd", new String[0]),
|
||||||
Arguments.of("\"a\"=\"b c d\"", null, null),
|
Arguments.of("\"a\"=\"b c d\"", new String[0]),
|
||||||
|
|
||||||
// lenient with spaces and EOF
|
// lenient with spaces and EOF
|
||||||
Arguments.of("abc=", "abc", ""),
|
Arguments.of("abc=", new String[]{"abc", ""}),
|
||||||
Arguments.of("abc= ", "abc", ""),
|
Arguments.of("abc= ", new String[]{"abc", ""}),
|
||||||
Arguments.of("abc= x", "abc", "x"),
|
Arguments.of("abc= x", new String[]{"abc", "x"}),
|
||||||
Arguments.of("abc = ", "abc", ""),
|
Arguments.of("abc = ", new String[]{"abc", ""}),
|
||||||
Arguments.of("abc = ;", "abc", ""),
|
Arguments.of("abc = ;", new String[]{"abc", ""}),
|
||||||
Arguments.of("abc = ; ", "abc", ""),
|
Arguments.of("abc = ; ", new String[]{"abc", ""}),
|
||||||
Arguments.of("abc = x ", "abc", "x"),
|
Arguments.of("abc = x ", new String[]{"abc", "x"}),
|
||||||
Arguments.of("abc=\"\"", "abc", ""),
|
Arguments.of("abc=\"\"", new String[]{"abc", ""}),
|
||||||
Arguments.of("abc= \"\" ", "abc", ""),
|
Arguments.of("abc= \"\" ", new String[]{"abc", ""}),
|
||||||
Arguments.of("abc= \"x\" ", "abc", "x"),
|
Arguments.of("abc= \"x\" ", new String[]{"abc", "x"}),
|
||||||
Arguments.of("abc= \"x\" ;", "abc", "x"),
|
Arguments.of("abc= \"x\" ;", new String[]{"abc", "x"}),
|
||||||
Arguments.of("abc= \"x\" ; ", "abc", "x"),
|
Arguments.of("abc= \"x\" ; ", new String[]{"abc", "x"}),
|
||||||
|
Arguments.of("abc = x y z ", new String[]{"abc", "x y z"}),
|
||||||
|
Arguments.of("abc = x y z ", new String[]{"abc", "x y z"}),
|
||||||
|
Arguments.of("abc=a:x b:y c:z", new String[]{"abc", "a:x b:y c:z"}),
|
||||||
|
Arguments.of("abc=a;x b;y c;z", new String[]{"abc", "a"}),
|
||||||
|
Arguments.of("abc=a ;b=x", new String[]{"abc", "a", "b", "x"}),
|
||||||
|
|
||||||
|
Arguments.of("abc=x y;def=w z", new String[]{"abc", "x y", "def", "w z"}),
|
||||||
|
Arguments.of("abc=\"x y\";def=w z", new String[]{"abc", "x y", "def", "w z"}),
|
||||||
|
Arguments.of("abc=x y;def=\"w z\"", new String[]{"abc", "x y", "def", "w z"}),
|
||||||
|
|
||||||
// The backslash character ("\") may be used as a single-character quoting
|
// The backslash character ("\") may be used as a single-character quoting
|
||||||
// mechanism only within quoted-string and comment constructs.
|
// mechanism only within quoted-string and comment constructs.
|
||||||
// quoted-pair = "\" CHAR
|
// quoted-pair = "\" CHAR
|
||||||
Arguments.of("abc=\"xyz\"", "abc", "xyz"),
|
Arguments.of("abc=\"xyz\"", new String[]{"abc", "xyz"}),
|
||||||
Arguments.of("abc=\"!bar\"", "abc", "!bar"),
|
Arguments.of("abc=\"!bar\"", new String[]{"abc", "!bar"}),
|
||||||
Arguments.of("abc=\"#hash\"", "abc", "#hash"),
|
Arguments.of("abc=\"#hash\"", new String[]{"abc", "#hash"}),
|
||||||
// RFC2109 - other valid name types that conform to 'attr'/'token' syntax
|
// RFC2109 - other valid name types that conform to 'attr'/'token' syntax
|
||||||
Arguments.of("!f!o!o!=wat", "!f!o!o!", "wat"),
|
Arguments.of("!f!o!o!=wat", new String[]{"!f!o!o!", "wat"}),
|
||||||
Arguments.of("__MyHost=Foo", "__MyHost", "Foo"),
|
Arguments.of("__MyHost=Foo", new String[]{"__MyHost", "Foo"}),
|
||||||
Arguments.of("some-thing-else=to-parse", "some-thing-else", "to-parse"),
|
Arguments.of("some-thing-else=to-parse", new String[]{"some-thing-else", "to-parse"}),
|
||||||
Arguments.of("$foo=bar", "$foo", "bar"),
|
Arguments.of("$foo=bar", new String[]{"$foo", "bar"}),
|
||||||
|
|
||||||
// Tests that conform to RFC6265
|
// Tests that conform to RFC6265
|
||||||
Arguments.of("abc=foobar!", "abc", "foobar!"),
|
Arguments.of("abc=foobar!", new String[]{"abc", "foobar!"}),
|
||||||
Arguments.of("abc=\"foobar!\"", "abc", "foobar!")
|
Arguments.of("abc=\"foobar!\"", new String[]{"abc", "foobar!"})
|
||||||
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource("data")
|
@MethodSource("data")
|
||||||
public void testLenientBehavior(String rawHeader, String expectedName, String expectedValue)
|
public void testLenientBehavior(String rawHeader, String... expected)
|
||||||
{
|
{
|
||||||
TestCutter cutter = new TestCutter();
|
TestParser parser = new TestParser();
|
||||||
cutter.parseField(rawHeader);
|
parser.parseField(rawHeader);
|
||||||
|
|
||||||
if (expectedName == null)
|
assertThat(expected.length % 2, is(0));
|
||||||
assertThat("Cookies.length", cutter.names.size(), is(0));
|
assertThat(parser.names.size(), equalTo(expected.length / 2));
|
||||||
else
|
for (int i = 0; i < expected.length; i += 2)
|
||||||
{
|
{
|
||||||
assertThat("Cookies.length", cutter.names.size(), is(1));
|
int cookie = i / 2;
|
||||||
assertThat("Cookie.name", cutter.names.get(0), is(expectedName));
|
assertThat("Cookie.name " + cookie, parser.names.get(cookie), is(expected[i]));
|
||||||
assertThat("Cookie.value", cutter.values.get(0), is(expectedValue));
|
assertThat("Cookie.value " + cookie, parser.values.get(cookie), is(expected[i + 1]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static class TestCutter implements CookieParser.Handler
|
static class TestParser implements CookieParser.Handler
|
||||||
{
|
{
|
||||||
CookieParser parser;
|
CookieParser parser;
|
||||||
List<String> names = new ArrayList<>();
|
List<String> names = new ArrayList<>();
|
||||||
List<String> values = new ArrayList<>();
|
List<String> values = new ArrayList<>();
|
||||||
|
|
||||||
protected TestCutter()
|
protected TestParser()
|
||||||
{
|
{
|
||||||
parser = new RFC6265CookieParser(this, CookieCompliance.RFC6265, null);
|
parser = new RFC6265CookieParser(this, CookieCompliance.RFC6265, null);
|
||||||
}
|
}
|
||||||
|
|
|
@ -315,15 +315,15 @@ public class RFC6265CookieParserTest
|
||||||
new Param("A=1 ; B=2; C=3", "A=1", "B=2", "C=3"),
|
new Param("A=1 ; B=2; C=3", "A=1", "B=2", "C=3"),
|
||||||
new Param("A=\"1; B=2\"; C=3", "C=3"),
|
new Param("A=\"1; B=2\"; C=3", "C=3"),
|
||||||
new Param("A=\"1; B=2; C=3"),
|
new Param("A=\"1; B=2; C=3"),
|
||||||
new Param("A=\"1 B=2\"; C=3", "C=3"),
|
new Param("A=\"1 B=2\"; C=3", "A=1 B=2", "C=3"),
|
||||||
new Param("A=\"\"1; B=2; C=3", "B=2", "C=3"),
|
new Param("A=\"\"1; B=2; C=3", "B=2", "C=3"),
|
||||||
new Param("A=\"\" ; B=2; C=3", "A=", "B=2", "C=3"),
|
new Param("A=\"\" ; B=2; C=3", "A=", "B=2", "C=3"),
|
||||||
new Param("A=1\"\"; B=2; C=3", "B=2", "C=3"),
|
new Param("A=1\"\"; B=2; C=3", "B=2", "C=3"),
|
||||||
new Param("A=1\"; B=2; C=3", "B=2", "C=3"),
|
new Param("A=1\"; B=2; C=3", "B=2", "C=3"),
|
||||||
new Param("A=1\"1; B=2; C=3", "B=2", "C=3"),
|
new Param("A=1\"1; B=2; C=3", "B=2", "C=3"),
|
||||||
new Param("A= 1; B=2; C=3", "A=1", "B=2", "C=3"),
|
new Param("A= 1; B=2; C=3", "A=1", "B=2", "C=3"),
|
||||||
new Param("A=\" 1\"; B=2; C=3", "B=2", "C=3"),
|
new Param("A=\" 1\"; B=2; C=3", "A= 1", "B=2", "C=3"),
|
||||||
new Param("A=\"1 \"; B=2; C=3", "B=2", "C=3"),
|
new Param("A=\"1 \"; B=2; C=3", "A=1 ", "B=2", "C=3"),
|
||||||
new Param("A=1,; B=2; C=3", "B=2", "C=3"),
|
new Param("A=1,; B=2; C=3", "B=2", "C=3"),
|
||||||
new Param("A=\"1,\"; B=2; C=3", "B=2", "C=3"),
|
new Param("A=\"1,\"; B=2; C=3", "B=2", "C=3"),
|
||||||
new Param("A=\\1; B=2; C=3", "B=2", "C=3"),
|
new Param("A=\\1; B=2; C=3", "B=2", "C=3"),
|
||||||
|
|
Loading…
Reference in New Issue