1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package fr.paris.lutece.portal.service.file.implementation;
35
36 import static fr.paris.lutece.portal.service.file.FileService.PARAMETER_VALIDITY_TIME;
37
38 import java.security.GeneralSecurityException;
39 import java.sql.Timestamp;
40 import java.time.LocalDateTime;
41 import java.util.HashMap;
42 import java.util.Map;
43
44 import javax.servlet.http.HttpServletRequest;
45
46 import org.apache.commons.lang3.StringUtils;
47 import org.apache.commons.text.StringEscapeUtils;
48
49 import fr.paris.lutece.portal.service.file.ExpiredLinkException;
50 import fr.paris.lutece.portal.service.file.FileService;
51 import fr.paris.lutece.portal.service.file.IFileDownloadUrlService;
52 import fr.paris.lutece.portal.service.security.RsaService;
53 import fr.paris.lutece.portal.service.util.AppLogService;
54 import fr.paris.lutece.portal.service.util.AppPathService;
55 import fr.paris.lutece.util.url.UrlItem;
56
57
58
59
60
61
62 public class DefaultFileDownloadService implements IFileDownloadUrlService
63 {
64 private static final long serialVersionUID = 1L;
65
66
67 protected static final String URL_FO = "jsp/site/file/download";
68 protected static final String URL_BO = "jsp/admin/file/download";
69 private static final String SERVICE_NAME = "DefaultFileDownloadService";
70 private static final String DEFAULT_SEPARATOR = "/";
71
72 private String _separator = DEFAULT_SEPARATOR;
73
74
75 public static final String KEY_LINK_VALIDITY_TIME = "link_validity_time";
76
77 public String getSeparator( )
78 {
79 return _separator;
80 }
81
82 public void setSeparator( String separator )
83 {
84 _separator = separator;
85 }
86
87
88
89
90
91
92
93
94
95 public static Map<String, String> buildAdditionnalDatas( String strFileId, String strResourceId, String strResourceType )
96 {
97 Map<String, String> map = new HashMap<>( );
98
99 map.put( FileService.PARAMETER_FILE_ID, strFileId );
100 map.put( FileService.PARAMETER_RESOURCE_ID, strResourceId );
101 map.put( FileService.PARAMETER_RESOURCE_TYPE, strResourceType );
102
103 return map;
104 }
105
106
107
108
109 @Override
110 public String getFileDownloadUrlFO( String strFileKey, String strFileStorageServiceProviderName )
111 {
112
113 return getFileDownloadUrlFO( strFileKey, null, strFileStorageServiceProviderName );
114 }
115
116
117
118
119 @Override
120 public String getFileDownloadUrlFO( String strFileKey, Map<String, String> additionnalData, String strFileStorageServiceProviderName )
121 {
122 StringBuilder sbUrl = new StringBuilder( );
123
124 sbUrl.append( AppPathService.getBaseUrl( null ) );
125 sbUrl.append( URL_FO );
126
127 if ( additionnalData == null )
128 {
129 additionnalData = new HashMap<>( );
130 }
131 additionnalData.put( FileService.PARAMETER_FILE_ID, strFileKey );
132
133 return getEncryptedUrl( sbUrl.toString( ), getDataToEncrypt( additionnalData ), strFileStorageServiceProviderName );
134 }
135
136
137
138
139 @Override
140 public String getFileDownloadUrlBO( String strFileKey, String strFileStorageServiceProviderName )
141 {
142 return getFileDownloadUrlBO( strFileKey, null, strFileStorageServiceProviderName );
143 }
144
145
146
147
148 @Override
149 public String getFileDownloadUrlBO( String strFileKey, Map<String, String> additionnalData, String strFileStorageServiceProviderName )
150 {
151
152 StringBuilder sbUrl = new StringBuilder( );
153
154 sbUrl.append( AppPathService.getBaseUrl( null ) );
155 sbUrl.append( URL_BO );
156
157 if ( additionnalData == null )
158 {
159 additionnalData = new HashMap<>( );
160 }
161 additionnalData.put( FileService.PARAMETER_FILE_ID, strFileKey );
162
163 return getEncryptedUrl( sbUrl.toString( ), getDataToEncrypt( additionnalData ), strFileStorageServiceProviderName );
164 }
165
166
167
168
169
170
171
172
173
174 protected String getEncryptedUrl( String strUrl, String dataToEncrypt, String strFileStorageServiceProviderName )
175 {
176 UrlItemil/url/UrlItem.html#UrlItem">UrlItem item = new UrlItem( strUrl );
177
178 try
179 {
180 String idEncrytped = RsaService.encryptRsa( dataToEncrypt );
181
182 item.addParameter( FileService.PARAMETER_PROVIDER, strFileStorageServiceProviderName );
183 item.addParameter( FileService.PARAMETER_DATA, idEncrytped );
184
185 return item.getUrlWithEntity( );
186 }
187 catch( GeneralSecurityException e )
188 {
189 AppLogService.error( e.getMessage( ), e );
190 return null;
191 }
192 }
193
194
195
196
197 @Override
198 public String getName( )
199 {
200 return SERVICE_NAME;
201 }
202
203
204
205
206
207
208
209 private String getDataToEncrypt( Map<String, String> additionnalData )
210 {
211 StringBuilder sb = new StringBuilder( );
212 sb.append( StringUtils.defaultIfEmpty( additionnalData.get( FileService.PARAMETER_FILE_ID ), "" ) ).append( _separator );
213 sb.append( StringUtils.defaultIfEmpty( additionnalData.get( FileService.PARAMETER_RESOURCE_ID ), "" ) ).append( _separator );
214 sb.append( StringUtils.defaultIfEmpty( additionnalData.get( FileService.PARAMETER_RESOURCE_TYPE ), "" ) ).append( _separator );
215 sb.append( calculateEndValidity( ) );
216
217 return sb.toString( );
218 }
219
220
221
222
223
224
225 protected long calculateEndValidity( )
226 {
227 LocalDateTime endValidity = LocalDateTime.MAX;
228 if ( getValidityTime( ) > 0 )
229 {
230 endValidity = LocalDateTime.now( ).plusMinutes( LINK_VALIDITY_TIME );
231 }
232 return Timestamp.valueOf( endValidity ).getTime( );
233 }
234
235
236
237
238 @Override
239 public Map<String, String> getRequestDataBO( HttpServletRequest request )
240 {
241 String strEncryptedDataParam = request.getParameter( FileService.PARAMETER_DATA );
242
243 try
244 {
245
246 String unescapedUrlParam = StringEscapeUtils.unescapeHtml4( strEncryptedDataParam );
247 String strDecryptedData = RsaService.decryptRsa( unescapedUrlParam );
248 return getDecryptedData( strDecryptedData );
249 }
250 catch( GeneralSecurityException e )
251 {
252 AppLogService.error( e.getMessage( ), e );
253 return null;
254 }
255 }
256
257
258
259
260 @Override
261 public Map<String, String> getRequestDataFO( HttpServletRequest request )
262 {
263 String strEncryptedDataParam = request.getParameter( FileService.PARAMETER_DATA );
264
265 try
266 {
267
268 String unescapedUrlParam = StringEscapeUtils.unescapeHtml4( strEncryptedDataParam );
269 String strDecryptedData = RsaService.decryptRsa( unescapedUrlParam );
270 return getDecryptedData( strDecryptedData );
271 }
272 catch( GeneralSecurityException e )
273 {
274 AppLogService.error( e.getMessage( ), e );
275 return null;
276 }
277 }
278
279
280
281
282
283
284
285 protected Map<String, String> getDecryptedData( String strData )
286 {
287 String [ ] data = strData.split( _separator );
288 Map<String, String> fileData = buildAdditionnalDatas( data [0], data [1], data [2] );
289 fileData.put( PARAMETER_VALIDITY_TIME, data [3] );
290
291 return fileData;
292 }
293
294
295
296
297 @Override
298 public void checkLinkValidity( Map<String, String> fileData ) throws ExpiredLinkException
299 {
300 LocalDateTime validityTime = new Timestamp( Long.parseLong( fileData.get( FileService.PARAMETER_VALIDITY_TIME ) ) ).toLocalDateTime( );
301
302 if ( LocalDateTime.now( ).isAfter( validityTime ) )
303 {
304 throw new ExpiredLinkException( "Link expired on : " + validityTime.toString( ) );
305 }
306 }
307 }