View Javadoc
1   /*
2    * Copyright (c) 2002-2017, 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.plugins.directory.business;
35  
36  import fr.paris.lutece.plugins.directory.service.upload.DirectoryAsynchronousUploadHandler;
37  import fr.paris.lutece.plugins.directory.utils.DirectoryErrorException;
38  import fr.paris.lutece.plugins.directory.utils.DirectoryUtils;
39  import fr.paris.lutece.portal.business.regularexpression.RegularExpression;
40  import fr.paris.lutece.portal.service.fileupload.FileUploadService;
41  import fr.paris.lutece.portal.service.i18n.I18nService;
42  import fr.paris.lutece.portal.service.message.AdminMessage;
43  import fr.paris.lutece.portal.service.message.AdminMessageService;
44  import fr.paris.lutece.portal.service.regularexpression.RegularExpressionService;
45  import fr.paris.lutece.portal.service.util.AppPropertiesService;
46  import fr.paris.lutece.util.filesystem.FileSystemUtil;
47  
48  import org.apache.commons.fileupload.FileItem;
49  import org.apache.commons.lang.StringUtils;
50  
51  import java.util.ArrayList;
52  import java.util.List;
53  import java.util.Locale;
54  
55  import javax.servlet.http.HttpServletRequest;
56  import javax.servlet.http.HttpSession;
57  
58  /**
59   *
60   * AbstractEntryTypeUpload
61   *
62   */
63  public abstract class AbstractEntryTypeUpload extends Entry
64  {
65      // PARAMETERS
66      protected static final String PARAMETER_MAX_FILES = "max_files";
67      protected static final String PARAMETER_FILE_MAX_SIZE = "file_max_size";
68  
69      // CONSTANTS
70      protected static final String CONSTANT_MAX_FILES = "max_files";
71      protected static final String CONSTANT_FILE_MAX_SIZE = "file_max_size";
72      protected static final String ALL = "*";
73      protected static final String COMMA = ",";
74  
75      // PROPERTIES
76      private static final String PROPERTY_MESSAGE_ERROR_UPLOADING_FILE_MAX_FILES = "directory.message.error.uploading_file.max_files";
77      private static final String PROPERTY_MESSAGE_ERROR_UPLOADING_FILE_FILE_MAX_SIZE = "directory.message.error.uploading_file.file_max_size";
78      private static final String PROPERTY_UPLOAD_FILE_DEFAULT_MAX_SIZE = "directory.upload.file.default_max_size";
79  
80      // FIELDS
81      private static final String FIELD_MAX_FILES = "directory.create_entry.label_max_files";
82      private static final String FIELD_FILE_MAX_SIZE = "directory.create_entry.label_file_max_size";
83  
84      /**
85       * Set the fields
86       * 
87       * @param request
88       *            the HTTP request
89       * @param listFields
90       *            the list of fields to set
91       */
92      protected abstract void setFields( HttpServletRequest request, List<Field> listFields );
93  
94      /**
95       * Check the record field data for a single file item
96       * 
97       * @param fileItem
98       *            the file item
99       * @param locale
100      *            the locale
101      * @throws DirectoryErrorException
102      *             exception if there is an error
103      */
104     protected abstract void checkRecordFieldData( FileItem fileItem, Locale locale ) throws DirectoryErrorException;
105 
106     /**
107      * {@inheritDoc}
108      */
109     @Override
110     public void canUploadFiles( List<FileItem> listUploadedFileItems, List<FileItem> listFileItemsToUpload, Locale locale ) throws DirectoryErrorException
111     {
112         /** 1) Check max files */
113         Field fieldMaxFiles = DirectoryUtils.findFieldByTitleInTheList( CONSTANT_MAX_FILES, getFields( ) );
114 
115         // By default, max file is set at 1
116         int nMaxFiles = 1;
117 
118         if ( ( fieldMaxFiles != null ) && StringUtils.isNotBlank( fieldMaxFiles.getValue( ) ) && StringUtils.isNumeric( fieldMaxFiles.getValue( ) ) )
119         {
120             nMaxFiles = DirectoryUtils.convertStringToInt( fieldMaxFiles.getValue( ) );
121         }
122 
123         if ( ( listUploadedFileItems != null ) && ( listFileItemsToUpload != null ) )
124         {
125             int nNbFiles = listUploadedFileItems.size( ) + listFileItemsToUpload.size( );
126 
127             if ( nNbFiles > nMaxFiles )
128             {
129                 Object [ ] params = {
130                     nMaxFiles
131                 };
132                 String strMessage = I18nService.getLocalizedString( PROPERTY_MESSAGE_ERROR_UPLOADING_FILE_MAX_FILES, params, locale );
133                 throw new DirectoryErrorException( this.getTitle( ), strMessage );
134             }
135         }
136 
137         /** 2) Check files size */
138         Field fieldFileMaxSize = DirectoryUtils.findFieldByTitleInTheList( CONSTANT_FILE_MAX_SIZE, getFields( ) );
139         int nMaxSize = DirectoryUtils.CONSTANT_ID_NULL;
140 
141         if ( ( fieldFileMaxSize != null ) && StringUtils.isNotBlank( fieldFileMaxSize.getValue( ) ) && StringUtils.isNumeric( fieldFileMaxSize.getValue( ) ) )
142         {
143             nMaxSize = DirectoryUtils.convertStringToInt( fieldFileMaxSize.getValue( ) );
144         }
145         else
146         {
147             // For version 2.0.13 and below, the max size was stored in the width of the field "option" for EntryTypeDownloadUrl
148             Field fieldOption = DirectoryUtils.findFieldByTitleInTheList( EntryTypeDownloadUrl.CONSTANT_OPTION, getFields( ) );
149 
150             if ( fieldOption != null )
151             {
152                 nMaxSize = fieldOption.getWidth( );
153             }
154         }
155 
156         // If no max size defined in the db, then fetch if from the directory.properties file
157         if ( nMaxSize == DirectoryUtils.CONSTANT_ID_NULL )
158         {
159             nMaxSize = AppPropertiesService.getPropertyInt( PROPERTY_UPLOAD_FILE_DEFAULT_MAX_SIZE, 5242880 );
160         }
161 
162         // If nMaxSize == -1, then no size limit
163         if ( ( nMaxSize != DirectoryUtils.CONSTANT_ID_NULL ) && ( listFileItemsToUpload != null ) && !listFileItemsToUpload.isEmpty( ) )
164         {
165             for ( FileItem fileItem : listFileItemsToUpload )
166             {
167                 if ( fileItem.getSize( ) > nMaxSize )
168                 {
169                     Object [ ] params = {
170                         nMaxSize
171                     };
172                     String strMessage = I18nService.getLocalizedString( PROPERTY_MESSAGE_ERROR_UPLOADING_FILE_FILE_MAX_SIZE, params, locale );
173                     throw new DirectoryErrorException( this.getTitle( ), strMessage );
174                 }
175             }
176         }
177     }
178 
179     // CHECKS
180 
181     /**
182      * Check the entry data
183      * 
184      * @param request
185      *            the HTTP request
186      * @param locale
187      *            the locale
188      * @return the error message url if there is an error, an empty string otherwise
189      */
190     protected String checkEntryData( HttpServletRequest request, Locale locale )
191     {
192         String strTitle = request.getParameter( PARAMETER_TITLE );
193         String strMaxFiles = request.getParameter( PARAMETER_MAX_FILES );
194         String strFileMaxSize = request.getParameter( PARAMETER_FILE_MAX_SIZE );
195         String strFieldError = DirectoryUtils.EMPTY_STRING;
196 
197         if ( StringUtils.isBlank( strTitle ) )
198         {
199             strFieldError = FIELD_TITLE;
200         }
201         else
202             if ( StringUtils.isBlank( strMaxFiles ) )
203             {
204                 strFieldError = FIELD_MAX_FILES;
205             }
206             else
207                 if ( StringUtils.isBlank( strFileMaxSize ) )
208                 {
209                     strFieldError = FIELD_FILE_MAX_SIZE;
210                 }
211 
212         if ( !strFieldError.equals( DirectoryUtils.EMPTY_STRING ) )
213         {
214             Object [ ] tabRequiredFields = {
215                 I18nService.getLocalizedString( strFieldError, locale )
216             };
217 
218             return AdminMessageService.getMessageUrl( request, MESSAGE_MANDATORY_FIELD, tabRequiredFields, AdminMessage.TYPE_STOP );
219         }
220 
221         if ( !StringUtils.isNumeric( strMaxFiles ) )
222         {
223             strFieldError = FIELD_MAX_FILES;
224         }
225         else
226             if ( !StringUtils.isNumeric( strFileMaxSize ) )
227             {
228                 strFieldError = FIELD_FILE_MAX_SIZE;
229             }
230 
231         if ( !strFieldError.equals( DirectoryUtils.EMPTY_STRING ) )
232         {
233             Object [ ] tabRequiredFields = {
234                 I18nService.getLocalizedString( strFieldError, locale )
235             };
236 
237             return AdminMessageService.getMessageUrl( request, MESSAGE_NUMERIC_FIELD, tabRequiredFields, AdminMessage.TYPE_STOP );
238         }
239 
240         return StringUtils.EMPTY;
241     }
242 
243     /**
244      * Check the record field data
245      * 
246      * @param listFilesSource
247      *            the file source to upload
248      * @param locale
249      *            the locale
250      * @throws DirectoryErrorException
251      *             exception if there is an error
252      */
253     protected void checkRecordFieldData( List<FileItem> listFilesSource, Locale locale ) throws DirectoryErrorException
254     {
255         for ( FileItem fileSource : listFilesSource )
256         {
257             // Check mandatory attribute
258             String strFilename = ( fileSource != null ) ? FileUploadService.getFileNameOnly( fileSource ) : StringUtils.EMPTY;
259 
260             if ( isMandatory( ) && StringUtils.isBlank( strFilename ) )
261             {
262                 throw new DirectoryErrorException( getTitle( ) );
263             }
264 
265             String strMimeType = FileSystemUtil.getMIMEType( strFilename );
266 
267             // Check mime type with regular expressions
268             List<RegularExpression> listRegularExpression = this.getFields( ).get( 0 ).getRegularExpressionList( );
269 
270             if ( StringUtils.isNotBlank( strFilename ) && ( listRegularExpression != null ) && !listRegularExpression.isEmpty( )
271                     && RegularExpressionService.getInstance( ).isAvailable( ) )
272             {
273                 for ( RegularExpression regularExpression : listRegularExpression )
274                 {
275                     if ( !RegularExpressionService.getInstance( ).isMatches( strMimeType, regularExpression ) )
276                     {
277                         throw new DirectoryErrorException( getTitle( ), regularExpression.getErrorMessage( ) );
278                     }
279                 }
280             }
281 
282             // Specific Check from each entry types
283             checkRecordFieldData( fileSource, locale );
284         }
285     }
286 
287     // FINDERS
288 
289     /**
290      * Get the file source from the session
291      * 
292      * @param request
293      *            the HttpServletRequest
294      * @return the file item
295      */
296     protected List<FileItem> getFileSources( HttpServletRequest request )
297     {
298         HttpSession session = request.getSession( false );
299 
300         if ( session != null )
301         {
302             // check the file in session - it might no be deleted
303             return DirectoryAsynchronousUploadHandler.getHandler( ).getFileItems( Integer.toString( getIdEntry( ) ), session.getId( ) );
304         }
305 
306         return null;
307     }
308 
309     // SET
310 
311     /**
312      * Set the list of fields
313      * 
314      * @param request
315      *            the HTTP request
316      */
317     protected void setFields( HttpServletRequest request )
318     {
319         List<Field> listFields = new ArrayList<Field>( );
320         listFields.add( buildFieldMaxFiles( request ) );
321         listFields.add( buildFieldFileMaxSize( request ) );
322 
323         setFields( request, listFields );
324 
325         this.setFields( listFields );
326     }
327 
328     // PRIVATE METHODS
329 
330     /**
331      * Build the field for max files
332      * 
333      * @param request
334      *            the HTTP request
335      * @return the field
336      */
337     private Field buildFieldMaxFiles( HttpServletRequest request )
338     {
339         String strMaxFiles = request.getParameter( PARAMETER_MAX_FILES );
340         int nMaxFiles = DirectoryUtils.convertStringToInt( strMaxFiles );
341         Field fieldMaxFiles = DirectoryUtils.findFieldByTitleInTheList( CONSTANT_MAX_FILES, getFields( ) );
342 
343         if ( fieldMaxFiles == null )
344         {
345             fieldMaxFiles = new Field( );
346         }
347 
348         fieldMaxFiles.setEntry( this );
349         fieldMaxFiles.setTitle( CONSTANT_MAX_FILES );
350         fieldMaxFiles.setValue( Integer.toString( nMaxFiles ) );
351 
352         return fieldMaxFiles;
353     }
354 
355     /**
356      * Build the field for file max size
357      * 
358      * @param request
359      *            the HTTP request
360      * @return the field
361      */
362     private Field buildFieldFileMaxSize( HttpServletRequest request )
363     {
364         String strFileMaxSize = request.getParameter( PARAMETER_FILE_MAX_SIZE );
365         int nFileMaxSize = DirectoryUtils.convertStringToInt( strFileMaxSize );
366         Field fieldMaxFiles = DirectoryUtils.findFieldByTitleInTheList( CONSTANT_FILE_MAX_SIZE, getFields( ) );
367 
368         if ( fieldMaxFiles == null )
369         {
370             fieldMaxFiles = new Field( );
371         }
372 
373         fieldMaxFiles.setEntry( this );
374         fieldMaxFiles.setTitle( CONSTANT_FILE_MAX_SIZE );
375         fieldMaxFiles.setValue( Integer.toString( nFileMaxSize ) );
376 
377         return fieldMaxFiles;
378     }
379 }