Package org.apache.cocoon.forms.formmodel

Source Code of org.apache.cocoon.forms.formmodel.CaptchaField

/*
* Copyright 1999-2005 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cocoon.forms.formmodel;

import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Locale;
import java.util.Map;

import org.apache.avalon.framework.CascadingRuntimeException;
import org.apache.avalon.framework.context.Context;
import org.apache.cocoon.components.ContextHelper;
import org.apache.cocoon.environment.ObjectModelHelper;
import org.apache.cocoon.environment.Session;
import org.apache.cocoon.forms.FormsConstants;
import org.apache.cocoon.xml.AttributesImpl;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;


/**
* A {@link Field} for CAPTCHA validation. Upon generation, a secret random string is stored
* in a session attribute having a randomly generated name, for use by a
* {@link org.apache.cocoon.forms.validation.impl.CaptchaValidator}.
* <br>
* Usage sample:
* <pre>
    &lt;fd:captcha id="f1" required="true">
      &lt;fd:label>Copy the number shown into the input field&lt;/fd:label>
      &lt;fd:datatype base="string"/>
      &lt;fd:validation>
        &lt;fd:captcha/>
      &lt;/fd:validation>
    &lt;/fd:captcha>
* </pre>
*
* @see <a href="http://www.captcha.net/">captcha.net</a>
* @version $Id: CaptchaField.java 367017 2006-01-08 11:09:40Z antonio $
*/
public class CaptchaField extends Field {

    public static final String SESSION_ATTR_PREFIX = "captcha-";

    private static final String IMAGE_EL = "captcha-image";
    private static final String SECRET_CHARS = "abcdefghijkmnopqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ123456789";
    private static final int SESSION_ATTR_NAME_LENGTH = 6;

    private Context avalonContext;
    private int length;

    /**
     * Random number generator used to create session attribute name.
     */
    protected static final SecureRandom random;

    static {
        SecureRandom sr = null;
        try {
            sr = SecureRandom.getInstance("SHA1PRNG");
        } catch(java.security.NoSuchAlgorithmException nsae) {
            // Maybe we are on IBM's SDK
            try {
                sr = SecureRandom.getInstance("IBMSecureRandom");
            } catch (NoSuchAlgorithmException e) {
                throw new CascadingRuntimeException("No random number generator available", e);
            }
        } finally {
            random = sr;
        }
        random.setSeed(System.currentTimeMillis());
    }

    public CaptchaField(CaptchaFieldDefinition fieldDefinition, Context avalonContext) {
        super(fieldDefinition);
        this.avalonContext = avalonContext;
        this.length = fieldDefinition.getLength();
    }

    private String generateSecret() {
        StringBuffer secret = new StringBuffer(length);
        for (int n = 0 ; n < length ; n++) {
            int randomnumber = random.nextInt(SECRET_CHARS.length());
            secret.append(SECRET_CHARS.charAt(randomnumber));
        }
        return secret.toString();
    }

    public void generateItemSaxFragment(ContentHandler contentHandler, Locale locale) throws SAXException {
        super.generateItemSaxFragment(contentHandler, locale);
        byte[] bytes = new byte[SESSION_ATTR_NAME_LENGTH];
        char[] result = new char[bytes.length * 2];
        random.nextBytes(bytes);
        for (int i = 0; i < SESSION_ATTR_NAME_LENGTH; i++) {
            byte ch = bytes[i];
            result[2 * i] = Character.forDigit(Math.abs(ch >> 4), 16);
            result[2 * i + 1] = Character.forDigit(Math.abs(ch & 0x0f), 16);
        }
        String id = new String(result);
        Map objectModel = ContextHelper.getObjectModel(this.avalonContext);
        Session session = ObjectModelHelper.getRequest(objectModel).getSession(true);
        String secret = generateSecret();
        session.setAttribute(SESSION_ATTR_PREFIX + id, secret);
        this.setAttribute("secret", secret);
        AttributesImpl attrs = new AttributesImpl();
        attrs.addAttribute("", "id", "id", "PCDATA", id);
        contentHandler.startElement(FormsConstants.INSTANCE_NS, IMAGE_EL, FormsConstants.INSTANCE_PREFIX_COLON + IMAGE_EL, attrs);
        contentHandler.endElement(FormsConstants.INSTANCE_NS, IMAGE_EL, FormsConstants.INSTANCE_PREFIX_COLON + IMAGE_EL);
    }
}
TOP

Related Classes of org.apache.cocoon.forms.formmodel.CaptchaField

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.