From 182c20b2ba2582f785a1f57c953b0ca6b7671af3 Mon Sep 17 00:00:00 2001 From: markt Date: Thu, 15 Apr 2010 22:57:36 +0000 Subject: [PATCH] Implement SRV.3.2. Non file parts should be exposed via getParameters() Cache results so multiple calls to getParts() work git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@934634 13f79535-47bb-0310-9956-ffa450edef68 --- java/org/apache/catalina/connector/Request.java | 95 ++++++++++++++++++---- java/org/apache/catalina/core/ApplicationPart.java | 36 ++++++++ java/org/apache/tomcat/util/http/Parameters.java | 6 +- 3 files changed, 122 insertions(+), 15 deletions(-) diff --git a/java/org/apache/catalina/connector/Request.java b/java/org/apache/catalina/connector/Request.java index 02b0cd7c2..5377bf553 100644 --- a/java/org/apache/catalina/connector/Request.java +++ b/java/org/apache/catalina/connector/Request.java @@ -318,6 +318,18 @@ public class Request /** + * The parts, if any, uploaded with this request. + */ + protected Collection parts = null; + + + /** + * The exception thrown, if any when parsing the parts. + */ + protected Exception partsParseException = null; + + + /** * The currently active session for this request. */ protected Session session = null; @@ -441,6 +453,8 @@ public class Request subject = null; sessionParsed = false; parametersParsed = false; + parts = null; + partsParseException = null; cookiesParsed = false; locales.clear(); localesParsed = false; @@ -2431,11 +2445,35 @@ public class Request public Collection getParts() throws IOException, IllegalStateException, ServletException { + parseParts(); + + if (partsParseException != null) { + if (partsParseException instanceof IOException) { + throw (IOException) partsParseException; + } else if (partsParseException instanceof IllegalStateException) { + throw (IllegalStateException) partsParseException; + } else if (partsParseException instanceof ServletException) { + throw (ServletException) partsParseException; + } + } + + return parts; + } + + private void parseParts() { + + // Return immediately if the parts have already been parsed + if (parts != null || partsParseException != null) + return; + MultipartConfigElement mce = getWrapper().getMultipartConfigElement(); if (mce == null) { - return Collections.emptyList(); + parts = Collections.emptyList(); + return; } + Parameters parameters = coyoteRequest.getParameters(); + File location; String locationStr = mce.getLocation(); if (locationStr == null || locationStr.length() == 0) { @@ -2446,14 +2484,20 @@ public class Request } if (!location.isAbsolute() || !location.isDirectory()) { - throw new IOException( + partsParseException = new IOException( sm.getString("coyoteRequest.uploadLocationInvalid", location)); + return; } // Create a new file upload handler DiskFileItemFactory factory = new DiskFileItemFactory(); - factory.setRepository(location.getCanonicalFile()); + try { + factory.setRepository(location.getCanonicalFile()); + } catch (IOException ioe) { + partsParseException = ioe; + return; + } factory.setSizeThreshold(mce.getFileSizeThreshold()); ServletFileUpload upload = new ServletFileUpload(); @@ -2461,31 +2505,48 @@ public class Request upload.setFileSizeMax(mce.getMaxFileSize()); upload.setSizeMax(mce.getMaxRequestSize()); - List result = new ArrayList(); + parts = new ArrayList(); try { - List items = upload.parseRequest(this); - for (FileItem item : items) { - result.add(new ApplicationPart(item, mce)); + List items = upload.parseRequest(this); + for (FileItem item : items) { + ApplicationPart part = new ApplicationPart(item, mce); + parts.add(part); + if (part.getFilename() == null) { + try { + parameters.addParameterValues(part.getName(), + new String[] {part.getString( + parameters.getEncoding())}); + } catch (UnsupportedEncodingException uee) { + try { + parameters.addParameterValues(part.getName(), + new String[] {part.getString( + Parameters.DEFAULT_ENCODING)}); + } catch (UnsupportedEncodingException e) { + // Should not be possible + } + } + } } } catch (InvalidContentTypeException e) { - throw new ServletException(e); + partsParseException = new ServletException(e); } catch (FileUploadBase.SizeException e) { - throw new IllegalStateException(e); + partsParseException = new IllegalStateException(e); } catch (FileUploadException e) { - throw new IOException(); + partsParseException = new IOException(); } - return result; + return; } - + + /** * {@inheritDoc} */ public Part getPart(String name) throws IOException, IllegalStateException, ServletException { - Collection parts = getParts(); - Iterator iterator = parts.iterator(); + Collection c = getParts(); + Iterator iterator = c.iterator(); while (iterator.hasNext()) { Part part = iterator.next(); if (name.equals(part.getName())) { @@ -2677,6 +2738,12 @@ public class Request } else { contentType = contentType.trim(); } + + if ("multipart/form-data".equals(contentType)) { + parseParts(); + return; + } + if (!("application/x-www-form-urlencoded".equals(contentType))) return; diff --git a/java/org/apache/catalina/core/ApplicationPart.java b/java/org/apache/catalina/core/ApplicationPart.java index 171b4750c..13c9b7edd 100644 --- a/java/org/apache/catalina/core/ApplicationPart.java +++ b/java/org/apache/catalina/core/ApplicationPart.java @@ -20,16 +20,19 @@ package org.apache.catalina.core; import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.io.UnsupportedEncodingException; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; +import java.util.Map; import javax.servlet.MultipartConfigElement; import javax.servlet.http.Part; import org.apache.tomcat.util.http.fileupload.DiskFileItem; import org.apache.tomcat.util.http.fileupload.FileItem; +import org.apache.tomcat.util.http.fileupload.ParameterParser; /** * Adaptor to allow {@link FileItem} objects generated by the package renamed @@ -120,4 +123,37 @@ public class ApplicationPart implements Part { } } + public String getString(String encoding) throws UnsupportedEncodingException { + return fileItem.getString(encoding); + } + + /* + * Adapted from FileUploadBase.getFileName() + */ + public String getFilename() { + String fileName = null; + String cd = getHeader("Content-Disposition"); + if (cd != null) { + String cdl = cd.toLowerCase(); + if (cdl.startsWith("form-data") || cdl.startsWith("attachment")) { + ParameterParser paramParser = new ParameterParser(); + paramParser.setLowerCaseNames(true); + // Parameter parser can handle null input + Map params = + paramParser.parse(cd, ';'); + if (params.containsKey("filename")) { + fileName = params.get("filename"); + if (fileName != null) { + fileName = fileName.trim(); + } else { + // Even if there is no value, the parameter is present, + // so we return an empty file name rather than no file + // name. + fileName = ""; + } + } + } + } + return fileName; + } } diff --git a/java/org/apache/tomcat/util/http/Parameters.java b/java/org/apache/tomcat/util/http/Parameters.java index 2566da18d..b7035941a 100644 --- a/java/org/apache/tomcat/util/http/Parameters.java +++ b/java/org/apache/tomcat/util/http/Parameters.java @@ -66,6 +66,10 @@ public final class Parameters extends MultiMap { this.queryMB=queryMB; } + public String getEncoding() { + return encoding; + } + public void setEncoding( String s ) { encoding=s; if(log.isDebugEnabled()) { @@ -194,7 +198,7 @@ public final class Parameters extends MultiMap { private ByteChunk origName=new ByteChunk(); private ByteChunk origValue=new ByteChunk(); CharChunk tmpNameC=new CharChunk(1024); - private static final String DEFAULT_ENCODING = "ISO-8859-1"; + public static final String DEFAULT_ENCODING = "ISO-8859-1"; public void processParameters( byte bytes[], int start, int len ) { processParameters(bytes, start, len, encoding); -- 2.11.0