View Javadoc
1   /*
2    * Copyright (c) 2002-2014, Mairie de Paris
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions
7    * are met:
8    *
9    *  1. Redistributions of source code must retain the above copyright notice
10   *     and the following disclaimer.
11   *
12   *  2. Redistributions in binary form must reproduce the above copyright notice
13   *     and the following disclaimer in the documentation and/or other materials
14   *     provided with the distribution.
15   *
16   *  3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
17   *     contributors may be used to endorse or promote products derived from
18   *     this software without specific prior written permission.
19   *
20   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
24   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30   * POSSIBILITY OF SUCH DAMAGE.
31   *
32   * License 1.0
33   */
34  package fr.paris.lutece.portal.web.upload;
35  
36  import fr.paris.lutece.portal.service.util.AppLogService;
37  import fr.paris.lutece.portal.service.util.AppPathService;
38  import fr.paris.lutece.util.http.MultipartUtil;
39  
40  import org.apache.commons.fileupload.FileUploadBase.SizeLimitExceededException;
41  import org.apache.commons.fileupload.FileUploadException;
42  
43  import java.io.IOException;
44  
45  import java.text.DecimalFormat;
46  
47  import javax.servlet.Filter;
48  import javax.servlet.FilterChain;
49  import javax.servlet.FilterConfig;
50  import javax.servlet.ServletException;
51  import javax.servlet.ServletRequest;
52  import javax.servlet.ServletResponse;
53  import javax.servlet.http.HttpServletRequest;
54  import javax.servlet.http.HttpServletResponse;
55  
56  
57  /**
58   * Upload filter
59   */
60  public abstract class UploadFilter implements Filter
61  {
62      private static final String PROPERTY_TITLE_FILE_SIZE_LIMIT_EXCEEDED = "portal.util.message.titleDefault";
63      private static final String PROPERTY_MESSAGE_FILE_SIZE_LIMIT_EXCEEDED = "portal.util.message.fileSizeLimitExceeded";
64      private static final int KILO_BYTE = 1024;
65      private static final String SIZE_THRESHOLD = "sizeThreshold";
66      private static final String REQUEST_SIZE_MAX = "requestSizeMax";
67      private static final String ACTIVATE_NORMALIZE_FILE_NAME = "activateNormalizeFileName";
68      private FilterConfig _filterConfig;
69      private int _nSizeThreshold = -1;
70      private long _nRequestSizeMax = -1;
71      private boolean _bActivateNormalizeFileName;
72  
73      /**
74       * Forward the error message url depends site or admin implementation.
75       *
76       * @param request The http request
77       * @param strMessageKey the str message key
78       * @param messageArgs the message args
79       * @param strTitleKey the str title key
80       * @return Message
81       */
82      protected abstract String getMessageRelativeUrl( HttpServletRequest request, String strMessageKey,
83          Object[] messageArgs, String strTitleKey );
84  
85      /**
86       * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
87       * @param config
88       *            The FilterConfig
89       * @throws ServletException
90       *             The ServletException
91       */
92      @Override
93      public void init( FilterConfig config ) throws ServletException
94      {
95          _filterConfig = config;
96  
97          try
98          {
99              String paramValue = _filterConfig.getInitParameter( SIZE_THRESHOLD );
100 
101             if ( paramValue != null )
102             {
103                 _nSizeThreshold = Integer.parseInt( paramValue );
104             }
105 
106             paramValue = _filterConfig.getInitParameter( REQUEST_SIZE_MAX );
107 
108             if ( paramValue != null )
109             {
110                 _nRequestSizeMax = Long.parseLong( paramValue );
111             }
112 
113             paramValue = _filterConfig.getInitParameter( ACTIVATE_NORMALIZE_FILE_NAME );
114 
115             if ( paramValue != null )
116             {
117                 _bActivateNormalizeFileName = Boolean.valueOf( paramValue );
118             }
119         }
120         catch ( NumberFormatException ex )
121         {
122             AppLogService.error( ex.getMessage(  ), ex );
123             throw new ServletException( ex.getMessage(  ), ex );
124         }
125     }
126 
127     /**
128      * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest,
129      *      javax.servlet.ServletResponse, javax.servlet.FilterChain)
130      * @param request
131      *            The ServletRequest
132      * @param response
133      *            The ServletResponse
134      * @param chain
135      *            The FilterChain
136      * @throws IOException
137      *             The IOException
138      * @throws ServletException
139      *             The SerletException
140      */
141     @Override
142     public void doFilter( ServletRequest request, ServletResponse response, FilterChain chain )
143         throws IOException, ServletException
144     {
145         HttpServletRequest httpRequest = (HttpServletRequest) request;
146 
147         if ( !MultipartUtil.isMultipart( httpRequest ) )
148         {
149             chain.doFilter( request, response );
150         }
151         else
152         {
153             try
154             {
155                 MultipartHttpServletRequest multiHtppRequest = MultipartUtil.convert( _nSizeThreshold,
156                         _nRequestSizeMax, _bActivateNormalizeFileName, httpRequest );
157                 chain.doFilter( multiHtppRequest, response );
158             }
159             catch ( SizeLimitExceededException e )
160             {
161                 AppLogService.error( e.getMessage(  ), e );
162 
163                 Object[] args = { getDisplaySize(  ) };
164                 ( (HttpServletResponse) response ).sendRedirect( getMessageRelativeUrl( httpRequest,
165                         PROPERTY_MESSAGE_FILE_SIZE_LIMIT_EXCEEDED, args, PROPERTY_TITLE_FILE_SIZE_LIMIT_EXCEEDED ) );
166             }
167             catch ( FileUploadException e )
168             {
169                 AppLogService.error( e.getMessage(  ), e );
170                 throw new ServletException( "Unkown error occured during the upload", e );
171             }
172         }
173     }
174 
175     /**
176      * Get the max size of upload file
177      *
178      * @return The max size
179      */
180     public long getRequestSizeMax(  )
181     {
182         return _nRequestSizeMax;
183     }
184 
185     /**
186      * Default implementation for subclasses
187      */
188     @Override
189     public void destroy(  )
190     {
191         // Do nothing
192     }
193 
194     /**
195      *
196      * @return the size of the request to display in the error message
197      */
198     private String getDisplaySize(  )
199     {
200         long lSizeMax = getRequestSizeMax(  );
201         DecimalFormat decimalFormat = (DecimalFormat) DecimalFormat.getInstance(  );
202         decimalFormat.applyPattern( "#" );
203 
204         String strMessage = ( lSizeMax >= KILO_BYTE ) ? ( String.valueOf( lSizeMax / KILO_BYTE ) )
205                                                       : ( decimalFormat.format( lSizeMax / KILO_BYTE ) );
206 
207         return strMessage;
208     }
209 }