// ------------------------------------------------------------- Properties
+ /**
+ * Set to <code>true</code> 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 <code>true</code> to allow such
+ * casual parsing, <code>false</code> otherwise.
+ */
+ public void setAllowCasualMultipartParsing(boolean allowCasualMultipartParsing);
+
+ /**
+ * Returns <code>true</code> if requests mapped to servlets without
+ * "multipart config" to parse multipart/form-data requests anyway.
+ *
+ * @return <code>true</code> if requests mapped to servlets without
+ * "multipart config" to parse multipart/form-data requests,
+ * <code>false</code> otherwise.
+ */
+ public boolean getAllowCasualMultipartParsing();
/**
* Return the set of initialized application event listener objects,
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<String,String> replacements =
new HashMap<String,String>();
static {
}
/**
- * Set to <code>true</code> 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 <code>true</code> to allow such
- * casual parsing, <code>false</code> otherwise.
- */
- public void setAllowCasualMultipartParsing(boolean allowCasualMultipartParsing)
- {
- this.allowCasualMultipartParsing = allowCasualMultipartParsing;
- }
-
- /**
- * Returns <code>true</code> if requests mapped to servlets without
- * "multipart config" to parse multipart/form-data requests anyway.
- *
- * @return <code>true</code> if requests mapped to servlets without
- * "multipart config" to parse multipart/form-data requests,
- * <code>false</code> 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.
*
MultipartConfigElement mce = getWrapper().getMultipartConfigElement();
if (mce == null) {
- Connector connector = getConnector();
- if(connector.getAllowCasualMultipartParsing()) {
+ if(getContext().getAllowCasualMultipartParsing()) {
mce = new MultipartConfigElement(null,
connector.getMaxPostSize(),
connector.getMaxPostSize(),
/**
+ * 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;
return allowLinking;
}
+ /**
+ * Set to <code>true</code> 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 <code>true</code> to allow such
+ * casual parsing, <code>false</code> otherwise.
+ */
+ @Override
+ public void setAllowCasualMultipartParsing(boolean allowCasualMultipartParsing)
+ {
+ this.allowCasualMultipartParsing = allowCasualMultipartParsing;
+ }
+
+ /**
+ * Returns <code>true</code> if requests mapped to servlets without
+ * "multipart config" to parse multipart/form-data requests anyway.
+ *
+ * @return <code>true</code> if requests mapped to servlets without
+ * "multipart config" to parse multipart/form-data requests,
+ * <code>false</code> otherwise.
+ */
+ @Override
+ public boolean getAllowCasualMultipartParsing()
+ {
+ return this.allowCasualMultipartParsing;
+ }
/**
* Set cache TTL.
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;
}
}
- /**
- * 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;
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;
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;
}
}
+
+ /**
+ * 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
+ }
+ }
}
<bug>49711</bug>: 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)
</fix>
<fix>
<bug>50582</bug>: Refactor access logging so chunked encoding is not
<attributes>
- <attribute name="allowCasualMultipartParsing" required="false">
- <p>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 <code>true</code> causes Tomcat
- to behave in a way that is not technically spec-compliant.
- The default is <code>false</code></p>
- </attribute>
-
<attribute name="allowTrace" required="false">
<p>A boolean value which can be used to enable or disable the TRACE
HTTP method. If not specified, this attribute is set to false.</p>
is un-deployed.</p>
</attribute>
+ <attribute name="allowCasualMultipartParsing" required="false">
+ <p>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 <code>true</code> causes Tomcat
+ to behave in a way that is not technically spec-compliant.
+ The default is <code>false</code></p>
+ </attribute>
+
<attribute name="allowLinking" required="false">
<p>If the value of this flag is <code>true</code>, symlinks will be
allowed inside the web application, pointing to resources outside the
<attributes>
- <attribute name="allowCasualMultipartParsing" required="false">
- <p>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 <code>true</code> causes Tomcat
- to behave in a way that is not technically spec-compliant.
- The default is <code>false</code></p>
- </attribute>
-
<attribute name="allowTrace" required="false">
<p>A boolean value which can be used to enable or disable the TRACE
HTTP method. If not specified, this attribute is set to false.</p>