    001// Copyright 2011-2013 The Apache Software Foundation
    002//
    003// Licensed under the Apache License, Version 2.0 (the "License");
    004// you may not use this file except in compliance with the License.
    005// You may obtain a copy of the License at
    006//
    007// http://www.apache.org/licenses/LICENSE-2.0
    008//
    009// Unless required by applicable law or agreed to in writing, software
    010// distributed under the License is distributed on an "AS IS" BASIS,
    011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    012// See the License for the specific language governing permissions and
    013// limitations under the License.
    014
    015package org.apache.tapestry5.kaptcha.components;
    016
    017import org.apache.tapestry5.BindingConstants;
    018import org.apache.tapestry5.FieldValidator;
    019import org.apache.tapestry5.MarkupWriter;
    020import org.apache.tapestry5.annotations.Import;
    021import org.apache.tapestry5.annotations.Parameter;
    022import org.apache.tapestry5.annotations.SupportsInformalParameters;
    023import org.apache.tapestry5.corelib.base.AbstractField;
    024import org.apache.tapestry5.internal.TapestryInternalUtils;
    025import org.apache.tapestry5.ioc.Messages;
    026import org.apache.tapestry5.ioc.annotations.Inject;
    027import org.apache.tapestry5.kaptcha.KaptchaSymbolConstants;
    028import org.apache.tapestry5.services.FieldValidatorSource;
    029
    030/**
    031 * Field paired with a {@link KaptchaImage} to ensure that the user has provided
    032 * the correct value. Renders a class attribute of "form-control", which can be extended
    033 * via the class informal attribute.
    034 *
    035 * @since 5.3
    036 * @tapestrydoc
    037 */
    038@SupportsInformalParameters
    039@Import(stylesheet = "kaptcha.css")
    040public class KaptchaField extends AbstractField
    041{
    042
    043    /**
    044     * The image output for this field. The image will display a distorted text
    045     * string. The user must decode the distorted text and enter the same value.
    046     */
    047    @Parameter(required = true, defaultPrefix = BindingConstants.COMPONENT)
    048    private KaptchaImage image;
    049
    050    /**
    051     * Controls whether the field is rendered like a password field (false)
    052     * or like a normal text field (true, the factory default).
    053     *
    054     * @see KaptchaSymbolConstants#KAPTCHA_DEFAULT_VISIBLE
    055     * @since 5.3
    056     */
    057    @Parameter("symbol:" + KaptchaSymbolConstants.KAPTCHA_DEFAULT_VISIBLE)
    058    private boolean visible;
    059
    060    @Inject
    061    private Messages messages;
    062
    063    @Inject
    064    private FieldValidatorSource fieldValidatorSource;
    065
    066    /**
    067     * Always required.
    068     */
    069    @Override
    070    public boolean isRequired()
    071    {
    072        return true;
    073    }
    074
    075    @Override
    076    protected void processSubmission(String controlName)
    077    {
    078        String userValue = request.getParameter(controlName);
    079
    080        validationTracker.recordInput(this, userValue);
    081
    082        if (TapestryInternalUtils.isEqual(image.getCaptchaText(), userValue))
    083            return;
    084
    085        validationTracker.recordError(this, messages.get("tapestry-incorrect-captcha"));
    086    }
    087
    088    @SuppressWarnings("rawtypes")
    089    boolean beginRender(MarkupWriter writer)
    090    {
    091        writer.element("input",
    092
    093                "type", visible ? "text" : "password",
    094
    095                "id", getClientId(),
    096
    097                "class", "form-control",
    098
    099                "name", getControlName(),
    100
    101                "value", visible ? validationTracker.getInput(this) : "");
    102
    103        resources.renderInformalParameters(writer);
    104
    105        FieldValidator fieldValidator = fieldValidatorSource.createValidator(this, "required", null);
    106
    107        fieldValidator.render(writer);
    108
    109        writer.end();
    110
    111        return false;
    112    }
    113}