Merge branch 'master' into jetty-9.3-ewyk

This commit is contained in:
Greg Wilkins 2014-12-31 16:29:40 +01:00
commit 20fc880c3e
9 changed files with 135 additions and 24 deletions

View File

@ -284,7 +284,7 @@ CYGWIN*) JETTY_STATE="`cygpath -w $JETTY_STATE`";;
esac esac
JETTY_ARGS=("$JETTY_ARGS" "jetty.state=$JETTY_STATE") JETTY_ARGS=(${JETTY_ARGS[*]} "jetty.state=$JETTY_STATE")
################################################## ##################################################
# Get the list of config.xml files from jetty.conf # Get the list of config.xml files from jetty.conf
@ -306,14 +306,14 @@ then
do do
if [ -r "$XMLFILE" ] && [ -f "$XMLFILE" ] if [ -r "$XMLFILE" ] && [ -f "$XMLFILE" ]
then then
JETTY_ARGS=("$JETTY_ARGS" "$XMLFILE") JETTY_ARGS=(${JETTY_ARGS[*]} "$XMLFILE")
else else
echo "** WARNING: Cannot read '$XMLFILE' specified in '$JETTY_CONF'" echo "** WARNING: Cannot read '$XMLFILE' specified in '$JETTY_CONF'"
fi fi
done done
else else
# assume it's a command line parameter (let start.jar deal with its validity) # assume it's a command line parameter (let start.jar deal with its validity)
JETTY_ARGS=("$JETTY_ARGS" "$CONF") JETTY_ARGS=(${JETTY_ARGS[*]} "$CONF")
fi fi
done < "$JETTY_CONF" done < "$JETTY_CONF"
fi fi
@ -350,7 +350,7 @@ then
CYGWIN*) JETTY_LOGS="`cygpath -w $JETTY_LOGS`";; CYGWIN*) JETTY_LOGS="`cygpath -w $JETTY_LOGS`";;
esac esac
JAVA_OPTIONS=("$JAVA_OPTIONS" "-Djetty.logs=$JETTY_LOGS") JAVA_OPTIONS=(${JAVA_OPTIONS[*]} "-Djetty.logs=$JETTY_LOGS")
fi fi
##################################################### #####################################################
@ -374,7 +374,7 @@ TMPDIR="`cygpath -w $TMPDIR`"
;; ;;
esac esac
JAVA_OPTIONS=("$JAVA_OPTIONS" "-Djetty.home=$JETTY_HOME" "-Djetty.base=$JETTY_BASE" "-Djava.io.tmpdir=$TMPDIR") JAVA_OPTIONS=(${JAVA_OPTIONS[*]} "-Djetty.home=$JETTY_HOME" "-Djetty.base=$JETTY_BASE" "-Djava.io.tmpdir=$TMPDIR")
##################################################### #####################################################
# This is how the Jetty server will be started # This is how the Jetty server will be started

View File

@ -271,7 +271,7 @@ public class MongoSessionManager extends NoSqlSessionManager
if (currentMaxIdle != null && getMaxInactiveInterval() > 0 && getMaxInactiveInterval() < currentMaxIdle) if (currentMaxIdle != null && getMaxInactiveInterval() > 0 && getMaxInactiveInterval() < currentMaxIdle)
sets.put(__MAX_IDLE, getMaxInactiveInterval()); sets.put(__MAX_IDLE, getMaxInactiveInterval());
if (currentExpiry != null && expiry > 0 && expiry != currentExpiry) if (currentExpiry != null && expiry > 0 && expiry != currentExpiry)
sets.put(__EXPIRY, currentExpiry); sets.put(__EXPIRY, expiry);
} }
} }

View File

@ -246,14 +246,14 @@ public class TestNamingEntries
{ {
ScopeA scope = new ScopeA(); ScopeA scope = new ScopeA();
InitialContext icontext = new InitialContext(); InitialContext icontext = new InitialContext();
Link link = new Link ("resourceA", "resourceB"); Link link = new Link ("linked-resourceA", "resourceB");
NamingEntry ne = NamingEntryUtil.lookupNamingEntry(null, "resourceA"); NamingEntry ne = NamingEntryUtil.lookupNamingEntry(null, "linked-resourceA");
assertNotNull(ne); assertNotNull(ne);
assertTrue(ne instanceof Link); assertTrue(ne instanceof Link);
assertEquals(icontext.lookup("resourceA"), "resourceB"); assertEquals(icontext.lookup("linked-resourceA"), "resourceB");
link = new Link (scope, "jdbc/resourceX", "jdbc/resourceY"); link = new Link (scope, "jdbc/linked-resourceX", "jdbc/linked-resourceY");
ne = NamingEntryUtil.lookupNamingEntry(scope, "jdbc/resourceX"); ne = NamingEntryUtil.lookupNamingEntry(scope, "jdbc/linked-resourceX");
assertNotNull(ne); assertNotNull(ne);
assertTrue(ne instanceof Link); assertTrue(ne instanceof Link);
} }

View File

@ -28,6 +28,12 @@ import org.eclipse.jetty.util.MultiPartInputStreamParser;
public class MultiPartCleanerListener implements ServletRequestListener public class MultiPartCleanerListener implements ServletRequestListener
{ {
public final static MultiPartCleanerListener INSTANCE = new MultiPartCleanerListener();
protected MultiPartCleanerListener()
{
}
@Override @Override
public void requestDestroyed(ServletRequestEvent sre) public void requestDestroyed(ServletRequestEvent sre)
{ {

View File

@ -495,10 +495,8 @@ public class Request implements HttpServletRequest
} }
catch (IOException | ServletException e) catch (IOException | ServletException e)
{ {
if (LOG.isDebugEnabled()) LOG.warn(e);
LOG.warn(e); throw new RuntimeException(e);
else
LOG.warn(e.toString());
} }
} }

View File

@ -276,6 +276,67 @@ public class RequestTest
// System.err.println(responses); // System.err.println(responses);
assertTrue(responses.startsWith("HTTP/1.1 200")); assertTrue(responses.startsWith("HTTP/1.1 200"));
} }
@Test
public void testBadMultiPart() throws Exception
{
//a bad multipart where one of the fields has no name
final File testTmpDir = File.createTempFile("badmptest", null);
if (testTmpDir.exists())
testTmpDir.delete();
testTmpDir.mkdir();
testTmpDir.deleteOnExit();
assertTrue(testTmpDir.list().length == 0);
ContextHandler contextHandler = new ContextHandler();
contextHandler.setContextPath("/foo");
contextHandler.setResourceBase(".");
contextHandler.setHandler(new BadMultiPartRequestHandler(testTmpDir));
contextHandler.addEventListener(new MultiPartCleanerListener()
{
@Override
public void requestDestroyed(ServletRequestEvent sre)
{
MultiPartInputStreamParser m = (MultiPartInputStreamParser)sre.getServletRequest().getAttribute(Request.__MULTIPART_INPUT_STREAM);
ContextHandler.Context c = (ContextHandler.Context)sre.getServletRequest().getAttribute(Request.__MULTIPART_CONTEXT);
assertNotNull (m);
assertNotNull (c);
assertTrue(c == sre.getServletContext());
super.requestDestroyed(sre);
String[] files = testTmpDir.list();
assertTrue(files.length == 0);
}
});
_server.stop();
_server.setHandler(contextHandler);
_server.start();
String multipart = "--AaB03x\r\n"+
"content-disposition: form-data; name=\"xxx\"\r\n"+
"\r\n"+
"Joe Blow\r\n"+
"--AaB03x\r\n"+
"content-disposition: form-data; filename=\"foo.upload\"\r\n"+
"Content-Type: text/plain;charset=ISO-8859-1\r\n"+
"\r\n"+
"000000000000000000000000000000000000000000000000000\r\n"+
"--AaB03x--\r\n";
String request="GET /foo/x.html HTTP/1.1\r\n"+
"Host: whatever\r\n"+
"Content-Type: multipart/form-data; boundary=\"AaB03x\"\r\n"+
"Content-Length: "+multipart.getBytes().length+"\r\n"+
"Connection: close\r\n"+
"\r\n"+
multipart;
String responses=_connector.getResponses(request);
//System.err.println(responses);
assertTrue(responses.startsWith("HTTP/1.1 500"));
}
@Test @Test
public void testBadUtf8ParamExtraction() throws Exception public void testBadUtf8ParamExtraction() throws Exception
@ -1286,4 +1347,38 @@ public class RequestTest
} }
} }
} }
private class BadMultiPartRequestHandler extends AbstractHandler
{
File tmpDir;
public BadMultiPartRequestHandler(File tmpDir)
{
this.tmpDir = tmpDir;
}
@Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
((Request)request).setHandled(true);
try
{
MultipartConfigElement mpce = new MultipartConfigElement(tmpDir.getAbsolutePath(),-1, -1, 2);
request.setAttribute(Request.__MULTIPART_CONFIG_ELEMENT, mpce);
//We should get an error when we getParams if there was a problem parsing the multipart
String field1 = request.getParameter("xxx");
//A 200 response is actually wrong here
}
catch (RuntimeException e)
{
response.sendError(500);
}
}
}
} }

View File

@ -696,7 +696,7 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
//servlet calling Request.getPart() or Request.getParts() //servlet calling Request.getPart() or Request.getParts()
ContextHandler ch = ContextHandler.getContextHandler(getServletHandler().getServletContext()); ContextHandler ch = ContextHandler.getContextHandler(getServletHandler().getServletContext());
ch.addEventListener(new MultiPartCleanerListener()); ch.addEventListener(MultiPartCleanerListener.INSTANCE);
} }
} }

View File

@ -41,6 +41,7 @@ import java.util.Collections;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.CopyOnWriteArraySet;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -121,7 +122,7 @@ public class SslContextFactory extends AbstractLifeCycle
/** Excluded cipher suites. */ /** Excluded cipher suites. */
private final Set<String> _excludeCipherSuites = new LinkedHashSet<>(); private final Set<String> _excludeCipherSuites = new LinkedHashSet<>();
/** Included cipher suites. */ /** Included cipher suites. */
private Set<String> _includeCipherSuites = null; private List<String> _includeCipherSuites = null;
/** Keystore path. */ /** Keystore path. */
private String _keyStorePath; private String _keyStorePath;
@ -428,7 +429,7 @@ public class SslContextFactory extends AbstractLifeCycle
public void setIncludeCipherSuites(String... cipherSuites) public void setIncludeCipherSuites(String... cipherSuites)
{ {
checkNotStarted(); checkNotStarted();
_includeCipherSuites = new LinkedHashSet<>(Arrays.asList(cipherSuites)); _includeCipherSuites = new CopyOnWriteArrayList<>(Arrays.asList(cipherSuites));
} }
/** /**
@ -1073,7 +1074,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/ */
public String[] selectCipherSuites(String[] enabledCipherSuites, String[] supportedCipherSuites) public String[] selectCipherSuites(String[] enabledCipherSuites, String[] supportedCipherSuites)
{ {
Set<String> selected_ciphers = new CopyOnWriteArraySet<>(); List<String> selected_ciphers = new CopyOnWriteArrayList<>(); // TODO is this the most efficient?
// Set the starting ciphers - either from the included or enabled list // Set the starting ciphers - either from the included or enabled list
if (_includeCipherSuites!=null) if (_includeCipherSuites!=null)
@ -1083,13 +1084,15 @@ public class SslContextFactory extends AbstractLifeCycle
removeExcludedCipherSuites(selected_ciphers); removeExcludedCipherSuites(selected_ciphers);
// TODO could we cache these results?
return selected_ciphers.toArray(new String[selected_ciphers.size()]); return selected_ciphers.toArray(new String[selected_ciphers.size()]);
} }
private void processIncludeCipherSuites(String[] supportedCipherSuites, Set<String> selected_ciphers) private void processIncludeCipherSuites(String[] supportedCipherSuites, List<String> selected_ciphers)
{ {
for (String cipherSuite : _includeCipherSuites) for (String cipherSuite : _includeCipherSuites)
{ {
// TODO precompile these patterns to make accepting faster
Pattern p = Pattern.compile(cipherSuite); Pattern p = Pattern.compile(cipherSuite);
for (String supportedCipherSuite : supportedCipherSuites) for (String supportedCipherSuite : supportedCipherSuites)
{ {
@ -1100,7 +1103,7 @@ public class SslContextFactory extends AbstractLifeCycle
} }
} }
private void removeExcludedCipherSuites(Set<String> selected_ciphers) private void removeExcludedCipherSuites(List<String> selected_ciphers)
{ {
for (String excludeCipherSuite : _excludeCipherSuites) for (String excludeCipherSuite : _excludeCipherSuites)
{ {

View File

@ -303,10 +303,19 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Inc
@Override @Override
public void incomingFrame(Frame frame) public void incomingFrame(Frame frame)
{ {
if (connection.getIOState().isInputAvailable()) ClassLoader old = Thread.currentThread().getContextClassLoader();
try
{ {
// Forward Frames Through Extension List Thread.currentThread().setContextClassLoader(classLoader);
incomingHandler.incomingFrame(frame); if (connection.getIOState().isInputAvailable())
{
// Forward Frames Through Extension List
incomingHandler.incomingFrame(frame);
}
}
finally
{
Thread.currentThread().setContextClassLoader(old);
} }
} }