View Javadoc
1   /*
2    * Copyright (c) 2002-2022, City of 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 java.io.IOException;
37  import java.text.DecimalFormat;
38  import java.text.NumberFormat;
39  
40  import javax.servlet.Filter;
41  import javax.servlet.FilterChain;
42  import javax.servlet.FilterConfig;
43  import javax.servlet.ServletException;
44  import javax.servlet.ServletRequest;
45  import javax.servlet.ServletResponse;
46  import javax.servlet.http.HttpServletRequest;
47  import javax.servlet.http.HttpServletResponse;
48  
49  import org.apache.commons.fileupload.FileUploadBase.SizeLimitExceededException;
50  import org.apache.commons.fileupload.FileUploadException;
51  
52  import fr.paris.lutece.portal.service.util.AppLogService;
53  import fr.paris.lutece.util.http.MultipartUtil;
54  
55  /**
56   * Upload filter
57   */
58  public abstract class UploadFilter implements Filter
59  {
60      private static final String PROPERTY_TITLE_FILE_SIZE_LIMIT_EXCEEDED = "portal.util.message.titleDefault";
61      private static final String PROPERTY_MESSAGE_FILE_SIZE_LIMIT_EXCEEDED = "portal.util.message.fileSizeLimitExceeded";
62      private static final int KILO_BYTE = 1024;
63      private static final String SIZE_THRESHOLD = "sizeThreshold";
64      private static final String REQUEST_SIZE_MAX = "requestSizeMax";
65      private static final String ACTIVATE_NORMALIZE_FILE_NAME = "activateNormalizeFileName";
66      private int _nSizeThreshold = -1;
67      private long _nRequestSizeMax = -1;
68      private boolean _bActivateNormalizeFileName;
69  
70      /**
71       * Forward the error message url depends site or admin implementation.
72       *
73       * @param request
74       *            The http request
75       * @param strMessageKey
76       *            the str message key
77       * @param messageArgs
78       *            the message args
79       * @param strTitleKey
80       *            the str title key
81       * @return Message
82       */
83      protected abstract String getMessageRelativeUrl( HttpServletRequest request, String strMessageKey, 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          try
96          {
97              String paramValue = config.getInitParameter( SIZE_THRESHOLD );
98  
99              if ( paramValue != null )
100             {
101                 _nSizeThreshold = Integer.parseInt( paramValue );
102             }
103 
104             paramValue = config.getInitParameter( REQUEST_SIZE_MAX );
105 
106             if ( paramValue != null )
107             {
108                 _nRequestSizeMax = Long.parseLong( paramValue );
109             }
110 
111             paramValue = config.getInitParameter( ACTIVATE_NORMALIZE_FILE_NAME );
112 
113             if ( paramValue != null )
114             {
115                 _bActivateNormalizeFileName = Boolean.valueOf( paramValue );
116             }
117         }
118         catch( NumberFormatException ex )
119         {
120             AppLogService.error( ex.getMessage( ), ex );
121             throw new ServletException( ex.getMessage( ), ex );
122         }
123     }
124 
125     /**
126      * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
127      * @param request
128      *            The ServletRequest
129      * @param response
130      *            The ServletResponse
131      * @param chain
132      *            The FilterChain
133      * @throws IOException
134      *             The IOException
135      * @throws ServletException
136      *             The SerletException
137      */
138     @Override
139     public void doFilter( ServletRequest request, ServletResponse response, FilterChain chain ) throws IOException, ServletException
140     {
141         HttpServletRequest httpRequest = (HttpServletRequest) request;
142 
143         if ( !MultipartUtil.isMultipart( httpRequest ) )
144         {
145             chain.doFilter( request, response );
146         }
147         else
148         {
149             try
150             {
151                 MultipartHttpServletRequest multiHtppRequest = MultipartUtil.convert( _nSizeThreshold, _nRequestSizeMax, _bActivateNormalizeFileName,
152                         httpRequest );
153                 chain.doFilter( multiHtppRequest, response );
154             }
155             catch( SizeLimitExceededException e )
156             {
157                 AppLogService.error( e.getMessage( ), e );
158 
159                 Object [ ] args = {
160                         getDisplaySize( )
161                 };
162                 ( (HttpServletResponse) response ).sendRedirect(
163                         getMessageRelativeUrl( httpRequest, PROPERTY_MESSAGE_FILE_SIZE_LIMIT_EXCEEDED, args, PROPERTY_TITLE_FILE_SIZE_LIMIT_EXCEEDED ) );
164             }
165             catch( FileUploadException e )
166             {
167                 AppLogService.error( e.getMessage( ), e );
168                 throw new ServletException( "Unkown error occured during the upload", e );
169             }
170         }
171     }
172 
173     /**
174      * Get the max size of upload file
175      *
176      * @return The max size
177      */
178     public long getRequestSizeMax( )
179     {
180         return _nRequestSizeMax;
181     }
182 
183     /**
184      * Default implementation for subclasses
185      */
186     @Override
187     public void destroy( )
188     {
189         // Do nothing
190     }
191 
192     /**
193      *
194      * @return the size of the request to display in the error message
195      */
196     private String getDisplaySize( )
197     {
198         long lSizeMax = getRequestSizeMax( );
199         DecimalFormat decimalFormat = (DecimalFormat) NumberFormat.getInstance( );
200         decimalFormat.applyPattern( "#" );
201 
202         return ( lSizeMax >= KILO_BYTE ) ? ( String.valueOf( lSizeMax / KILO_BYTE ) ) : ( decimalFormat.format( lSizeMax / KILO_BYTE ) );
203     }
204 }