0001: /*
0002: * File : $Source: /usr/local/cvs/alkacon/com.alkacon.opencms.formgenerator/src/com/alkacon/opencms/formgenerator/CmsFormHandler.java,v $
0003: * Date : $Date: 2008-02-19 11:55:26 $
0004: * Version: $Revision: 1.5 $
0005: *
0006: * This file is part of the Alkacon OpenCms Add-On Module Package
0007: *
0008: * Copyright (c) 2007 Alkacon Software GmbH (http://www.alkacon.com)
0009: *
0010: * The Alkacon OpenCms Add-On Module Package is free software:
0011: * you can redistribute it and/or modify
0012: * it under the terms of the GNU General Public License as published by
0013: * the Free Software Foundation, either version 3 of the License, or
0014: * (at your option) any later version.
0015: *
0016: * The Alkacon OpenCms Add-On Module Package is distributed
0017: * in the hope that it will be useful,
0018: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0019: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0020: * GNU General Public License for more details.
0021: *
0022: * You should have received a copy of the GNU General Public License
0023: * along with the Alkacon OpenCms Add-On Module Package.
0024: * If not, see http://www.gnu.org/licenses/.
0025: *
0026: * For further information about Alkacon Software GmbH, please see the
0027: * company website: http://www.alkacon.com.
0028: *
0029: * For further information about OpenCms, please see the
0030: * project website: http://www.opencms.org.
0031: */
0032:
0033: package com.alkacon.opencms.formgenerator;
0034:
0035: import com.alkacon.opencms.formgenerator.database.CmsFormDataAccess;
0036:
0037: import org.opencms.i18n.CmsEncoder;
0038: import org.opencms.i18n.CmsMessages;
0039: import org.opencms.jsp.CmsJspActionElement;
0040: import org.opencms.mail.CmsHtmlMail;
0041: import org.opencms.mail.CmsSimpleMail;
0042: import org.opencms.main.CmsLog;
0043: import org.opencms.main.OpenCms;
0044: import org.opencms.module.CmsModule;
0045: import org.opencms.util.CmsByteArrayDataSource;
0046: import org.opencms.util.CmsDateUtil;
0047: import org.opencms.util.CmsMacroResolver;
0048: import org.opencms.util.CmsRequestUtil;
0049: import org.opencms.util.CmsStringUtil;
0050:
0051: import java.io.File;
0052: import java.text.DateFormat;
0053: import java.util.ArrayList;
0054: import java.util.Collections;
0055: import java.util.Date;
0056: import java.util.HashMap;
0057: import java.util.Iterator;
0058: import java.util.List;
0059: import java.util.Map;
0060: import java.util.StringTokenizer;
0061:
0062: import javax.mail.internet.AddressException;
0063: import javax.mail.internet.InternetAddress;
0064: import javax.servlet.http.HttpServletRequest;
0065: import javax.servlet.http.HttpServletResponse;
0066: import javax.servlet.jsp.PageContext;
0067:
0068: import org.apache.commons.fileupload.FileItem;
0069: import org.apache.commons.logging.Log;
0070:
0071: /**
0072: * The form handler controls the html or mail output of a configured email form.<p>
0073: *
0074: * Provides methods to determine the action that takes place and methods to create different
0075: * output formats of a submitted form.<p>
0076: *
0077: * @author Andreas Zahner
0078: * @author Thomas Weckert
0079: * @author Jan Baudisch
0080: *
0081: * @version $Revision: 1.5 $
0082: *
0083: * @since 7.0.4
0084: */
0085: public class CmsFormHandler extends CmsJspActionElement {
0086:
0087: /** Request parameter value for the form action parameter: correct the input. */
0088: public static final String ACTION_CONFIRMED = "confirmed";
0089:
0090: /** Request parameter value for the form action parameter: correct the input. */
0091: public static final String ACTION_CORRECT_INPUT = "correct";
0092:
0093: /** Request parameter value for the form action parameter: Jump to the download page of the csv data (allow only for offline project!!!). */
0094: public static final String ACTION_DOWNLOAD_DATA_1 = "export1";
0095:
0096: /** Request parameter value for the form action parameter: Download the csv data. */
0097: public static final String ACTION_DOWNLOAD_DATA_2 = "export2";
0098:
0099: /** Request parameter value for the form action parameter: form submitted. */
0100: public static final String ACTION_SUBMIT = "submit";
0101:
0102: /** Name of the file item session attribute. */
0103: public static final String ATTRIBUTE_FILEITEMS = "fileitems";
0104:
0105: /** Form error: mandatory field not filled out. */
0106: public static final String ERROR_MANDATORY = "mandatory";
0107:
0108: /** Form error: validation error of input. */
0109: public static final String ERROR_VALIDATION = "validation";
0110:
0111: /** Macro name for the date macro that can be used in mail text fields. */
0112: public static final String MACRO_DATE = "date";
0113:
0114: /** Macro name for the form data macro that can be used in mail text fields. */
0115: public static final String MACRO_FORMDATA = "formdata";
0116:
0117: /** Request parameter name for the hidden form action parameter to determine the action. */
0118: public static final String PARAM_FORMACTION = "formaction";
0119:
0120: /** The log object for this class. */
0121: private static final Log LOG = CmsLog.getLog(CmsFormHandler.class);
0122:
0123: /** The module name. */
0124: private static final String MODULE = "com.alkacon.opencms.formgenerator";
0125:
0126: /** Contains eventual validation errors. */
0127: protected Map m_errors;
0128:
0129: /** The form configuration object. */
0130: protected CmsForm m_formConfiguration;
0131:
0132: /** Temporarily stores the fields as hidden fields in the String. */
0133: protected String m_hiddenFields;
0134:
0135: /** Flag indicating if the form is displayed for the first time. */
0136: protected boolean m_initial;
0137:
0138: /** Boolean indicating if the form is validated correctly. */
0139: protected Boolean m_isValidatedCorrect;
0140:
0141: /** Needed to implant form fields into the mail text. */
0142: protected transient CmsMacroResolver m_macroResolver;
0143:
0144: /** The localized messages for the form handler. */
0145: protected CmsMessages m_messages;
0146:
0147: /** The multipart file items. */
0148: protected List m_mulipartFileItems;
0149:
0150: /** The map of request parameters. */
0151: protected Map m_parameterMap;
0152:
0153: /**
0154: * Constructor, creates the necessary form configuration objects.<p>
0155: *
0156: * @param context the JSP page context object
0157: * @param req the JSP request
0158: * @param res the JSP response
0159: * @throws Exception if creating the form configuration objects fails
0160: */
0161: public CmsFormHandler(PageContext context, HttpServletRequest req,
0162: HttpServletResponse res) throws Exception {
0163:
0164: super (context, req, res);
0165: m_errors = new HashMap();
0166: init(req, null);
0167: }
0168:
0169: /**
0170: * Constructor, creates the necessary form configuration objects using a given configuration file URI.<p>
0171: *
0172: * @param context the JSP page context object
0173: * @param req the JSP request
0174: * @param res the JSP response
0175: * @param formConfigUri URI of the form configuration file, if not provided, current URI is used for configuration
0176: * @throws Exception if creating the form configuration objects fails
0177: */
0178: public CmsFormHandler(PageContext context, HttpServletRequest req,
0179: HttpServletResponse res, String formConfigUri)
0180: throws Exception {
0181:
0182: super (context, req, res);
0183: m_errors = new HashMap();
0184: init(req, formConfigUri);
0185: }
0186:
0187: /**
0188: * Replaces line breaks with html <br>.<p>
0189: *
0190: * @param value the value to substitute
0191: * @return the substituted value
0192: */
0193: public String convertToHtmlValue(String value) {
0194:
0195: return convertValue(value, "html");
0196: }
0197:
0198: /**
0199: * Replaces html <br> with line breaks.<p>
0200: *
0201: * @param value the value to substitute
0202: * @return the substituted value
0203: */
0204: public String convertToPlainValue(String value) {
0205:
0206: return convertValue(value, "");
0207: }
0208:
0209: /**
0210: * Converts a given String value to the desired output format.<p>
0211: *
0212: * The following output formats are possible:
0213: * <ul>
0214: * <li>"html" meaning that <br> tags are added</li>
0215: * <li>"plain" or any other String value meaning that <br> tags are removed</li>
0216: * </ul>
0217: *
0218: * @param value the String value to convert
0219: * @param outputType the type of the resulting output
0220: * @return the converted String in the desired output format
0221: */
0222: public String convertValue(String value, String outputType) {
0223:
0224: if ("html".equalsIgnoreCase(outputType)) {
0225: // output should be html, add line break tags and characters
0226: value = CmsStringUtil.escapeHtml(value);
0227: } else {
0228: // output should be plain, remove html line break tags and characters
0229: value = CmsStringUtil.substitute(value, "<br>", "\n");
0230: }
0231: return value;
0232: }
0233:
0234: /**
0235: * Returns the configured form field values as hidden input fields.<p>
0236: *
0237: * @return the configured form field values as hidden input fields
0238: */
0239: public String createHiddenFields() {
0240:
0241: if (CmsStringUtil.isEmpty(m_hiddenFields)) {
0242: List fields = getFormConfiguration().getFields();
0243: StringBuffer result = new StringBuffer(fields.size() * 8);
0244: // iterate the form fields
0245: for (int i = 0, n = fields.size(); i < n; i++) {
0246:
0247: I_CmsField currentField = (I_CmsField) fields.get(i);
0248:
0249: if (currentField == null) {
0250: continue;
0251: } else if (CmsCheckboxField.class
0252: .isAssignableFrom(currentField.getClass())) {
0253: // special case: checkbox, can have more than one value
0254: Iterator k = currentField.getItems().iterator();
0255: while (k.hasNext()) {
0256: CmsFieldItem item = (CmsFieldItem) k.next();
0257: if (item.isSelected()) {
0258: result
0259: .append("<input type=\"hidden\" name=\"");
0260: result.append(currentField.getName());
0261: result.append("\" value=\"");
0262: result.append(CmsEncoder.escapeXml(item
0263: .getValue()));
0264: result.append("\">\n");
0265: }
0266: }
0267: } else if (CmsStringUtil.isNotEmpty(currentField
0268: .getValue())) {
0269: // all other fields are converted to a simple hidden field
0270: result.append("<input type=\"hidden\" name=\"");
0271: result.append(currentField.getName());
0272: result.append("\" value=\"");
0273: result.append(CmsEncoder.escapeXml(currentField
0274: .getValue()));
0275: result.append("\">\n");
0276: }
0277:
0278: }
0279: // store the generated input fields for further usage to avoid unnecessary rebuilding
0280: m_hiddenFields = result.toString();
0281: }
0282: // return generated result list
0283: return m_hiddenFields;
0284: }
0285:
0286: /**
0287: * Creates the output String of the submitted fields for email creation.<p>
0288: *
0289: * @param isHtmlMail if true, the output is formatted as HTML, otherwise as plain text
0290: * @param isConfirmationMail if true, the text for the confirmation mail is created, otherwise the text for mail receiver
0291: *
0292: * @return the output String of the submitted fields for email creation
0293: */
0294: public String createMailTextFromFields(boolean isHtmlMail,
0295: boolean isConfirmationMail) {
0296:
0297: List fieldValues = getFormConfiguration().getAllFields();
0298: StringBuffer result = new StringBuffer(2048 + fieldValues
0299: .size() * 16);
0300: StringBuffer fieldsResult = new StringBuffer(
0301: fieldValues.size() * 16);
0302: boolean useOwnStyle = false;
0303: if (isHtmlMail) {
0304: // create html head with style definitions and body
0305: result.append("<html><head>\n");
0306: result.append("<style type=\"text/css\"><!--\n");
0307: String style = getMessages().key("form.email.css");
0308: if (CmsStringUtil.isNotEmpty(style)) {
0309: // use own user defined CSS
0310: useOwnStyle = true;
0311: result.append(style);
0312: } else {
0313: // use common css
0314: style = getMessages().key("form.email.style.body");
0315: if (CmsStringUtil.isNotEmpty(style)) {
0316: result.append("body,h1,p,td { ");
0317: result.append(style);
0318: result.append(" }\n");
0319: }
0320: style = getMessages().key("form.email.style.h1");
0321: if (CmsStringUtil.isNotEmpty(style)) {
0322: result.append("h1 { ");
0323: result.append(style);
0324: result.append(" }\n");
0325: }
0326: style = getMessages().key("form.email.style.p");
0327: if (CmsStringUtil.isNotEmpty(style)) {
0328: result.append("p { ");
0329: result.append(style);
0330: result.append(" }\n");
0331: }
0332: style = getMessages().key("form.email.style.fields");
0333: if (CmsStringUtil.isNotEmpty(style)) {
0334: result.append("table.fields { ");
0335: result.append(style);
0336: result.append(" }\n");
0337: }
0338: style = getMessages()
0339: .key("form.email.style.fieldlabel");
0340: if (CmsStringUtil.isNotEmpty(style)) {
0341: result.append("td.fieldlabel { ");
0342: result.append(style);
0343: result.append(" }\n");
0344: }
0345: style = getMessages()
0346: .key("form.email.style.fieldvalue");
0347: if (CmsStringUtil.isNotEmpty(style)) {
0348: result.append("td.fieldvalue { ");
0349: result.append(style);
0350: result.append(" }\n");
0351: }
0352: style = getMessages().key("form.email.style.misc");
0353: if (CmsStringUtil.isNotEmpty(style)) {
0354: result.append(getMessages().key(
0355: "form.email.style.misc"));
0356: }
0357: }
0358: result.append("\n//--></style>\n");
0359: result.append("</head><body>\n");
0360: }
0361:
0362: // generate output for submitted form fields
0363: if (isHtmlMail) {
0364: fieldsResult.append("<table border=\"0\"");
0365: if (!useOwnStyle) {
0366: fieldsResult.append(" class=\"fields\"");
0367: }
0368: fieldsResult.append(">\n");
0369: }
0370: // loop the fields
0371: Iterator i = fieldValues.iterator();
0372: while (i.hasNext()) {
0373: I_CmsField current = (I_CmsField) i.next();
0374: if (!useInFormDataMacro(current)) {
0375: continue;
0376: }
0377: String value = current.toString();
0378: if ((current instanceof CmsDynamicField)) {
0379: if (!current.isMandatory()) {
0380: // show dynamic fields only if they are marked as mandatory
0381: continue;
0382: }
0383: // compute the value for the dynamic field
0384: value = getFormConfiguration()
0385: .getFieldStringValueByName(current.getName());
0386: }
0387: if (isHtmlMail) {
0388: // format output as HTML
0389: if (useOwnStyle) {
0390: fieldsResult.append("<tr><td>");
0391: } else {
0392: fieldsResult
0393: .append("<tr><td class=\"fieldlabel\">");
0394: }
0395: if (isConfirmationMail) {
0396: fieldsResult.append(current.getLabel());
0397: } else {
0398: fieldsResult.append(current.getDbLabel() + ":");
0399: }
0400: if (useOwnStyle) {
0401: fieldsResult.append("</td><td class=\"data\">");
0402: } else {
0403: fieldsResult
0404: .append("</td><td class=\"fieldvalue\">");
0405: }
0406: fieldsResult.append(convertToHtmlValue(value));
0407: fieldsResult.append("</td></tr>\n");
0408: } else {
0409: // format output as plain text
0410: if (isConfirmationMail) {
0411: fieldsResult.append(current.getLabel());
0412: } else {
0413: fieldsResult.append(current.getDbLabel() + ":");
0414: }
0415: fieldsResult.append("\t");
0416: fieldsResult.append(value);
0417: fieldsResult.append("\n");
0418: }
0419: }
0420: if (isHtmlMail) {
0421: // create html table closing tag
0422: fieldsResult.append("</table>\n");
0423: }
0424:
0425: // generate the main mail text
0426: String mailText;
0427: if (isHtmlMail) {
0428: if (isConfirmationMail) {
0429: // append the confirmation mail text
0430: mailText = getFormConfiguration()
0431: .getConfirmationMailText();
0432: } else {
0433: // append the email text
0434: mailText = getFormConfiguration().getMailText();
0435: }
0436:
0437: } else {
0438: // generate simple text mail
0439: if (isConfirmationMail) {
0440: // append the confirmation mail text
0441: mailText = getFormConfiguration()
0442: .getConfirmationMailTextPlain();
0443: } else {
0444: // append the email text
0445: mailText = getFormConfiguration().getMailTextPlain();
0446: }
0447:
0448: }
0449: // resolve the common macros
0450: mailText = m_macroResolver.resolveMacros(mailText);
0451: // check presence of formdata macro in mail text using new macro resolver (important, do not use the same here!)
0452: CmsMacroResolver macroResolver = CmsMacroResolver.newInstance();
0453: macroResolver.setKeepEmptyMacros(true);
0454: macroResolver.addMacro(MACRO_FORMDATA, "");
0455: if (mailText.length() > macroResolver.resolveMacros(mailText)
0456: .length()) {
0457: // form data macro found, resolve it
0458: macroResolver.addMacro(MACRO_FORMDATA, fieldsResult
0459: .toString());
0460: mailText = macroResolver.resolveMacros(mailText);
0461: result.append(mailText);
0462: } else {
0463: // no form data macro found, append the fields below the mail text
0464: result.append(mailText);
0465: if (!isHtmlMail) {
0466: result.append("\n\n");
0467: }
0468: result.append(fieldsResult);
0469: }
0470:
0471: if (isHtmlMail) {
0472: if (!isConfirmationMail
0473: && getFormConfiguration().hasConfigurationErrors()) {
0474: // write form configuration errors to html mail
0475: result.append("<h1>");
0476: result.append(getMessages().key(
0477: "form.configuration.error.headline"));
0478: result.append("</h1>\n<p>");
0479: for (int k = 0; k < getFormConfiguration()
0480: .getConfigurationErrors().size(); k++) {
0481: result.append(getFormConfiguration()
0482: .getConfigurationErrors().get(k));
0483: result.append("<br>");
0484: }
0485: result.append("</p>\n");
0486: }
0487: // create body and html closing tags
0488: result.append("</body></html>");
0489: } else if (!isConfirmationMail
0490: && getFormConfiguration().hasConfigurationErrors()) {
0491: // write form configuration errors to text mail
0492: result.append("\n");
0493: result.append(getMessages().key(
0494: "form.configuration.error.headline"));
0495: result.append("\n");
0496: for (int k = 0; k < getFormConfiguration()
0497: .getConfigurationErrors().size(); k++) {
0498: result.append(getFormConfiguration()
0499: .getConfigurationErrors().get(k));
0500: result.append("\n");
0501: }
0502: }
0503:
0504: return result.toString();
0505: }
0506:
0507: /**
0508: * Returns if the data download should be initiated.<p>
0509: *
0510: * @return true if the data download should be initiated, otherwise false
0511: */
0512: public boolean downloadData() {
0513:
0514: boolean result = false;
0515:
0516: String paramAction = getParameter(CmsFormHandler.PARAM_FORMACTION);
0517: if (CmsFormHandler.ACTION_DOWNLOAD_DATA_2.equals(paramAction)) {
0518: result = true;
0519: }
0520: return result;
0521: }
0522:
0523: /**
0524: * Returns the errors found when validating the form.<p>
0525: *
0526: * @return the errors found when validating the form
0527: */
0528: public Map getErrors() {
0529:
0530: return m_errors;
0531: }
0532:
0533: /**
0534: * Returns the check page text, after resolving macros.<p>
0535: *
0536: * @return the check page text
0537: */
0538: public String getFormCheckText() {
0539:
0540: CmsMacroResolver macroResolver = CmsMacroResolver.newInstance();
0541: macroResolver.setKeepEmptyMacros(true);
0542: List fields = getFormConfiguration().getFields();
0543: I_CmsField field;
0544: Iterator itFields = fields.iterator();
0545: // add field values as macros
0546: while (itFields.hasNext()) {
0547: field = (I_CmsField) itFields.next();
0548: macroResolver.addMacro(field.getLabel(), field.getValue());
0549: if (!field.getLabel().equals(field.getDbLabel())) {
0550: macroResolver.addMacro(field.getDbLabel(), field
0551: .getValue());
0552: }
0553: }
0554: return macroResolver.resolveMacros(getFormConfiguration()
0555: .getFormCheckText());
0556: }
0557:
0558: /**
0559: * Returns the form configuration.<p>
0560: *
0561: * @return the form configuration
0562: */
0563: public CmsForm getFormConfiguration() {
0564:
0565: return m_formConfiguration;
0566: }
0567:
0568: /**
0569: * Returns the confirmation text, after resolving macros.<p>
0570: *
0571: * @return the confirmation text
0572: */
0573: public String getFormConfirmationText() {
0574:
0575: return m_macroResolver.resolveMacros(getFormConfiguration()
0576: .getFormConfirmationText());
0577: }
0578:
0579: /**
0580: * Returns the localized messages.<p>
0581: *
0582: * @return the localized messages
0583: */
0584: public CmsMessages getMessages() {
0585:
0586: return m_messages;
0587: }
0588:
0589: /**
0590: * Returns the map of request parameters.<p>
0591: *
0592: * @return the map of request parameters
0593: */
0594: public Map getParameterMap() {
0595:
0596: return m_parameterMap;
0597: }
0598:
0599: /**
0600: * Return <code>null</code> or the file item for the given field in
0601: * case it is of type <code>{@link CmsFileUploadField}</code>.<p>
0602: *
0603: * @param isFileUploadField the field to the the file item of
0604: *
0605: * @return <code>null</code> or the file item for the given field in
0606: * case it is of type <code>{@link CmsFileUploadField}</code>
0607: */
0608: public FileItem getUploadFile(I_CmsField isFileUploadField) {
0609:
0610: FileItem result = null;
0611: FileItem current;
0612: String fieldName = isFileUploadField.getName();
0613: String uploadFileFieldName;
0614: Map fileUploads = (Map) getRequest().getSession().getAttribute(
0615: ATTRIBUTE_FILEITEMS);
0616:
0617: if (fileUploads != null) {
0618: Iterator i = fileUploads.values().iterator();
0619: while (i.hasNext()) {
0620: current = (FileItem) i.next();
0621: uploadFileFieldName = current.getFieldName();
0622: if (fieldName.equals(uploadFileFieldName)) {
0623: result = current;
0624: }
0625: }
0626: }
0627: return result;
0628: }
0629:
0630: /**
0631: * Returns if the submitted values contain validation errors.<p>
0632: *
0633: * @return true if the submitted values contain validation errors, otherwise false
0634: */
0635: public boolean hasValidationErrors() {
0636:
0637: return (!isInitial() && (getErrors().size() > 0));
0638: }
0639:
0640: /**
0641: * Initializes the form handler and creates the necessary configuration objects.<p>
0642: *
0643: * @param req the JSP request
0644: * @param formConfigUri URI of the form configuration file, if not provided, current URI is used for configuration
0645: * @throws Exception if creating the form configuration objects fails
0646: */
0647: public void init(HttpServletRequest req, String formConfigUri)
0648: throws Exception {
0649:
0650: m_mulipartFileItems = CmsRequestUtil
0651: .readMultipartFileItems(req);
0652: m_macroResolver = CmsMacroResolver.newInstance();
0653: m_macroResolver.setKeepEmptyMacros(true);
0654:
0655: if (m_mulipartFileItems != null) {
0656: m_parameterMap = CmsRequestUtil
0657: .readParameterMapFromMultiPart(getRequestContext()
0658: .getEncoding(), m_mulipartFileItems);
0659: } else {
0660: m_parameterMap = new HashMap();
0661: m_parameterMap.putAll(getRequest().getParameterMap());
0662: }
0663:
0664: if (m_mulipartFileItems != null) {
0665: Map fileUploads = (Map) req.getSession().getAttribute(
0666: ATTRIBUTE_FILEITEMS);
0667: if (fileUploads == null) {
0668: fileUploads = new HashMap();
0669: }
0670: // check, if there are any attachments
0671: Iterator i = m_mulipartFileItems.iterator();
0672: while (i.hasNext()) {
0673: FileItem fileItem = (FileItem) i.next();
0674: if (CmsStringUtil.isNotEmpty(fileItem.getName())) {
0675: // append file upload to the map of file items
0676: fileUploads.put(fileItem.getFieldName(), fileItem);
0677: m_parameterMap.put(fileItem.getFieldName(),
0678: new String[] { fileItem.getName() });
0679: }
0680: }
0681: req.getSession().setAttribute(ATTRIBUTE_FILEITEMS,
0682: fileUploads);
0683: } else {
0684: req.getSession().removeAttribute(ATTRIBUTE_FILEITEMS);
0685: }
0686: String formAction = getParameter(PARAM_FORMACTION);
0687: // security check: some form actions are not allowed for everyone:
0688: if (this .getCmsObject().getRequestContext().currentProject()
0689: .isOnlineProject()) {
0690: if (CmsFormHandler.ACTION_DOWNLOAD_DATA_1
0691: .equals(formAction)) {
0692: LOG
0693: .error("Received an illegal request for download data of form "
0694: + formConfigUri + " (online request)");
0695: formAction = ACTION_SUBMIT;
0696: }
0697: }
0698: m_isValidatedCorrect = null;
0699: setInitial(CmsStringUtil.isEmpty(formAction));
0700: // get the localized messages
0701: CmsModule module = OpenCms.getModuleManager().getModule(MODULE);
0702: String para = module.getParameter("message",
0703: "/com/alkacon/opencms/formgenerator/workplace");
0704:
0705: setMessages(new CmsMessages(para, getRequestContext()
0706: .getLocale()));
0707: // get the form configuration
0708: setFormConfiguration(new CmsForm(this , getMessages(),
0709: isInitial(), formConfigUri, formAction));
0710: }
0711:
0712: /**
0713: * Returns if the form is displayed for the first time.<p>
0714: *
0715: * @return true if the form is displayed for the first time, otherwise false
0716: */
0717: public boolean isInitial() {
0718:
0719: return m_initial;
0720: }
0721:
0722: /**
0723: * Sends the confirmation mail with the form data to the specified email address.<p>
0724: *
0725: * @throws Exception if sending the confirmation mail fails
0726: */
0727: public void sendConfirmationMail() throws Exception {
0728:
0729: // get the field which contains the confirmation email address
0730: I_CmsField mailField = (I_CmsField) getFormConfiguration()
0731: .getFields().get(
0732: getFormConfiguration()
0733: .getConfirmationMailField());
0734: String mailTo = mailField.getValue();
0735:
0736: // create the new confirmation mail message depending on the configured email type
0737: if (getFormConfiguration().getMailType().equals(
0738: CmsForm.MAILTYPE_HTML)) {
0739: // create a HTML email
0740: CmsHtmlMail theMail = new CmsHtmlMail();
0741: theMail.setCharset(getCmsObject().getRequestContext()
0742: .getEncoding());
0743: if (CmsStringUtil.isNotEmpty(getFormConfiguration()
0744: .getMailFrom())) {
0745: theMail.setFrom(m_macroResolver
0746: .resolveMacros(getFormConfiguration()
0747: .getMailFrom()));
0748: }
0749: theMail.setTo(createInternetAddresses(mailTo));
0750: theMail.setSubject(m_macroResolver
0751: .resolveMacros(getFormConfiguration()
0752: .getMailSubjectPrefix()
0753: + getFormConfiguration()
0754: .getConfirmationMailSubject()));
0755: theMail.setHtmlMsg(createMailTextFromFields(true, true));
0756: theMail.setTextMsg(createMailTextFromFields(false, true));
0757: // send the mail
0758: theMail.send();
0759: } else {
0760: // create a plain text email
0761: CmsSimpleMail theMail = new CmsSimpleMail();
0762: theMail.setCharset(getCmsObject().getRequestContext()
0763: .getEncoding());
0764: if (CmsStringUtil.isNotEmpty(getFormConfiguration()
0765: .getMailFrom())) {
0766: theMail.setFrom(getFormConfiguration().getMailFrom());
0767: }
0768: theMail.setTo(createInternetAddresses(mailTo));
0769: theMail.setSubject(m_macroResolver
0770: .resolveMacros(getFormConfiguration()
0771: .getMailSubjectPrefix()
0772: + getFormConfiguration()
0773: .getConfirmationMailSubject()));
0774: theMail.setMsg(createMailTextFromFields(false, true));
0775: // send the mail
0776: theMail.send();
0777: }
0778: }
0779:
0780: /**
0781: * Sends the collected data due to the configuration of the form
0782: * (email, database or both).<p>
0783: *
0784: * @return true if successful
0785: */
0786: public boolean sendData() {
0787:
0788: boolean result = true;
0789: try {
0790: CmsForm data = getFormConfiguration();
0791: data.removeCaptchaField();
0792: // fill the macro resolver for resolving in subject and content:
0793: List fields = data.getAllFields();
0794: Iterator itFields = fields.iterator();
0795: // add field values as macros
0796: while (itFields.hasNext()) {
0797: I_CmsField field = (I_CmsField) itFields.next();
0798: String fValue = field.getValue();
0799: if (field instanceof CmsDynamicField) {
0800: fValue = data.getFieldStringValueByName(field
0801: .getName());
0802: }
0803: m_macroResolver.addMacro(field.getLabel(), fValue);
0804: if (!field.getLabel().equals(field.getDbLabel())) {
0805: m_macroResolver
0806: .addMacro(field.getDbLabel(), fValue);
0807: }
0808: }
0809: // add current date as macro
0810: m_macroResolver.addMacro(MACRO_DATE, CmsDateUtil
0811: .getDateTime(new Date(), DateFormat.LONG,
0812: getRequestContext().getLocale()));
0813: // send optional confirmation mail
0814: if (data.isConfirmationMailEnabled()) {
0815: if (!data.isConfirmationMailOptional()
0816: || Boolean
0817: .valueOf(
0818: getParameter(CmsForm.PARAM_SENDCONFIRMATION))
0819: .booleanValue()) {
0820: sendConfirmationMail();
0821: }
0822: }
0823: if (data.isTransportDatabase()) {
0824: result &= sendDatabase();
0825: }
0826: if (data.isTransportEmail()) {
0827: result &= sendMail();
0828: }
0829:
0830: } catch (Exception e) {
0831: // an error occurred during mail creation
0832: if (LOG.isErrorEnabled()) {
0833: LOG.error("An unexpected error occured.", e);
0834: }
0835: getErrors().put("sendmail", e.getMessage());
0836: result = false;
0837: }
0838: return result;
0839: }
0840:
0841: /**
0842: * Returns if the optional check page should be displayed.<p>
0843: *
0844: * @return true if the optional check page should be displayed, otherwise false
0845: */
0846: public boolean showCheck() {
0847:
0848: boolean result = false;
0849:
0850: if (getFormConfiguration().getShowCheck()
0851: && ACTION_SUBMIT.equals(getParameter(PARAM_FORMACTION))) {
0852: result = true;
0853: } else if (getFormConfiguration().captchaFieldIsOnCheckPage()
0854: && ACTION_CONFIRMED
0855: .equals(getParameter(PARAM_FORMACTION))
0856: && !validate()) {
0857: result = true;
0858: }
0859:
0860: return result;
0861: }
0862:
0863: /**
0864: * Returns if the data download page should be displayed.<p>
0865: *
0866: * @return true if the data download page should be displayed, otherwise false
0867: */
0868: public boolean showDownloadData() {
0869:
0870: boolean result = false;
0871:
0872: String paramAction = getParameter(CmsFormHandler.PARAM_FORMACTION);
0873: if (CmsFormHandler.ACTION_DOWNLOAD_DATA_1.equals(paramAction)) {
0874: result = true;
0875: } else if (CmsFormHandler.ACTION_DOWNLOAD_DATA_2
0876: .equals(paramAction)) {
0877: result = true;
0878: }
0879: return result;
0880: }
0881:
0882: /**
0883: * Returns if the input form should be displayed.<p>
0884: *
0885: * @return true if the input form should be displayed, otherwise false
0886: */
0887: public boolean showForm() {
0888:
0889: boolean result = false;
0890: String formAction = getParameter(PARAM_FORMACTION);
0891:
0892: if (isInitial()) {
0893: // initial call
0894: result = true;
0895: } else if (ACTION_CORRECT_INPUT.equalsIgnoreCase(formAction)) {
0896: // user decided to modify his inputs
0897: result = true;
0898: } else if (ACTION_SUBMIT.equalsIgnoreCase(formAction)
0899: && !validate()) {
0900: // input field validation failed
0901: result = true;
0902:
0903: if (getFormConfiguration().hasCaptchaField()
0904: && getFormConfiguration()
0905: .captchaFieldIsOnCheckPage()) {
0906: // if there is a captcha field and a check page configured, we do have to remove the already
0907: // initialized captcha field from the form again. the captcha field gets initialized together with
0908: // the form, in this moment it is not clear yet whether we have validation errors or and need to
0909: // to go back to the input form...
0910: getFormConfiguration().removeCaptchaField();
0911: }
0912: } else if (ACTION_CONFIRMED.equalsIgnoreCase(formAction)
0913: && getFormConfiguration().captchaFieldIsOnCheckPage()
0914: && !validate()) {
0915: // captcha field validation on check page failed- redisplay the check page, not the input page!
0916: result = false;
0917: } else if (ACTION_DOWNLOAD_DATA_1.equalsIgnoreCase(formAction)) {
0918: result = false;
0919: } else if (ACTION_DOWNLOAD_DATA_2.equalsIgnoreCase(formAction)) {
0920: result = false;
0921: }
0922:
0923: return result;
0924: }
0925:
0926: /**
0927: * Returns if template head or other HTML should be inclulded (the page does not serve as a download page).<p>
0928: *
0929: * @return true if template head or other HTML should be inclulded (the page does not serve as a download page)
0930: */
0931: public boolean showTemplate() {
0932:
0933: boolean result = true;
0934:
0935: String paramAction = getParameter(CmsFormHandler.PARAM_FORMACTION);
0936: if (CmsFormHandler.ACTION_DOWNLOAD_DATA_2.equals(paramAction)) {
0937: result = false;
0938: }
0939: return result;
0940: }
0941:
0942: /**
0943: * Validation method that checks the given input fields.<p>
0944: *
0945: * All errors are stored in the member m_errors Map, with the input field name as key
0946: * and the error message String as value.<p>
0947: *
0948: * @return true if all necessary fields can be validated, otherwise false
0949: */
0950: public boolean validate() {
0951:
0952: if (m_isValidatedCorrect != null) {
0953: return m_isValidatedCorrect.booleanValue();
0954: }
0955:
0956: boolean allOk = true;
0957: // iterate the form fields
0958: List fields = getFormConfiguration().getFields();
0959:
0960: // validate each form field
0961: for (int i = 0, n = fields.size(); i < n; i++) {
0962:
0963: I_CmsField currentField = (I_CmsField) fields.get(i);
0964:
0965: if (currentField == null) {
0966: continue;
0967: }
0968:
0969: if (CmsCaptchaField.class.isAssignableFrom(currentField
0970: .getClass())) {
0971: // the captcha field doesn't get validated here...
0972: continue;
0973: }
0974:
0975: String validationError = currentField.validate(this );
0976: if (CmsStringUtil.isNotEmpty(validationError)) {
0977: getErrors()
0978: .put(currentField.getName(), validationError);
0979: allOk = false;
0980: }
0981: }
0982:
0983: CmsCaptchaField captchaField = getFormConfiguration()
0984: .getCaptchaField();
0985: if (captchaField != null) {
0986:
0987: boolean captchaFieldIsOnInputPage = getFormConfiguration()
0988: .captchaFieldIsOnInputPage()
0989: && getFormConfiguration().isInputFormSubmitted();
0990: boolean captchaFieldIsOnCheckPage = getFormConfiguration()
0991: .captchaFieldIsOnCheckPage()
0992: && getFormConfiguration().isCheckPageSubmitted();
0993:
0994: if (captchaFieldIsOnInputPage || captchaFieldIsOnCheckPage) {
0995: if (!captchaField.validateCaptchaPhrase(this ,
0996: captchaField.getValue())) {
0997: getErrors().put(captchaField.getName(),
0998: ERROR_VALIDATION);
0999: allOk = false;
1000: }
1001: }
1002: }
1003:
1004: m_isValidatedCorrect = Boolean.valueOf(allOk);
1005: return allOk;
1006: }
1007:
1008: /**
1009: * Creates a list of internet addresses (email) from a semicolon separated String.<p>
1010: *
1011: * @param mailAddresses a semicolon separated String with email addresses
1012: * @return list of internet addresses (email)
1013: * @throws AddressException if an email address is not correct
1014: */
1015: protected List createInternetAddresses(String mailAddresses)
1016: throws AddressException {
1017:
1018: if (CmsStringUtil.isNotEmpty(mailAddresses)) {
1019: // at least one email address is present, generate list
1020: StringTokenizer T = new StringTokenizer(mailAddresses, ";");
1021: List addresses = new ArrayList(T.countTokens());
1022: while (T.hasMoreTokens()) {
1023: InternetAddress address = new InternetAddress(T
1024: .nextToken());
1025: addresses.add(address);
1026: }
1027: return addresses;
1028: } else {
1029: // no address given, return empty list
1030: return Collections.EMPTY_LIST;
1031: }
1032: }
1033:
1034: /**
1035: * Returns the request parameter with the specified name.<p>
1036: *
1037: * @param parameter the parameter to return
1038: *
1039: * @return the parameter value
1040: */
1041: protected String getParameter(String parameter) {
1042:
1043: try {
1044: return ((String[]) m_parameterMap.get(parameter))[0];
1045: } catch (NullPointerException e) {
1046: return "";
1047: }
1048: }
1049:
1050: /**
1051: * Stores the given form data in the database.<p>
1052: *
1053: * @return true if successful
1054: *
1055: * @throws Exception if something goes wrong
1056: */
1057: protected boolean sendDatabase() throws Exception {
1058:
1059: return CmsFormDataAccess.getInstance().writeFormData(this );
1060: }
1061:
1062: /**
1063: * Sends the mail with the form data to the specified recipients.<p>
1064: *
1065: * If configured, sends also a confirmation mail to the form submitter.<p>
1066: *
1067: * @return true if the mail has been successfully sent, otherwise false
1068: */
1069: protected boolean sendMail() {
1070:
1071: try {
1072: // create the new mail message depending on the configured email type
1073: if (getFormConfiguration().getMailType().equals(
1074: CmsForm.MAILTYPE_HTML)) {
1075: // create a HTML email
1076: CmsHtmlMail theMail = new CmsHtmlMail();
1077: theMail.setCharset(getCmsObject().getRequestContext()
1078: .getEncoding());
1079: if (CmsStringUtil.isNotEmpty(getFormConfiguration()
1080: .getMailFrom())) {
1081: theMail.setFrom(m_macroResolver
1082: .resolveMacros(getFormConfiguration()
1083: .getMailFrom()));
1084: }
1085: theMail
1086: .setTo(createInternetAddresses(getFormConfiguration()
1087: .getMailTo()));
1088: theMail.setCc(createInternetAddresses(m_macroResolver
1089: .resolveMacros(getFormConfiguration()
1090: .getMailCC())));
1091: theMail.setBcc(createInternetAddresses(m_macroResolver
1092: .resolveMacros(getFormConfiguration()
1093: .getMailBCC())));
1094: theMail.setSubject(m_macroResolver
1095: .resolveMacros(getFormConfiguration()
1096: .getMailSubjectPrefix()
1097: + getFormConfiguration()
1098: .getMailSubject()));
1099: theMail
1100: .setHtmlMsg(createMailTextFromFields(true,
1101: false));
1102: theMail.setTextMsg(createMailTextFromFields(false,
1103: false));
1104:
1105: // attach file uploads
1106: Map fileUploads = (Map) getRequest().getSession()
1107: .getAttribute(ATTRIBUTE_FILEITEMS);
1108: if (fileUploads != null) {
1109: Iterator i = fileUploads.values().iterator();
1110: while (i.hasNext()) {
1111: FileItem attachment = (FileItem) i.next();
1112: if (attachment != null) {
1113: String filename = attachment
1114: .getName()
1115: .substring(
1116: attachment
1117: .getName()
1118: .lastIndexOf(
1119: File.separator) + 1);
1120: theMail
1121: .attach(
1122: new CmsByteArrayDataSource(
1123: filename,
1124: attachment.get(),
1125: OpenCms
1126: .getResourceManager()
1127: .getMimeType(
1128: filename,
1129: null,
1130: "application/octet-stream")),
1131: filename, filename);
1132: }
1133: }
1134: }
1135: // send the mail
1136: theMail.send();
1137: } else {
1138: // create a plain text email
1139: CmsSimpleMail theMail = new CmsSimpleMail();
1140: theMail.setCharset(getCmsObject().getRequestContext()
1141: .getEncoding());
1142: if (CmsStringUtil.isNotEmpty(getFormConfiguration()
1143: .getMailFrom())) {
1144: theMail.setFrom(m_macroResolver
1145: .resolveMacros(getFormConfiguration()
1146: .getMailFrom()));
1147: }
1148: theMail
1149: .setTo(createInternetAddresses(getFormConfiguration()
1150: .getMailTo()));
1151: theMail.setCc(createInternetAddresses(m_macroResolver
1152: .resolveMacros(getFormConfiguration()
1153: .getMailCC())));
1154: theMail.setBcc(createInternetAddresses(m_macroResolver
1155: .resolveMacros(getFormConfiguration()
1156: .getMailBCC())));
1157: theMail.setSubject(m_macroResolver
1158: .resolveMacros(getFormConfiguration()
1159: .getMailSubjectPrefix()
1160: + getFormConfiguration()
1161: .getMailSubject()));
1162: theMail.setMsg(createMailTextFromFields(false, false));
1163: // send the mail
1164: theMail.send();
1165: }
1166: } catch (Exception e) {
1167: // an error occured during mail creation
1168: if (LOG.isErrorEnabled()) {
1169: LOG.error(e.getLocalizedMessage(), e);
1170: }
1171: getErrors().put("sendmail", e.getMessage());
1172: return false;
1173: }
1174: return true;
1175: }
1176:
1177: /**
1178: * Sets the form configuration.<p>
1179: *
1180: * @param configuration the form configuration
1181: */
1182: protected void setFormConfiguration(CmsForm configuration) {
1183:
1184: m_formConfiguration = configuration;
1185: }
1186:
1187: /**
1188: * Sets if the form is displayed for the first time.<p>
1189: *
1190: * @param initial true if the form is displayed for the first time, otherwise false
1191: */
1192: protected void setInitial(boolean initial) {
1193:
1194: m_initial = initial;
1195: }
1196:
1197: /**
1198: * Sets the localized messages.<p>
1199: *
1200: * @param messages the localized messages
1201: */
1202: protected void setMessages(CmsMessages messages) {
1203:
1204: m_messages = messages;
1205: }
1206:
1207: /**
1208: * Checks if the given field should be used in form data macros.<p>
1209: *
1210: * @param field the field to check
1211: *
1212: * @return if the given field should be used in form data macros
1213: */
1214: protected boolean useInFormDataMacro(I_CmsField field) {
1215:
1216: // don't show the letter of agreement (CmsPrivacyField) and captcha field value
1217: return !((field instanceof CmsPrivacyField) || (field instanceof CmsCaptchaField));
1218: }
1219: }
|