/* * $Id: FileUploadFilter.java 110 2006-02-28 06:59:40Z jeff $ * $URL: https://svn.infohazard.org/blorn/trunk/frontend/src/com/blorn/web/util/FileUploadFilter.java $ */ package org.subethamail.web.util; import java.io.IOException; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import javax.servlet.http.HttpServletResponse; import org.apache.commons.fileupload.DiskFileUpload; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileUploadBase; import org.apache.commons.fileupload.FileUploadException; import org.subethamail.common.EnumerationAdapter; /** * Uses the jakarta commons-fileupload code as a filter, presenting * what looks like a more-or-less normal http request. Theoretically * commons-fileupload 1.1 will have a filter class builtin which can * replace this, but that code is not available yet. */ public class FileUploadFilter extends AbstractFilter { /** * Maximum size of an upload, currently 512MB. */ public static final int MAX_UPLOAD_BYTES = 1024 * 1024 * 512; /** * Attribute in the request where the files are stored. Clients to * this filter should use getFiles() */ protected static final String ATTR_FILES = FileUploadFilter.class.getName() + ".files"; /** * Attribute in the request where an exception will be stored. This * will only be the case if an exception was thrown during processing. */ protected static final String ATTR_EXCEPTION = FileUploadFilter.class.getName() + ".exception"; /** * Use this method to obtain the files extracted from the multipart request. * Form fields will not show up in this list. * * @throws any exception that might have been thrown during the processing of the * upload. The stack trace will seem a little odd. */ @SuppressWarnings("unchecked") public static List<FileItem> getFiles(HttpServletRequest request) throws FileUploadException { FileUploadException ex = (FileUploadException)request.getAttribute(ATTR_EXCEPTION); if (ex != null) throw ex; List<FileItem> files = (List<FileItem>)request.getAttribute(ATTR_FILES); if (files == null) throw new IllegalStateException("Missing files, perhaps filter not configured or form enctype was wrong"); return files; } /** * Filter the current request. If it is a multipart request, parse it and * wrap it before chaining to the next filter or servlet. Otherwise, pass * it on untouched. */ @Override @SuppressWarnings("unchecked") public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { if (!FileUploadBase.isMultipartContent(request)) { chain.doFilter(request, response); return; } try { //FileItemFactory fact = new DiskFileItemFactory(); //FileUpload upload = new ServletFileUpload(fact); DiskFileUpload upload = new DiskFileUpload(); upload.setSizeMax(MAX_UPLOAD_BYTES); List<FileItem> items = upload.parseRequest(request); Map<String, String[]> params = new HashMap<String, String[]>(); List<FileItem> files = new ArrayList<FileItem>(items.size()); for (FileItem item: items) { if (item.isFormField()) { // Add it to the array in the params, creating the array if necessary String[] array = params.get(item.getFieldName()); if (array == null) { array = new String[] { item.getString() }; } else { String[] newArray = new String[array.length + 1]; System.arraycopy(array, 0, newArray, 0, array.length); newArray[newArray.length - 1] = item.getString(); array = newArray; } params.put(item.getFieldName(), array); } else files.add(item); } request.setAttribute(ATTR_FILES, files); HttpServletRequest wrapped = new RequestWrapper(request, params); chain.doFilter(wrapped, response); } catch (FileUploadException ex) { // Just save the exception for later. request.setAttribute(ATTR_EXCEPTION, ex); chain.doFilter(request, response); } } /** * Wraps the request providing a set of params as if they were the * normal servlet params. */ class RequestWrapper extends HttpServletRequestWrapper { /** */ protected Map<String, String[]> params; /** */ public RequestWrapper(HttpServletRequest orig, Map<String, String[]> params) { super(orig); this.params = params; } /* (non-Javadoc) * @see javax.servlet.ServletRequestWrapper#getParameter(java.lang.String) */ @Override public String getParameter(String name) { String[] val = this.params.get(name); if (val == null) return null; else return val[0]; } /* (non-Javadoc) * @see javax.servlet.ServletRequestWrapper#getParameterMap() */ @Override public Map<String, String[]> getParameterMap() { return this.params; } /* (non-Javadoc) * @see javax.servlet.ServletRequestWrapper#getParameterNames() */ @Override public Enumeration<String> getParameterNames() { return new EnumerationAdapter<String>(this.params.keySet().iterator()); } /* (non-Javadoc) * @see javax.servlet.ServletRequestWrapper#getParameterValues(java.lang.String) */ @Override public String[] getParameterValues(String name) { return this.params.get(name); } } }