PortalJspBean.java

  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;

  35. import fr.paris.lutece.portal.service.admin.AdminUserService;
  36. import fr.paris.lutece.portal.service.content.ContentPostProcessorService;
  37. import fr.paris.lutece.portal.service.content.ContentService;
  38. import fr.paris.lutece.portal.service.datastore.DatastoreService;
  39. import fr.paris.lutece.portal.service.editor.EditorBbcodeService;
  40. import fr.paris.lutece.portal.service.i18n.I18nService;
  41. import fr.paris.lutece.portal.service.init.AppInfo;
  42. import fr.paris.lutece.portal.service.init.AppInit;
  43. import fr.paris.lutece.portal.service.mail.MailService;
  44. import fr.paris.lutece.portal.service.message.ISiteMessageHandler;
  45. import fr.paris.lutece.portal.service.message.SiteMessage;
  46. import fr.paris.lutece.portal.service.message.SiteMessageException;
  47. import fr.paris.lutece.portal.service.message.SiteMessageService;
  48. import fr.paris.lutece.portal.service.portal.PortalService;
  49. import fr.paris.lutece.portal.service.portal.ThemesService;
  50. import fr.paris.lutece.portal.service.resource.IExtendableResource;
  51. import fr.paris.lutece.portal.service.resource.IExtendableResourceService;
  52. import fr.paris.lutece.portal.service.security.LuteceUser;
  53. import fr.paris.lutece.portal.service.security.SecurityService;
  54. import fr.paris.lutece.portal.service.security.UserNotSignedException;
  55. import fr.paris.lutece.portal.service.spring.SpringContextService;
  56. import fr.paris.lutece.portal.service.template.AppTemplateService;
  57. import fr.paris.lutece.portal.service.util.AppException;
  58. import fr.paris.lutece.portal.service.util.AppLogService;
  59. import fr.paris.lutece.portal.service.util.AppPathService;
  60. import fr.paris.lutece.portal.service.util.AppPropertiesService;
  61. import fr.paris.lutece.portal.web.constants.Markers;
  62. import fr.paris.lutece.portal.web.constants.Parameters;
  63. import fr.paris.lutece.util.html.HtmlTemplate;
  64. import fr.paris.lutece.util.url.UrlItem;

  65. import org.apache.commons.lang3.StringUtils;
  66. import org.apache.commons.lang3.BooleanUtils;

  67. import java.io.UnsupportedEncodingException;

  68. import java.net.URLEncoder;

  69. import java.util.Enumeration;
  70. import java.util.HashMap;
  71. import java.util.List;
  72. import java.util.Locale;
  73. import java.util.Map;

  74. import javax.servlet.http.HttpServletRequest;
  75. import javax.servlet.http.HttpSession;

  76. /**
  77.  * This class provides the methods to display the page of the site
  78.  */
  79. public class PortalJspBean
  80. {
  81.     public static final int MODE_HTML = 0;
  82.     public static final int MODE_ADMIN = 1;
  83.     private static final String TEMPLATE_PAGE_ERROR404 = "skin/site/page_error404.html";
  84.     private static final String TEMPLATE_PAGE_ERROR500 = "skin/site/page_error500.html";
  85.     private static final String TEMPLATE_POPUP_CREDITS = "skin/site/popup_credits.html";
  86.     private static final String TEMPLATE_POPUP_LEGAL_INFO = "skin/site/popup_legal_info.html";
  87.     private static final String TEMPLATE_STARTUP_FAILURE = "skin/site/startup_failure.html";
  88.     private static final String TEMPLATE_SEND_RESOURCE = "skin/site/popup_send_resource.html";
  89.     private static final String TEMPLATE_EMAIL_SEND_RESOURCE = "skin/site/mail_send_resource.html";
  90.     private static final String PROPERTY_INFOS_CNIL = "lutece.legal.infos";
  91.     private static final String ATTRIBUTE_LOGIN_NEXT_URL = "luteceLoginNextUrl";
  92.     private static final String ATTRIBUTE_UPLOAD_FILTER_SITE_NEXT_URL = "uploadFilterSiteNextUrl";
  93.     private static final String MARK_PORTAL_DOMAIN = "portal_domain";
  94.     private static final String MARK_ADDRESS_INFOS_CNIL = "confidentiality_info";
  95.     private static final String MARK_APP_VERSION = "app_version";
  96.     private static final String MARK_FAILURE_MESSAGE = "failure_message";
  97.     private static final String MARK_FAILURE_DETAILS = "failure_details";
  98.     private static final String MARK_RESOURCE_URL = "resource_url";
  99.     private static final String MARK_RESOURCE = "resource";
  100.     private static final String MARK_ERROR = "error";
  101.     private static final String MARK_SUCCESS = "success";
  102.     private static final String MARK_ERROR_CAUSE = "error_cause";
  103.     private static final String MARK_PLUGIN_THEME = "plugin_theme";
  104.     private static final String MARK_THEME = "theme";
  105.     private static final String BEAN_SITE_MESSAGE_HANDLER = "siteMessageHandler";
  106.     private static final String PARAMETER_EXTENDABLE_RESOURCE_TYPE = "extendableResourceType";
  107.     private static final String PARAMETER_ID_EXTENDABLE_RESOURCE = "idExtendableResource";
  108.     private static final String PARAMETER_SENDER_NAME = "senderName";
  109.     private static final String PARAMETER_SENDER_FIRST_NAME = "senderFirstname";
  110.     private static final String PARAMETER_SENDER_EMAIL = "senderEmail";
  111.     private static final String PARAMETER_CONTENT = "content";
  112.     private static final String PARAMETER_SEND = "send";
  113.     private static final String MESSAGE_ERROR_WRONG_SENDER_EMAIL = "portal.site.error.wrongEmailFormat";
  114.     private static final String MESSAGE_ERROR_MANDATORY_FIELDS = "portal.util.message.mandatoryFields";
  115.     private static final String MESSAGE_NO_RESOURCE_FOUND = "portal.site.error.noResourceFound";
  116.     private static final String PROPERTY_PAGE_TITLE_ERROR404 = "portal.util.error404.title";
  117.     private static final String PROPERTY_PAGE_TITLE_CREDITS = "portal.site.popup_credits.pageTitle";
  118.     private static final String PROPERTY_PAGE_TITLE_LEGAL_INFO = "portal.site.popup_legal_info.pageTitle";
  119.     private static final String PROPERTY_PAGE_TITLE_STARTUP_FAILURE = "portal.util.startup.failure.title";
  120.     private static final String PROPERTY_PAGE_TITLE_ERROR500 = "portal.util.error500.title";
  121.     private static final String PROPERTY_DEBUG = "error.page.debug";
  122.     private static final String PROPERTY_DEBUG_DEFAULT = "true";
  123.     private static final String CONSTANT_SPACE = " ";
  124.     private static final String KEY_WEBMASTER_EMAIL = "portal.site.site_property.noreply_email";

  125.     /**
  126.      * Returns the content of a page according to the parameters found in the http request. One distinguishes article, page and xpage and the mode.
  127.      *
  128.      * @param request
  129.      *            The http request
  130.      * @return the html code for the display of a page of a site
  131.      * @throws UserNotSignedException
  132.      *             The UserNotSignedException
  133.      * @throws SiteMessageException
  134.      *             occurs when a site message need to be displayed
  135.      */
  136.     public String getContent( HttpServletRequest request ) throws UserNotSignedException, SiteMessageException
  137.     {
  138.         return getContent( request, MODE_HTML );
  139.     }

  140.     /**
  141.      * Returns the content of a page according to the parameters found in the http request. One distinguishes article, page and xpage and the mode.
  142.      *
  143.      * @param request
  144.      *            The http request
  145.      * @param nMode
  146.      *            The mode (normal or administration)
  147.      * @return the html code for the display of a page of a site
  148.      * @throws UserNotSignedException
  149.      *             The UserNotSignedException
  150.      * @throws SiteMessageException
  151.      *             occurs when a site message need to be displayed
  152.      */
  153.     public String getContent( HttpServletRequest request, int nMode ) throws UserNotSignedException, SiteMessageException
  154.     {
  155.         if ( !AppInit.isWebappSuccessfullyLoaded( ) )
  156.         {
  157.             return getStartUpFailurePage( request );
  158.         }

  159.         // Try to register the user in case of external authentication
  160.         if ( SecurityService.isAuthenticationEnable( ) )
  161.         {
  162.             try
  163.             {
  164.                 if ( SecurityService.getInstance( ).isExternalAuthentication( ) && !SecurityService.getInstance( ).isMultiAuthenticationSupported( ) )
  165.                 {
  166.                     SecurityService.getInstance( ).getRemoteUser( request );
  167.                 }
  168.                 else
  169.                 {
  170.                     LuteceUser user = SecurityService.getInstance( ).getRegisteredUser( request );

  171.                     // no checks are needed if the user is already registered
  172.                     // if multiauthentication is supported, then when have to check remote user
  173.                     // before other check
  174.                     if ( user == null && SecurityService.getInstance( ).isMultiAuthenticationSupported( ) )
  175.                     {

  176.                         // getRemoteUser needs to be checked before any check so the user is registered
  177.                         // getRemoteUser throws an exception if no user found, but here we have to
  178.                         // bypass this exception to display login page.
  179.                         SecurityService.getInstance( ).getRemoteUser( request );
  180.                     }
  181.                 }
  182.             }
  183.             catch( UserNotSignedException unse )
  184.             {
  185.                 // nothing to do,Leave LuteceAuthenticationFilter testing if the access to the
  186.                 // content requires authentication
  187.             }
  188.         }

  189.         // Search the content service invoked and call its getPage method
  190.         ContentService cs = PortalService.getInvokedContentService( request );

  191.         String strContent = ( cs != null ) ? cs.getPage( request, nMode ) : PortalService.getDefaultPage( request, nMode );

  192.         if ( ContentPostProcessorService.hasProcessor( ) )
  193.         {
  194.             strContent = ContentPostProcessorService.process( request, strContent );
  195.         }

  196.         return strContent;
  197.     }

  198.     /**
  199.      * Returns the content of a page according to the parameters found in the http request. One distinguishes article, page and xpage and the mode.
  200.      *
  201.      * @param request
  202.      *            The http request
  203.      * @return the html code for the display of a page of a site
  204.      *
  205.      */
  206.     public String getSiteMessageContent( HttpServletRequest request )
  207.     {
  208.         return getSiteMessageContent( request, MODE_HTML );
  209.     }

  210.     /**
  211.      * Returns the content of a page according to the parameters found in the http request. One distinguishes article, page and xpage and the mode.
  212.      *
  213.      * @param request
  214.      *            The http request
  215.      * @param nMode
  216.      *            The mode (normal or administration)
  217.      * @return the html code for the display of a page of a site
  218.      *
  219.      */
  220.     public String getSiteMessageContent( HttpServletRequest request, int nMode )
  221.     {
  222.         String strContent = null;

  223.         if ( !AppInit.isWebappSuccessfullyLoaded( ) )
  224.         {
  225.             return getStartUpFailurePage( request );
  226.         }

  227.         ISiteMessageHandler handler = SpringContextService.getBean( BEAN_SITE_MESSAGE_HANDLER );

  228.         if ( handler.hasMessage( request ) )
  229.         {
  230.             strContent = handler.getPage( request, nMode );
  231.         }

  232.         return strContent;
  233.     }

  234.     /**
  235.      * Returns the code for the popup of the credits
  236.      *
  237.      * @param request
  238.      *            The HTTP request
  239.      * @return the html code for the popup credits
  240.      */
  241.     public String getStartUpFailurePage( HttpServletRequest request )
  242.     {
  243.         HashMap<String, Object> model = new HashMap<>( );
  244.         fillPageModel( request, model );
  245.         model.put( MARK_FAILURE_MESSAGE, AppInit.getLoadingFailureCause( ) );
  246.         model.put( MARK_FAILURE_DETAILS, AppInit.getLoadingFailureDetails( ) );
  247.         model.put( Markers.PAGE_TITLE, I18nService.getLocalizedString( PROPERTY_PAGE_TITLE_STARTUP_FAILURE, request.getLocale( ) ) );

  248.         HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_STARTUP_FAILURE, request.getLocale( ), model );

  249.         return template.getHtml( );
  250.     }

  251.     /**
  252.      * Returns the code for the popup of the credits
  253.      *
  254.      * @param request
  255.      *            The Http Request
  256.      * @return the html code for the popup credits
  257.      */
  258.     public String getCredits( HttpServletRequest request )
  259.     {
  260.         HashMap<String, Object> model = new HashMap<>( );
  261.         fillPageModel( request, model );
  262.         model.put( MARK_APP_VERSION, AppInfo.getVersion( ) );
  263.         model.put( MARK_PORTAL_DOMAIN, PortalService.getSiteName( ) );
  264.         model.put( Markers.PAGE_TITLE, I18nService.getLocalizedString( PROPERTY_PAGE_TITLE_CREDITS, request.getLocale( ) ) );

  265.         HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_POPUP_CREDITS, request.getLocale( ), model );

  266.         return template.getHtml( );
  267.     }

  268.     /**
  269.      * Returns the code for the popup of the legal infos
  270.      *
  271.      * @param request
  272.      *            The Http Request
  273.      * @return the html code for the legal infos
  274.      */
  275.     public String getLegalInfos( HttpServletRequest request )
  276.     {
  277.         HashMap<String, Object> model = new HashMap<>( );
  278.         fillPageModel( request, model );
  279.         model.put( MARK_ADDRESS_INFOS_CNIL, AppPropertiesService.getProperty( PROPERTY_INFOS_CNIL ) );
  280.         model.put( MARK_PORTAL_DOMAIN, PortalService.getSiteName( ) );
  281.         model.put( Markers.PAGE_TITLE, I18nService.getLocalizedString( PROPERTY_PAGE_TITLE_LEGAL_INFO, request.getLocale( ) ) );

  282.         HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_POPUP_LEGAL_INFO, request.getLocale( ), model );

  283.         return template.getHtml( );
  284.     }

  285.     /**
  286.      * Returns the 404 Error page
  287.      *
  288.      * @param request
  289.      *            The HTTP request
  290.      * @return The page
  291.      */
  292.     public String getError404Page( HttpServletRequest request )
  293.     {
  294.         HashMap<String, Object> model = new HashMap<>( );
  295.         fillPageModel( request, model );
  296.         model.put( Markers.PAGE_TITLE, I18nService.getLocalizedString( PROPERTY_PAGE_TITLE_ERROR404, request.getLocale( ) ) );

  297.         HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_PAGE_ERROR404, request.getLocale( ), model );

  298.         return template.getHtml( );
  299.     }

  300.     /**
  301.      * Returns the 500 Error page
  302.      *
  303.      * @param request
  304.      *            The HTTP request
  305.      * @param exception
  306.      *            The Exception
  307.      * @return The page
  308.      */
  309.     public String getError500Page( HttpServletRequest request, Throwable exception )
  310.     {
  311.         if ( exception instanceof AppException )
  312.         {
  313.             // AppException calls AppLogService.error( message, this ) in the
  314.             // constructor, so don't call it here again Call toString to have
  315.             // the Class and the message to be able to indentify the correct
  316.             // stacktrace in the preceding logs.
  317.             AppLogService.error( "Error 500 : Caused by previous Critical AppException" );
  318.         }
  319.         else
  320.         {
  321.             AppLogService.error( "Error 500 : {}", exception.getMessage( ), exception );
  322.         }

  323.         String strCause = null;

  324.         if ( AppPropertiesService.getProperty( PROPERTY_DEBUG, PROPERTY_DEBUG_DEFAULT ).equalsIgnoreCase( "true" ) )
  325.         {
  326.             strCause = exception.getMessage( );

  327.             if ( exception.getCause( ) != null )
  328.             {
  329.                 strCause += exception.getCause( ).getMessage( );
  330.             }
  331.         }

  332.         return getError500Page( request, strCause );
  333.     }

  334.     /**
  335.      * Returns the 500 Error page
  336.      *
  337.      * @param request
  338.      *            The HTTP request
  339.      * @param strCause
  340.      *            The message
  341.      * @return The page
  342.      */
  343.     public String getError500Page( HttpServletRequest request, String strCause )
  344.     {
  345.         HashMap<String, Object> model = new HashMap<>( );
  346.         fillPageModel( request, model );
  347.         model.put( Markers.PAGE_TITLE, I18nService.getLocalizedString( PROPERTY_PAGE_TITLE_ERROR500, request.getLocale( ) ) );
  348.         model.put( MARK_ERROR_CAUSE, strCause );

  349.         HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_PAGE_ERROR500, request.getLocale( ), model );

  350.         return template.getHtml( );
  351.     }

  352.     /**
  353.      * Fill the model'map with commons values
  354.      *
  355.      * @param request
  356.      *            The HTTP request
  357.      * @param model
  358.      *            The map containing the model
  359.      */
  360.     private static void fillPageModel( HttpServletRequest request, HashMap<String, Object> model )
  361.     {
  362.         model.put( Markers.BASE_URL, AppPathService.getBaseUrl( request ) );
  363.         model.put( MARK_PLUGIN_THEME, null );
  364.         model.put( MARK_THEME, ThemesService.getGlobalThemeObject( ) );
  365.     }

  366.     /**
  367.      * This method is called by Portal.jsp when it caught an UserNotSignedException. It gives the login url and stores in the session the url asked
  368.      *
  369.      * @param request
  370.      *            The HTTP request
  371.      * @return The login page URL
  372.      * @since v1.1
  373.      */
  374.     public static String redirectLogin( HttpServletRequest request )
  375.     {
  376.         String strNextUrl = request.getRequestURI( );
  377.         UrlItem url = new UrlItem( strNextUrl );
  378.         Enumeration<String> enumParams = request.getParameterNames( );

  379.         while ( enumParams.hasMoreElements( ) )
  380.         {
  381.             String strParamName = enumParams.nextElement( );

  382.             try
  383.             {
  384.                 url.addParameter( strParamName, URLEncoder.encode( request.getParameter( strParamName ), "UTF-8" ) );
  385.             }
  386.             catch( UnsupportedEncodingException ex )
  387.             {
  388.                 AppLogService.error( "Redirection error while encoding URL : {}", ex.getMessage( ), ex );
  389.             }
  390.         }

  391.         HttpSession session = request.getSession( true );
  392.         session.setAttribute( ATTRIBUTE_LOGIN_NEXT_URL, url.getUrl( ) );

  393.         String strRedirect = SecurityService.getInstance( ).getLoginPageUrl( );

  394.         return AppPathService.getAbsoluteUrl( request, strRedirect );
  395.     }

  396.     /**
  397.      * Returns the url (asked before login) to redirect after login
  398.      *
  399.      * @param request
  400.      *            The Http request
  401.      * @return The url asked before login
  402.      * @since v1.1
  403.      */
  404.     public static String getLoginNextUrl( HttpServletRequest request )
  405.     {
  406.         HttpSession session = request.getSession( );
  407.         return (String) session.getAttribute( ATTRIBUTE_LOGIN_NEXT_URL );
  408.     }

  409.     /**
  410.      * Set the upload filter site next url
  411.      *
  412.      * @param request
  413.      *            the HTTP request
  414.      */
  415.     public static void setUploadFilterSiteNextUrl( HttpServletRequest request )
  416.     {
  417.         String strNextUrl = request.getRequestURI( );
  418.         UrlItem url = new UrlItem( strNextUrl );
  419.         Enumeration<String> enumParams = request.getParameterNames( );

  420.         while ( enumParams.hasMoreElements( ) )
  421.         {
  422.             String strParamName = enumParams.nextElement( );
  423.             url.addParameter( strParamName, request.getParameter( strParamName ) );
  424.         }

  425.         HttpSession session = request.getSession( true );
  426.         session.setAttribute( ATTRIBUTE_UPLOAD_FILTER_SITE_NEXT_URL, url.getUrl( ) );
  427.     }

  428.     /**
  429.      * Get the upload filter site next url
  430.      *
  431.      * @param request
  432.      *            the HTTP request
  433.      * @return the next url
  434.      */
  435.     public static String getUploadFilterSiteNextUrl( HttpServletRequest request )
  436.     {
  437.         HttpSession session = request.getSession( );
  438.         return (String) session.getAttribute( ATTRIBUTE_UPLOAD_FILTER_SITE_NEXT_URL );
  439.     }

  440.     /**
  441.      * Remove the upload filter next url from the session
  442.      *
  443.      * @param request
  444.      *            the HTTP request
  445.      */
  446.     public static void removeUploadFilterSiteNextUrl( HttpServletRequest request )
  447.     {
  448.         HttpSession session = request.getSession( );
  449.         session.removeAttribute( ATTRIBUTE_UPLOAD_FILTER_SITE_NEXT_URL );
  450.     }

  451.     /**
  452.      * Do send a resource
  453.      *
  454.      * @param request
  455.      *            The request
  456.      * @return The HTML content to display
  457.      * @throws SiteMessageException
  458.      *             If the resource or its associated service is not found
  459.      */
  460.     public static String sendResource( HttpServletRequest request ) throws SiteMessageException
  461.     {
  462.         String strSenderEmail = DatastoreService.getDataValue( KEY_WEBMASTER_EMAIL, "no-reply@mydomain.com" );
  463.         String strSenderName = request.getParameter( PARAMETER_SENDER_NAME );
  464.         String strSenderFirstName = request.getParameter( PARAMETER_SENDER_FIRST_NAME );
  465.         String strReceipientEmail = request.getParameter( Parameters.EMAIL );
  466.         String strContent = request.getParameter( PARAMETER_CONTENT );
  467.         String strExtendableResourceType = request.getParameter( PARAMETER_EXTENDABLE_RESOURCE_TYPE );
  468.         String strIdExtendableResource = request.getParameter( PARAMETER_ID_EXTENDABLE_RESOURCE );
  469.         String strSend = request.getParameter( PARAMETER_SEND );
  470.         IExtendableResource resource = null;

  471.         String strError = checkSendParams( strSend, strSenderEmail, strSenderName, strSenderFirstName, strReceipientEmail, strContent, request.getLocale( ) );

  472.         // We get the resource from its resource service
  473.         IExtendableResourceService resourceService = null;
  474.         List<IExtendableResourceService> listExtendableResourceService = SpringContextService.getBeansOfType( IExtendableResourceService.class );

  475.         for ( IExtendableResourceService extendableResourceService : listExtendableResourceService )
  476.         {
  477.             if ( extendableResourceService.isInvoked( strExtendableResourceType ) )
  478.             {
  479.                 resourceService = extendableResourceService;
  480.                 resource = extendableResourceService.getResource( strIdExtendableResource, strExtendableResourceType );
  481.             }
  482.         }

  483.         if ( ( resourceService == null ) || ( resource == null ) )
  484.         {
  485.             SiteMessageService.setMessage( request, MESSAGE_NO_RESOURCE_FOUND, SiteMessage.TYPE_ERROR );
  486.             throw new SiteMessageException( );
  487.         }

  488.         String strResourceUrl = resourceService.getResourceUrl( strIdExtendableResource, strExtendableResourceType );
  489.         Map<String, Object> model = new HashMap<>( );
  490.         model.put( MARK_RESOURCE, resource );
  491.         model.put( MARK_RESOURCE_URL, strResourceUrl );
  492.         model.put( Markers.BASE_URL, AppPathService.getBaseUrl( request ) );

  493.         if ( ( strSend != null ) && ( strError == null ) )
  494.         {
  495.             Map<String, Object> mailModel = new HashMap<>( );
  496.             mailModel.put( Markers.BASE_URL, AppPathService.getBaseUrl( request ) );
  497.             mailModel.put( MARK_RESOURCE, resource );
  498.             mailModel.put( PARAMETER_SENDER_EMAIL, strSenderEmail );
  499.             mailModel.put( PARAMETER_SENDER_NAME, strSenderName );
  500.             mailModel.put( PARAMETER_SENDER_FIRST_NAME, strSenderFirstName );
  501.             mailModel.put( Parameters.EMAIL, strReceipientEmail );
  502.             mailModel.put( PARAMETER_CONTENT, EditorBbcodeService.getInstance( ).parse( strContent ) );
  503.             mailModel.put( MARK_RESOURCE_URL, resourceService.getResourceUrl( strIdExtendableResource, strExtendableResourceType ) );

  504.             HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_EMAIL_SEND_RESOURCE, request.getLocale( ), mailModel );
  505.             MailService.sendMailHtml( strReceipientEmail, strSenderFirstName + CONSTANT_SPACE + strSenderName, strSenderEmail,
  506.                     resource.getExtendableResourceName( ), template.getHtml( ) );
  507.             model.put( MARK_SUCCESS, MARK_SUCCESS );
  508.         }
  509.         else
  510.         {
  511.             model.put( PARAMETER_SENDER_NAME, strSenderName );
  512.             model.put( PARAMETER_SENDER_FIRST_NAME, strSenderFirstName );
  513.             model.put( Parameters.EMAIL, strReceipientEmail );
  514.             model.put( PARAMETER_CONTENT, strContent );
  515.             model.put( MARK_ERROR, strError );
  516.         }

  517.         model.put( Markers.PAGE_MAIN_MENU, StringUtils.EMPTY );

  518.         HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_SEND_RESOURCE, request.getLocale( ), model );

  519.         return template.getHtml( );
  520.     }

  521.     private static String checkSendParams( String strSend, String strSenderEmail, String strSenderName, String strSenderFirstName, String strReceipientEmail,
  522.             String strContent, Locale locale )
  523.     {
  524.         String strError = null;
  525.         // If the form was submited, we check data
  526.         if ( strSend != null )
  527.         {
  528.             boolean [ ] conditions = new boolean [ ] {
  529.                     StringUtils.isBlank( strSenderEmail ), StringUtils.isBlank( strSenderName ), StringUtils.isBlank( strSenderFirstName ),
  530.                     StringUtils.isBlank( strReceipientEmail ), StringUtils.isBlank( strContent )
  531.             };

  532.             if ( BooleanUtils.or( conditions ) )
  533.             {
  534.                 strError = I18nService.getLocalizedString( MESSAGE_ERROR_MANDATORY_FIELDS, locale );
  535.             }

  536.             if ( ( strError != null ) && ( !AdminUserService.checkEmail( strSenderEmail ) || !AdminUserService.checkEmail( strReceipientEmail ) ) )
  537.             {
  538.                 strError = I18nService.getLocalizedString( MESSAGE_ERROR_WRONG_SENDER_EMAIL, locale );
  539.             }
  540.         }
  541.         return strError;
  542.     }
  543. }