/** * This file Copyright (c) 2003-2012 Magnolia International * Ltd. (http://www.magnolia-cms.com). All rights reserved. * * * This file is dual-licensed under both the Magnolia * Network Agreement and the GNU General Public License. * You may elect to use one or the other of these licenses. * * This file is distributed in the hope that it will be * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT. * Redistribution, except as permitted by whichever of the GPL * or MNA you select, is prohibited. * * 1. For the GPL license (GPL), you can redistribute and/or * modify this file under the terms of the GNU General * Public License, Version 3, as published by the Free Software * Foundation. You should have received a copy of the GNU * General Public License, Version 3 along with this program; * if not, write to the Free Software Foundation, Inc., 51 * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * 2. For the Magnolia Network Agreement (MNA), this file * and the accompanying materials are made available under the * terms of the MNA which accompanies this distribution, and * is available at http://www.magnolia-cms.com/mna.html * * Any modifications to this file must keep this entire header * intact. * */ package info.magnolia.cms.filters; import info.magnolia.cms.beans.runtime.Document; import info.magnolia.cms.beans.runtime.MultipartForm; import info.magnolia.cms.core.Path; import info.magnolia.context.MgnlContext; import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.Iterator; import java.util.List; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileUploadBase; import org.apache.commons.fileupload.FileUploadException; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.apache.commons.fileupload.servlet.ServletRequestContext; import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * A <code>Filter</code> that determines if a <code>HttpServletRequest</code> contains multipart content and if so * parses it into a request attribute for further processing. This implementation uses jakarta commons-fileupload for * parsing multipart requests. Maximum file size can be configured using the "maxFileSize" init parameter, defaulting to * 2 GB. * @author Andreas Brenk * @author Fabrizio Giustina * @version $Id$ */ public class MultipartRequestFilter extends OncePerRequestAbstractMgnlFilter { private static final Logger log = LoggerFactory.getLogger(MultipartRequestFilter.class); /** * Default max file upload size (2 GB). */ private static final int DEFAULT_MAX_FILE_SIZE = 2000000000; // 2GB /** * Config parameter name for max file size. */ private static final String PARAM_MAX_FILE_SIZE = "maxFileSize"; /** * The maximum size a file upload may have. */ private long maxFileSize = DEFAULT_MAX_FILE_SIZE; /** * The directory for temporary storage of uploaded files. */ private File tempDir; /** * @see javax.servlet.Filter#init(javax.servlet.FilterConfig) */ @Override public void init(FilterConfig config) throws ServletException { super.init(config); String maxFileSize = config.getInitParameter(PARAM_MAX_FILE_SIZE); if (maxFileSize != null) { this.maxFileSize = Long.parseLong(maxFileSize); } this.tempDir = new File(Path.getTempDirectoryPath()); } /** * Determine if the request has multipart content and if so parse it into a <code>MultipartForm</code> and store * it as a request attribute. */ @Override public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { boolean isMultipartContent = FileUploadBase.isMultipartContent(new ServletRequestContext(request)); MultipartForm mpf = null; try { if (isMultipartContent) { mpf = parseRequest(request); // wrap the request request = new MultipartRequestWrapper(request, mpf); MgnlContext.push(request, response); } try { chain.doFilter(request, response); } finally { if(isMultipartContent){ MgnlContext.pop(); } } } finally { if (mpf != null) { Iterator<Document> keys = mpf.getDocuments().values().iterator(); while (keys.hasNext()) { Document doc = keys.next(); if (doc != null && doc.getFile() != null && doc.getFile().exists()) { doc.delete(); } } } } } /** * Parse the request and store it as a request attribute. */ private MultipartForm parseRequest(HttpServletRequest request) throws IOException, ServletException { MultipartForm form = new MultipartForm(); ServletFileUpload upload = newServletFileUpload(); final List fileItems; try { fileItems = upload.parseRequest(request); } catch (FileUploadException e) { throw new ServletException("Could not upload files:" + e.getMessage(), e); } for (Iterator fileItemIterator = fileItems.iterator(); fileItemIterator.hasNext();) { FileItem item = (FileItem) fileItemIterator.next(); if (item.isFormField()) { addField(request, item, form); } else { addFile(item, form); } } request.setAttribute(MultipartForm.REQUEST_ATTRIBUTE_NAME, form); return form; } /** * Create a new <code>DiskFileUpload</code>. */ private ServletFileUpload newServletFileUpload() { ServletFileUpload upload = new ServletFileUpload(); upload.setSizeMax(this.maxFileSize); DiskFileItemFactory fif = new DiskFileItemFactory(); fif.setRepository(Path.getTempDirectory()); upload.setFileItemFactory(fif); return upload; } /** * Add the <code>FileItem</code> as a paramter into the <code>MultipartForm</code>. */ private void addField(HttpServletRequest request, FileItem item, MultipartForm form) { String name = item.getFieldName(); String value; try { String encoding = StringUtils.defaultString(request.getCharacterEncoding(), "UTF-8"); value = item.getString(encoding); } catch (UnsupportedEncodingException ex) { value = item.getString(); } form.addParameter(name, value); String[] values = form.getParameterValues(name); if (values == null) { form.addparameterValues(name, new String[]{value}); } else { form.addparameterValues(name, (String[]) ArrayUtils.add(values, value)); } } /** * Add the <code>FileItem</code> as a document into the <code>MultipartForm</code>. */ private void addFile(FileItem item, MultipartForm form) throws IOException { String atomName = item.getFieldName(); String fileName = item.getName(); String type = item.getContentType(); File file = File.createTempFile(atomName, null, this.tempDir); try { item.write(file); } catch (Exception e) { log.error("Could not write uploaded file: " + e.getMessage(), e); throw new IOException("Could not write uploaded file: " + e.getMessage()); } form.addDocument(atomName, fileName, type, file); } }