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.system;
35  
36  import java.io.File;
37  import java.io.FileInputStream;
38  import java.io.FileNotFoundException;
39  import java.io.IOException;
40  import java.io.Serializable;
41  import java.util.ArrayList;
42  import java.util.Collection;
43  import java.util.Collections;
44  import java.util.Date;
45  import java.util.HashMap;
46  import java.util.List;
47  import java.util.Map;
48  
49  import javax.servlet.ServletContext;
50  import javax.servlet.http.HttpServletRequest;
51  
52  import fr.paris.lutece.portal.service.admin.AccessDeniedException;
53  import fr.paris.lutece.portal.service.admin.AdminUserService;
54  import fr.paris.lutece.portal.service.datastore.DatastoreService;
55  import fr.paris.lutece.portal.service.datastore.LocalizedData;
56  import fr.paris.lutece.portal.service.datastore.LocalizedDataGroup;
57  import fr.paris.lutece.portal.service.i18n.I18nService;
58  import fr.paris.lutece.portal.service.security.SecurityTokenService;
59  import fr.paris.lutece.portal.service.site.properties.SitePropertiesService;
60  import fr.paris.lutece.portal.service.template.AppTemplateService;
61  import fr.paris.lutece.portal.service.util.AppPathService;
62  import fr.paris.lutece.portal.service.util.AppPropertiesService;
63  import fr.paris.lutece.portal.web.admin.AdminFeaturesPageJspBean;
64  import fr.paris.lutece.util.html.HtmlTemplate;
65  import fr.paris.lutece.util.http.SecurityUtil;
66  
67  /**
68   * This class provides the user interface to manage system features ( manage logs, view system files, ... ).
69   */
70  public class SystemJspBean extends AdminFeaturesPageJspBean
71  {
72      // Right
73      public static final String RIGHT_PROPERTIES_MANAGEMENT = "CORE_PROPERTIES_MANAGEMENT";
74      public static final String RIGHT_LOGS_VISUALISATION = "CORE_LOGS_VISUALISATION";
75  
76      // Jsp definition
77      public static final String JSP_MANAGE_PROPERTIES = "ManageProperties.jsp";
78  
79      /** serial id */
80      private static final long serialVersionUID = 3770485521087669430L;
81  
82      // Markers
83      private static final String MARK_FILES_LIST = "files_list";
84      private static final String MARK_FILES_SYSTEM_DIRECTORY = "files_system_directory";
85      private static final String MARK_FILES_SYSTEM_NAME = "file_system_name";
86      private static final String MARK_FILE_SYSTEM_DATA = "file_system_data";
87      private static final String MARK_PROPERTIES_GROUPS_LIST = "groups_list";
88  
89      // Template Files path
90      private static final String TEMPLATE_MANAGE_FILES_SYSTEM = "admin/system/manage_files_system.html";
91      private static final String TEMPLATE_VIEW_FILES_SYSTEM = "admin/system/view_files_system.html";
92      private static final String TEMPLATE_VIEW_FILE = "admin/system/view_file.html";
93  
94      private static final String TEMPLATE_MODIFY_PROPERTIES = "admin/system/modify_properties.html";
95  
96      // Parameters
97      private static final String PARAMETER_FILE = "file";
98      private static final String PARAMETER_DIRECTORY = "directory";
99      private static final String PARAMETER_DIR = "dir";
100 
101     // Properties file definition
102     private static final String PROPERTY_FILES_SYSTEM_LIST = "system.list";
103     private static final String PROPERTY_TITLE_MANAGE_FILES_SYSTEM = "portal.system.manage_files_system.pageTitle";
104     private static final String PROPERTY_FILE_DESCRIPTION = "portal.system.manage_files_system.description.";
105     private static final String PROPERTY_FILE_NAME = "portal.system.manage_files_system.name.";
106     private static final String PROPERTY_TITLE_VIEW_FILES_SYSTEM = "portal.system.view_files_system.pageTitle";
107     private static final String PROPERTY_TITLE_VIEW_FILE = "portal.system.view_file.pageTitle";
108     private static final String MARK_WEBAPP_URL = "webapp_url";
109     private static final String MARK_LOCALE = "locale";
110 
111     /**
112      * Returns ViewLogs page
113      *
114      * @param request
115      *            The HTTP request.
116      * @return The HTML code
117      */
118     public String getManageFilesSystem( HttpServletRequest request )
119     {
120         setPageTitleProperty( PROPERTY_TITLE_MANAGE_FILES_SYSTEM );
121         ArrayList<SystemFile> list = new ArrayList<>( );
122 
123         for ( String strDirectory : getDirectories( ) )
124         {
125             SystemFileeb/system/SystemFile.html#SystemFile">SystemFile file = new SystemFile( );
126             file.setName( I18nService.getLocalizedString( PROPERTY_FILE_NAME + strDirectory, request.getLocale( ) ) );
127             file.setDescription( I18nService.getLocalizedString( PROPERTY_FILE_DESCRIPTION + strDirectory, request.getLocale( ) ) );
128             file.setDirectory( AppPropertiesService.getProperty( "system." + strDirectory + ".directory" ) );
129             list.add( file );
130         }
131 
132         Map<String, Collection<SystemFile>> model = new HashMap<>( );
133         model.put( MARK_FILES_LIST, list );
134 
135         HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_MANAGE_FILES_SYSTEM, getLocale( ), model );
136 
137         return getAdminPage( template.getHtml( ) );
138     }
139 
140     /**
141      * Get directory list
142      *
143      * @param request
144      *            The request
145      * @return The html code
146      */
147     public String getManageFilesSystemDir( HttpServletRequest request )
148     {
149         setPageTitleProperty( PROPERTY_TITLE_VIEW_FILES_SYSTEM );
150         String strDir = request.getParameter( PARAMETER_DIR );
151 
152         if ( !isValidDirectoryPath( strDir ) )
153         {
154             return getManageFilesSystem( request );
155         }
156 
157         String strDirectory = AppPathService.getWebAppPath( ) + strDir;
158         File directory = new File( strDirectory );
159         ArrayList<SystemFile> listFiles = new ArrayList<>( );
160         for ( File file : directory.listFiles( ) )
161         {
162             SystemFileb/system/SystemFile.html#SystemFile">SystemFile sFile = new SystemFile( );
163             sFile.setName( file.getName( ) );
164             sFile.setDirectory( strDir );
165             sFile.setSize( (int) ( file.length( ) / 1000 ) + 1 );
166             sFile.setDate( new Date( file.lastModified( ) ) );
167             listFiles.add( sFile );
168         }
169         Collections.sort( listFiles );
170 
171         Map<String, Serializable> model = new HashMap<>( );
172         model.put( MARK_FILES_LIST, listFiles );
173         model.put( MARK_FILES_SYSTEM_DIRECTORY, strDir );
174 
175         HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_VIEW_FILES_SYSTEM, getLocale( ), model );
176 
177         return getAdminPage( template.getHtml( ) );
178     }
179 
180     // //////////////////////////////////////////////////////////////////////////
181     // Methods to display a system file
182     /**
183      * Returns a FileView page
184      *
185      * @param request
186      *            The HTTP request.
187      * @return The HTML code
188      */
189     public String getFileView( HttpServletRequest request )
190     {
191         Map<String, Object> model = new HashMap<>( );
192         setPageTitleProperty( PROPERTY_TITLE_VIEW_FILE );
193 
194         String strFileData;
195         String strFile = request.getParameter( PARAMETER_FILE );
196         String strDirectory = request.getParameter( PARAMETER_DIRECTORY );
197 
198         if ( strFile == null )
199         {
200             strFileData = "ERROR : No file selected !";
201         }
202         else
203             if ( !isValidDirectoryPath( strDirectory ) )
204             {
205                 strFileData = "ERROR : Invalid directory !";
206             }
207             else
208             {
209                 String strFilePath = AppPathService.getWebAppPath( );
210 
211                 if ( strFilePath != null && !SecurityUtil.containsPathManipulationChars( request, strFile ) )
212                 {
213                     strFileData = getFileData( strFilePath + strDirectory + strFile );
214                 }
215                 else
216                 {
217                     strFileData = "ERROR : " + strFile + " not found !";
218                 }
219             }
220 
221         model.put( MARK_FILES_SYSTEM_NAME, strDirectory + strFile );
222         model.put( MARK_FILE_SYSTEM_DATA, strFileData );
223         model.put( MARK_FILES_SYSTEM_DIRECTORY, strDirectory );
224 
225         HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_VIEW_FILE, getLocale( ), model );
226 
227         return getAdminPage( template.getHtml( ) );
228     }
229 
230     /**
231      * Returns the form to update info about the webmaster.properties
232      *
233      * @param request
234      *            The Http request
235      * @return The HTML form to update info
236      */
237     public String getManageProperties( HttpServletRequest request )
238     {
239         Map<String, Object> model = new HashMap<>( );
240         model.put( MARK_PROPERTIES_GROUPS_LIST, SitePropertiesService.getGroups( getLocale( ) ) );
241         model.put( MARK_WEBAPP_URL, AppPathService.getBaseUrl( request ) );
242         model.put( MARK_LOCALE, getLocale( ).getLanguage( ) );
243         model.put( SecurityTokenService.MARK_TOKEN, SecurityTokenService.getInstance( ).getToken( request, TEMPLATE_MODIFY_PROPERTIES ) );
244 
245         HtmlTemplate templateList = AppTemplateService.getTemplate( TEMPLATE_MODIFY_PROPERTIES, getLocale( ), model );
246 
247         return getAdminPage( templateList.getHtml( ) );
248     }
249 
250     /**
251      * Process the change form of the webmaster.properties
252      *
253      * @param request
254      *            The Http request
255      * @param context
256      *            The context
257      * @return The Jsp URL of the process result
258      * @throws AccessDeniedException
259      *             if the security token is invalid
260      */
261     public static String doModifyProperties( HttpServletRequest request, ServletContext context ) throws AccessDeniedException
262     {
263         if ( !SecurityTokenService.getInstance( ).validate( request, TEMPLATE_MODIFY_PROPERTIES ) )
264         {
265             throw new AccessDeniedException( ERROR_INVALID_TOKEN );
266         }
267         List<LocalizedDataGroup> groups = SitePropertiesService.getGroups( AdminUserService.getAdminUser( request ).getLocale( ) );
268 
269         for ( LocalizedDataGroup group : groups )
270         {
271             List<LocalizedData> datas = group.getLocalizedDataList( );
272 
273             for ( LocalizedData data : datas )
274             {
275                 String strValue = request.getParameter( data.getKey( ) );
276 
277                 if ( ( strValue != null ) && !data.getValue( ).equals( strValue ) )
278                 {
279                     DatastoreService.setDataValue( data.getKey( ), strValue );
280                 }
281             }
282         }
283 
284         // if the operation occurred well, redirects towards the view of the Properties
285         return JSP_MANAGE_PROPERTIES;
286     }
287 
288     // /////////////////////////////////////////////////////////////////////////////
289     // Private Implementation
290     /**
291      * Returns the content of a file.
292      *
293      * @param strFilePath
294      *            The file Path
295      * @return The content of the file.
296      */
297     private static String getFileData( String strFilePath )
298     {
299         StringBuilder sbData = new StringBuilder( );
300 
301         try ( FileInputStream fis = new FileInputStream( strFilePath ) )
302         {
303             int chr = 0;
304 
305             while ( chr != -1 )
306             {
307                 chr = fis.read( );
308                 sbData.append( (char) chr );
309             }
310 
311             // we delete the end of file character
312             sbData.setLength( sbData.length( ) - 1 );
313         }
314         catch( FileNotFoundException e )
315         {
316             sbData.append( "ERROR : File " ).append( strFilePath ).append( " not found" );
317         }
318         catch( IOException e )
319         {
320             sbData.append( "ERROR : Error reading the file : " ).append( strFilePath );
321         }
322         return sbData.toString( );
323     }
324 
325     /**
326      * Returns all authorized directories
327      * 
328      * @return a directories array
329      */
330     private String [ ] getDirectories( )
331     {
332         String strDirectories = AppPropertiesService.getProperty( PROPERTY_FILES_SYSTEM_LIST );
333         return strDirectories.split( "," );
334     }
335 
336     /**
337      * Checks if a given path is among the authorized list
338      * 
339      * @param strPath
340      *            The path to check
341      * @return true if authorized
342      */
343     private boolean isValidDirectoryPath( String strPath )
344     {
345         for ( String strFileSystemName : getDirectories( ) )
346         {
347             String strDirectoryPath = AppPropertiesService.getProperty( "system." + strFileSystemName + ".directory" );
348 
349             if ( strDirectoryPath.equals( strPath ) )
350             {
351                 return true;
352             }
353         }
354         return false;
355     }
356 
357 }