/** * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. */ package com.liferay.web.form.web.internal.portlet; import com.liferay.counter.kernel.service.CounterLocalService; import com.liferay.expando.kernel.model.ExpandoRow; import com.liferay.expando.kernel.service.ExpandoRowLocalService; import com.liferay.expando.kernel.service.ExpandoTableLocalService; import com.liferay.expando.kernel.service.ExpandoValueLocalService; import com.liferay.mail.kernel.model.MailMessage; import com.liferay.mail.kernel.service.MailService; import com.liferay.portal.configuration.metatype.bnd.util.ConfigurableUtil; import com.liferay.portal.kernel.captcha.CaptchaTextException; import com.liferay.portal.kernel.captcha.CaptchaUtil; import com.liferay.portal.kernel.dao.orm.QueryUtil; import com.liferay.portal.kernel.exception.PortalException; import com.liferay.portal.kernel.log.Log; import com.liferay.portal.kernel.log.LogFactoryUtil; import com.liferay.portal.kernel.portlet.PortletPreferencesFactoryUtil; import com.liferay.portal.kernel.portlet.PortletResponseUtil; import com.liferay.portal.kernel.portlet.bridges.mvc.MVCPortlet; import com.liferay.portal.kernel.security.permission.ActionKeys; import com.liferay.portal.kernel.service.permission.PortletPermissionUtil; import com.liferay.portal.kernel.servlet.SessionErrors; import com.liferay.portal.kernel.servlet.SessionMessages; import com.liferay.portal.kernel.theme.ThemeDisplay; import com.liferay.portal.kernel.util.CharPool; import com.liferay.portal.kernel.util.Constants; import com.liferay.portal.kernel.util.ContentTypes; import com.liferay.portal.kernel.util.FileUtil; import com.liferay.portal.kernel.util.GetterUtil; import com.liferay.portal.kernel.util.LocalizationUtil; import com.liferay.portal.kernel.util.ParamUtil; import com.liferay.portal.kernel.util.Portal; import com.liferay.portal.kernel.util.StringBundler; import com.liferay.portal.kernel.util.StringPool; import com.liferay.portal.kernel.util.StringUtil; import com.liferay.portal.kernel.util.Validator; import com.liferay.portal.kernel.util.WebKeys; import com.liferay.web.form.web.configuration.WebFormGroupServiceConfiguration; import com.liferay.web.form.web.internal.constants.WebFormPortletKeys; import com.liferay.web.form.web.internal.util.WebFormUtil; import java.util.ArrayList; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; import javax.mail.internet.InternetAddress; import javax.portlet.ActionRequest; import javax.portlet.ActionResponse; import javax.portlet.Portlet; import javax.portlet.PortletPreferences; import javax.portlet.ResourceRequest; import javax.portlet.ResourceResponse; import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.ConfigurationPolicy; import org.osgi.service.component.annotations.Modified; import org.osgi.service.component.annotations.Reference; /** * @author Daniel Weisser * @author Jorge Ferrer * @author Alberto Montero * @author Julio Camarero * @author Brian Wing Shun Chan * @author Peter Fellwock */ @Component( configurationPid = "com.liferay.web.form.web.configuration.WebFormConfiguration", configurationPolicy = ConfigurationPolicy.OPTIONAL, immediate = true, property = { "com.liferay.portlet.css-class-wrapper=web-form-portlet", "com.liferay.portlet.display-category=category.tools", "com.liferay.portlet.header-portlet-css=/css/main.css", "com.liferay.portlet.icon=/icons/web_form.png", "com.liferay.portlet.use-default-template=true", "javax.portlet.display-name=Web Form", "javax.portlet.expiration-cache=0", "javax.portlet.init-param.copy-request-parameters=true", "javax.portlet.init-param.template-path=/", "javax.portlet.init-param.view-template=/view.jsp", "javax.portlet.name=" + WebFormPortletKeys.WEB_FORM, "javax.portlet.portlet-info.keywords=Web Form", "javax.portlet.portlet-info.short-title=Web Form", "javax.portlet.portlet-info.title=Web Form", "javax.portlet.preferences=classpath:/META-INF/portlet-preferences/default-portlet-preferences.xml", "javax.portlet.resource-bundle=content.Language", "javax.portlet.security-role-ref=administrator,guest,power-user,user", "javax.portlet.supports.mime-type=text/html" }, service = Portlet.class ) public class WebFormPortlet extends MVCPortlet { public void deleteData( ActionRequest actionRequest, ActionResponse actionResponse) throws Exception { ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute( WebKeys.THEME_DISPLAY); String portletId = _portal.getPortletId(actionRequest); PortletPermissionUtil.check( themeDisplay.getPermissionChecker(), themeDisplay.getPlid(), portletId, ActionKeys.CONFIGURATION); PortletPreferences preferences = PortletPreferencesFactoryUtil.getPortletSetup(actionRequest); String databaseTableName = preferences.getValue( "databaseTableName", StringPool.BLANK); if (Validator.isNotNull(databaseTableName)) { _expandoTableLocalService.deleteTable( themeDisplay.getCompanyId(), WebFormUtil.class.getName(), databaseTableName); } } public void saveData( ActionRequest actionRequest, ActionResponse actionResponse) throws Exception { ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute( WebKeys.THEME_DISPLAY); String portletId = _portal.getPortletId(actionRequest); PortletPreferences preferences = PortletPreferencesFactoryUtil.getPortletSetup( actionRequest, portletId); boolean requireCaptcha = GetterUtil.getBoolean( preferences.getValue("requireCaptcha", StringPool.BLANK)); String successURL = GetterUtil.getString( preferences.getValue("successURL", StringPool.BLANK)); boolean sendAsEmail = GetterUtil.getBoolean( preferences.getValue("sendAsEmail", StringPool.BLANK)); boolean saveToDatabase = GetterUtil.getBoolean( preferences.getValue("saveToDatabase", StringPool.BLANK)); String databaseTableName = GetterUtil.getString( preferences.getValue("databaseTableName", StringPool.BLANK)); boolean saveToFile = GetterUtil.getBoolean( preferences.getValue("saveToFile", StringPool.BLANK)); if (requireCaptcha) { try { CaptchaUtil.check(actionRequest); } catch (CaptchaTextException cte) { // LPS-52675 if (_log.isDebugEnabled()) { _log.debug(cte, cte); } SessionErrors.add( actionRequest, CaptchaTextException.class.getName()); return; } } Map<String, String> fieldsMap = new LinkedHashMap<>(); for (int i = 1; true; i++) { String fieldLabel = preferences.getValue( "fieldLabel" + i, StringPool.BLANK); String fieldType = preferences.getValue( "fieldType" + i, StringPool.BLANK); if (Validator.isNull(fieldLabel)) { break; } if (StringUtil.equalsIgnoreCase(fieldType, "paragraph")) { continue; } fieldsMap.put(fieldLabel, actionRequest.getParameter("field" + i)); } Set<String> validationErrors = null; try { validationErrors = validate(fieldsMap, preferences); } catch (Exception e) { SessionErrors.add( actionRequest, "validationScriptError", e.getMessage().trim()); return; } if (validationErrors.isEmpty()) { boolean emailSuccess = true; boolean databaseSuccess = true; boolean fileSuccess = true; if (sendAsEmail) { emailSuccess = sendEmail( themeDisplay.getCompanyId(), fieldsMap, preferences); } if (saveToDatabase) { if (Validator.isNull(databaseTableName)) { databaseTableName = WebFormUtil.getNewDatabaseTableName( portletId); preferences.setValue( "databaseTableName", databaseTableName); preferences.store(); } databaseSuccess = saveDatabase( themeDisplay.getCompanyId(), fieldsMap, preferences, databaseTableName); } if (saveToFile) { String fileName = WebFormUtil.getFileName( themeDisplay, portletId, _webFormGroupServiceConfiguration.dataRootDir()); fileSuccess = saveFile(fieldsMap, fileName); } if (emailSuccess && databaseSuccess && fileSuccess) { if (Validator.isNull(successURL)) { SessionMessages.add(actionRequest, "success"); } else { SessionMessages.add( actionRequest, portletId + SessionMessages. KEY_SUFFIX_HIDE_DEFAULT_SUCCESS_MESSAGE); } } else { SessionErrors.add(actionRequest, "error"); } } else { for (String badField : validationErrors) { SessionErrors.add(actionRequest, "error" + badField); } } if (SessionErrors.isEmpty(actionRequest) && Validator.isNotNull(successURL)) { actionResponse.sendRedirect(successURL); } } @Override public void serveResource( ResourceRequest resourceRequest, ResourceResponse resourceResponse) { String cmd = ParamUtil.getString(resourceRequest, Constants.CMD); try { if (cmd.equals("captcha")) { serveCaptcha(resourceRequest, resourceResponse); } else if (cmd.equals("export")) { exportData(resourceRequest, resourceResponse); } } catch (Exception e) { _log.error(e, e); } } @Activate @Modified protected void activate(Map<String, Object> properties) { _webFormGroupServiceConfiguration = ConfigurableUtil.createConfigurable( WebFormGroupServiceConfiguration.class, properties); } protected void appendFieldLabels( Map<String, String> fieldsMap, StringBundler sb) { for (String fieldLabel : fieldsMap.keySet()) { sb.append(getCSVFormattedValue(fieldLabel)); sb.append(_webFormGroupServiceConfiguration.csvSeparator()); } sb.setIndex(sb.index() - 1); sb.append(CharPool.NEW_LINE); } protected void appendFieldValues( Map<String, String> fieldsMap, StringBundler sb) { for (String fieldLabel : fieldsMap.keySet()) { String fieldValue = fieldsMap.get(fieldLabel); sb.append(getCSVFormattedValue(fieldValue)); sb.append(_webFormGroupServiceConfiguration.csvSeparator()); } sb.setIndex(sb.index() - 1); sb.append(CharPool.NEW_LINE); } protected void exportData( ResourceRequest resourceRequest, ResourceResponse resourceResponse) throws Exception { ThemeDisplay themeDisplay = (ThemeDisplay)resourceRequest.getAttribute( WebKeys.THEME_DISPLAY); String portletId = _portal.getPortletId(resourceRequest); PortletPermissionUtil.check( themeDisplay.getPermissionChecker(), themeDisplay.getPlid(), portletId, ActionKeys.CONFIGURATION); PortletPreferences preferences = PortletPreferencesFactoryUtil.getPortletSetup(resourceRequest); String databaseTableName = preferences.getValue( "databaseTableName", StringPool.BLANK); String title = preferences.getValue("title", "no-title"); StringBundler sb = new StringBundler(); List<String> fieldLabels = new ArrayList<>(); for (int i = 1; true; i++) { String fieldLabel = preferences.getValue( "fieldLabel" + i, StringPool.BLANK); String localizedfieldLabel = LocalizationUtil.getPreferencesValue( preferences, "fieldLabel" + i, themeDisplay.getLanguageId()); if (Validator.isNull(fieldLabel)) { break; } fieldLabels.add(fieldLabel); sb.append(getCSVFormattedValue(localizedfieldLabel)); sb.append(_webFormGroupServiceConfiguration.csvSeparator()); } sb.setIndex(sb.index() - 1); sb.append(CharPool.NEW_LINE); if (Validator.isNotNull(databaseTableName)) { List<ExpandoRow> rows = _expandoRowLocalService.getRows( themeDisplay.getCompanyId(), WebFormUtil.class.getName(), databaseTableName, QueryUtil.ALL_POS, QueryUtil.ALL_POS); for (ExpandoRow row : rows) { for (String fieldName : fieldLabels) { String data = _expandoValueLocalService.getData( themeDisplay.getCompanyId(), WebFormUtil.class.getName(), databaseTableName, fieldName, row.getClassPK(), StringPool.BLANK); sb.append(getCSVFormattedValue(data)); sb.append(_webFormGroupServiceConfiguration.csvSeparator()); } sb.setIndex(sb.index() - 1); sb.append(CharPool.NEW_LINE); } } String fileName = title + ".csv"; byte[] bytes = sb.toString().getBytes(); String contentType = ContentTypes.APPLICATION_TEXT; PortletResponseUtil.sendFile( resourceRequest, resourceResponse, fileName, bytes, contentType); } protected String getCSVFormattedValue(String value) { StringBundler sb = new StringBundler(3); sb.append(CharPool.QUOTE); sb.append( StringUtil.replace(value, CharPool.QUOTE, StringPool.DOUBLE_QUOTE)); sb.append(CharPool.QUOTE); return sb.toString(); } protected String getMailBody(Map<String, String> fieldsMap) { StringBundler sb = new StringBundler(); for (String fieldLabel : fieldsMap.keySet()) { String fieldValue = fieldsMap.get(fieldLabel); sb.append(fieldLabel); sb.append(" : "); sb.append(fieldValue); sb.append(CharPool.NEW_LINE); } return sb.toString(); } protected boolean saveDatabase( long companyId, Map<String, String> fieldsMap, PortletPreferences preferences, String databaseTableName) throws Exception { WebFormUtil.checkTable(companyId, databaseTableName, preferences); long classPK = _counterLocalService.increment( WebFormUtil.class.getName()); try { for (String fieldLabel : fieldsMap.keySet()) { String fieldValue = fieldsMap.get(fieldLabel); _expandoValueLocalService.addValue( companyId, WebFormUtil.class.getName(), databaseTableName, fieldLabel, classPK, fieldValue); } return true; } catch (Exception e) { _log.error( "The web form data could not be saved to the database", e); return false; } } protected boolean saveFile(Map<String, String> fieldsMap, String fileName) throws PortalException { StringBundler sb = new StringBundler(); if (!FileUtil.exists(fileName)) { appendFieldLabels(fieldsMap, sb); } appendFieldValues(fieldsMap, sb); try { FileUtil.write(fileName, sb.toString(), false, true); return true; } catch (Exception e) { _log.error("The web form data could not be saved to a file", e); return false; } } protected boolean sendEmail( long companyId, Map<String, String> fieldsMap, PortletPreferences preferences) { try { String emailAddresses = preferences.getValue( "emailAddress", StringPool.BLANK); if (Validator.isNull(emailAddresses)) { _log.error( "The web form email cannot be sent because no email " + "address is configured"); return false; } InternetAddress fromAddress = new InternetAddress( _webFormGroupServiceConfiguration.emailFromAddress(), _webFormGroupServiceConfiguration.emailFromName()); String subject = preferences.getValue("subject", StringPool.BLANK); String body = getMailBody(fieldsMap); MailMessage mailMessage = new MailMessage( fromAddress, subject, body, false); InternetAddress[] toAddresses = InternetAddress.parse( emailAddresses); mailMessage.setTo(toAddresses); _mailService.sendEmail(mailMessage); return true; } catch (Exception e) { _log.error("The web form email could not be sent", e); return false; } } protected void serveCaptcha( ResourceRequest resourceRequest, ResourceResponse resourceResponse) throws Exception { CaptchaUtil.serveImage(resourceRequest, resourceResponse); } @Reference(unbind = "-") protected void setCounterLocalService( CounterLocalService counterLocalService) { _counterLocalService = counterLocalService; } @Reference(unbind = "-") protected void setExpandoRowLocalService( ExpandoRowLocalService expandoRowLocalService) { _expandoRowLocalService = expandoRowLocalService; } @Reference(unbind = "-") protected void setExpandoTableLocalService( ExpandoTableLocalService expandoTableLocalService) { _expandoTableLocalService = expandoTableLocalService; } @Reference(unbind = "-") protected void setExpandoValueLocalService( ExpandoValueLocalService expandoValueLocalService) { _expandoValueLocalService = expandoValueLocalService; } @Reference(unbind = "-") protected void setMailService(MailService mailService) { _mailService = mailService; } protected Set<String> validate( Map<String, String> fieldsMap, PortletPreferences preferences) throws Exception { Set<String> validationErrors = new HashSet<>(); for (int i = 0; i < fieldsMap.size(); i++) { String fieldType = preferences.getValue( "fieldType" + (i + 1), StringPool.BLANK); String fieldLabel = preferences.getValue( "fieldLabel" + (i + 1), StringPool.BLANK); String fieldValue = fieldsMap.get(fieldLabel); boolean fieldOptional = GetterUtil.getBoolean( preferences.getValue( "fieldOptional" + (i + 1), StringPool.BLANK)); if (Objects.equals(fieldType, "paragraph")) { continue; } if (!fieldOptional && Validator.isNotNull(fieldLabel) && Validator.isNull(fieldValue)) { validationErrors.add(fieldLabel); continue; } if (!_webFormGroupServiceConfiguration.validationScriptEnable()) { continue; } String validationScript = GetterUtil.getString( preferences.getValue( "fieldValidationScript" + (i + 1), StringPool.BLANK)); if (Validator.isNotNull(validationScript) && !WebFormUtil.validate( fieldValue, fieldsMap, validationScript)) { validationErrors.add(fieldLabel); continue; } } return validationErrors; } private static final Log _log = LogFactoryUtil.getLog(WebFormPortlet.class); private static CounterLocalService _counterLocalService; private static ExpandoRowLocalService _expandoRowLocalService; private static ExpandoTableLocalService _expandoTableLocalService; private static ExpandoValueLocalService _expandoValueLocalService; private static MailService _mailService; @Reference private Portal _portal; private WebFormGroupServiceConfiguration _webFormGroupServiceConfiguration; }