/* * File : $Source: /alkacon/cvs/alkacon/com.alkacon.opencms.comments/src/com/alkacon/opencms/comments/CmsCommentFormHandler.java,v $ * Date : $Date: 2011/03/10 11:56:34 $ * Version: $Revision: 1.9 $ * * This file is part of the Alkacon OpenCms Add-On Module Package * * Copyright (c) 2010 Alkacon Software GmbH (http://www.alkacon.com) * * The Alkacon OpenCms Add-On Module Package is free software: * you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The Alkacon OpenCms Add-On Module Package 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with the Alkacon OpenCms Add-On Module Package. * If not, see http://www.gnu.org/licenses/. * * For further information about Alkacon Software GmbH, please see the * company website: http://www.alkacon.com. * * For further information about OpenCms, please see the * project website: http://www.opencms.org. */ package com.alkacon.opencms.comments; import com.alkacon.opencms.formgenerator.CmsFileUploadField; import com.alkacon.opencms.formgenerator.CmsForm; import com.alkacon.opencms.formgenerator.CmsFormHandler; import com.alkacon.opencms.formgenerator.CmsStringTemplateErrorListener; import com.alkacon.opencms.formgenerator.I_CmsField; import org.opencms.cache.CmsVfsMemoryObjectCache; import org.opencms.file.CmsFile; import org.opencms.i18n.CmsMessages; import org.opencms.main.CmsException; import org.opencms.main.CmsLog; import org.opencms.main.OpenCms; import org.opencms.module.CmsModule; import org.opencms.util.CmsHtmlStripper; import org.opencms.util.CmsMacroResolver; import org.opencms.util.CmsStringUtil; import org.opencms.workplace.CmsWorkplace; import java.io.IOException; import java.io.StringReader; import java.io.Writer; import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.jsp.PageContext; import org.apache.commons.logging.Log; import org.antlr.stringtemplate.StringTemplate; import org.antlr.stringtemplate.StringTemplateErrorListener; import org.antlr.stringtemplate.StringTemplateGroup; import org.antlr.stringtemplate.language.DefaultTemplateLexer; import org.htmlparser.util.ParserException; /** * The form handler controls the html or mail output of a configured comment form.<p> * * Provides methods to determine the action that takes place and methods to create different * output formats of a submitted form.<p> * * @author Michael Moossen * * @version $Revision: 1.9 $ * * @since 7.0.5 */ public class CmsCommentFormHandler extends CmsFormHandler { /** The comment field name constant. */ public static final String FIELD_COMMENT = "comment"; /** The ip address field name constant. */ public static final String FIELD_IPADDRESS = "ipaddress"; /** The locale field name constant. */ public static final String FIELD_LOCALE = "locale"; /** The name field name constant. */ public static final String FIELD_NAME = "name"; /** The user field name constant. */ public static final String FIELD_USERNAME = "username"; /** The module name. */ public static final String MODULE_NAME = "com.alkacon.opencms.comments"; /** Module parameter name prefix constant. */ public static final String MODULE_PARAM_CONFIG_PREFIX = "config:"; /** Module parameter name for default mail to address. */ public static final String MODULE_PARAM_DEFAUL_MAIL_TO = "default_mail_to"; /** The path to the default HTML templates for the form. */ public static final String VFS_PATH_DEFAULT_TEMPLATEFILE = CmsWorkplace.VFS_PATH_MODULES + MODULE_NAME + "/resources/formtemplates/default.st"; /** The log object for this class. */ private static final Log LOG = CmsLog.getLog(CmsCommentFormHandler.class); /** Some predefined comment substitutions. */ private Map<String, String> m_substitutions; /** * Empty constructor, be sure to call one of the available initialization methods afterwards.<p> * * Possible initialization methods are:<p> * <ul> * <li>{@link #init(PageContext, HttpServletRequest, HttpServletResponse)}</li> * <li>{@link #init(PageContext, HttpServletRequest, HttpServletResponse, String)}</li> * </ul> */ public CmsCommentFormHandler() { super(); } /** * Special form output for the comments.<p> * * @see com.alkacon.opencms.formgenerator.CmsFormHandler#createForm() */ @Override public void createForm() throws IOException { // the output writer Writer out = getJspContext().getOut(); // check the template group syntax and show eventual errors out.write(buildTemplateGroupCheckHtml()); boolean showForm = showForm(); if (!showForm) { // form has been submitted with correct values // try to send a notification email with the submitted form field values if (sendData()) { // successfully submitted if (getFormConfirmationText().equals("")) { // and no confirmation required out.write("ok"); return; } // confirmation output StringTemplate sTemplate = getOutputTemplate("confirmationoutput"); sTemplate.setAttribute("formconfig", getCommentFormConfiguration()); sTemplate.setAttribute("closebutton", getMessages().key("form.button.close")); out.write(sTemplate.toString()); } else { // problem while submitting StringTemplate sTemplate = getOutputTemplate("emailerror"); sTemplate.setAttribute("headline", getMessages().key("form.error.mail.headline")); sTemplate.setAttribute("text", getMessages().key("form.error.mail.text")); sTemplate.setAttribute("error", getErrors().get("sendmail")); out.write(sTemplate.toString()); } return; } // create the form out.write(buildFormHtml()); // add additional JS StringTemplate sTemplate = getOutputTemplate("formscript"); sTemplate.setAttribute( "formlink", link("/system/modules/com.alkacon.opencms.comments/elements/comment_form.jsp")); sTemplate.setAttribute("isguest", new Boolean(getRequestContext().getCurrentUser().isGuestUser())); sTemplate.setAttribute( "username", ("" + getRequestContext().getCurrentUser().getFirstname() + " " + getRequestContext().getCurrentUser().getLastname()).trim()); sTemplate.setAttribute("useremail", getRequestContext().getCurrentUser().getEmail()); sTemplate.setAttribute("namefield", getCommentFormConfiguration().getFieldByDbLabel("name")); sTemplate.setAttribute("emailfield", getCommentFormConfiguration().getFieldByDbLabel("email")); sTemplate.setAttribute("commentfield", getCommentFormConfiguration().getFieldByDbLabel("comment")); sTemplate.setAttribute("charleft", getMessages().key("form.comment.char.left")); out.write(sTemplate.toString()); } /** * Returns the form configuration.<p> * * @return the form configuration */ public CmsCommentForm getCommentFormConfiguration() { return (CmsCommentForm)super.getFormConfiguration(); } /** * Returns the output template group that generates the web form HTML output.<p> * * @return the output template group that generates the web form HTML output */ @Override public StringTemplateGroup getOutputTemplateGroup() { if (m_outputTemplates == null) { // first get super template group of web form module StringTemplateGroup superGroup = super.getOutputTemplateGroup(); // read default output templates from module parameter String vfsPath = OpenCms.getModuleManager().getModule(MODULE_NAME).getParameter( CmsForm.MODULE_PARAM_TEMPLATE_FILE, VFS_PATH_DEFAULT_TEMPLATEFILE); try { // first try to get the initialized template group from VFS cache String rootPath = getRequestContext().addSiteRoot(vfsPath); StringTemplateGroup stGroup = (StringTemplateGroup)CmsVfsMemoryObjectCache.getVfsMemoryObjectCache().getCachedObject( getCmsObject(), rootPath); if (stGroup == null) { // template group is not in cache, read the file and generate template group CmsFile stFile = getCmsObject().readFile(vfsPath); String stContent = new String( stFile.getContents(), getCmsObject().getRequestContext().getEncoding()); StringTemplateErrorListener errors = new CmsStringTemplateErrorListener(); stGroup = new StringTemplateGroup(new StringReader(stContent), DefaultTemplateLexer.class, errors); stGroup.setSuperGroup(superGroup); // store the template group in cache CmsVfsMemoryObjectCache.getVfsMemoryObjectCache().putCachedObject(getCmsObject(), rootPath, stGroup); } m_outputTemplates = stGroup; } catch (Exception e) { // something went wrong, log error LOG.error("Error while creating web form HTML output templates from file \"" + vfsPath + "\"."); } } return m_outputTemplates; } /** * Initializes the form handler and creates the necessary configuration objects.<p> * * Internally used by {@link CmsCommentsAccess}.<p> * * @param context the JSP page context object * @param req the JSP request * @param res the JSP response * @param access the comment configuration bean * * @throws CmsException if creating the form configuration object fails */ public void init(PageContext context, HttpServletRequest req, HttpServletResponse res, CmsCommentsAccess access) throws CmsException { super.init(context, req, res, access.getConfig().getConfigUri()); // set URI to access URI getCmsObject().getRequestContext().setUri(access.getUri()); } /** * Initializes the form handler and creates the necessary configuration objects.<p> * * @see com.alkacon.opencms.formgenerator.CmsFormHandler#init(javax.servlet.jsp.PageContext, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.String) */ @Override public void init(PageContext context, HttpServletRequest req, HttpServletResponse res, String formConfigUri) throws CmsException { CmsCommentsAccess access = new CmsCommentsAccess(context, req, res, formConfigUri); init(context, req, res, access); } /** * @see com.alkacon.opencms.formgenerator.CmsFormHandler#sendData() */ @Override public boolean sendData() { I_CmsField field = getFormConfiguration().getFieldByDbLabel(FIELD_COMMENT); if (field != null) { String value = field.getValue(); try { value = new CmsHtmlStripper(false).stripHtml(value); } catch (ParserException e) { // ignore } value = CmsLinkDetector.substituteLinks(value); value = CmsStringUtil.substitute(value, getSubstitutions()); field.setValue(value); } // only trigger error handling for the offline project boolean result = super.sendData() || getCmsObject().getRequestContext().getCurrentProject().isOnlineProject(); return result; } /** * Returns the HTML for the input form, generated by using the given string template file.<p> * * @return the HTML for the input form, generated by using the given string template file */ @Override protected String buildFormHtml() { // determine if form type has to be set to "multipart/form-data" in case of upload fields String encType = null; // determine error message String errorMessage = null; if (hasValidationErrors()) { errorMessage = getMessages().key("form.error.message"); } // determine mandatory message String mandatoryMessage = null; if (getFormConfiguration().isShowMandatory() && getFormConfiguration().hasMandatoryFields()) { mandatoryMessage = getMessages().key("form.message.mandatory"); } // calculate fields to show (e.g. if paging is activated) int pos = 0; int place = 0; // generate HTML for the input fields StringBuffer fieldHtml = new StringBuffer(getFormConfiguration().getFields().size() * 256); for (int i = 0, n = getFormConfiguration().getFields().size(); i < n; i++) { // loop through all form input fields I_CmsField field = getFormConfiguration().getFields().get(i); if (i == (n - 1)) { // the last one has to close the row place = 1; } field.setPlaceholder(place); field.setPosition(pos); String infoMessage = getInfos().get(field.getName()); // validate the file upload field here already because of the lost values in these fields if (field instanceof CmsFileUploadField) { infoMessage = field.validateForInfo(this); } fieldHtml.append(field.buildHtml( this, getMessages(), getErrors().get(field.getName()), getFormConfiguration().isShowMandatory(), infoMessage)); pos = field.getPosition(); place = field.getPlaceholder(); } // determine if subfield JavaScript has to be added String subFieldJS = null; // determine if the submit and other buttons are shown String submitButton = getMessages().key("form.button.submit"); String resetButton = getMessages().key("form.button.cancel"); String prevButton = null; String downloadButton = null; // create necessary hidden fields String hiddenFields = null; StringBuffer hFieldsBuf = new StringBuffer(256); hFieldsBuf.append("<input type=\"hidden\" name=\"cmturi\" value=\"").append(getRequest().getParameter("cmturi")).append( "\" />"); hFieldsBuf.append("<input type=\"hidden\" name=\"cmtminimized\" value=\"").append( getRequest().getParameter("cmtminimized}")).append("\" />"); hFieldsBuf.append("<input type=\"hidden\" name=\"cmtlist\" value=\"").append( getRequest().getParameter("cmtlist")).append("\" />"); hFieldsBuf.append("<input type=\"hidden\" name=\"cmtsecurity\" value=\"").append( getRequest().getParameter("cmtsecurity")).append("\" />"); hFieldsBuf.append("<input type=\"hidden\" name=\"configUri\" value=\"").append( getCommentFormConfiguration().getConfigUri()).append("\" />"); hFieldsBuf.append("<input type=\"hidden\" name=\"__locale\" value=\"").append( getRequest().getParameter("__locale")).append("\" />"); hiddenFields = hFieldsBuf.toString(); // create the main form and pass the previously generated field HTML as attribute StringTemplate sTemplate = getOutputTemplate("form"); // set the necessary attributes to use in the string template sTemplate.setAttribute("formuri", getRequest().getParameter("cmturi")); sTemplate.setAttribute("enctype", encType); sTemplate.setAttribute("errormessage", errorMessage); sTemplate.setAttribute("mandatorymessage", mandatoryMessage); sTemplate.setAttribute("formconfig", getFormConfiguration()); sTemplate.setAttribute("fields", fieldHtml.toString()); sTemplate.setAttribute("subfieldjs", subFieldJS); sTemplate.setAttribute("downloadbutton", downloadButton); sTemplate.setAttribute("submitbutton", submitButton); sTemplate.setAttribute("resetbutton", resetButton); sTemplate.setAttribute("hiddenfields", hiddenFields); sTemplate.setAttribute("prevbutton", prevButton); return sTemplate.toString(); } /** * Initializes the form handler and creates the necessary configuration objects.<p> * * @param req the JSP request * @param formConfigUri URI of the form configuration file, if not provided, current URI is used for configuration * * @throws Exception if creating the form configuration objects fails */ @SuppressWarnings({"unchecked", "rawtypes"}) @Override protected void configureForm(HttpServletRequest req, String formConfigUri) throws Exception { if (formConfigUri == null) { return; } m_parameterMap = new HashMap(); m_parameterMap.putAll(getRequest().getParameterMap()); m_macroResolver = CmsMacroResolver.newInstance(); m_macroResolver.setKeepEmptyMacros(false); m_macroResolver.addMacro(MACRO_URL, OpenCms.getSiteManager().getCurrentSite(getCmsObject()).getServerPrefix( getCmsObject(), getRequestContext().getUri()) + link(getRequestContext().getUri())); m_macroResolver.addMacro(MACRO_LOCALE, getRequestContext().getLocale().toString()); String formAction = getParameter(PARAM_FORMACTION); m_isValidatedCorrect = null; setInitial(CmsStringUtil.isEmpty(formAction)); // get the localized messages CmsModule module = OpenCms.getModuleManager().getModule(MODULE_NAME); String para = module.getParameter("message", "/com/alkacon/opencms/comments/workplace"); setMessages(new CmsMessages(para, getRequestContext().getLocale())); // get the form configuration setFormConfiguration(new CmsCommentForm(this, getMessages(), isInitial(), formConfigUri, formAction)); } /** * Returns some predefined comment substitutions.<p> * * @return some predefined comment substitutions */ protected Map<String, String> getSubstitutions() { if (m_substitutions == null) { m_substitutions = new HashMap<String, String>(); m_substitutions.put("\n\n", "<p>"); m_substitutions.put("\n", "<br>"); } return m_substitutions; } }