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.xsl;
35  
36  import fr.paris.lutece.portal.business.file.File;
37  import fr.paris.lutece.portal.business.file.FileHome;
38  import fr.paris.lutece.portal.business.physicalfile.PhysicalFile;
39  import fr.paris.lutece.portal.business.physicalfile.PhysicalFileHome;
40  import fr.paris.lutece.portal.business.rbac.RBAC;
41  import fr.paris.lutece.portal.business.xsl.XslExport;
42  import fr.paris.lutece.portal.business.xsl.XslExportHome;
43  import fr.paris.lutece.portal.service.admin.AccessDeniedException;
44  import fr.paris.lutece.portal.service.fileupload.FileUploadService;
45  import fr.paris.lutece.portal.service.i18n.I18nService;
46  import fr.paris.lutece.portal.service.message.AdminMessage;
47  import fr.paris.lutece.portal.service.message.AdminMessageService;
48  import fr.paris.lutece.portal.service.plugin.Plugin;
49  import fr.paris.lutece.portal.service.plugin.PluginService;
50  import fr.paris.lutece.portal.service.rbac.RBACService;
51  import fr.paris.lutece.portal.service.security.SecurityTokenService;
52  import fr.paris.lutece.portal.service.template.AppTemplateService;
53  import fr.paris.lutece.portal.service.xsl.XslExportResourceIdService;
54  import fr.paris.lutece.portal.web.admin.PluginAdminPageJspBean;
55  import fr.paris.lutece.portal.web.upload.MultipartHttpServletRequest;
56  import fr.paris.lutece.util.ReferenceItem;
57  import fr.paris.lutece.util.ReferenceList;
58  import fr.paris.lutece.util.filesystem.FileSystemUtil;
59  import fr.paris.lutece.util.html.HtmlTemplate;
60  
61  import org.apache.commons.fileupload.FileItem;
62  import org.apache.commons.lang3.StringUtils;
63  
64  import org.xml.sax.InputSource;
65  
66  import java.io.ByteArrayInputStream;
67  import java.io.IOException;
68  import java.io.OutputStream;
69  
70  import java.util.Collection;
71  import java.util.HashMap;
72  import java.util.Map;
73  
74  import javax.servlet.http.HttpServletRequest;
75  import javax.servlet.http.HttpServletResponse;
76  
77  import javax.xml.parsers.SAXParser;
78  import javax.xml.parsers.SAXParserFactory;
79  
80  /**
81   *
82   * class XslExportJspBean
83   *
84   */
85  public class XslExportJspBean extends PluginAdminPageJspBean
86  {
87      /**
88       * Right to manage XSL Export
89       */
90      public static final String RIGHT_MANAGE_XSL_EXPORT = "CORE_XSL_EXPORT_MANAGEMENT";
91  
92      /**
93       * Serial version UID
94       */
95      private static final long serialVersionUID = -8697851692630602527L;
96  
97      // templates
98      private static final String TEMPLATE_CREATE_XSL_EXPORT = "admin/xsl/create_xsl_export.html";
99      private static final String TEMPLATE_MODIFY_XSL_EXPORT = "admin/xsl/modify_xsl_export.html";
100 
101     // Markers
102     private static final String MARK_XSL_EXPORT = "xsl_export";
103     private static final String MARK_LIST_PLUGINS = "list_plugins";
104 
105     // parameters form
106     private static final String PARAMETER_ID_XSL_EXPORT = "id_xsl_export";
107     private static final String PARAMETER_ID_FILE = "id_file";
108     private static final String PARAMETER_TITLE = "title";
109     private static final String PARAMETER_DESCRIPTION = "description";
110     private static final String PARAMETER_EXTENSION = "extension";
111     private static final String PARAMETER_PLUGIN = "plugin";
112 
113     // other constants
114     private static final String EMPTY_STRING = "";
115 
116     // message
117     private static final String MESSAGE_CONFIRM_REMOVE_XSL_EXPORT = "portal.xsl.message.confirm_remove_xsl_export";
118     private static final String MESSAGE_MANDATORY_FIELD = "portal.util.message.mandatoryField";
119 
120     private static final String FIELD_TITLE = "portal.xsl.create_xsl_export.label_title";
121     private static final String FIELD_DESCRIPTION = "portal.xsl.create_xsl_export.label_description";
122     private static final String FIELD_EXTENSION = "portal.xsl.create_xsl_export.label_extension";
123 
124     private static final String FIELD_FILE = "portal.xsl.create_xsl_export.label_file";
125     private static final String MESSAGE_XML_NOT_VALID = "portal.xsl.message.xml_not_valid";
126     private static final String MESSAGE_PERMISSION_DENIED = "portal.xsl.message.permission_denied";
127 
128     // properties
129     private static final String PROPERTY_MODIFY_XSL_EXPORT_TITLE = "portal.xsl.modify_xsl_export.title";
130     private static final String PROPERTY_CREATE_XSL_EXPORT_TITLE = "portal.xsl.create_xsl_export.title";
131 
132     // Jsp Definition
133     private static final String ANCHOR_ADMIN_DASHBOARDS = "xslexport";
134     private static final String JSP_DO_REMOVE_XSL_EXPORT = "jsp/admin/xsl/DoRemoveXslExport.jsp";
135 
136     /**
137      * Gets the xsl export creation page
138      * 
139      * @param request
140      *            The HTTP request
141      * @throws AccessDeniedException
142      *             the {@link AccessDeniedException}
143      * @return The xsl export creation page
144      */
145     public String getCreateXslExport( HttpServletRequest request ) throws AccessDeniedException
146     {
147         HashMap<String, Object> model = new HashMap<>( );
148 
149         Collection<Plugin> listPlugins = PluginService.getPluginList( );
150         ReferenceListml#ReferenceList">ReferenceList refListPlugins = new ReferenceList( );
151         ReferenceItemItem.html#ReferenceItem">ReferenceItem refItem = new ReferenceItem( );
152         Plugin pluginCore = PluginService.getCore( );
153         refItem.setCode( pluginCore.getName( ) );
154         refItem.setName( pluginCore.getName( ) );
155         refListPlugins.add( refItem );
156 
157         for ( Plugin plugin : listPlugins )
158         {
159             if ( plugin != null )
160             {
161                 refItem = new ReferenceItem( );
162                 refItem.setCode( plugin.getName( ) );
163                 refItem.setName( plugin.getName( ) );
164                 refListPlugins.add( refItem );
165             }
166         }
167 
168         model.put( MARK_LIST_PLUGINS, refListPlugins );
169         model.put( SecurityTokenService.MARK_TOKEN, SecurityTokenService.getInstance( ).getToken( request, TEMPLATE_CREATE_XSL_EXPORT ) );
170 
171         if ( !RBACService.isAuthorized( XslExport.RESOURCE_TYPE, RBAC.WILDCARD_RESOURCES_ID, XslExportResourceIdService.PERMISSION_CREATE, getUser( ) ) )
172         {
173             throw new AccessDeniedException( MESSAGE_PERMISSION_DENIED );
174         }
175 
176         setPageTitleProperty( PROPERTY_CREATE_XSL_EXPORT_TITLE );
177 
178         HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_CREATE_XSL_EXPORT, getLocale( ), model );
179 
180         return getAdminPage( template.getHtml( ) );
181     }
182 
183     /**
184      * Perform the xsl export creation
185      * 
186      * @param request
187      *            The HTTP request
188      * @throws AccessDeniedException
189      *             the {@link AccessDeniedException}
190      * @return The URL to go after performing the action
191      */
192     public String doCreateXslExport( HttpServletRequest request ) throws AccessDeniedException
193     {
194         XslExportess/xsl/XslExport.html#XslExport">XslExport xslExport = new XslExport( );
195         String strError = getXslExportData( request, xslExport );
196 
197         if ( !RBACService.isAuthorized( XslExport.RESOURCE_TYPE, RBAC.WILDCARD_RESOURCES_ID, XslExportResourceIdService.PERMISSION_CREATE, getUser( ) ) )
198         {
199             throw new AccessDeniedException( MESSAGE_PERMISSION_DENIED );
200         }
201 
202         if ( strError != null )
203         {
204             return strError;
205         }
206 
207         if ( !SecurityTokenService.getInstance( ).validate( request, TEMPLATE_CREATE_XSL_EXPORT ) )
208         {
209             throw new AccessDeniedException( ERROR_INVALID_TOKEN );
210         }
211 
212         if ( xslExport.getFile( ) != null )
213         {
214             xslExport.getFile( ).setIdFile( FileHome.create( xslExport.getFile( ) ) );
215         }
216 
217         XslExportHome.create( xslExport );
218 
219         return getJspManageXslExport( request );
220     }
221 
222     /**
223      * Gets the export format modification page
224      * 
225      * @param request
226      *            The HTTP request
227      * @throws AccessDeniedException
228      *             the {@link AccessDeniedException}
229      * @return The export format creation page
230      */
231     public String getModifyXslExport( HttpServletRequest request ) throws AccessDeniedException
232     {
233         if ( !RBACService.isAuthorized( XslExport.RESOURCE_TYPE, RBAC.WILDCARD_RESOURCES_ID, XslExportResourceIdService.PERMISSION_MODIFY, getUser( ) ) )
234         {
235             throw new AccessDeniedException( MESSAGE_PERMISSION_DENIED );
236         }
237 
238         XslExport xslExport;
239         String strIdXslExport = request.getParameter( PARAMETER_ID_XSL_EXPORT );
240         HashMap<String, Object> model = new HashMap<>( );
241         int nIdXslExport = Integer.parseInt( strIdXslExport );
242         xslExport = XslExportHome.findByPrimaryKey( nIdXslExport );
243         model.put( MARK_XSL_EXPORT, xslExport );
244 
245         Collection<Plugin> listPlugins = PluginService.getPluginList( );
246         ReferenceListml#ReferenceList">ReferenceList refListPlugins = new ReferenceList( );
247         ReferenceItemItem.html#ReferenceItem">ReferenceItem refItem = new ReferenceItem( );
248         Plugin pluginCore = PluginService.getCore( );
249         refItem.setCode( pluginCore.getName( ) );
250         refItem.setName( pluginCore.getName( ) );
251         refListPlugins.add( refItem );
252 
253         for ( Plugin plugin : listPlugins )
254         {
255             if ( plugin != null )
256             {
257                 refItem = new ReferenceItem( );
258                 refItem.setCode( plugin.getName( ) );
259                 refItem.setName( plugin.getName( ) );
260                 refListPlugins.add( refItem );
261             }
262         }
263 
264         model.put( MARK_LIST_PLUGINS, refListPlugins );
265         model.put( SecurityTokenService.MARK_TOKEN, SecurityTokenService.getInstance( ).getToken( request, TEMPLATE_MODIFY_XSL_EXPORT ) );
266 
267         setPageTitleProperty( PROPERTY_MODIFY_XSL_EXPORT_TITLE );
268 
269         HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_MODIFY_XSL_EXPORT, getLocale( ), model );
270 
271         return getAdminPage( template.getHtml( ) );
272     }
273 
274     /**
275      * Perform the xsl export modification
276      * 
277      * @param request
278      *            The HTTP request
279      * @throws AccessDeniedException
280      *             the {@link AccessDeniedException}
281      * @return The URL to go after performing the action
282      */
283     public String doModifyXslExport( HttpServletRequest request ) throws AccessDeniedException
284     {
285         if ( !RBACService.isAuthorized( XslExport.RESOURCE_TYPE, RBAC.WILDCARD_RESOURCES_ID, XslExportResourceIdService.PERMISSION_MODIFY, getUser( ) ) )
286         {
287             throw new AccessDeniedException( MESSAGE_PERMISSION_DENIED );
288         }
289 
290         XslExport xslExport;
291         String strIdXslExport = request.getParameter( PARAMETER_ID_XSL_EXPORT );
292         int nIdXslExport = Integer.parseInt( strIdXslExport );
293         xslExport = XslExportHome.findByPrimaryKey( nIdXslExport );
294 
295         String strError = getXslExportData( request, xslExport );
296 
297         if ( strError != null )
298         {
299             return strError;
300         }
301         if ( !SecurityTokenService.getInstance( ).validate( request, TEMPLATE_MODIFY_XSL_EXPORT ) )
302         {
303             throw new AccessDeniedException( ERROR_INVALID_TOKEN );
304         }
305 
306         // if xslExport
307         File fileStore = XslExportHome.findByPrimaryKey( nIdXslExport ).getFile( );
308 
309         if ( xslExport.getFile( ) != null )
310         {
311             // the file has been modified
312             File fileSource = xslExport.getFile( );
313             // init id file source and id physical file before update
314             fileSource.setIdFile( fileStore.getIdFile( ) );
315 
316             if ( fileStore.getPhysicalFile( ) != null )
317             {
318                 fileSource.getPhysicalFile( ).setIdPhysicalFile( fileStore.getPhysicalFile( ).getIdPhysicalFile( ) );
319             }
320 
321             FileHome.update( fileSource );
322         }
323         else
324         {
325             xslExport.setFile( fileStore );
326         }
327 
328         XslExportHome.update( xslExport );
329 
330         return getJspManageXslExport( request );
331     }
332 
333     /**
334      * Gets the confirmation page of delete xsl export
335      * 
336      * @param request
337      *            The HTTP request
338      * @throws AccessDeniedException
339      *             the {@link AccessDeniedException}
340      * @return the confirmation page of delete xsl export
341      */
342     public String getConfirmRemoveXslExport( HttpServletRequest request ) throws AccessDeniedException
343     {
344         if ( !RBACService.isAuthorized( XslExport.RESOURCE_TYPE, RBAC.WILDCARD_RESOURCES_ID, XslExportResourceIdService.PERMISSION_DELETE, getUser( ) ) )
345         {
346             throw new AccessDeniedException( MESSAGE_PERMISSION_DENIED );
347         }
348 
349         String strIdXslExport = request.getParameter( PARAMETER_ID_XSL_EXPORT );
350 
351         Map<String, String> parameters = new HashMap<>( );
352         parameters.put( PARAMETER_ID_XSL_EXPORT, strIdXslExport );
353         parameters.put( SecurityTokenService.PARAMETER_TOKEN, SecurityTokenService.getInstance( ).getToken( request, JSP_DO_REMOVE_XSL_EXPORT ) );
354 
355         return AdminMessageService.getMessageUrl( request, MESSAGE_CONFIRM_REMOVE_XSL_EXPORT, JSP_DO_REMOVE_XSL_EXPORT, AdminMessage.TYPE_CONFIRMATION,
356                 parameters );
357     }
358 
359     /**
360      * Perform the export format supression
361      * 
362      * @param request
363      *            The HTTP request
364      * @throws AccessDeniedException
365      *             the {@link AccessDeniedException}
366      * @return The URL to go after performing the action
367      */
368     public String doRemoveXslExport( HttpServletRequest request ) throws AccessDeniedException
369     {
370         if ( !RBACService.isAuthorized( XslExport.RESOURCE_TYPE, RBAC.WILDCARD_RESOURCES_ID, XslExportResourceIdService.PERMISSION_DELETE, getUser( ) ) )
371         {
372             throw new AccessDeniedException( MESSAGE_PERMISSION_DENIED );
373         }
374         if ( !SecurityTokenService.getInstance( ).validate( request, JSP_DO_REMOVE_XSL_EXPORT ) )
375         {
376             throw new AccessDeniedException( ERROR_INVALID_TOKEN );
377         }
378 
379         String strIdXslExport = request.getParameter( PARAMETER_ID_XSL_EXPORT );
380         int nIdXslExport = Integer.parseInt( strIdXslExport );
381         XslExport xslExport = XslExportHome.findByPrimaryKey( nIdXslExport );
382 
383         XslExportHome.remove( nIdXslExport );
384 
385         if ( xslExport.getFile( ) != null )
386         {
387             FileHome.remove( xslExport.getFile( ).getIdFile( ) );
388         }
389 
390         return getJspManageXslExport( request );
391     }
392 
393     /**
394      * Initiate a download of a XSL file
395      * 
396      * @param request
397      *            The request
398      * @param response
399      *            The response
400      * @throws IOException
401      *             Throw an exception if the outputstream has error.
402      */
403     public void doDownloadXslExport( HttpServletRequest request, HttpServletResponse response ) throws IOException
404     {
405         String strXslExportId = request.getParameter( PARAMETER_ID_XSL_EXPORT );
406 
407         if ( strXslExportId != null )
408         {
409             int nXslExportId = Integer.parseInt( strXslExportId );
410             XslExport xslExport = XslExportHome.findByPrimaryKey( nXslExportId );
411 
412             String strMimetype = xslExport.getFile( ).getMimeType( );
413             response.setContentType( ( strMimetype != null ) ? strMimetype : "application/octet-stream" );
414             response.setHeader( "Content-Disposition", "attachement; filename=\"" + xslExport.getFile( ).getTitle( ) + "\"" );
415 
416             OutputStream out = response.getOutputStream( );
417             PhysicalFile physicalFile = PhysicalFileHome.findByPrimaryKey( xslExport.getFile( ).getPhysicalFile( ).getIdPhysicalFile( ) );
418             out.write( physicalFile.getValue( ) );
419             out.flush( );
420             out.close( );
421         }
422     }
423 
424     /**
425      * Get the request data and if there is no error insert the data in the exportFormat object specified in parameter. return null if there is no error or else
426      * return the error page url
427      * 
428      * @param request
429      *            the request
430      * @param xslExport
431      *            the exportFormat Object
432      * @return null if there is no error or else return the error page url
433      */
434     private String getXslExportData( HttpServletRequest request, XslExport xslExport )
435     {
436         String strError = StringUtils.EMPTY;
437         String strTitle = request.getParameter( PARAMETER_TITLE );
438         String strDescription = request.getParameter( PARAMETER_DESCRIPTION );
439         String strExtension = request.getParameter( PARAMETER_EXTENSION );
440         String strPlugin = request.getParameter( PARAMETER_PLUGIN );
441         File fileSource = getFileData( PARAMETER_ID_FILE, request );
442 
443         if ( ( strTitle == null ) || strTitle.trim( ).equals( EMPTY_STRING ) )
444         {
445             strError = FIELD_TITLE;
446         }
447 
448         else
449             if ( ( strDescription == null ) || strDescription.trim( ).equals( EMPTY_STRING ) )
450             {
451                 strError = FIELD_DESCRIPTION;
452             }
453 
454             else
455                 if ( StringUtils.isBlank( strExtension ) )
456                 {
457                     strError = FIELD_EXTENSION;
458                 }
459 
460                 else
461                     if ( ( xslExport.getFile( ) == null ) && ( fileSource == null ) )
462                     {
463                         strError = FIELD_FILE;
464                     }
465 
466         if ( strPlugin == null )
467         {
468             strPlugin = StringUtils.EMPTY;
469         }
470 
471         // Mandatory fields
472         if ( !strError.equals( EMPTY_STRING ) )
473         {
474             Object [ ] tabRequiredFields = {
475                     I18nService.getLocalizedString( strError, getLocale( ) )
476             };
477 
478             return AdminMessageService.getMessageUrl( request, MESSAGE_MANDATORY_FIELD, tabRequiredFields, AdminMessage.TYPE_STOP );
479         }
480 
481         // Check the XML validity of the XSL stylesheet
482         if ( fileSource != null )
483         {
484             strError = isValid( fileSource.getPhysicalFile( ).getValue( ) );
485 
486             if ( strError != null )
487             {
488                 Object [ ] args = {
489                         strError
490                 };
491 
492                 return AdminMessageService.getMessageUrl( request, MESSAGE_XML_NOT_VALID, args, AdminMessage.TYPE_STOP );
493             }
494         }
495 
496         xslExport.setTitle( strTitle );
497         xslExport.setDescription( strDescription );
498         xslExport.setExtension( strExtension );
499         xslExport.setPlugin( strPlugin );
500 
501         xslExport.setFile( fileSource );
502 
503         return null;
504     }
505 
506     /**
507      * Use parsing for validate the modify xsl file
508      * 
509      * @param baXslSource
510      *            the xsl source
511      * @return the message exception when the validation is false
512      */
513     private String isValid( byte [ ] baXslSource )
514     {
515         String strError = null;
516 
517         try
518         {
519             SAXParserFactory factory = SAXParserFactory.newInstance( );
520             factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
521             factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
522             SAXParser analyzer = factory.newSAXParser( );
523             InputSource is = new InputSource( new ByteArrayInputStream( baXslSource ) );
524             analyzer.getXMLReader( ).parse( is );
525         }
526         catch( Exception e )
527         {
528             strError = e.getMessage( );
529         }
530 
531         return strError;
532     }
533 
534     /**
535      * return the url of manage export format
536      * 
537      * @param request
538      *            the request
539      * @return the url of manage export format
540      */
541     private String getJspManageXslExport( HttpServletRequest request )
542     {
543         return getAdminDashboardsUrl( request, ANCHOR_ADMIN_DASHBOARDS );
544     }
545 
546     /**
547      * Get a file contained in the request from the name of the parameter
548      *
549      * @param strFileInputName
550      *            name of the file parameter of the request
551      * @param request
552      *            the request
553      * @return file the file contained in the request with the given parameter key
554      */
555     private static File getFileData( String strFileInputName, HttpServletRequest request )
556     {
557         MultipartHttpServletRequestce/portal/web/upload/MultipartHttpServletRequest.html#MultipartHttpServletRequest">MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
558         FileItem fileItem = multipartRequest.getFile( strFileInputName );
559 
560         if ( ( fileItem != null ) && ( fileItem.getName( ) != null ) && !EMPTY_STRING.equals( fileItem.getName( ) ) )
561         {
562             Filertal/business/file/File.html#File">File file = new File( );
563             PhysicalFileysicalfile/PhysicalFile.html#PhysicalFile">PhysicalFile physicalFile = new PhysicalFile( );
564             physicalFile.setValue( fileItem.get( ) );
565             file.setTitle( FileUploadService.getFileNameOnly( fileItem ) );
566             file.setSize( (int) fileItem.getSize( ) );
567             file.setPhysicalFile( physicalFile );
568             file.setMimeType( FileSystemUtil.getMIMEType( FileUploadService.getFileNameOnly( fileItem ) ) );
569 
570             return file;
571         }
572 
573         return null;
574     }
575 }