From dcfbdf3d33427e8d94b4ea7c9857acb6dcc40c6a Mon Sep 17 00:00:00 2001 From: WalkerWatch Date: Wed, 15 Mar 2017 15:21:39 -0400 Subject: [PATCH 1/9] Minor formatting updates. Signed-off-by: WalkerWatch --- .../default-logging-with-stderrlog.adoc | 34 ++++++++++--------- .../logging/example-java-util-logging.adoc | 4 +-- .../example-logback-centralized-logging.adoc | 6 ++-- .../logging/example-logback.adoc | 4 +-- .../example-slf4j-multiple-loggers.adoc | 4 +-- 5 files changed, 27 insertions(+), 25 deletions(-) diff --git a/jetty-documentation/src/main/asciidoc/administration/logging/default-logging-with-stderrlog.adoc b/jetty-documentation/src/main/asciidoc/administration/logging/default-logging-with-stderrlog.adoc index 13d7d6a5279..ff68b108aff 100644 --- a/jetty-documentation/src/main/asciidoc/administration/logging/default-logging-with-stderrlog.adoc +++ b/jetty-documentation/src/main/asciidoc/administration/logging/default-logging-with-stderrlog.adoc @@ -20,7 +20,7 @@ [[stderrlog-configuration]] ==== StdErrLog Configuration -If you do nothing to configure a separate logging framework, Jetty will default to using an internal `org.eclipse.jetty.util.log.StdErrLog` implementation. +If you do nothing to configure a separate logging framework, Jetty will default to using an internal `org.eclipse.jetty.util.log.StdErrLog` implementation. This will output all logging events to STDERR (aka `System.err`). Simply use Jetty and `StdErrLog` based logging is output. @@ -45,6 +45,8 @@ The default configuration for logging output will create a file `${jetty.logs}/y For more advanced logging configurations, please consider use of a separate logging library. +[[stderr-properties]] +==== The jetty-logging.properties File The recommended way to configure `StdErrLog` is to create a `${jetty.home}/resources/jetty-logging.properties` file, specify the log implementation to `StdErrLog` and then setup logging levels. [source,properties] @@ -60,31 +62,31 @@ org.eclipse.jetty.websocket.LEVEL=DEBUG There are a number of properties that can be defined in the configuration that will affect the behavior of `StdErrLog`. `.LEVEL=`:: - Sets the logging level for all loggers within the `name` specified to the level, which can be (in increasing order of restriction) `ALL`, `DEBUG`, `INFO`, `WARN`, `OFF`. + Sets the logging level for all loggers within the `name` specified to the level, which can be (in increasing order of restriction) `ALL`, `DEBUG`, `INFO`, `WARN`, `OFF`. The name (or hierarchy) can be a specific fully qualified class or a package namespace. - For example, `org.eclipse.jetty.http.LEVEL=DEBUG` is a package namespace approach to turn all loggers in the Jetty HTTP package to DEBUG level, and `org.eclipse.jetty.io.ChanelEndPoint.LEVEL=ALL` turns on all logging events for the specific class, including `DEBUG`, `INFO`, `WARN` (and even special internally ignored exception classes). + For example, `org.eclipse.jetty.http.LEVEL=DEBUG` is a package namespace approach to turn all loggers in the Jetty HTTP package to DEBUG level, and `org.eclipse.jetty.io.ChanelEndPoint.LEVEL=ALL` turns on all logging events for the specific class, including `DEBUG`, `INFO`, `WARN` (and even special internally ignored exception classes). If more than one system property specifies a logging level, the most specific one applies. `.SOURCE=`:: - Named Logger specific, attempts to print the Java source file name and line number from where the logging event originated. - Name must be a fully qualified class name (this configurable does not support package name hierarchy). - Default is false. + Named Logger specific, attempts to print the Java source file name and line number from where the logging event originated. + Name must be a fully qualified class name (this configurable does not support package name hierarchy). + Default is false. Be aware that this is a slow operation and has an impact on performance. `.STACKS=`:: - Named Logger specific, controls the display of stacktraces. + Named Logger specific, controls the display of stacktraces. Name must be a fully qualified class name (this configurable does not support package name hierarchy). Default is true. `org.eclipse.jetty.util.log.stderr.SOURCE=`:: - Special Global Configuration. - Attempts to print the Java source file name and line number from where the logging event originated. + Special Global Configuration. + Attempts to print the Java source file name and line number from where the logging event originated. Default is false. `org.eclipse.jetty.util.log.stderr.LONG=`:: - Special Global Configuration. - When true, outputs logging events to `STDERR` using long form, fully qualified class names. + Special Global Configuration. + When true, outputs logging events to `STDERR` using long form, fully qualified class names. When false, uses abbreviated package names. Default is false. - + ++ * Example when set to false: - + ++ [source, screen, subs="{sub-order}"] .... 2014-06-03 14:36:16.013:INFO:oejs.Server:main: jetty-9.2.0.v20140526 @@ -93,9 +95,9 @@ There are a number of properties that can be defined in the configuration that w 2014-06-03 14:36:17.880:INFO:oejs.ServerConnector:main: Started ServerConnector@34f2d11a{HTTP/1.1}{0.0.0.0:8080} 2014-06-03 14:36:17.888:INFO:oejs.Server:main: Started @257ms .... - + ++ * Example when set to true: - + ++ [source, screen, subs="{sub-order}"] .... 2014-06-03 14:38:19.019:INFO:org.eclipse.jetty.server.Server:main: jetty-9.2.0.v20140526 @@ -108,7 +110,7 @@ There are a number of properties that can be defined in the configuration that w [[deprecated-parameters]] ==== Deprecated Parameters -These parameters existed in prior versions of Jetty, and are no longer supported. +These parameters existed in prior versions of Jetty, and are no longer supported. They are included here for historical (and search engine) reasons. `org.eclipse.jetty.util.log.DEBUG`:: diff --git a/jetty-documentation/src/main/asciidoc/administration/logging/example-java-util-logging.adoc b/jetty-documentation/src/main/asciidoc/administration/logging/example-java-util-logging.adoc index ab23492ec0e..5f205af3e23 100644 --- a/jetty-documentation/src/main/asciidoc/administration/logging/example-java-util-logging.adoc +++ b/jetty-documentation/src/main/asciidoc/administration/logging/example-java-util-logging.adoc @@ -52,7 +52,7 @@ INFO: resources enabled in ${jetty.base}/start.ini The replacement `logging.mod` performs a number of tasks. . `mybase` is a `${jetty.base}` directory -. The jetty-distribution is unpacked (and untouched) into `/opt/jetty-dist/ `and becomes the `${jetty.home}` directory for this demonstration. +. The jetty-distribution is unpacked (and untouched) into `/opt/jetty-dist/` and becomes the `${jetty.home}` directory for this demonstration. . The `curl` command downloads the replacement `logging.mod` and puts it into the `${jetty.base}/modules/` directory for use by `mybase` only. . The `start.jar --add-to-start=logging` command performs a number of steps to make the logging module available to the `${jetty.base}` configuration. .. The `--module=logging` command is added to the `${jetty.base}/start.ini` configuration. @@ -82,4 +82,4 @@ Other logging frameworks are more reliable in that they always initialize and co * While it is possible to configure `java.util.logging` sooner, even at JVM startup, the example demonstrated here does not show this technique. For more information consult the official `java.util.logging.LogManager` javadoc http://docs.oracle.com/javase/7/docs/api/java/util/logging/LogManager.html[documentation from Oracle]. -____ \ No newline at end of file +____ diff --git a/jetty-documentation/src/main/asciidoc/administration/logging/example-logback-centralized-logging.adoc b/jetty-documentation/src/main/asciidoc/administration/logging/example-logback-centralized-logging.adoc index 49f38ab23a7..069f345077f 100644 --- a/jetty-documentation/src/main/asciidoc/administration/logging/example-logback-centralized-logging.adoc +++ b/jetty-documentation/src/main/asciidoc/administration/logging/example-logback-centralized-logging.adoc @@ -17,7 +17,7 @@ [[example-logging-logback-centralized]] === Example: Centralized Logging with Logback -The term _Centralized Logging_ refers to a forced logging configuration for the Jetty Server and all web applications that are deployed on the server. +The term _Centralized Logging_ refers to a forced logging configuration for the Jetty Server and all web applications that are deployed on the server. It routes all logging events from the web applications to a single configuration on the Server side. The example below shows how to accomplish this with Jetty and Slf4j, using `Logback` to manage the final writing of logs to disk. @@ -30,7 +30,7 @@ ____ This configuration is essentially the multiple logger configuration with added configuration to the deployers to force a `WebAppClassLoader` change to use the server classpath over the webapps classpath for the logger specific classes. -The technique used by this configuration is to provide an link:{JDURL}org/eclipse/jetty/deploy/AppLifeCycle.Binding.html[AppLifeCycle.Binding] against the link:{JDURL}/org/eclipse/jetty/deploy/AppLifeCycle.html[`"deploying"`node] that modifies the link:{JDURL}/org/eclipse/jetty/webapp/WebAppContext.html#addSystemClass(java.lang.String)[WebAppContext.addSystemClass(String)] for the common logging classes. +The technique used by this configuration is to provide an link:{JDURL}org/eclipse/jetty/deploy/AppLifeCycle.Binding.html[AppLifeCycle.Binding] against the link:{JDURL}/org/eclipse/jetty/deploy/AppLifeCycle.html[`"deploying"`node] that modifies the link:{JDURL}/org/eclipse/jetty/webapp/WebAppContext.html#addSystemClass(java.lang.String)[WebAppContext.addSystemClass(String)] for the common logging classes. See https://github.com/jetty-project/jetty-webapp-logging/blob/master/src/main/java/org/eclipse/jetty/webapp/logging/CentralizedWebAppLoggingBinding.java[org.eclipse.jetty.logging.CentralizedWebAppLoggingBinding] for actual implementation. A convenient replacement `logging` module has been created to bootstrap your `${jetty.base}` directory for capturing all Jetty server logging from multiple logging frameworks into a single logging output file managed by Logback. @@ -81,7 +81,7 @@ INFO: resources enabled in ${jetty.base}/start.ini The replacement `logging.mod` performs a number of tasks. . `mybase` is a `${jetty.base}` directory. -. The jetty-distribution is unpacked (and untouched) into `/opt/jetty-dist/ `and becomes the `${jetty.home}` directory for this demonstration. +. The jetty-distribution is unpacked (and untouched) into `/opt/jetty-dist/` and becomes the `${jetty.home}` directory for this demonstration. . The `curl` command downloads the replacement `logging.mod` and puts it into the `${jetty.base}/modules/` directory for use by mybase only. . The `start.jar --add-to-start=logging,webapp-logging` command performs a number of steps to make the logging module available to the `${jetty.base}` configuration. .. Several entries are added to the `${jetty.base}/start.ini` configuration. diff --git a/jetty-documentation/src/main/asciidoc/administration/logging/example-logback.adoc b/jetty-documentation/src/main/asciidoc/administration/logging/example-logback.adoc index 1c4b64e8b1b..a939037df9d 100644 --- a/jetty-documentation/src/main/asciidoc/administration/logging/example-logback.adoc +++ b/jetty-documentation/src/main/asciidoc/administration/logging/example-logback.adoc @@ -17,7 +17,7 @@ [[example-logging-logback]] === Example: Logging with Logback -It is possible to have the Jetty Server logging configured so that Logback controls the output of logging events produced by Jetty. +It is possible to have the Jetty Server logging configured so that Logback controls the output of logging events produced by Jetty. This is accomplished by configuring Jetty for logging to `Logback`, which uses http://slf4j.org/manual.html[Slf4j] and the http://logback.qos.ch/[Logback Implementation for Slf4j]. A convenient replacement `logging` module has been created to bootstrap the `${jetty.base}` directory for logging with logback. @@ -48,7 +48,7 @@ DOWNLOAD: https://raw.githubusercontent.com/jetty-project/logging-modules/master The replacement `logging.mod` performs a number of tasks. . `mybase` is a `${jetty.base}` directory. -. The jetty-distribution is unpacked (and untouched) into `/opt/jetty-dist/ `and becomes the `${jetty.home}` directory for this demonstration. +. The jetty-distribution is unpacked (and untouched) into `/opt/jetty-dist/` and becomes the `${jetty.home}` directory for this demonstration. . The `curl` command downloads the replacement `logging.mod` and puts it into the `${jetty.base}/modules/` directory for use by `mybase` only. . The `start.jar --add-to-start=logging` command performs a number of steps to make the logging module available to the `${jetty.base}` configuration. .. The `--module=logging` command is added to the `${jetty.base}/start.ini` configuration. diff --git a/jetty-documentation/src/main/asciidoc/administration/logging/example-slf4j-multiple-loggers.adoc b/jetty-documentation/src/main/asciidoc/administration/logging/example-slf4j-multiple-loggers.adoc index d63930e4f25..32a7ece950a 100644 --- a/jetty-documentation/src/main/asciidoc/administration/logging/example-slf4j-multiple-loggers.adoc +++ b/jetty-documentation/src/main/asciidoc/administration/logging/example-slf4j-multiple-loggers.adoc @@ -70,7 +70,7 @@ Logging API:: Slf4j Binding JAR:: * Special JARs, created and maintained by the Slf4j project, that pretend to be the various Logging API implementation classes, but instead just route that Logging API's events to Slf4j to handle. * There MAY be multiple Slf4j binding JARs present on the classpath at the same time. - + * For a single logging API, if you choose to use the Slf4j binding JAR, then you MUST NOT include the SLf4j adapter JAR or underlying logging framework in the classpath as well. Slf4j Adapter Jar:: * These JARs are created and maintained by the Slf4j project and route Slf4j logging events to a specific underlying logging framework. @@ -118,7 +118,7 @@ INFO: resources enabled in ${jetty.base}/start.ini The replacement `logging.mod` performs a number of tasks. . `mybase` is a `${jetty.base}` directory. -. The jetty-distribution is unpacked (and untouched) into `/opt/jetty-dist/ `and becomes the `${jetty.home}` directory for this demonstration. +. The jetty-distribution is unpacked (and untouched) into `/opt/jetty-dist/` and becomes the `${jetty.home}` directory for this demonstration. . The `curl` command downloads the replacement `logging.mod` and puts it into the `${jetty.base}/modules/` directory for use by `mybase` only. . The `start.jar --add-to-start=logging` command performs a number of steps to make the logging module available to the `${jetty.base}` configuration. .. The `--module=logging` command is added to the `${jetty.base}/start.ini` configuration. From 136ae624ef3fb4bae1f2649873408b65662d397b Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Wed, 15 Mar 2017 18:11:18 +1100 Subject: [PATCH 2/9] Issue #1399 --- .../test/java/org/eclipse/jetty/server/ssl/SlowClientsTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SlowClientsTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SlowClientsTest.java index 27ad7fc965f..baec8f9c622 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SlowClientsTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SlowClientsTest.java @@ -44,8 +44,10 @@ import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.thread.QueuedThreadPool; +import org.junit.Ignore; import org.junit.Test; +@Ignore public class SlowClientsTest { private Logger logger = Log.getLogger(getClass()); From 706042e131d502a3cf2150d4678949006064f698 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Wed, 15 Mar 2017 15:35:18 -0700 Subject: [PATCH 3/9] Issue #1015 - excluding files not intended from distribution --- .../src/main/assembly/jetty-assembly.xml | 30 +++++++++++++++++++ .../src/main/assembly/jetty-src.xml | 30 +++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/jetty-distribution/src/main/assembly/jetty-assembly.xml b/jetty-distribution/src/main/assembly/jetty-assembly.xml index c0198eb679b..7a3fe1c4da0 100644 --- a/jetty-distribution/src/main/assembly/jetty-assembly.xml +++ b/jetty-distribution/src/main/assembly/jetty-assembly.xml @@ -14,6 +14,36 @@ **/META-INF/** *-config.jar + + **/.DS_Store + **/Thumbs.db + **/desktop.ini + + **/*~ + **/*.bak + **/*.backup + **/*.old + **/*.swp + **/*.debug + **/*.dump + **/*.log + **/~* + + **/*.orig + **/*.diff + **/*.patch + **/.gitignore + + **/*.iml + **/*.ipr + **/*.iws + **/*.idea + **/.classpath + **/.project + **/.settings + + **/*.versionsBackup + **/*.releaseBackup diff --git a/jetty-distribution/src/main/assembly/jetty-src.xml b/jetty-distribution/src/main/assembly/jetty-src.xml index f908b1e6e67..37657e368a0 100644 --- a/jetty-distribution/src/main/assembly/jetty-src.xml +++ b/jetty-distribution/src/main/assembly/jetty-src.xml @@ -12,6 +12,36 @@ **/target/** + + **/.DS_Store + **/Thumbs.db + **/desktop.ini + + **/*~ + **/*.bak + **/*.backup + **/*.old + **/*.swp + **/*.debug + **/*.dump + **/*.log + **/~* + + **/*.orig + **/*.diff + **/*.patch + **/.gitignore + + **/*.iml + **/*.ipr + **/*.iws + **/*.idea + **/.classpath + **/.project + **/.settings + + **/*.versionsBackup + **/*.releaseBackup From ff3db3653e737c6b6456674111ee0dbf8b1cec7c Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Wed, 15 Mar 2017 16:56:22 -0700 Subject: [PATCH 4/9] Issue #1396 - correcting Cookie name verification step --- .../org/eclipse/jetty/server/Response.java | 51 ++++++++++++++++- .../eclipse/jetty/server/ResponseTest.java | 55 +++++++++++++++---- 2 files changed, 94 insertions(+), 12 deletions(-) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java index 819ed2d1fc8..48da17dfa3f 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java @@ -259,8 +259,7 @@ public class Response implements HttpServletResponse // Name is checked for legality by servlet spec, but can also be passed directly so check again for quoting // Per RFC6265, Cookie.name follows RFC2616 Section 2.2 token rules - if(isQuoteNeededForCookie(name)) - throw new IllegalArgumentException("Cookie name not RFC6265 compliant"); + assertRFC2616Token("RFC6265 Cookie name", name); // Ensure that Per RFC6265, Cookie.value follows syntax rules assertRFC6265CookieValue(value); @@ -364,6 +363,54 @@ public class Response implements HttpServletResponse } } + /** + * Per RFC2616: Section 2.2, a token follows these syntax rules + *
+     *  token          = 1*<any CHAR except CTLs or separators>
+     *  CHAR           = <any US-ASCII character (octets 0 - 127)>
+     *  CTL            = <any US-ASCII control character
+     *                   (octets 0 - 31) and DEL (127)>
+     *  separators     = "(" | ")" | "<" | ">" | "@"
+     *                 | "," | ";" | ":" | "\" | <">
+     *                 | "/" | "[" | "]" | "?" | "="
+     *                 | "{" | "}" | SP | HT
+     * 
+ * @param value the value to test + * @throws IllegalArgumentException if the value is invalid per spec + */ + public static void assertRFC2616Token(String scope, String value) + { + if (value == null) + { + return; + } + + int valueLen = value.length(); + if (valueLen == 0) + { + return; + } + + for (int i = 0; i < valueLen; i++) + { + char c = value.charAt(i); + + // 0x00 - 0x1F are low order control characters + // 0x7F is the DEL control character + if ((c <= 0x1F) || (c == 0x7F)) + throw new IllegalArgumentException(scope + ": Control characters not allowed in RFC2616 token"); + if (c == '(' || c == ')' || c == '<' || c == '>' || c == '@' + || c == ',' || c == ';' || c == ':' || c == '\\' || c == '"' + || c == '/' || c == '[' || c == ']' || c == '?' || c == '=' + || c == '{' || c == '}' || c == ' ') + { + throw new IllegalArgumentException(scope + ": RFC2616 token may not contain separator character: [" + c + "]"); + } + if (c >= 0x80) + throw new IllegalArgumentException(scope + ": RFC2616 token characters restricted to US-ASCII range: 0x" + Integer.toHexString(c)); + } + } + /** * Format a set cookie value * diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java index 06e419af23e..001bfbfe087 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java @@ -18,6 +18,7 @@ package org.eclipse.jetty.server; +import static org.hamcrest.CoreMatchers.allOf; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; @@ -78,6 +79,7 @@ import org.eclipse.jetty.server.session.SessionHandler; import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.util.thread.Scheduler; import org.eclipse.jetty.util.thread.TimerScheduler; +import org.hamcrest.Matcher; import org.hamcrest.Matchers; import org.junit.After; import org.junit.Assert; @@ -1185,15 +1187,31 @@ public class ResponseTest assertEquals("everything=value;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Max-Age=0;Secure;HttpOnly",e.nextElement()); assertFalse(e.hasMoreElements()); - fields.clear(); - - try + String badNameExamples[] = { + "\"name\"", + "name\t", + "na me", + "name\u0082", + "na\tme", + "na;me", + "{name}", + "[name]", + "\"" + }; + + for (String badNameExample : badNameExamples) { - response.addSetRFC6265Cookie("ev erything","va lue","do main","pa th",1,true,true); - } - catch(IllegalArgumentException ex) - { - assertThat(ex.getMessage(),Matchers.containsString("RFC6265")); + fields.clear(); + try + { + response.addSetRFC6265Cookie(badNameExample, "value", null, "/", 1, true, true); + } + catch (IllegalArgumentException ex) + { + // System.err.printf("%s: %s%n", ex.getClass().getSimpleName(), ex.getMessage()); + assertThat("Testing bad name: [" + badNameExample + "]", ex.getMessage(), + allOf(containsString("RFC6265"), containsString("RFC2616"))); + } } String badValueExamples[] = { @@ -1219,11 +1237,27 @@ public class ResponseTest } catch (IllegalArgumentException ex) { + // System.err.printf("%s: %s%n", ex.getClass().getSimpleName(), ex.getMessage()); assertThat("Testing bad value [" + badValueExample + "]", ex.getMessage(), Matchers.containsString("RFC6265")); } } + + String goodNameExamples[] = { + "name", + "n.a.m.e", + "na-me", + "+name", + "na*me", + "na$me", + "#name" + }; - fields.clear(); + for (String goodNameExample : goodNameExamples) + { + fields.clear(); + response.addSetRFC6265Cookie(goodNameExample, "value", null, "/", 1, true, true); + // should not throw an exception + } String goodValueExamples[] = { "value", @@ -1239,6 +1273,7 @@ public class ResponseTest { fields.clear(); response.addSetRFC6265Cookie("name", goodValueExample, null, "/", 1, true, true); + // should not throw an exception } fields.clear(); @@ -1256,7 +1291,7 @@ public class ResponseTest response.addSetRFC6265Cookie("foo","bob","domain",null,-1,false,false); assertThat(fields.get("Set-Cookie"), Matchers.startsWith("name=value")); } - + private Response getResponse() { _channel.recycle(); From 5bc7882190fe56a675aa1796440389f4509b4b2d Mon Sep 17 00:00:00 2001 From: Jan Bartel Date: Thu, 16 Mar 2017 14:27:48 +1100 Subject: [PATCH 5/9] Issue #1398 --- .../session/GCloudSessionDataStore.java | 32 +++++++++++++++++++ .../nosql/mongodb/MongoSessionDataStore.java | 21 +++++++++--- .../server/session/FileSessionDataStore.java | 1 + 3 files changed, 50 insertions(+), 4 deletions(-) diff --git a/jetty-gcloud/jetty-gcloud-session-manager/src/main/java/org/eclipse/jetty/gcloud/session/GCloudSessionDataStore.java b/jetty-gcloud/jetty-gcloud-session-manager/src/main/java/org/eclipse/jetty/gcloud/session/GCloudSessionDataStore.java index 7e6179b52ea..98bfe17dddf 100644 --- a/jetty-gcloud/jetty-gcloud-session-manager/src/main/java/org/eclipse/jetty/gcloud/session/GCloudSessionDataStore.java +++ b/jetty-gcloud/jetty-gcloud-session-manager/src/main/java/org/eclipse/jetty/gcloud/session/GCloudSessionDataStore.java @@ -98,6 +98,7 @@ public class GCloudSessionDataStore extends AbstractSessionDataStore public static final String EXPIRY = "expiry"; public static final String MAXINACTIVE = "maxInactive"; public static final String ATTRIBUTES = "attributes"; + public static final String LASTSAVED = "lastSaved"; public static final String KIND = "GCloudSession"; protected String _kind = KIND; @@ -107,6 +108,7 @@ public class GCloudSessionDataStore extends AbstractSessionDataStore protected String _accessed = ACCESSED; protected String _lastAccessed = LASTACCESSED; protected String _lastNode = LASTNODE; + protected String _lastSaved = LASTSAVED; protected String _createTime = CREATETIME; protected String _cookieSetTime = COOKIESETTIME; protected String _expiry = EXPIRY; @@ -302,6 +304,23 @@ public class GCloudSessionDataStore extends AbstractSessionDataStore _attributes = attributes; } + /** + * @return the lastSaved + */ + public String getLastSaved() + { + return _lastSaved; + } + + /** + * @param lastSaved the lastSaved to set + */ + public void setLastSaved(String lastSaved) + { + checkNotNull(lastSaved); + _lastSaved = lastSaved; + } + /** * @see java.lang.Object#toString() */ @@ -868,6 +887,7 @@ public class GCloudSessionDataStore extends AbstractSessionDataStore .set(_model.getLastNode(),session.getLastNode()) .set(_model.getExpiry(), session.getExpiry()) .set(_model.getMaxInactive(), session.getMaxInactiveMs()) + .set(_model.getLastSaved(), session.getLastSaved()) .set(_model.getAttributes(), BlobValue.newBuilder(Blob.copyFrom(baos.toByteArray())).setExcludeFromIndexes(true).build()).build(); @@ -902,6 +922,17 @@ public class GCloudSessionDataStore extends AbstractSessionDataStore long createTime = entity.getLong(_model.getCreateTime()); long cookieSet = entity.getLong(_model.getCookieSetTime()); String lastNode = entity.getString(_model.getLastNode()); + + long lastSaved = 0; + //for compatibility with previously saved sessions, lastSaved may not be present + try + { + lastSaved = entity.getLong(_model.getLastSaved()); + } + catch (DatastoreException e) + { + LOG.ignore(e); + } long expiry = entity.getLong(_model.getExpiry()); long maxInactive = entity.getLong(_model.getMaxInactive()); Blob blob = (Blob) entity.getBlob(_model.getAttributes()); @@ -912,6 +943,7 @@ public class GCloudSessionDataStore extends AbstractSessionDataStore session.setVhost(vhost); session.setCookieSet(cookieSet); session.setLastNode(lastNode); + session.setLastSaved(lastSaved); session.setExpiry(expiry); try (ClassLoadingObjectInputStream ois = new ClassLoadingObjectInputStream(blob.asInputStream())) { diff --git a/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/mongodb/MongoSessionDataStore.java b/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/mongodb/MongoSessionDataStore.java index 7e6f8725447..9ed9e279170 100644 --- a/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/mongodb/MongoSessionDataStore.java +++ b/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/mongodb/MongoSessionDataStore.java @@ -117,6 +117,12 @@ public class MongoSessionDataStore extends NoSqlSessionDataStore */ public final static String __VERSION = __METADATA + ".version"; + + public final static String __LASTSAVED = __METADATA + ".lastSaved"; + + + public final static String __LASTNODE = __METADATA + ".lastNode"; + /** * Last access time of session */ @@ -202,14 +208,15 @@ public class MongoSessionDataStore extends NoSqlSessionDataStore if (valid == null || !valid) return; - Object version = getNestedValue(sessionDocument, getContextSubfield(__VERSION)); + Long lastSaved = (Long)getNestedValue(sessionDocument, getContextSubfield(__LASTSAVED)); + String lastNode = (String)getNestedValue(sessionDocument, getContextSubfield(__LASTNODE)); Long created = (Long)sessionDocument.get(__CREATED); Long accessed = (Long)sessionDocument.get(__ACCESSED); Long maxInactive = (Long)sessionDocument.get(__MAX_IDLE); - Long expiry = (Long)sessionDocument.get(__EXPIRY); - + Long expiry = (Long)sessionDocument.get(__EXPIRY); + NoSqlSessionData data = null; // get the session for the context @@ -228,6 +235,8 @@ public class MongoSessionDataStore extends NoSqlSessionDataStore data.setExpiry(expiry); data.setContextPath(_context.getCanonicalContextPath()); data.setVhost(_context.getVhost()); + data.setLastSaved(lastSaved); + data.setLastNode(lastNode); HashMap attributes = new HashMap<>(); for (String name : sessionSubDocumentForContext.keySet()) @@ -427,7 +436,7 @@ public class MongoSessionDataStore extends NoSqlSessionDataStore */ @Override public void doStore(String id, SessionData data, long lastSaveTime) throws Exception - { + { NoSqlSessionData nsqd = (NoSqlSessionData)data; // Form query for upsert @@ -449,12 +458,16 @@ public class MongoSessionDataStore extends NoSqlSessionDataStore sets.put(__CREATED,nsqd.getCreated()); sets.put(__VALID,true); sets.put(getContextSubfield(__VERSION),version); + sets.put(getContextSubfield(__LASTSAVED), data.getLastSaved()); + sets.put(getContextSubfield(__LASTNODE), data.getLastNode()); sets.put(__MAX_IDLE, nsqd.getMaxInactiveMs()); sets.put(__EXPIRY, nsqd.getExpiry()); nsqd.setVersion(version); } else { + sets.put(getContextSubfield(__LASTSAVED), data.getLastSaved()); + sets.put(getContextSubfield(__LASTNODE), data.getLastNode()); version = new Long(((Number)version).longValue() + 1); nsqd.setVersion(version); update.put("$inc",_version_1); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/FileSessionDataStore.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/FileSessionDataStore.java index 74c2f2bff5f..4642894dcf2 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/FileSessionDataStore.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/FileSessionDataStore.java @@ -196,6 +196,7 @@ public class FileSessionDataStore extends AbstractSessionDataStore try (FileInputStream in = new FileInputStream(file)) { SessionData data = load(in); + data.setLastSaved(file.lastModified()); //delete restored file file.delete(); reference.set(data); From ed9f7ddd4cbaa70387005246e6e3c463e68608fc Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Thu, 16 Mar 2017 11:25:21 -0700 Subject: [PATCH 6/9] Issue #1402 - Moving RFC asserts to jetty-http Syntax class --- .../java/org/eclipse/jetty/http/Syntax.java | 142 ++++++++++++++++++ .../org/eclipse/jetty/http/SyntaxTest.java | 134 +++++++++++++++++ .../org/eclipse/jetty/server/Response.java | 111 +------------- .../eclipse/jetty/server/ResponseTest.java | 11 +- 4 files changed, 284 insertions(+), 114 deletions(-) create mode 100644 jetty-http/src/main/java/org/eclipse/jetty/http/Syntax.java create mode 100644 jetty-http/src/test/java/org/eclipse/jetty/http/SyntaxTest.java diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/Syntax.java b/jetty-http/src/main/java/org/eclipse/jetty/http/Syntax.java new file mode 100644 index 00000000000..e85d745ceee --- /dev/null +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/Syntax.java @@ -0,0 +1,142 @@ +// +// ======================================================================== +// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + +package org.eclipse.jetty.http; + +import java.util.Objects; + +/** + * Collection of Syntax validation methods. + *

+ * Use in a similar way as you would {@link java.util.Objects#requireNonNull(Object)} + *

+ */ +public final class Syntax +{ + + /** + * Per RFC2616: Section 2.2, a token follows these syntax rules + *
+     *  token          = 1*<any CHAR except CTLs or separators>
+     *  CHAR           = <any US-ASCII character (octets 0 - 127)>
+     *  CTL            = <any US-ASCII control character
+     *                   (octets 0 - 31) and DEL (127)>
+     *  separators     = "(" | ")" | "<" | ">" | "@"
+     *                 | "," | ";" | ":" | "\" | <">
+     *                 | "/" | "[" | "]" | "?" | "="
+     *                 | "{" | "}" | SP | HT
+     * 
+ * + * @param value the value to test + * @param msg the message to be prefixed if an {@link IllegalArgumentException} is thrown. + * @throws IllegalArgumentException if the value is invalid per spec + */ + public static void requireValidRFC2616Token(String value, String msg) + { + Objects.requireNonNull(msg, "msg cannot be null"); + + if (value == null) + { + return; + } + + int valueLen = value.length(); + if (valueLen == 0) + { + return; + } + + for (int i = 0; i < valueLen; i++) + { + char c = value.charAt(i); + + // 0x00 - 0x1F are low order control characters + // 0x7F is the DEL control character + if ((c <= 0x1F) || (c == 0x7F)) + throw new IllegalArgumentException(msg + ": Control characters not allowed in RFC2616 token"); + if (c == '(' || c == ')' || c == '<' || c == '>' || c == '@' + || c == ',' || c == ';' || c == ':' || c == '\\' || c == '"' + || c == '/' || c == '[' || c == ']' || c == '?' || c == '=' + || c == '{' || c == '}' || c == ' ') + { + throw new IllegalArgumentException(msg + ": RFC2616 token may not contain separator character: [" + c + "]"); + } + if (c >= 0x80) + throw new IllegalArgumentException(msg + ": RFC2616 token characters restricted to US-ASCII range: 0x" + Integer.toHexString(c)); + } + } + + /** + * Per RFC6265, Cookie.value follows these syntax rules + *
+     *  cookie-value      = *cookie-octet / ( DQUOTE *cookie-octet DQUOTE )
+     *  cookie-octet      = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E
+     *                      ; US-ASCII characters excluding CTLs,
+     *                      ; whitespace DQUOTE, comma, semicolon,
+     *                      ; and backslash
+     * 
+ * + * @param value the value to test + * @throws IllegalArgumentException if the value is invalid per spec + */ + public static void requireValidRFC6265CookieValue(String value) + { + if (value == null) + { + return; + } + + int valueLen = value.length(); + if (valueLen == 0) + { + return; + } + + int i = 0; + if (value.charAt(0) == '"') + { + // Has starting DQUOTE + if (valueLen <= 1 || (value.charAt(valueLen - 1) != '"')) + { + throw new IllegalArgumentException("RFC6265 Cookie value must have balanced DQUOTES (if used)"); + } + + // adjust search range to exclude DQUOTES + i++; + valueLen--; + } + for (; i < valueLen; i++) + { + char c = value.charAt(i); + + // 0x00 - 0x1F are low order control characters + // 0x7F is the DEL control character + if ((c <= 0x1F) || (c == 0x7F)) + throw new IllegalArgumentException("Control characters not allowed in RFC6265 Cookie value"); + if ((c == ' ' /* 0x20 */) || + (c == '"' /* 0x2C */) || + (c == ';' /* 0x3B */) || + (c == '\\' /* 0x5C */)) + { + throw new IllegalArgumentException("RFC6265 Cookie value may not contain character: [" + c + "]"); + } + if (c >= 0x80) + throw new IllegalArgumentException("RFC6265 Cookie value characters restricted to US-ASCII range: 0x" + Integer.toHexString(c)); + } + } +} diff --git a/jetty-http/src/test/java/org/eclipse/jetty/http/SyntaxTest.java b/jetty-http/src/test/java/org/eclipse/jetty/http/SyntaxTest.java new file mode 100644 index 00000000000..eece45c1060 --- /dev/null +++ b/jetty-http/src/test/java/org/eclipse/jetty/http/SyntaxTest.java @@ -0,0 +1,134 @@ +// +// ======================================================================== +// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + +package org.eclipse.jetty.http; + +import static org.hamcrest.CoreMatchers.allOf; +import static org.hamcrest.CoreMatchers.containsString; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; + +import org.junit.Test; + +public class SyntaxTest +{ + @Test + public void testRequireValidRFC2616Token_Good() + { + String tokens[] = { + "name", + "", + null, + "n.a.m.e", + "na-me", + "+name", + "na*me", + "na$me", + "#name" + }; + + for (String token : tokens) + { + Syntax.requireValidRFC2616Token(token, "Test Based"); + // No exception should occur here + } + } + + @Test + public void testRequireValidRFC2616Token_Bad() + { + String tokens[] = { + "\"name\"", + "name\t", + "na me", + "name\u0082", + "na\tme", + "na;me", + "{name}", + "[name]", + "\"" + }; + + for (String token : tokens) + { + try + { + Syntax.requireValidRFC2616Token(token, "Test Based"); + fail("RFC2616 Token [" + token + "] Should have thrown " + IllegalArgumentException.class.getName()); + } + catch (IllegalArgumentException e) + { + assertThat("Testing Bad RFC2616 Token [" + token + "]", e.getMessage(), + allOf(containsString("Test Based"), + containsString("RFC2616"))); + } + } + } + + @Test + public void testRequireValidRFC6265CookieValue_Good() + { + String values[] = { + "value", + "", + null, + "val=ue", + "val-ue", + "\"value\"", + "val/ue", + "v.a.l.u.e" + }; + + for (String value : values) + { + Syntax.requireValidRFC6265CookieValue(value); + // No exception should occur here + } + } + + @Test + public void testRequireValidRFC6265CookieValue_Bad() + { + String values[] = { + "va\tlue", + "\t", + "value\u0000", + "val\u0082ue", + "va lue", + "va;lue", + "\"value", + "value\"", + "val\\ue", + "val\"ue", + "\"" + }; + + for (String value : values) + { + try + { + Syntax.requireValidRFC6265CookieValue(value); + fail("RFC6265 Cookie Value [" + value + "] Should have thrown " + IllegalArgumentException.class.getName()); + } + catch (IllegalArgumentException e) + { + assertThat("Testing Bad RFC6265 Cookie Value [" + value + "]", e.getMessage(), containsString("RFC6265")); + } + } + } +} diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java index 48da17dfa3f..ee2d39f8c5b 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java @@ -50,6 +50,7 @@ import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; import org.eclipse.jetty.http.MimeTypes; import org.eclipse.jetty.http.PreEncodedHttpField; +import org.eclipse.jetty.http.Syntax; import org.eclipse.jetty.io.RuntimeIOException; import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.handler.ErrorHandler; @@ -259,9 +260,9 @@ public class Response implements HttpServletResponse // Name is checked for legality by servlet spec, but can also be passed directly so check again for quoting // Per RFC6265, Cookie.name follows RFC2616 Section 2.2 token rules - assertRFC2616Token("RFC6265 Cookie name", name); + Syntax.requireValidRFC2616Token(name, "RFC6265 Cookie name"); // Ensure that Per RFC6265, Cookie.value follows syntax rules - assertRFC6265CookieValue(value); + Syntax.requireValidRFC6265CookieValue(value); // Format value and params StringBuilder buf = __cookieBuilder.get(); @@ -305,112 +306,6 @@ public class Response implements HttpServletResponse } - /** - * Per RFC6265, Cookie.value follows these syntax rules - *
-     *  cookie-value      = *cookie-octet / ( DQUOTE *cookie-octet DQUOTE )
-     *  cookie-octet      = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E
-     *                      ; US-ASCII characters excluding CTLs,
-     *                      ; whitespace DQUOTE, comma, semicolon,
-     *                      ; and backslash
-     * 
- * @param value the value to test - * @throws IllegalArgumentException if the value is invalid per spec - */ - public static void assertRFC6265CookieValue(String value) - { - if (value == null) - { - return; - } - - int valueLen = value.length(); - if (valueLen == 0) - { - return; - } - - int i = 0; - if (value.charAt(0) == '"') - { - // Has starting DQUOTE - if (valueLen <= 1 || (value.charAt(valueLen - 1) != '"')) - { - throw new IllegalArgumentException("RFC6265 Cookie value must have balanced DQUOTES (if used)"); - } - - // adjust search range to exclude DQUOTES - i++; - valueLen--; - } - for(; i= 0x80) - throw new IllegalArgumentException("RFC6265 Cookie value characters restricted to US-ASCII range: 0x" + Integer.toHexString(c)); - } - } - - /** - * Per RFC2616: Section 2.2, a token follows these syntax rules - *
-     *  token          = 1*<any CHAR except CTLs or separators>
-     *  CHAR           = <any US-ASCII character (octets 0 - 127)>
-     *  CTL            = <any US-ASCII control character
-     *                   (octets 0 - 31) and DEL (127)>
-     *  separators     = "(" | ")" | "<" | ">" | "@"
-     *                 | "," | ";" | ":" | "\" | <">
-     *                 | "/" | "[" | "]" | "?" | "="
-     *                 | "{" | "}" | SP | HT
-     * 
- * @param value the value to test - * @throws IllegalArgumentException if the value is invalid per spec - */ - public static void assertRFC2616Token(String scope, String value) - { - if (value == null) - { - return; - } - - int valueLen = value.length(); - if (valueLen == 0) - { - return; - } - - for (int i = 0; i < valueLen; i++) - { - char c = value.charAt(i); - - // 0x00 - 0x1F are low order control characters - // 0x7F is the DEL control character - if ((c <= 0x1F) || (c == 0x7F)) - throw new IllegalArgumentException(scope + ": Control characters not allowed in RFC2616 token"); - if (c == '(' || c == ')' || c == '<' || c == '>' || c == '@' - || c == ',' || c == ';' || c == ':' || c == '\\' || c == '"' - || c == '/' || c == '[' || c == ']' || c == '?' || c == '=' - || c == '{' || c == '}' || c == ' ') - { - throw new IllegalArgumentException(scope + ": RFC2616 token may not contain separator character: [" + c + "]"); - } - if (c >= 0x80) - throw new IllegalArgumentException(scope + ": RFC2616 token characters restricted to US-ASCII range: 0x" + Integer.toHexString(c)); - } - } - /** * Format a set cookie value * diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java index 001bfbfe087..564528274be 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java @@ -18,6 +18,7 @@ package org.eclipse.jetty.server; +import static java.nio.charset.StandardCharsets.UTF_8; import static org.hamcrest.CoreMatchers.allOf; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.is; @@ -30,19 +31,18 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import static java.nio.charset.StandardCharsets.UTF_8; import java.io.IOException; import java.io.InputStreamReader; import java.io.LineNumberReader; import java.io.PrintWriter; +import java.net.HttpCookie; import java.net.Inet4Address; import java.net.InetAddress; import java.net.InetSocketAddress; -import java.net.HttpCookie; import java.net.Socket; -import java.net.UnknownHostException; import java.net.URLEncoder; +import java.net.UnknownHostException; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collections; @@ -57,7 +57,6 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; -import org.eclipse.jetty.http.HttpCompliance; import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpHeader; @@ -70,8 +69,8 @@ import org.eclipse.jetty.io.RuntimeIOException; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.handler.ErrorHandler; -import org.eclipse.jetty.server.session.DefaultSessionIdManager; import org.eclipse.jetty.server.session.DefaultSessionCache; +import org.eclipse.jetty.server.session.DefaultSessionIdManager; import org.eclipse.jetty.server.session.NullSessionDataStore; import org.eclipse.jetty.server.session.Session; import org.eclipse.jetty.server.session.SessionData; @@ -79,7 +78,6 @@ import org.eclipse.jetty.server.session.SessionHandler; import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.util.thread.Scheduler; import org.eclipse.jetty.util.thread.TimerScheduler; -import org.hamcrest.Matcher; import org.hamcrest.Matchers; import org.junit.After; import org.junit.Assert; @@ -180,6 +178,7 @@ public class ResponseTest _server.join(); } + @SuppressWarnings("InjectedReferences") // to allow for invalid encoding strings in this testcase @Test public void testContentType() throws Exception { From f753b5468c59734a146f31e5db2bb27b5c604221 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Thu, 16 Mar 2017 11:26:18 -0700 Subject: [PATCH 7/9] Issue #1405 - Cookie.name cannot be blank --- .../main/java/org/eclipse/jetty/server/Response.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java index ee2d39f8c5b..4266a5c61d2 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java @@ -173,6 +173,11 @@ public class Response implements HttpServletResponse public void addCookie(HttpCookie cookie) { + if (StringUtil.isBlank(cookie.getName())) + { + throw new IllegalArgumentException("Cookie.name cannot be blank/null"); + } + if (getHttpChannel().getHttpConfiguration().isCookieCompliance(CookieCompliance.RFC2965)) addSetRFC2965Cookie( cookie.getName(), @@ -212,6 +217,11 @@ public class Response implements HttpServletResponse comment = null; } } + + if (StringUtil.isBlank(cookie.getName())) + { + throw new IllegalArgumentException("Cookie.name cannot be blank/null"); + } if (getHttpChannel().getHttpConfiguration().isCookieCompliance(CookieCompliance.RFC2965)) addSetRFC2965Cookie(cookie.getName(), From ccf72d6752ca6b3b6f1d7ad28ed0a040592a9597 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Thu, 16 Mar 2017 11:28:43 -0700 Subject: [PATCH 8/9] Issue #1403 - moving CookieCompliance to jetty-http module --- .../main/java/org/eclipse/jetty/http}/CookieCompliance.java | 4 ++-- jetty-server/src/main/config/etc/jetty.xml | 2 +- .../main/java/org/eclipse/jetty/server/HttpConfiguration.java | 1 + .../src/main/java/org/eclipse/jetty/server/Response.java | 1 + .../src/test/java/org/eclipse/jetty/server/ResponseTest.java | 1 + 5 files changed, 6 insertions(+), 3 deletions(-) rename {jetty-server/src/main/java/org/eclipse/jetty/server => jetty-http/src/main/java/org/eclipse/jetty/http}/CookieCompliance.java (91%) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/CookieCompliance.java b/jetty-http/src/main/java/org/eclipse/jetty/http/CookieCompliance.java similarity index 91% rename from jetty-server/src/main/java/org/eclipse/jetty/server/CookieCompliance.java rename to jetty-http/src/main/java/org/eclipse/jetty/http/CookieCompliance.java index de4e5410581..5e64dad1f79 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/CookieCompliance.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/CookieCompliance.java @@ -16,10 +16,10 @@ // ======================================================================== // -package org.eclipse.jetty.server; +package org.eclipse.jetty.http; /** * The compliance for Cookie handling. * */ -public enum CookieCompliance { RFC6265, RFC2965 } \ No newline at end of file +public enum CookieCompliance { RFC6265, RFC2965 } diff --git a/jetty-server/src/main/config/etc/jetty.xml b/jetty-server/src/main/config/etc/jetty.xml index 3ee6a989214..a7082741a24 100644 --- a/jetty-server/src/main/config/etc/jetty.xml +++ b/jetty-server/src/main/config/etc/jetty.xml @@ -90,7 +90,7 @@ - + diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConfiguration.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConfiguration.java index df9acc868b6..11e0fb77d78 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConfiguration.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConfiguration.java @@ -23,6 +23,7 @@ import java.util.List; import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; +import org.eclipse.jetty.http.CookieCompliance; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.util.Jetty; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java index 4266a5c61d2..0502955eb92 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java @@ -35,6 +35,7 @@ import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; +import org.eclipse.jetty.http.CookieCompliance; import org.eclipse.jetty.http.DateGenerator; import org.eclipse.jetty.http.HttpContent; import org.eclipse.jetty.http.HttpCookie; diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java index 564528274be..bad490a1653 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java @@ -57,6 +57,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; +import org.eclipse.jetty.http.CookieCompliance; import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpHeader; From 398e5b3462621d919f9dcd1fab4b9f764f6b1b3b Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Thu, 16 Mar 2017 11:52:48 -0700 Subject: [PATCH 9/9] Minor verbiage change in exception messages --- .../main/java/org/eclipse/jetty/http/Syntax.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/Syntax.java b/jetty-http/src/main/java/org/eclipse/jetty/http/Syntax.java index e85d745ceee..3a001eb8f7d 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/Syntax.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/Syntax.java @@ -68,16 +68,16 @@ public final class Syntax // 0x00 - 0x1F are low order control characters // 0x7F is the DEL control character if ((c <= 0x1F) || (c == 0x7F)) - throw new IllegalArgumentException(msg + ": Control characters not allowed in RFC2616 token"); + throw new IllegalArgumentException(msg + ": RFC2616 tokens may not contain control characters"); if (c == '(' || c == ')' || c == '<' || c == '>' || c == '@' || c == ',' || c == ';' || c == ':' || c == '\\' || c == '"' || c == '/' || c == '[' || c == ']' || c == '?' || c == '=' || c == '{' || c == '}' || c == ' ') { - throw new IllegalArgumentException(msg + ": RFC2616 token may not contain separator character: [" + c + "]"); + throw new IllegalArgumentException(msg + ": RFC2616 tokens may not contain separator character: [" + c + "]"); } if (c >= 0x80) - throw new IllegalArgumentException(msg + ": RFC2616 token characters restricted to US-ASCII range: 0x" + Integer.toHexString(c)); + throw new IllegalArgumentException(msg + ": RFC2616 tokens characters restricted to US-ASCII: 0x" + Integer.toHexString(c)); } } @@ -113,7 +113,7 @@ public final class Syntax // Has starting DQUOTE if (valueLen <= 1 || (value.charAt(valueLen - 1) != '"')) { - throw new IllegalArgumentException("RFC6265 Cookie value must have balanced DQUOTES (if used)"); + throw new IllegalArgumentException("RFC6265 Cookie values must have balanced DQUOTES (if used)"); } // adjust search range to exclude DQUOTES @@ -127,16 +127,16 @@ public final class Syntax // 0x00 - 0x1F are low order control characters // 0x7F is the DEL control character if ((c <= 0x1F) || (c == 0x7F)) - throw new IllegalArgumentException("Control characters not allowed in RFC6265 Cookie value"); + throw new IllegalArgumentException("RFC6265 Cookie values may not contain control characters"); if ((c == ' ' /* 0x20 */) || (c == '"' /* 0x2C */) || (c == ';' /* 0x3B */) || (c == '\\' /* 0x5C */)) { - throw new IllegalArgumentException("RFC6265 Cookie value may not contain character: [" + c + "]"); + throw new IllegalArgumentException("RFC6265 Cookie values may not contain character: [" + c + "]"); } if (c >= 0x80) - throw new IllegalArgumentException("RFC6265 Cookie value characters restricted to US-ASCII range: 0x" + Integer.toHexString(c)); + throw new IllegalArgumentException("RFC6265 Cookie values characters restricted to US-ASCII: 0x" + Integer.toHexString(c)); } } }