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.web.stylesheet;
35
36 import java.io.ByteArrayInputStream;
37 import java.io.File;
38 import java.io.FileOutputStream;
39 import java.io.IOException;
40 import java.util.Collection;
41 import java.util.Collections;
42 import java.util.HashMap;
43 import java.util.List;
44 import java.util.Map;
45
46 import javax.servlet.http.HttpServletRequest;
47 import javax.xml.parsers.SAXParser;
48 import javax.xml.parsers.SAXParserFactory;
49
50 import org.apache.commons.fileupload.FileItem;
51 import org.xml.sax.InputSource;
52
53 import fr.paris.lutece.portal.business.portalcomponent.PortalComponentHome;
54 import fr.paris.lutece.portal.business.portlet.PortletType;
55 import fr.paris.lutece.portal.business.portlet.PortletTypeHome;
56 import fr.paris.lutece.portal.business.style.Mode;
57 import fr.paris.lutece.portal.business.style.ModeHome;
58 import fr.paris.lutece.portal.business.style.Style;
59 import fr.paris.lutece.portal.business.style.StyleHome;
60 import fr.paris.lutece.portal.business.stylesheet.StyleSheet;
61 import fr.paris.lutece.portal.business.stylesheet.StyleSheetHome;
62 import fr.paris.lutece.portal.service.admin.AccessDeniedException;
63 import fr.paris.lutece.portal.service.fileupload.FileUploadService;
64 import fr.paris.lutece.portal.service.i18n.I18nService;
65 import fr.paris.lutece.portal.service.message.AdminMessage;
66 import fr.paris.lutece.portal.service.message.AdminMessageService;
67 import fr.paris.lutece.portal.service.security.SecurityTokenService;
68 import fr.paris.lutece.portal.service.template.AppTemplateService;
69 import fr.paris.lutece.portal.service.util.AppLogService;
70 import fr.paris.lutece.portal.service.xsl.XslSecurityService;
71 import fr.paris.lutece.portal.service.util.AppPathService;
72 import fr.paris.lutece.portal.service.util.AppPropertiesService;
73 import fr.paris.lutece.portal.web.admin.AdminFeaturesPageJspBean;
74 import fr.paris.lutece.portal.web.constants.Messages;
75 import fr.paris.lutece.portal.web.constants.Parameters;
76 import fr.paris.lutece.portal.web.upload.MultipartHttpServletRequest;
77 import fr.paris.lutece.portal.web.util.LocalizedPaginator;
78 import fr.paris.lutece.util.ReferenceList;
79 import fr.paris.lutece.util.file.FileUtil;
80 import fr.paris.lutece.util.html.AbstractPaginator;
81 import fr.paris.lutece.util.html.HtmlTemplate;
82 import fr.paris.lutece.util.sort.AttributeComparator;
83
84
85
86
87 public class StyleSheetJspBean extends AdminFeaturesPageJspBean
88 {
89
90
91
92
93
94
95
96 public static final String RIGHT_MANAGE_STYLESHEET = "CORE_STYLESHEET_MANAGEMENT";
97
98
99
100
101 private static final long serialVersionUID = 8176263113722225633L;
102
103
104 private static final String MARK_MODE_ID = "mode_id";
105 private static final String MARK_MODE_LIST = "mode_list";
106 private static final String MARK_STYLESHEET_LIST = "stylesheet_list";
107 private static final String MARK_STYLE_LIST = "style_list";
108 private static final String MARK_STYLESHEET = "stylesheet";
109 private static final String MARK_PAGINATOR = "paginator";
110 private static final String MARK_NB_ITEMS_PER_PAGE = "nb_items_per_page";
111 private static final String MARK_PORTAL_COMPONENT_NAME = "portal_component_name";
112 private static final String MARK_PORTLET_TYPE_NAME = "portlet_type_name";
113 private static final String MARK_STYLE_DESCRIPTION = "style_description";
114
115
116 private static final String TEMPLATE_MANAGE_STYLESHEETS = "admin/stylesheet/manage_stylesheets.html";
117 private static final String TEMPLATE_CREATE_STYLESHEET = "admin/stylesheet/create_stylesheet.html";
118 private static final String TEMPLATE_MODIFY_STYLESHEET = "admin/stylesheet/modify_stylesheet.html";
119 private static final String TEMPLATE_STYLE_SELECT_OPTION = "admin/stylesheet/style_select_option.html";
120
121
122 private static final String PROPERTY_PATH_XSL = "path.stylesheet";
123 private static final String PROPERTY_STYLESHEETS_PER_PAGE = "paginator.stylesheet.itemsPerPage";
124 private static final String MESSAGE_STYLESHEET_ALREADY_EXISTS = "portal.style.message.stylesheetAlreadyExists";
125 private static final String MESSAGE_STYLESHEET_NOT_VALID = "portal.style.message.stylesheetNotValid";
126 private static final String MESSAGE_STYLESHEET_SECURITY_VIOLATION = "portal.style.message.stylesheetSecurityViolation";
127 private static final String MESSAGE_CONFIRM_DELETE_STYLESHEET = "portal.style.message.stylesheetConfirmDelete";
128 private static final String LABEL_ALL = "portal.util.labelAll";
129 private static final String JSP_DO_REMOVE_STYLESHEET = "jsp/admin/style/DoRemoveStyleSheet.jsp";
130 private static final String JSP_REMOVE_STYLE = "RemoveStyle.jsp";
131 private int _nItemsPerPage;
132 private String _strCurrentPageIndex;
133
134
135
136
137
138
139
140
141 public String getManageStyleSheet( HttpServletRequest request )
142 {
143
144 String strModeId = request.getParameter( Parameters.MODE_ID );
145 strModeId = ( strModeId != null ) ? strModeId : "-1";
146
147 int nModeId = Integer.parseInt( strModeId );
148
149 ReferenceList listModes = ModeHome.getModes( );
150 String strComboItem = I18nService.getLocalizedString( LABEL_ALL, getLocale( ) );
151 listModes.addItem( -1, strComboItem );
152
153 List<StyleSheet> listStyleSheets = (List<StyleSheet>) StyleSheetHome.getStyleSheetList( nModeId );
154
155 String strSortedAttributeName = request.getParameter( Parameters.SORTED_ATTRIBUTE_NAME );
156 String strAscSort = null;
157
158 if ( strSortedAttributeName != null )
159 {
160 strAscSort = request.getParameter( Parameters.SORTED_ASC );
161
162 boolean bIsAscSort = Boolean.parseBoolean( strAscSort );
163
164 Collections.sort( listStyleSheets, new AttributeComparator( strSortedAttributeName, bIsAscSort ) );
165 }
166
167 int defaultItemsPerPage = AppPropertiesService.getPropertyInt( PROPERTY_STYLESHEETS_PER_PAGE, 50 );
168 _strCurrentPageIndex = AbstractPaginator.getPageIndex( request, AbstractPaginator.PARAMETER_PAGE_INDEX, _strCurrentPageIndex );
169 _nItemsPerPage = AbstractPaginator.getItemsPerPage( request, AbstractPaginator.PARAMETER_ITEMS_PER_PAGE, _nItemsPerPage, defaultItemsPerPage );
170
171 String strURL = getHomeUrl( request );
172
173 if ( strSortedAttributeName != null )
174 {
175 strURL += ( "?" + Parameters.SORTED_ATTRIBUTE_NAME + "=" + strSortedAttributeName );
176 }
177
178 if ( strAscSort != null )
179 {
180 strURL += ( "&" + Parameters.SORTED_ASC + "=" + strAscSort );
181 }
182
183 LocalizedPaginator<StyleSheet> paginator = new LocalizedPaginator<>( listStyleSheets, _nItemsPerPage, strURL, AbstractPaginator.PARAMETER_PAGE_INDEX,
184 _strCurrentPageIndex, getLocale( ) );
185
186 Map<String, Object> model = new HashMap<>( );
187 model.put( MARK_MODE_ID, strModeId );
188 model.put( MARK_NB_ITEMS_PER_PAGE, "" + _nItemsPerPage );
189 model.put( MARK_PAGINATOR, paginator );
190 model.put( MARK_STYLESHEET_LIST, paginator.getPageItems( ) );
191 model.put( MARK_MODE_LIST, listModes );
192
193 HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_MANAGE_STYLESHEETS, getLocale( ), model );
194
195 return getAdminPage( template.getHtml( ) );
196 }
197
198
199
200
201
202
203
204
205 public String getCreateStyleSheet( HttpServletRequest request )
206 {
207 String strModeId = request.getParameter( Parameters.MODE_ID );
208
209 Map<String, Object> model = new HashMap<>( );
210 model.put( MARK_STYLE_LIST, getStyleList( ) );
211 model.put( MARK_MODE_LIST, ModeHome.getModes( ) );
212 model.put( MARK_MODE_ID, strModeId );
213 model.put( SecurityTokenService.MARK_TOKEN, SecurityTokenService.getInstance( ).getToken( request, TEMPLATE_CREATE_STYLESHEET ) );
214
215 HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_CREATE_STYLESHEET, getLocale( ), model );
216
217 return getAdminPage( template.getHtml( ) );
218 }
219
220
221
222
223
224
225
226
227
228
229 public String doCreateStyleSheet( HttpServletRequest request ) throws AccessDeniedException
230 {
231 StyleSheets/stylesheet/StyleSheet.html#StyleSheet">StyleSheet stylesheet = new StyleSheet( );
232 MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
233 String strErrorUrl = getData( multipartRequest, stylesheet );
234
235 if ( strErrorUrl != null )
236 {
237 return strErrorUrl;
238 }
239 if ( !SecurityTokenService.getInstance( ).validate( multipartRequest, TEMPLATE_CREATE_STYLESHEET ) )
240 {
241 throw new AccessDeniedException( ERROR_INVALID_TOKEN );
242 }
243
244
245 StyleSheetHome.create( stylesheet );
246
247
248
249
250
251 return getHomeUrl( request );
252 }
253
254
255
256
257
258
259
260
261
262
263 private String getData( MultipartHttpServletRequest multipartRequest, StyleSheet stylesheet )
264 {
265 String strErrorUrl = null;
266 String strDescription = multipartRequest.getParameter( Parameters.STYLESHEET_NAME );
267 String strStyleId = multipartRequest.getParameter( Parameters.STYLES );
268 String strModeId = multipartRequest.getParameter( Parameters.MODE_STYLESHEET );
269
270 FileItem fileSource = multipartRequest.getFile( Parameters.STYLESHEET_SOURCE );
271 byte [ ] baXslSource = fileSource.get( );
272 String strFilename = FileUploadService.getFileNameOnly( fileSource );
273
274
275 if ( strDescription.equals( "" ) || ( strFilename == null ) || strFilename.equals( "" ) )
276 {
277 return AdminMessageService.getMessageUrl( multipartRequest, Messages.MANDATORY_FIELDS, AdminMessage.TYPE_STOP );
278 }
279
280
281 int nStyleId = Integer.parseInt( strStyleId );
282 int nModeId = Integer.parseInt( strModeId );
283 int nCount = StyleSheetHome.getStyleSheetNbPerStyleMode( nStyleId, nModeId );
284
285
286 if ( ( nCount >= 1 ) && ( stylesheet.getId( ) == 0 ) )
287 {
288 return AdminMessageService.getMessageUrl( multipartRequest, MESSAGE_STYLESHEET_ALREADY_EXISTS, AdminMessage.TYPE_STOP );
289 }
290
291
292 if ( isValid( baXslSource ) != null )
293 {
294 return AdminMessageService.getMessageUrl( multipartRequest, MESSAGE_STYLESHEET_NOT_VALID, AdminMessage.TYPE_STOP );
295 }
296
297
298 List<String> listSecurityViolations = XslSecurityService.validateXslSecurity( baXslSource );
299
300 if ( !listSecurityViolations.isEmpty( ) )
301 {
302 return AdminMessageService.getMessageUrl( multipartRequest, MESSAGE_STYLESHEET_SECURITY_VIOLATION, AdminMessage.TYPE_STOP );
303 }
304
305 stylesheet.setDescription( strDescription );
306 stylesheet.setStyleId( Integer.parseInt( strStyleId ) );
307 stylesheet.setModeId( Integer.parseInt( strModeId ) );
308 stylesheet.setSource( baXslSource );
309 stylesheet.setFile( strFilename );
310
311 return strErrorUrl;
312 }
313
314
315
316
317
318
319
320
321 public String getModifyStyleSheet( HttpServletRequest request )
322 {
323 String strStyleSheetId = request.getParameter( Parameters.STYLESHEET_ID );
324 int nId = Integer.parseInt( strStyleSheetId );
325
326 Map<String, Object> model = new HashMap<>( );
327 model.put( MARK_STYLE_LIST, getStyleList( ) );
328 model.put( MARK_MODE_LIST, ModeHome.getModes( ) );
329 model.put( MARK_STYLESHEET, StyleSheetHome.findByPrimaryKey( nId ) );
330 model.put( SecurityTokenService.MARK_TOKEN, SecurityTokenService.getInstance( ).getToken( request, TEMPLATE_MODIFY_STYLESHEET ) );
331
332 HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_MODIFY_STYLESHEET, getLocale( ), model );
333
334 return getAdminPage( template.getHtml( ) );
335 }
336
337
338
339
340
341
342 public ReferenceList getStyleList( )
343 {
344 Collection<Style> stylesList = StyleHome.getStylesList( );
345 ReferenceList stylesListWithLabels = new ReferenceList( );
346
347 for ( Style style : stylesList )
348 {
349 HashMap<String, Object> model = new HashMap<>( );
350 model.put( MARK_PORTAL_COMPONENT_NAME, PortalComponentHome.findByPrimaryKey( style.getPortalComponentId( ) ).getName( ) );
351
352 PortletType portletType = PortletTypeHome.findByPrimaryKey( style.getPortletTypeId( ) );
353
354 model.put( MARK_PORTLET_TYPE_NAME,
355 ( ( portletType != null ) ? ( I18nService.getLocalizedString( portletType.getNameKey( ), getLocale( ) ) ) : "" ) );
356 model.put( MARK_STYLE_DESCRIPTION, style.getDescription( ) );
357
358 HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_STYLE_SELECT_OPTION, getLocale( ), model );
359 stylesListWithLabels.addItem( style.getId( ), template.getHtml( ) );
360 }
361
362 return stylesListWithLabels;
363 }
364
365
366
367
368
369
370
371
372
373
374 public String doModifyStyleSheet( HttpServletRequest request ) throws AccessDeniedException
375 {
376 MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
377 int nId = Integer.parseInt( multipartRequest.getParameter( Parameters.STYLESHEET_ID ) );
378 StyleSheet stylesheet = StyleSheetHome.findByPrimaryKey( nId );
379 String strErrorUrl = getData( multipartRequest, stylesheet );
380
381 if ( strErrorUrl != null )
382 {
383 return strErrorUrl;
384 }
385 if ( !SecurityTokenService.getInstance( ).validate( multipartRequest, TEMPLATE_MODIFY_STYLESHEET ) )
386 {
387 throw new AccessDeniedException( ERROR_INVALID_TOKEN );
388 }
389
390
391
392
393
394 StyleSheetHome.update( stylesheet );
395
396
397
398
399
400 return getHomeUrl( request );
401 }
402
403
404
405
406
407
408
409
410 public String getRemoveStyleSheet( HttpServletRequest request )
411 {
412 String strId = request.getParameter( Parameters.STYLESHEET_ID );
413
414 StyleSheet stylesheet = StyleSheetHome.findByPrimaryKey( Integer.parseInt( strId ) );
415 Object [ ] args = {
416 stylesheet.getDescription( )
417 };
418
419 Map<String, Object> parameters = new HashMap<>( );
420 parameters.put( Parameters.STYLESHEET_ID, strId );
421 parameters.put( Parameters.STYLE_ID, stylesheet.getStyleId( ) );
422 parameters.put( SecurityTokenService.PARAMETER_TOKEN, SecurityTokenService.getInstance( ).getToken( request, JSP_DO_REMOVE_STYLESHEET ) );
423 return AdminMessageService.getMessageUrl( request, MESSAGE_CONFIRM_DELETE_STYLESHEET, args, null, JSP_DO_REMOVE_STYLESHEET, null,
424 AdminMessage.TYPE_CONFIRMATION, parameters );
425 }
426
427
428
429
430
431
432
433
434
435
436 public String doRemoveStyleSheet( HttpServletRequest request ) throws AccessDeniedException
437 {
438 if ( !SecurityTokenService.getInstance( ).validate( request, JSP_DO_REMOVE_STYLESHEET ) )
439 {
440 throw new AccessDeniedException( ERROR_INVALID_TOKEN );
441 }
442 int nId = Integer.parseInt( request.getParameter( Parameters.STYLESHEET_ID ) );
443 int nIdStyle = Integer.parseInt( request.getParameter( Parameters.STYLE_ID ) );
444 StyleSheet stylesheet = StyleSheetHome.findByPrimaryKey( nId );
445 String strFile = stylesheet.getFile( );
446 StyleSheetHome.remove( nId );
447
448
449 int nModeId = stylesheet.getModeId( );
450 Mode mode = ModeHome.findByPrimaryKey( nModeId );
451 String strPathStyleSheet = AppPathService.getPath( PROPERTY_PATH_XSL ) + mode.getPath( );
452 File fileToDelete = new File( strPathStyleSheet, strFile );
453 FileUtil.deleteFile( fileToDelete );
454
455 return JSP_REMOVE_STYLE + "?" + Parameters.STYLE_ID + "=" + nIdStyle;
456 }
457
458
459
460
461
462
463
464
465
466
467
468 private String isValid( byte [ ] baXslSource )
469 {
470 String strError = null;
471
472 try
473 {
474 SAXParserFactory factory = SAXParserFactory.newInstance( );
475 factory.setFeature( "http://apache.org/xml/features/disallow-doctype-decl", true );
476 factory.setFeature( "http://xml.org/sax/features/external-general-entities", false );
477 factory.setFeature( "http://xml.org/sax/features/external-parameter-entities", false );
478 SAXParser analyzer = factory.newSAXParser( );
479 InputSource is = new InputSource( new ByteArrayInputStream( baXslSource ) );
480 analyzer.getXMLReader( ).parse( is );
481 }
482 catch( Exception e )
483 {
484 strError = "invalid XSL stylesheet";
485 AppLogService.error( "XSL validation error: {}", e.getMessage( ), e );
486 }
487
488 return strError;
489 }
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535 }