1 Reply Latest reply on Apr 14, 2009 4:55 AM by walterjwhite

    MultipartFilter

    walterjwhite

      Hi all,


      I thought it might be useful to be able to limit file uploads on a page by page basis.  I am modifying the existing MultipartFilter by adding additional parameters into a map.  You may specify a Url Pattern and Max Upload Size.  The MultipartRequest is then passed the corresponding information.


      I have some pages which I allow users to upload text files that never exceed a few kb.  On some other pages; however, uploads may exceed a few GB.  For security reasons as well as performance, I want to be able to restrict each page accordingly.


      I would like this to be incorporated into Seam since it is a small, yet powerful change.  I'll post code once I implement this.



      Thanks,
      Walter

        • 1. Re: MultipartFilter
          walterjwhite

          Hi all,


          Here is a quick mockup of what I was suggesting:


          package com.walterjwhite.servlet.filter;
          
          import static org.jboss.seam.ScopeType.APPLICATION;
          import static org.jboss.seam.annotations.Install.BUILT_IN;
          
          import java.io.IOException;
          
          import java.util.HashMap;
          import java.util.Map;
          import java.util.regex.Pattern;
          import javax.servlet.FilterChain;
          import javax.servlet.ServletException;
          import javax.servlet.ServletRequest;
          import javax.servlet.ServletResponse;
          import javax.servlet.http.HttpServletRequest;
          import javax.servlet.http.HttpServletResponse;
          
          import org.jboss.seam.annotations.Install;
          import org.jboss.seam.annotations.Name;
          import org.jboss.seam.annotations.Scope;
          import org.jboss.seam.annotations.intercept.BypassInterceptors;
          import org.jboss.seam.annotations.web.Filter;
          import org.jboss.seam.web.FileUploadException;
          import org.jboss.seam.web.MultipartRequest;
          import org.jboss.seam.web.MultipartRequestImpl;
          
          /**
           * A filter for decoding multipart requests, for
           * use with the file upload control.
           *
           * @author Shane Bryzak
           * @author Walter White
           *
           */
          @Scope(APPLICATION)
          @Name("com.walterjwhite.servlet.multipartFilter")
          @Install(precedence = BUILT_IN)
          @BypassInterceptors
          @Filter(within = {"org.jboss.seam.web.ajax4jsfFilter", "org.jboss.seam.web.exceptionFilter"})
          public class MultipartFilter extends AbstractFilter {
          
               public static final String MULTIPART = "multipart/";
               /**
                * Flag indicating whether a temporary file should be used to cache the uploaded file
                */
               protected boolean createTempFiles = false;
               /**
                * The maximum size of a file upload request.  0 means no limit.
                */
               protected Map<String, Integer> urlPatternToMaxUploadSize = new HashMap<String, Integer>();
          
               public boolean getCreateTempFiles() {
                    return createTempFiles;
               }
          
               public void setCreateTempFiles(boolean createTempFiles) {
                    this.createTempFiles = createTempFiles;
               }
          
               public Map<String, Integer> getUrlPatternToMaxUploadSize() {
                    return urlPatternToMaxUploadSize;
               }
          
               public void setUrlPatternToMaxUploadSize(Map<String, Integer> urlPatternToMaxUploadSize) {
                    this.urlPatternToMaxUploadSize = urlPatternToMaxUploadSize;
               }
          
               public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                         throws IOException, ServletException {
                    if (!(response instanceof HttpServletResponse)) {
                         chain.doFilter(request, response);
                         return;
                    }
          
                    HttpServletRequest httpRequest = (HttpServletRequest) request;
          
                    if (isMultipartRequest(httpRequest)) {
                         // here is where we differ from the Seam MultipartFilter
                         // we restrict uploads by Url, some Urls may not even permit uploads
          
                         int maxUploadSize = getUrlUploadLimit(httpRequest.getRequestURI());
                         if (maxUploadSize > 0) {
                              MultipartRequest multipartRequest = new MultipartRequestImpl(httpRequest, createTempFiles,
                                        maxUploadSize);
          
                              // Force the request to be parsed now
                              multipartRequest.getParameterNames();
          
                              chain.doFilter(multipartRequest, response);
                         } else {
                              throw new FileUploadException(httpRequest.getRequestURI() + " is not configured for uploads, value(" + maxUploadSize + ")");
                         }
                    } else {
                         chain.doFilter(request, response);
                    }
               }
          
               /**
                * Get the upload limit for this Url
                * @param url
                * @return
                */
               protected int getUrlUploadLimit(final String url) {
                    for (String urlPattern : urlPatternToMaxUploadSize.keySet()) {
                         if (Pattern.compile(urlPattern).matcher(url).matches()) {
                              return (urlPatternToMaxUploadSize.get(urlPattern).intValue());
                         }
                    }
          
                    // no match found, by default deny the upload
                    // in order for the default to allow some limit, * may be used, but should be the last rule
                    return (0);
               }
          
               private boolean isMultipartRequest(HttpServletRequest request) {
                    if (!"post".equals(request.getMethod().toLowerCase())) {
                         return false;
                    }
          
                    String contentType = request.getContentType();
                    if (contentType == null) {
                         return false;
                    }
          
                    if (contentType.toLowerCase().startsWith(MULTIPART)) {
                         return true;
                    }
          
                    return false;
               }
          }
          




          The pattern matching will have to change, but I was thinking it would work something like that.


          Walter