001: /*
002: * File : $Source: /usr/local/cvs/alkacon/com.alkacon.opencms.registration/src/com/alkacon/opencms/registration/CmsRegistrationFormHandler.java,v $
003: * Date : $Date: 2008-02-19 13:22:30 $
004: * Version: $Revision: 1.1 $
005: *
006: * This file is part of the Alkacon OpenCms Add-On Module Package
007: *
008: * Copyright (c) 2007 Alkacon Software GmbH (http://www.alkacon.com)
009: *
010: * The Alkacon OpenCms Add-On Module Package is free software:
011: * you can redistribute it and/or modify
012: * it under the terms of the GNU General Public License as published by
013: * the Free Software Foundation, either version 3 of the License, or
014: * (at your option) any later version.
015: *
016: * The Alkacon OpenCms Add-On Module Package is distributed
017: * in the hope that it will be useful,
018: * but WITHOUT ANY WARRANTY; without even the implied warranty of
019: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
020: * GNU General Public License for more details.
021: *
022: * You should have received a copy of the GNU General Public License
023: * along with the Alkacon OpenCms Add-On Module Package.
024: * If not, see http://www.gnu.org/licenses/.
025: *
026: * For further information about Alkacon Software GmbH, please see the
027: * company website: http://www.alkacon.com.
028: *
029: * For further information about OpenCms, please see the
030: * project website: http://www.opencms.org.
031: */
032:
033: package com.alkacon.opencms.registration;
034:
035: import com.alkacon.opencms.formgenerator.CmsDynamicField;
036: import com.alkacon.opencms.formgenerator.CmsEmailField;
037: import com.alkacon.opencms.formgenerator.CmsForm;
038: import com.alkacon.opencms.formgenerator.CmsFormHandler;
039: import com.alkacon.opencms.formgenerator.I_CmsField;
040:
041: import org.opencms.file.CmsObject;
042: import org.opencms.file.CmsUser;
043: import org.opencms.i18n.CmsEncoder;
044: import org.opencms.i18n.CmsMessages;
045: import org.opencms.main.CmsException;
046: import org.opencms.main.CmsLog;
047: import org.opencms.main.OpenCms;
048: import org.opencms.module.CmsModule;
049: import org.opencms.util.CmsDateUtil;
050: import org.opencms.util.CmsMacroResolver;
051: import org.opencms.util.CmsRequestUtil;
052: import org.opencms.util.CmsStringUtil;
053:
054: import java.lang.reflect.Method;
055: import java.text.DateFormat;
056: import java.util.Arrays;
057: import java.util.Date;
058: import java.util.HashMap;
059: import java.util.Iterator;
060: import java.util.List;
061: import java.util.Map;
062:
063: import javax.servlet.http.HttpServletRequest;
064: import javax.servlet.http.HttpServletResponse;
065: import javax.servlet.jsp.PageContext;
066:
067: import org.apache.commons.codec.binary.Base64;
068: import org.apache.commons.fileupload.FileItem;
069: import org.apache.commons.logging.Log;
070:
071: /**
072: * The form handler controls the html or mail output of a configured email form.<p>
073: *
074: * Provides methods to determine the action that takes place and methods to create different
075: * output formats of a submitted form.<p>
076: *
077: * @author Michael Moossen
078: *
079: * @version $Revision: 1.1 $
080: *
081: * @since 7.0.4
082: */
083: public class CmsRegistrationFormHandler extends CmsFormHandler {
084:
085: /** Macro name for the activation uri macro that can be used in mail text fields. */
086: public static final String MACRO_ACTURI = "acturi";
087:
088: /** Parameter name for the activation code. */
089: public static final String PARAM_ACTCODE = "ac";
090:
091: /** Field name for email address. */
092: private static final String FIELD_EMAIL = "email";
093:
094: /** Field name for login. */
095: private static final String FIELD_LOGIN = "login";
096:
097: /** Field name for password. */
098: private static final String FIELD_PASSWORD = "password";
099:
100: /** The log object for this class. */
101: private static final Log LOG = CmsLog
102: .getLog(CmsRegistrationFormHandler.class);
103:
104: /** The module name. */
105: private static final String MODULE = "com.alkacon.opencms.registration";
106:
107: /** Reflection method prefix constant. */
108: private static final String REFLECTION_GETTER_PREFIX = "get";
109:
110: /** Reflection method prefix constant. */
111: private static final String REFLECTION_SETTER_PREFIX = "set";
112:
113: /**
114: * Constructor, creates the necessary form configuration objects.<p>
115: *
116: * @param context the JSP page context object
117: * @param req the JSP request
118: * @param res the JSP response
119: *
120: * @throws Exception if creating the form configuration objects fails
121: */
122: public CmsRegistrationFormHandler(PageContext context,
123: HttpServletRequest req, HttpServletResponse res)
124: throws Exception {
125:
126: super (context, req, res);
127: }
128:
129: /**
130: * Constructor, creates the necessary form configuration objects using a given configuration file URI.<p>
131: *
132: * @param context the JSP page context object
133: * @param req the JSP request
134: * @param res the JSP response
135: * @param formConfigUri URI of the form configuration file, if not provided, current URI is used for configuration
136: *
137: * @throws Exception if creating the form configuration objects fails
138: */
139: public CmsRegistrationFormHandler(PageContext context,
140: HttpServletRequest req, HttpServletResponse res,
141: String formConfigUri) throws Exception {
142:
143: super (context, req, res, formConfigUri);
144: }
145:
146: /**
147: * Returns the user name from the activation code.<p>
148: *
149: * @param code the activation code
150: *
151: * @return the user name
152: */
153: public static String getUserName(String code) {
154:
155: String reverse = "";
156: for (int i = 0; i < code.length(); i++) {
157: reverse = (code.charAt(i) + reverse);
158: }
159: return new String(Base64.decodeBase64(reverse.getBytes()));
160: }
161:
162: /**
163: * As test case.<p>
164: *
165: * @param args not used
166: */
167: public static void main(String[] args) {
168:
169: CmsUser user = new CmsUser(null,
170: "/mylongouname/m.moossen@alkacon.com", "", "", "", "",
171: 0, 0, 0, null);
172: String code = getActivationCode(user);
173: System.out.println(code);
174: System.out.println(getUserName(code));
175: }
176:
177: /**
178: * Returns the activation code for the given user.<p>
179: *
180: * @param user the user to generate an activation code for
181: *
182: * @return the activation code
183: */
184: private static String getActivationCode(CmsUser user) {
185:
186: String code = new String(Base64.encodeBase64(user.getName()
187: .getBytes()));
188: String reverse = "";
189: for (int i = 0; i < code.length(); i++) {
190: reverse = (code.charAt(i) + reverse);
191: }
192: return reverse;
193: }
194:
195: /**
196: * Activates the user identified by the current activation code code.<p>
197: *
198: * @throws CmsException if something goes wrong
199: */
200: public void activateUser() throws CmsException {
201:
202: CmsUser user = getUser();
203: user.setEnabled(true);
204: CmsRegistrationModuleAction.getAdminCms().writeUser(user);
205: }
206:
207: /**
208: * Checks if the current activation code identifies an existing user.<p>
209: *
210: * @return if the user is exists
211: */
212: public boolean existUser() {
213:
214: return (getUser() != null);
215: }
216:
217: /**
218: * Fills the fields with the data of the current user.<p>
219: */
220: public void fillFields() {
221:
222: if (getRequestContext().currentUser().isGuestUser()) {
223: // ignore if guest user
224: return;
225: }
226: Iterator fields = getRegFormConfiguration().getFields()
227: .iterator();
228: while (fields.hasNext()) {
229: I_CmsField field = (I_CmsField) fields.next();
230: if (CmsStringUtil.isEmptyOrWhitespaceOnly(field
231: .getDbLabel())) {
232: continue;
233: }
234: String value = getUserValue(getRequestContext()
235: .currentUser(), field.getDbLabel());
236: field.setValue(value);
237: }
238: }
239:
240: /**
241: * Returns the text to be show in the profile page.<p>
242: *
243: * @return the text to be show in the profile page
244: */
245: public String getEditFormText() {
246:
247: CmsMacroResolver macroResolver = getUserMacroResolver();
248: return macroResolver.resolveMacros(getRegFormConfiguration()
249: .getFormText());
250: }
251:
252: /**
253: * Returns the text to be show when the user activates his account.<p>
254: *
255: * @return the text to be show when the user activates his account
256: */
257: public String getFormActivatedText() {
258:
259: CmsMacroResolver macroResolver = getUserMacroResolver();
260: return macroResolver.resolveMacros(getRegFormConfiguration()
261: .getFormActivationText());
262: }
263:
264: /**
265: * Returns the form configuration.<p>
266: *
267: * @return the form configuration
268: */
269: public CmsRegistrationForm getRegFormConfiguration() {
270:
271: return (CmsRegistrationForm) super .getFormConfiguration();
272: }
273:
274: /**
275: * Initializes the form handler and creates the necessary configuration objects.<p>
276: *
277: * @param req the JSP request
278: * @param formConfigUri URI of the form configuration file, if not provided, current URI is used for configuration
279: * @throws Exception if creating the form configuration objects fails
280: */
281: public void init(HttpServletRequest req, String formConfigUri)
282: throws Exception {
283:
284: m_mulipartFileItems = CmsRequestUtil
285: .readMultipartFileItems(req);
286: m_macroResolver = CmsMacroResolver.newInstance();
287: m_macroResolver.setKeepEmptyMacros(true);
288:
289: if (m_mulipartFileItems != null) {
290: m_parameterMap = CmsRequestUtil
291: .readParameterMapFromMultiPart(getRequestContext()
292: .getEncoding(), m_mulipartFileItems);
293: } else {
294: m_parameterMap = new HashMap();
295: m_parameterMap.putAll(getRequest().getParameterMap());
296: }
297:
298: if (m_mulipartFileItems != null) {
299: Map fileUploads = (Map) req.getSession().getAttribute(
300: ATTRIBUTE_FILEITEMS);
301: if (fileUploads == null) {
302: fileUploads = new HashMap();
303: }
304: // check, if there are any attachments
305: Iterator i = m_mulipartFileItems.iterator();
306: while (i.hasNext()) {
307: FileItem fileItem = (FileItem) i.next();
308: if (CmsStringUtil.isNotEmpty(fileItem.getName())) {
309: // append file upload to the map of file items
310: fileUploads.put(fileItem.getFieldName(), fileItem);
311: m_parameterMap.put(fileItem.getFieldName(),
312: new String[] { fileItem.getName() });
313: }
314: }
315: req.getSession().setAttribute(ATTRIBUTE_FILEITEMS,
316: fileUploads);
317: } else {
318: req.getSession().removeAttribute(ATTRIBUTE_FILEITEMS);
319: }
320: String formAction = getParameter(PARAM_FORMACTION);
321: m_isValidatedCorrect = null;
322: setInitial(CmsStringUtil.isEmpty(formAction));
323: // get the localized messages
324: CmsModule module = OpenCms.getModuleManager().getModule(MODULE);
325: String para = module.getParameter("message",
326: "/com/alkacon/opencms/registration/workplace");
327:
328: setMessages(new CmsMessages(para, getRequestContext()
329: .getLocale()));
330: // get the form configuration
331: setFormConfiguration(new CmsRegistrationForm(this ,
332: getMessages(), isInitial(), formConfigUri, formAction));
333: }
334:
335: /**
336: * Checks if the current activation code identifies an existing user and if it is already activated.<p>
337: *
338: * @return if the user is activated
339: */
340: public boolean isUserActivated() {
341:
342: CmsUser user = getUser();
343: if (user == null) {
344: return false;
345: }
346: return user.isEnabled();
347: }
348:
349: /**
350: * Sends the collected data due to the configuration of the form
351: * (email, database or both).<p>
352: *
353: * @return true if successful
354: */
355: public boolean sendData() {
356:
357: boolean result = true;
358: try {
359: CmsRegistrationForm data = getRegFormConfiguration();
360: data.removeCaptchaField();
361: // fill the macro resolver for resolving in subject and content:
362: List fields = data.getAllFields();
363: Iterator itFields = fields.iterator();
364: // add field values as macros
365: while (itFields.hasNext()) {
366: I_CmsField field = (I_CmsField) itFields.next();
367: String fValue = field.getValue();
368: if (field instanceof CmsDynamicField) {
369: fValue = data.getFieldStringValueByName(field
370: .getName());
371: }
372: m_macroResolver.addMacro(field.getLabel(), fValue);
373: if (field instanceof CmsEmailField) {
374: if (data.isEmailAsLogin()) {
375: m_macroResolver.addMacro(FIELD_LOGIN, fValue);
376: }
377: }
378: if (!field.getLabel().equals(field.getDbLabel())) {
379: m_macroResolver
380: .addMacro(field.getDbLabel(), fValue);
381: }
382: }
383: // add current date as macro
384: m_macroResolver.addMacro(MACRO_DATE, CmsDateUtil
385: .getDateTime(new Date(), DateFormat.LONG,
386: getRequestContext().getLocale()));
387: if (getRequestContext().currentUser().isGuestUser()) {
388: // create the user here
389: createUser();
390: } else {
391: editUser();
392: }
393: // send optional confirmation mail
394: if (data.isConfirmationMailEnabled()) {
395: if (!data.isConfirmationMailOptional()
396: || Boolean
397: .valueOf(
398: getParameter(CmsForm.PARAM_SENDCONFIRMATION))
399: .booleanValue()) {
400: sendConfirmationMail();
401: }
402: }
403: if (data.isTransportEmail()) {
404: result = sendMail();
405: }
406: } catch (Exception e) {
407: // an error occurred during mail creation
408: if (LOG.isErrorEnabled()) {
409: LOG.error("An unexpected error occured.", e);
410: }
411: getErrors().put("sendmail", e.getMessage());
412: result = false;
413: }
414: return result;
415: }
416:
417: /**
418: * @see com.alkacon.opencms.formgenerator.CmsFormHandler#useInFormDataMacro(com.alkacon.opencms.formgenerator.I_CmsField)
419: */
420: protected boolean useInFormDataMacro(I_CmsField field) {
421:
422: boolean ret = super .useInFormDataMacro(field);
423: ret &= !(field instanceof CmsPasswordField);
424: return ret;
425: }
426:
427: /**
428: * Creates the user.<p>
429: *
430: * @throws CmsException if something goes wrong
431: */
432: private void createUser() throws CmsException {
433:
434: // first create the user with the basics
435: CmsRegistrationForm form = getRegFormConfiguration();
436: CmsObject cms = CmsRegistrationModuleAction.getAdminCms();
437: String email = form.getFieldByDbLabel(FIELD_EMAIL).getValue();
438: String login = form.getOrgUnit();
439: if (form.isEmailAsLogin()) {
440: login += email;
441: } else {
442: login += form.getFieldByDbLabel(FIELD_LOGIN).getValue();
443: }
444: String password = form.getFieldByDbLabel(FIELD_PASSWORD)
445: .getValue();
446: // default description
447: String description = Messages.get().getBundle(
448: getCmsObject().getRequestContext().getLocale()).key(
449: Messages.GUI_USER_DESCRIPTION_0);
450: CmsUser user = cms.createUser(login, password, description,
451: null);
452: user.setEmail(email);
453: user.setEnabled(false);
454: cms.writeUser(user);
455: // add activation uri macro
456: String link = OpenCms.getSiteManager().getCurrentSite(
457: getCmsObject()).getServerPrefix(cms,
458: getRequestContext().getUri())
459: + link(CmsRequestUtil.appendParameter(
460: getRequestContext().getUri(), PARAM_ACTCODE,
461: CmsEncoder.encode(getActivationCode(user))));
462: m_macroResolver.addMacro(MACRO_ACTURI, "<a href=\"" + link
463: + "\">" + link + "</a>");
464: // now add additional information
465: // iterate all fields except email, login and password
466: List excludes = Arrays.asList(new String[] { FIELD_EMAIL,
467: FIELD_PASSWORD, FIELD_LOGIN });
468: Iterator it = form.getAllFields().iterator();
469: while (it.hasNext()) {
470: I_CmsField field = (I_CmsField) it.next();
471: if (excludes.contains(field.getDbLabel())) {
472: continue;
473: }
474: setUserValue(user, field);
475: }
476: cms.writeUser(user);
477: // now assign the user to the given group only if needed
478: if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(form.getGroup())) {
479: cms.addUserToGroup(user.getName(), form.getGroup());
480: }
481: }
482:
483: /**
484: * Sets all fields to the current user.<p>
485: *
486: * @throws CmsException if something goes wrong
487: */
488: private void editUser() throws CmsException {
489:
490: CmsObject cms = CmsRegistrationModuleAction.getAdminCms();
491: CmsUser user = getRequestContext().currentUser();
492: CmsRegistrationForm form = getRegFormConfiguration();
493: Iterator it = form.getAllFields().iterator();
494: while (it.hasNext()) {
495: I_CmsField field = (I_CmsField) it.next();
496: setUserValue(user, field);
497: if (field.getDbLabel().equals(FIELD_PASSWORD)) {
498: if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(field
499: .getValue())) {
500: cms.setPassword(user.getName(), field.getValue());
501: }
502: }
503: }
504: cms.writeUser(user);
505: }
506:
507: /**
508: * Checks if the current activation code identifies an existing user.<p>
509: *
510: * @return if the user is exists
511: */
512: private CmsUser getUser() {
513:
514: String code = getJspContext().getRequest().getParameter(
515: PARAM_ACTCODE);
516: if (code == null) {
517: return getRequestContext().currentUser();
518: }
519: String userName = getUserName(code);
520: try {
521: return getCmsObject().readUser(userName);
522: } catch (Exception e) {
523: return null;
524: }
525: }
526:
527: /**
528: * Returns the macro resolver for the activation and profile pages.<p>
529: *
530: * @return the macro resolver for the activation and profile pages
531: */
532: private CmsMacroResolver getUserMacroResolver() {
533:
534: // TODO: create macros for properties and addinfo keys instead of fields!
535: CmsUser user = getUser();
536: CmsMacroResolver macroResolver = CmsMacroResolver.newInstance();
537: macroResolver.setKeepEmptyMacros(true);
538: List fields = getRegFormConfiguration().getFields();
539: Iterator itFields = fields.iterator();
540: // add field values as macros
541: while (itFields.hasNext()) {
542: I_CmsField field = (I_CmsField) itFields.next();
543: String label = field.getDbLabel();
544: if (CmsStringUtil.isEmptyOrWhitespaceOnly(label)) {
545: continue;
546: }
547: if (label.equals(FIELD_LOGIN)) {
548: String value = user.getName();
549: macroResolver.addMacro(label, value);
550: }
551: String value = getUserValue(user, label);
552: macroResolver.addMacro(label, value);
553: if (!field.getLabel().equals(label)) {
554: macroResolver.addMacro(field.getLabel(), value);
555: }
556: }
557: return macroResolver;
558: }
559:
560: /**
561: * Returns the value of the given field for the given user.<p>
562: *
563: * @param user the user
564: * @param label the field
565: *
566: * @return the value of the given field for the given user
567: */
568: private String getUserValue(CmsUser user, String label) {
569:
570: String methodName = REFLECTION_GETTER_PREFIX;
571: methodName += ("" + label.charAt(0)).toUpperCase();
572: if (label.length() > 1) {
573: methodName += label.substring(1);
574: }
575: Object value = null;
576: try {
577: // try to access the method
578: Method method = CmsUser.class.getMethod(methodName,
579: new Class[] {});
580: value = method.invoke(user, new Object[] {});
581: } catch (Exception e) {
582: // get additional info
583: value = user.getAdditionalInfo(label);
584: }
585: return value == null ? "" : value.toString();
586: }
587:
588: /**
589: * Sets the field value for the given user.<p>
590: *
591: * @param user the user to set the field for
592: * @param field the field to set
593: */
594: private void setUserValue(CmsUser user, I_CmsField field) {
595:
596: String methodName = REFLECTION_SETTER_PREFIX;
597: methodName += ("" + field.getDbLabel().charAt(0)).toUpperCase();
598: if (field.getDbLabel().length() > 1) {
599: methodName += field.getDbLabel().substring(1);
600: }
601: try {
602: // try to access the method
603: Method method = CmsUser.class.getMethod(methodName,
604: new Class[] { String.class });
605: method.invoke(user, new String[] { field.getValue() });
606: } catch (Exception e) {
607: // set additional info
608: user
609: .setAdditionalInfo(field.getDbLabel(), field
610: .getValue());
611: }
612: }
613: }
|