1 /*
2 * Copyright (c) 2002-2025, 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.plugins.forms.web.file;
35
36 import javax.servlet.http.HttpServletRequest;
37
38 import org.apache.commons.fileupload.FileItem;
39 import org.apache.commons.lang3.math.NumberUtils;
40
41 import fr.paris.lutece.plugins.forms.service.FormService;
42 import fr.paris.lutece.plugins.forms.util.FormsConstants;
43 import fr.paris.lutece.portal.business.file.File;
44 import fr.paris.lutece.portal.business.file.FileHome;
45 import fr.paris.lutece.portal.business.physicalfile.PhysicalFile;
46 import fr.paris.lutece.portal.business.physicalfile.PhysicalFileHome;
47 import fr.paris.lutece.portal.service.image.ImageResource;
48 import fr.paris.lutece.portal.service.image.ImageResourceManager;
49 import fr.paris.lutece.portal.service.image.ImageResourceProvider;
50 import fr.paris.lutece.portal.service.spring.SpringContextService;
51 import fr.paris.lutece.portal.service.util.AppException;
52 import fr.paris.lutece.portal.web.LocalVariables;
53 import fr.paris.lutece.util.file.FileUtil;
54
55 /**
56 * Image Resource Service for the plugin Forms
57 */
58 public final class FormsFileImageService implements ImageResourceProvider
59 {
60 // Constants
61 private static final String IMAGE_RESOURCE_TYPE_ID = "forms_entry_img";
62 private static final int ID_RESPONSE_NOT_FOUND = NumberUtils.INTEGER_MINUS_ONE;
63
64 /**
65 * Constructor
66 */
67 private FormsFileImageService( )
68 {
69
70 }
71
72 /**
73 * Get the unique instance of the service
74 *
75 * @return the unique instance of the FormsFileImageService service
76 */
77 public static FormsFileImageService getInstance( )
78 {
79 return FormsFileImageServiceHolder._singleton;
80 }
81
82 /**
83 * Initializes the service
84 */
85 public void register( )
86 {
87 ImageResourceManager.registerProvider( this );
88 }
89
90 /**
91 * Return the Resource id
92 *
93 * @param nIdResource
94 * The resource identifier
95 * @return The Resource Image
96 */
97 @Override
98 public ImageResource getImageResource( int nIdResource )
99 {
100 // When using an older core version (before 5.1.5), the local variables will not
101 // have been set by the image servlet. So we can get null or a request from another thread.
102 // We could try to detect this by checking request.getServletPath( ) (or maybe other things?)
103 // but it would break if we decide to expose this provider through another entry point.
104 // Also, on Tomcat (tested 8.5.5), it seems like the request object is reused just like
105 // the thread, so that even if the local variables were set in another request,
106 // the object we get here is the correct one (with the correct LuteceUser or AdminUser etc).
107 // Also, Portal.jsp, the main entry point of the webapp, does clean up the local variables.
108 // Note that the other request could even have run code from another webapp (not even a Lutece webapp)
109 // Also, we could log a warning here when request is null, but then it would prevent from using
110 // this function from code not associated with a request. So no warnings.
111 HttpServletRequest request = LocalVariables.getRequest( );
112
113 ImageResource imageResource = null;
114
115 File file = FileHome.findByPrimaryKey( nIdResource );
116 if ( file != null && file.getPhysicalFile( ) != null && FileUtil.hasImageExtension( file.getTitle( ) ) && request != null )
117 {
118 FormService formService = SpringContextService.getBean( FormService.BEAN_NAME );
119 int nIdResponse = NumberUtils.toInt( request.getParameter( FormsConstants.PARAMETER_ID_RESPONSE ), ID_RESPONSE_NOT_FOUND );
120
121 if ( formService.isFileAccessAuthorized( request, nIdResponse, nIdResource ) )
122 {
123 imageResource = createImageResource( file );
124 }
125 }
126
127 return imageResource;
128 }
129
130 /**
131 * Create an ImageResource associated to the given File
132 *
133 * @param file
134 * The File on which to based to create the create the ImageResource
135 * @return the ImageResource associated to the given File or null if an error occurred
136 */
137 private ImageResource createImageResource( File file )
138 {
139 ImageResource imageResource = null;
140
141 if ( file != null && file.getPhysicalFile( ) != null )
142 {
143 PhysicalFile physicalFile = PhysicalFileHome.findByPrimaryKey( file.getPhysicalFile( ).getIdPhysicalFile( ) );
144 if ( physicalFile != null )
145 {
146 imageResource = new ImageResource( );
147 imageResource.setImage( physicalFile.getValue( ) );
148 imageResource.setMimeType( file.getMimeType( ) );
149 }
150 }
151
152 return imageResource;
153 }
154
155 /**
156 * Return the Resource Type id
157 *
158 * @return The Resource Type Id
159 */
160 @Override
161 public String getResourceTypeId( )
162 {
163 return IMAGE_RESOURCE_TYPE_ID;
164 }
165
166 /**
167 * Class holder for the singleton of the FormsFileImageService service
168 */
169 private static class FormsFileImageServiceHolder
170 {
171 // Variables
172 private static final FormsFileImageService/FormsFileImageService.html#FormsFileImageService">FormsFileImageService _singleton = new FormsFileImageService( );
173 }
174
175 @Override
176 public String addImageResource(FileItem fileItem) {
177 throw new AppException( "Not implemented yet" );
178 }
179 }