Merge remote-tracking branch 'origin/jetty-9.4.x' into jetty-9.4.x-ewyk
This commit is contained in:
commit
01349ac935
|
@ -14,6 +14,36 @@
|
|||
<excludes>
|
||||
<exclude>**/META-INF/**</exclude>
|
||||
<exclude>*-config.jar</exclude>
|
||||
<!-- common OS detritus -->
|
||||
<exclude>**/.DS_Store</exclude>
|
||||
<exclude>**/Thumbs.db</exclude>
|
||||
<exclude>**/desktop.ini</exclude>
|
||||
<!-- common temp files -->
|
||||
<exclude>**/*~</exclude>
|
||||
<exclude>**/*.bak</exclude>
|
||||
<exclude>**/*.backup</exclude>
|
||||
<exclude>**/*.old</exclude>
|
||||
<exclude>**/*.swp</exclude>
|
||||
<exclude>**/*.debug</exclude>
|
||||
<exclude>**/*.dump</exclude>
|
||||
<exclude>**/*.log</exclude>
|
||||
<exclude>**/~*</exclude>
|
||||
<!-- common git/scm files -->
|
||||
<exclude>**/*.orig</exclude>
|
||||
<exclude>**/*.diff</exclude>
|
||||
<exclude>**/*.patch</exclude>
|
||||
<exclude>**/.gitignore</exclude>
|
||||
<!-- various editor files -->
|
||||
<exclude>**/*.iml</exclude>
|
||||
<exclude>**/*.ipr</exclude>
|
||||
<exclude>**/*.iws</exclude>
|
||||
<exclude>**/*.idea</exclude>
|
||||
<exclude>**/.classpath</exclude>
|
||||
<exclude>**/.project</exclude>
|
||||
<exclude>**/.settings</exclude>
|
||||
<!-- maven dust -->
|
||||
<exclude>**/*.versionsBackup</exclude>
|
||||
<exclude>**/*.releaseBackup</exclude>
|
||||
</excludes>
|
||||
</fileSet>
|
||||
</fileSets>
|
||||
|
|
|
@ -12,6 +12,36 @@
|
|||
</includes>
|
||||
<excludes>
|
||||
<exclude>**/target/**</exclude>
|
||||
<!-- common OS detritus -->
|
||||
<exclude>**/.DS_Store</exclude>
|
||||
<exclude>**/Thumbs.db</exclude>
|
||||
<exclude>**/desktop.ini</exclude>
|
||||
<!-- common temp files -->
|
||||
<exclude>**/*~</exclude>
|
||||
<exclude>**/*.bak</exclude>
|
||||
<exclude>**/*.backup</exclude>
|
||||
<exclude>**/*.old</exclude>
|
||||
<exclude>**/*.swp</exclude>
|
||||
<exclude>**/*.debug</exclude>
|
||||
<exclude>**/*.dump</exclude>
|
||||
<exclude>**/*.log</exclude>
|
||||
<exclude>**/~*</exclude>
|
||||
<!-- common git/scm files -->
|
||||
<exclude>**/*.orig</exclude>
|
||||
<exclude>**/*.diff</exclude>
|
||||
<exclude>**/*.patch</exclude>
|
||||
<exclude>**/.gitignore</exclude>
|
||||
<!-- various editor files -->
|
||||
<exclude>**/*.iml</exclude>
|
||||
<exclude>**/*.ipr</exclude>
|
||||
<exclude>**/*.iws</exclude>
|
||||
<exclude>**/*.idea</exclude>
|
||||
<exclude>**/.classpath</exclude>
|
||||
<exclude>**/.project</exclude>
|
||||
<exclude>**/.settings</exclude>
|
||||
<!-- maven dust -->
|
||||
<exclude>**/*.versionsBackup</exclude>
|
||||
<exclude>**/*.releaseBackup</exclude>
|
||||
</excludes>
|
||||
</fileSet>
|
||||
</fileSets>
|
||||
|
|
|
@ -51,7 +51,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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -47,7 +47,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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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()))
|
||||
{
|
||||
|
|
|
@ -16,10 +16,10 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.server;
|
||||
package org.eclipse.jetty.http;
|
||||
|
||||
/**
|
||||
* The compliance for Cookie handling.
|
||||
*
|
||||
*/
|
||||
public enum CookieCompliance { RFC6265, RFC2965 }
|
||||
public enum CookieCompliance { RFC6265, RFC2965 }
|
|
@ -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.
|
||||
* <p>
|
||||
* Use in a similar way as you would {@link java.util.Objects#requireNonNull(Object)}
|
||||
* </p>
|
||||
*/
|
||||
public final class Syntax
|
||||
{
|
||||
|
||||
/**
|
||||
* Per RFC2616: Section 2.2, a token follows these syntax rules
|
||||
* <pre>
|
||||
* 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
|
||||
* </pre>
|
||||
*
|
||||
* @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 + ": 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 tokens may not contain separator character: [" + c + "]");
|
||||
}
|
||||
if (c >= 0x80)
|
||||
throw new IllegalArgumentException(msg + ": RFC2616 tokens characters restricted to US-ASCII: 0x" + Integer.toHexString(c));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Per RFC6265, Cookie.value follows these syntax rules
|
||||
* <pre>
|
||||
* 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
|
||||
* </pre>
|
||||
*
|
||||
* @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 values 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("RFC6265 Cookie values may not contain control characters");
|
||||
if ((c == ' ' /* 0x20 */) ||
|
||||
(c == '"' /* 0x2C */) ||
|
||||
(c == ';' /* 0x3B */) ||
|
||||
(c == '\\' /* 0x5C */))
|
||||
{
|
||||
throw new IllegalArgumentException("RFC6265 Cookie values may not contain character: [" + c + "]");
|
||||
}
|
||||
if (c >= 0x80)
|
||||
throw new IllegalArgumentException("RFC6265 Cookie values characters restricted to US-ASCII: 0x" + Integer.toHexString(c));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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<String, Object> 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);
|
||||
|
|
|
@ -90,7 +90,7 @@
|
|||
<Set name="maxErrorDispatches"><Property name="jetty.httpConfig.maxErrorDispatches" default="10"/></Set>
|
||||
<Set name="blockingTimeout"><Property name="jetty.httpConfig.blockingTimeout" default="-1"/></Set>
|
||||
<Set name="persistentConnectionsEnabled"><Property name="jetty.httpConfig.persistentConnectionsEnabled" default="true"/></Set>
|
||||
<Set name="cookieCompliance"><Call class="org.eclipse.jetty.server.CookieCompliance" name="valueOf"><Arg><Property name="jetty.httpConfig.cookieCompliance" default="RFC6265"/></Arg></Call></Set>
|
||||
<Set name="cookieCompliance"><Call class="org.eclipse.jetty.http.CookieCompliance" name="valueOf"><Arg><Property name="jetty.httpConfig.cookieCompliance" default="RFC6265"/></Arg></Call></Set>
|
||||
</New>
|
||||
|
||||
<!-- =========================================================== -->
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
@ -50,6 +51,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;
|
||||
|
@ -172,6 +174,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(),
|
||||
|
@ -211,6 +218,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(),
|
||||
|
@ -259,10 +271,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
|
||||
if(isQuoteNeededForCookie(name))
|
||||
throw new IllegalArgumentException("Cookie name not RFC6265 compliant");
|
||||
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();
|
||||
|
@ -306,64 +317,6 @@ public class Response implements HttpServletResponse
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Per RFC6265, Cookie.value follows these syntax rules
|
||||
* <pre>
|
||||
* 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
|
||||
* </pre>
|
||||
* @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<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));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a set cookie value
|
||||
*
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
|
||||
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;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
|
@ -29,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;
|
||||
|
@ -56,7 +57,7 @@ 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.CookieCompliance;
|
||||
import org.eclipse.jetty.http.HttpField;
|
||||
import org.eclipse.jetty.http.HttpFields;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
|
@ -69,8 +70,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;
|
||||
|
@ -178,6 +179,7 @@ public class ResponseTest
|
|||
_server.join();
|
||||
}
|
||||
|
||||
@SuppressWarnings("InjectedReferences") // to allow for invalid encoding strings in this testcase
|
||||
@Test
|
||||
public void testContentType() throws Exception
|
||||
{
|
||||
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue