From: schultz Date: Fri, 21 Jan 2011 18:32:39 +0000 (+0000) Subject: Re-fixed bug #49711: HttpServletRequest#getParts() does not work in a Filter X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=03f437e96ad158d7d0d787b8766b46e19d07a679;p=tomcat7.0 Re-fixed bug #49711: HttpServletRequest#getParts() does not work in a Filter - Moved allowCasualMultipartParsing setting from to git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@1061953 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/java/org/apache/catalina/Context.java b/java/org/apache/catalina/Context.java index 33c03a237..6743085fb 100644 --- a/java/org/apache/catalina/Context.java +++ b/java/org/apache/catalina/Context.java @@ -89,6 +89,26 @@ public interface Context extends Container { // ------------------------------------------------------------- Properties + /** + * Set to true to allow requests mapped to servlets that + * do not explicitly declare @MultipartConfig or have + * <multipart-config> specified in web.xml to parse + * multipart/form-data requests. + * + * @param allowCasualMultipartParsing true to allow such + * casual parsing, false otherwise. + */ + public void setAllowCasualMultipartParsing(boolean allowCasualMultipartParsing); + + /** + * Returns true if requests mapped to servlets without + * "multipart config" to parse multipart/form-data requests anyway. + * + * @return true if requests mapped to servlets without + * "multipart config" to parse multipart/form-data requests, + * false otherwise. + */ + public boolean getAllowCasualMultipartParsing(); /** * Return the set of initialized application event listener objects, diff --git a/java/org/apache/catalina/connector/Connector.java b/java/org/apache/catalina/connector/Connector.java index 6f54c66d6..98fbc1c2e 100644 --- a/java/org/apache/catalina/connector/Connector.java +++ b/java/org/apache/catalina/connector/Connector.java @@ -247,13 +247,6 @@ public class Connector extends LifecycleMBeanBase { protected boolean useBodyEncodingForURI = false; - /** - * Allow multipart/form-data requests to be parsed even when the - * target servlet doesn't specify @MultipartConfig or have a - * <multipart-config> element. - */ - protected boolean allowCasualMultipartParsing = false; - protected static HashMap replacements = new HashMap(); static { @@ -775,33 +768,6 @@ public class Connector extends LifecycleMBeanBase { } /** - * Set to true to allow requests mapped to servlets that - * do not explicitly declare @MultipartConfig or have - * <multipart-config> specified in web.xml to parse - * multipart/form-data requests. - * - * @param allowCasualMultipartParsing true to allow such - * casual parsing, false otherwise. - */ - public void setAllowCasualMultipartParsing(boolean allowCasualMultipartParsing) - { - this.allowCasualMultipartParsing = allowCasualMultipartParsing; - } - - /** - * Returns true if requests mapped to servlets without - * "multipart config" to parse multipart/form-data requests anyway. - * - * @return true if requests mapped to servlets without - * "multipart config" to parse multipart/form-data requests, - * false otherwise. - */ - protected boolean getAllowCasualMultipartParsing() - { - return this.allowCasualMultipartParsing; - } - - /** * Indicates whether the generation of an X-Powered-By response header for * servlet-generated responses is enabled or disabled for this Connector. * diff --git a/java/org/apache/catalina/connector/Request.java b/java/org/apache/catalina/connector/Request.java index f65607878..0163c6ba7 100644 --- a/java/org/apache/catalina/connector/Request.java +++ b/java/org/apache/catalina/connector/Request.java @@ -2547,8 +2547,7 @@ public class Request MultipartConfigElement mce = getWrapper().getMultipartConfigElement(); if (mce == null) { - Connector connector = getConnector(); - if(connector.getAllowCasualMultipartParsing()) { + if(getContext().getAllowCasualMultipartParsing()) { mce = new MultipartConfigElement(null, connector.getMaxPostSize(), connector.getMaxPostSize(), diff --git a/java/org/apache/catalina/core/StandardContext.java b/java/org/apache/catalina/core/StandardContext.java index 0556cdd1b..331d78daf 100644 --- a/java/org/apache/catalina/core/StandardContext.java +++ b/java/org/apache/catalina/core/StandardContext.java @@ -191,6 +191,13 @@ public class StandardContext extends ContainerBase /** + * Allow multipart/form-data requests to be parsed even when the + * target servlet doesn't specify @MultipartConfig or have a + * <multipart-config> element. + */ + protected boolean allowCasualMultipartParsing = false; + + /** * The alternate deployment descriptor name. */ private String altDDName = null; @@ -1001,6 +1008,34 @@ public class StandardContext extends ContainerBase return allowLinking; } + /** + * Set to true to allow requests mapped to servlets that + * do not explicitly declare @MultipartConfig or have + * <multipart-config> specified in web.xml to parse + * multipart/form-data requests. + * + * @param allowCasualMultipartParsing true to allow such + * casual parsing, false otherwise. + */ + @Override + public void setAllowCasualMultipartParsing(boolean allowCasualMultipartParsing) + { + this.allowCasualMultipartParsing = allowCasualMultipartParsing; + } + + /** + * Returns true if requests mapped to servlets without + * "multipart config" to parse multipart/form-data requests anyway. + * + * @return true if requests mapped to servlets without + * "multipart config" to parse multipart/form-data requests, + * false otherwise. + */ + @Override + public boolean getAllowCasualMultipartParsing() + { + return this.allowCasualMultipartParsing; + } /** * Set cache TTL. diff --git a/test/org/apache/catalina/connector/TestRequest.java b/test/org/apache/catalina/connector/TestRequest.java index 8195543d0..90358ce20 100644 --- a/test/org/apache/catalina/connector/TestRequest.java +++ b/test/org/apache/catalina/connector/TestRequest.java @@ -25,9 +25,7 @@ import java.net.URL; import java.util.Enumeration; import java.util.TreeMap; -import javax.servlet.MultipartConfigElement; import javax.servlet.ServletException; -import javax.servlet.annotation.MultipartConfig; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -527,167 +525,6 @@ public class TestRequest extends TomcatBaseTest { } } - /** - * Test case for bug 49711: HttpServletRequest.getParts does not work - * in a filter. - */ - public void testBug49711() { - Bug49711Client client = new Bug49711Client(); - client.setPort(getPort()); - - // Make sure non-multipart works properly - client.doRequest("/regular", false, false); - - assertEquals("Incorrect response for GET request", - "parts=0", - client.getResponseBody()); - - client.reset(); - - // Make sure regular multipart works properly - client.doRequest("/multipart", false, true); // send multipart request - - assertEquals("Regular multipart doesn't work", - "parts=1", - client.getResponseBody()); - - client.reset(); - - // Make casual multipart request to "regular" servlet w/o config - // We expect that no parts will be available - client.doRequest("/regular", false, true); // send multipart request - - assertEquals("Incorrect response for non-configured casual multipart request", - "parts=0", // multipart request should be ignored - client.getResponseBody()); - - client.reset(); - - // Make casual multipart request to "regular" servlet w/config - // We expect that the server /will/ parse the parts, even though - // there is no @MultipartConfig - client.doRequest("/regular", true, true); // send multipart request - - assertEquals("Incorrect response for configured casual multipart request", - "parts=1", - client.getResponseBody()); - - client.reset(); - } - - private static class Bug49711Servlet extends HttpServlet { - @Override - protected void service(HttpServletRequest req, HttpServletResponse resp) - throws ServletException, IOException { - // Just echo the parameters and values back as plain text - resp.setContentType("text/plain"); - resp.setCharacterEncoding("UTF-8"); - - PrintWriter out = resp.getWriter(); - - out.println("parts=" + (null == req.getParts() - ? "null" - : req.getParts().size())); - } - } - - @MultipartConfig - private static class Bug49711Servlet_multipart extends Bug49711Servlet { - } - - /** - * Bug 49711 test client: test for casual getParts calls. - */ - private class Bug49711Client extends SimpleHttpClient { - - private boolean init; - - private synchronized void init() throws Exception { - if (init) return; - - Tomcat tomcat = getTomcatInstance(); - Context root = tomcat.addContext("", TEMP_DIR); - Tomcat.addServlet(root, "regular", new Bug49711Servlet()); - Wrapper w = Tomcat.addServlet(root, "multipart", new Bug49711Servlet_multipart()); - - // Tomcat.addServlet does not respect annotations, so we have - // to set our own MultipartConfigElement. - w.setMultipartConfigElement(new MultipartConfigElement("")); - - root.addServletMapping("/regular", "regular"); - root.addServletMapping("/multipart", "multipart"); - tomcat.start(); - - init = true; - } - - private Exception doRequest(String uri, - boolean allowCasualMultipart, - boolean makeMultipartRequest) { - Tomcat tomcat = getTomcatInstance(); - - tomcat.getConnector().setAllowCasualMultipartParsing(allowCasualMultipart); - - try { - init(); - - // Open connection - connect(); - - // Send specified request body using method - String[] request; - - if(makeMultipartRequest) { - String boundary = "--simpleboundary"; - - String content = "--" + boundary + CRLF - + "Content-Disposition: form-data; name=\"name\"" + CRLF + CRLF - + "value" + CRLF - + "--" + boundary + "--" + CRLF - ; - - // Re-encode the content so that bytes = characters - if(null != content) - content = new String(content.getBytes("UTF-8"), "ASCII"); - - request = new String[] { - "POST http://localhost:" + getPort() + uri + " HTTP/1.1" + CRLF - + "Host: localhost" + CRLF - + "Connection: close" + CRLF - + "Content-Type: multipart/form-data; boundary=" + boundary + CRLF - + "Content-Length: " + content.length() + CRLF - + CRLF - + content - + CRLF - }; - } - else - { - request = new String[] { - "GET http://localhost:" + getPort() + uri + " HTTP/1.1" + CRLF - + "Host: localhost" + CRLF - + "Connection: close" + CRLF - + CRLF - }; - } - - setRequest(request); - processRequest(); // blocks until response has been read - - // Close the connection - disconnect(); - } catch (Exception e) { - return e; - } - return null; - } - - @Override - public boolean isResponseBodyOK() { - return false; // Don't care - } - } - private HttpURLConnection getConnection() throws IOException { final String query = "http://localhost:" + getPort() + "/"; URL postURL; diff --git a/test/org/apache/catalina/core/TestStandardContext.java b/test/org/apache/catalina/core/TestStandardContext.java index 270d4340b..dd344ae75 100644 --- a/test/org/apache/catalina/core/TestStandardContext.java +++ b/test/org/apache/catalina/core/TestStandardContext.java @@ -19,12 +19,14 @@ package org.apache.catalina.core; import java.io.File; import java.io.IOException; +import java.io.PrintWriter; import java.util.Set; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.HttpConstraintElement; +import javax.servlet.MultipartConfigElement; import javax.servlet.Servlet; import javax.servlet.ServletContainerInitializer; import javax.servlet.ServletContext; @@ -33,12 +35,14 @@ import javax.servlet.ServletRegistration; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.ServletSecurityElement; +import javax.servlet.annotation.MultipartConfig; import javax.servlet.annotation.ServletSecurity.TransportGuarantee; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.catalina.Context; +import org.apache.catalina.Wrapper; import org.apache.catalina.authenticator.BasicAuthenticator; import org.apache.catalina.deploy.FilterDef; import org.apache.catalina.deploy.FilterMap; @@ -316,4 +320,165 @@ public class TestStandardContext extends TomcatBaseTest { } } + + /** + * Test case for bug 49711: HttpServletRequest.getParts does not work + * in a filter. + */ + public void testBug49711() { + Bug49711Client client = new Bug49711Client(); + client.setPort(getPort()); + + // Make sure non-multipart works properly + client.doRequest("/regular", false, false); + + assertEquals("Incorrect response for GET request", + "parts=0", + client.getResponseBody()); + + client.reset(); + + // Make sure regular multipart works properly + client.doRequest("/multipart", false, true); // send multipart request + + assertEquals("Regular multipart doesn't work", + "parts=1", + client.getResponseBody()); + + client.reset(); + + // Make casual multipart request to "regular" servlet w/o config + // We expect that no parts will be available + client.doRequest("/regular", false, true); // send multipart request + + assertEquals("Incorrect response for non-configured casual multipart request", + "parts=0", // multipart request should be ignored + client.getResponseBody()); + + client.reset(); + + // Make casual multipart request to "regular" servlet w/config + // We expect that the server /will/ parse the parts, even though + // there is no @MultipartConfig + client.doRequest("/regular", true, true); // send multipart request + + assertEquals("Incorrect response for configured casual multipart request", + "parts=1", + client.getResponseBody()); + + client.reset(); + } + + private static class Bug49711Servlet extends HttpServlet { + @Override + protected void service(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + // Just echo the parameters and values back as plain text + resp.setContentType("text/plain"); + resp.setCharacterEncoding("UTF-8"); + + PrintWriter out = resp.getWriter(); + + out.println("parts=" + (null == req.getParts() + ? "null" + : req.getParts().size())); + } + } + + @MultipartConfig + private static class Bug49711Servlet_multipart extends Bug49711Servlet { + } + + /** + * Bug 49711 test client: test for casual getParts calls. + */ + private class Bug49711Client extends SimpleHttpClient { + + private boolean init; + private Context context; + + private synchronized void init() throws Exception { + if (init) return; + + Tomcat tomcat = getTomcatInstance(); + context = tomcat.addContext("", TEMP_DIR); + Tomcat.addServlet(context, "regular", new Bug49711Servlet()); + Wrapper w = Tomcat.addServlet(context, "multipart", new Bug49711Servlet_multipart()); + + // Tomcat.addServlet does not respect annotations, so we have + // to set our own MultipartConfigElement. + w.setMultipartConfigElement(new MultipartConfigElement("")); + + context.addServletMapping("/regular", "regular"); + context.addServletMapping("/multipart", "multipart"); + tomcat.start(); + + init = true; + } + + private Exception doRequest(String uri, + boolean allowCasualMultipart, + boolean makeMultipartRequest) { + try { + init(); + + context.setAllowCasualMultipartParsing(allowCasualMultipart); + + // Open connection + connect(); + + // Send specified request body using method + String[] request; + + if(makeMultipartRequest) { + String boundary = "--simpleboundary"; + + String content = "--" + boundary + CRLF + + "Content-Disposition: form-data; name=\"name\"" + CRLF + CRLF + + "value" + CRLF + + "--" + boundary + "--" + CRLF + ; + + // Re-encode the content so that bytes = characters + if(null != content) + content = new String(content.getBytes("UTF-8"), "ASCII"); + + request = new String[] { + "POST http://localhost:" + getPort() + uri + " HTTP/1.1" + CRLF + + "Host: localhost" + CRLF + + "Connection: close" + CRLF + + "Content-Type: multipart/form-data; boundary=" + boundary + CRLF + + "Content-Length: " + content.length() + CRLF + + CRLF + + content + + CRLF + }; + } + else + { + request = new String[] { + "GET http://localhost:" + getPort() + uri + " HTTP/1.1" + CRLF + + "Host: localhost" + CRLF + + "Connection: close" + CRLF + + CRLF + }; + } + + setRequest(request); + processRequest(); // blocks until response has been read + + // Close the connection + disconnect(); + } catch (Exception e) { + return e; + } + + return null; + } + + @Override + public boolean isResponseBodyOK() { + return false; // Don't care + } + } } diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index 7a7d89603..fa0d90cd2 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -69,7 +69,7 @@ 49711: HttpServletRequest#getParts will work in a filter or servlet without an @MultipartConfig annotation or MultipartConfigElement if the new "allowCasualMultipartParsing" - connector attribute is set to "true". (schultz) + context attribute is set to "true". (schultz) 50582: Refactor access logging so chunked encoding is not diff --git a/webapps/docs/config/ajp.xml b/webapps/docs/config/ajp.xml index 0e56e0a8e..c5cb35bbd 100644 --- a/webapps/docs/config/ajp.xml +++ b/webapps/docs/config/ajp.xml @@ -74,17 +74,6 @@ - -

Set to true if Tomcat should automatically parse - multipart/form-data request bodies when HttpServletRequest.getPart* - or HttpServletRequest.getParameter* is called, even when the - target servlet isn't marked with the @MultipartConfig annotation - (See Servlet Specification 3.0, Section 3.2 for details). - Note that any setting other than true causes Tomcat - to behave in a way that is not technically spec-compliant. - The default is false

-
-

A boolean value which can be used to enable or disable the TRACE HTTP method. If not specified, this attribute is set to false.

diff --git a/webapps/docs/config/context.xml b/webapps/docs/config/context.xml index 3a41c8c92..e06389469 100644 --- a/webapps/docs/config/context.xml +++ b/webapps/docs/config/context.xml @@ -425,6 +425,17 @@ is un-deployed.

+ +

Set to true if Tomcat should automatically parse + multipart/form-data request bodies when HttpServletRequest.getPart* + or HttpServletRequest.getParameter* is called, even when the + target servlet isn't marked with the @MultipartConfig annotation + (See Servlet Specification 3.0, Section 3.2 for details). + Note that any setting other than true causes Tomcat + to behave in a way that is not technically spec-compliant. + The default is false

+
+

If the value of this flag is true, symlinks will be allowed inside the web application, pointing to resources outside the diff --git a/webapps/docs/config/http.xml b/webapps/docs/config/http.xml index ce51cd82c..9cdf55682 100644 --- a/webapps/docs/config/http.xml +++ b/webapps/docs/config/http.xml @@ -74,17 +74,6 @@ - -

Set to true if Tomcat should automatically parse - multipart/form-data request bodies when HttpServletRequest.getPart* - or HttpServletRequest.getParameter* is called, even when the - target servlet isn't marked with the @MultipartConfig annotation - (See Servlet Specification 3.0, Section 3.2 for details). - Note that any setting other than true causes Tomcat - to behave in a way that is not technically spec-compliant. - The default is false

-
-

A boolean value which can be used to enable or disable the TRACE HTTP method. If not specified, this attribute is set to false.