391080 Multipart temp files can be left on disk from Request.getPart and getParts

This commit is contained in:
Jan Bartel 2012-10-04 18:31:09 +10:00
parent 25cdef966c
commit 36a2ed10be
4 changed files with 92 additions and 13 deletions

View File

@ -50,6 +50,8 @@ import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
@ -80,6 +82,7 @@ import org.eclipse.jetty.server.handler.ContextHandler.Context;
import org.eclipse.jetty.util.Attributes;
import org.eclipse.jetty.util.AttributesMap;
import org.eclipse.jetty.util.LazyList;
import org.eclipse.jetty.util.MultiException;
import org.eclipse.jetty.util.MultiMap;
import org.eclipse.jetty.util.MultiPartInputStream;
import org.eclipse.jetty.util.StringUtil;
@ -123,12 +126,44 @@ import org.eclipse.jetty.util.log.Logger;
public class Request implements HttpServletRequest
{
public static final String __MULTIPART_CONFIG_ELEMENT = "org.eclipse.multipartConfig";
public static final String __MULTIPART_INPUT_STREAM = "org.eclipse.multiPartInputStream";
private static final Logger LOG = Log.getLogger(Request.class);
private static final String __ASYNC_FWD = "org.eclipse.asyncfwd";
private static final Collection __defaultLocale = Collections.singleton(Locale.getDefault());
private static final int __NONE = 0, _STREAM = 1, __READER = 2;
public static class MultiPartCleanerListener implements ServletRequestListener
{
@Override
public void requestDestroyed(ServletRequestEvent sre)
{
//Clean up any tmp files created by MultiPartInputStream
MultiPartInputStream mpis = (MultiPartInputStream)sre.getServletRequest().getAttribute(__MULTIPART_INPUT_STREAM);
if (mpis != null)
{
try
{
mpis.deleteParts();
}
catch (MultiException e)
{
sre.getServletContext().log("Errors deleting multipart tmp files", e);
}
}
}
@Override
public void requestInitialized(ServletRequestEvent sre)
{
//nothing to do, multipart config set up by ServletHolder.handle()
}
}
/* ------------------------------------------------------------ */
public static Request getRequest(HttpServletRequest request)
{
@ -1975,6 +2010,7 @@ public class Request implements HttpServletRequest
_multiPartInputStream = new MultiPartInputStream(getInputStream(),
getContentType(),(MultipartConfigElement)getAttribute(__MULTIPART_CONFIG_ELEMENT),
(_context != null?(File)_context.getAttribute("javax.servlet.context.tempdir"):null));
setAttribute(__MULTIPART_INPUT_STREAM, _multiPartInputStream);
Collection<Part> parts = _multiPartInputStream.getParts(); //causes parsing
for (Part p:parts)
{
@ -2006,6 +2042,7 @@ public class Request implements HttpServletRequest
_multiPartInputStream = new MultiPartInputStream(getInputStream(),
getContentType(),(MultipartConfigElement)getAttribute(__MULTIPART_CONFIG_ELEMENT),
(_context != null?(File)_context.getAttribute("javax.servlet.context.tempdir"):null));
setAttribute(__MULTIPART_INPUT_STREAM, _multiPartInputStream);
Collection<Part> parts = _multiPartInputStream.getParts(); //causes parsing
for (Part p:parts)
{

View File

@ -514,6 +514,8 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
initJspServlet();
}
initMultiPart();
_servlet.init(_config);
}
catch (UnavailableException e)
@ -570,6 +572,25 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
}
}
/* ------------------------------------------------------------ */
/**
* Register a ServletRequestListener that will ensure tmp multipart
* files are deleted when the request goes out of scope.
*
* @throws Exception
*/
protected void initMultiPart () throws Exception
{
//if this servlet can handle multipart requests, ensure tmp files will be
//cleaned up correctly
if (((Registration)getRegistration()).getMultipartConfig() != null)
{
//Register a listener to delete tmp files that are created as a result of this
//servlet calling Request.getPart() or Request.getParts()
ContextHandler ch = ((ContextHandler.Context)getServletHandler().getServletContext()).getContextHandler();
ch.addEventListener(new Request.MultiPartCleanerListener());
}
}
/* ------------------------------------------------------------ */
/**

View File

@ -84,7 +84,7 @@ import org.eclipse.jetty.util.TypeUtil;
public class MultiPartFilter implements Filter
{
public final static String CONTENT_TYPE_SUFFIX=".org.eclipse.jetty.servlet.contentType";
private final static String MULTIPART = "org.eclipse.jetty.servlet.MultiPartInputStream";
private final static String MULTIPART = "org.eclipse.jetty.servlet.MultiPartFile.multiPartInputStream";
private File tempdir;
private boolean _deleteFiles;
private ServletContext _context;
@ -191,23 +191,24 @@ public class MultiPartFilter implements Filter
deleteFiles(request);
}
}
/* ------------------------------------------------------------ */
private void deleteFiles(ServletRequest request)
{
if (!_deleteFiles)
return;
MultiPartInputStream mpis = (MultiPartInputStream)request.getAttribute(MULTIPART);
if (mpis != null)
{
Collection<Part> parts = mpis.getParsedParts();
for (Part p:parts)
try
{
try
{
p.delete();
}
catch(Exception e)
{
_context.log("Failed to delete "+p.getName(),e);
}
mpis.deleteParts();
}
catch (Exception e)
{
_context.log("Error deleting multipart tmp files", e);
}
}
request.removeAttribute(MULTIPART);

View File

@ -236,7 +236,7 @@ public class MultiPartInputStream
*/
public long getSize()
{
return _size;
return _size;
}
/**
@ -322,6 +322,7 @@ public class MultiPartInputStream
_contextTmpDir = contextTmpDir;
if (_contextTmpDir == null)
_contextTmpDir = new File (System.getProperty("java.io.tmpdir"));
if (_config == null)
_config = new MultipartConfigElement(_contextTmpDir.getAbsolutePath());
}
@ -340,6 +341,25 @@ public class MultiPartInputStream
}
return parts;
}
public void deleteParts ()
throws MultiException
{
Collection<Part> parts = getParsedParts();
MultiException err = new MultiException();
for (Part p:parts)
{
try
{
p.delete();
}
catch(Exception e)
{
err.add(e);
}
}
err.ifExceptionThrowMulti();
}
public Collection<Part> getParts()