001// Copyright 2011, 2012 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.*;
018import org.apache.tapestry5.annotations.Environmental;
019import org.apache.tapestry5.annotations.Import;
020import org.apache.tapestry5.annotations.Parameter;
021import org.apache.tapestry5.annotations.SupportsInformalParameters;
022import org.apache.tapestry5.corelib.base.AbstractField;
023import org.apache.tapestry5.internal.TapestryInternalUtils;
024import org.apache.tapestry5.ioc.Messages;
025import org.apache.tapestry5.ioc.annotations.Inject;
026import org.apache.tapestry5.kaptcha.KaptchaSymbolConstants;
027import org.apache.tapestry5.services.FieldValidatorSource;
028import org.apache.tapestry5.services.Request;
029
030/**
031 * Field paired with a {@link KaptchaImage} to ensure that the user has provided
032 * the correct value.
033 *
034 * @since 5.3
035 * @tapestrydoc
036 */
037@SupportsInformalParameters
038@Import(stylesheet = "kaptcha.css")
039public class KaptchaField extends AbstractField
040{
041
042    /**
043     * The image output for this field. The image will display a distorted text
044     * string. The user must decode the distorted text and enter the same value.
045     */
046    @Parameter(required = true, defaultPrefix = BindingConstants.COMPONENT)
047    private KaptchaImage image;
048
049    /**
050     * Controls whether the field is rendered like a password field (false, the factory default)
051     * or like a normal text field (true).
052     *
053     * @see KaptchaSymbolConstants#KAPTCHA_DEFAULT_VISIBLE
054     * @since 5.3
055     */
056    @Parameter("symbol:" + KaptchaSymbolConstants.KAPTCHA_DEFAULT_VISIBLE)
057    private boolean visible;
058
059    @Inject
060    private Request request;
061
062    @Inject
063    private Messages messages;
064
065    @Inject
066    private ComponentResources resources;
067
068    @Environmental
069    private ValidationTracker validationTracker;
070
071    @Inject
072    private FieldValidatorSource fieldValidatorSource;
073
074    /**
075     * Always required.
076     */
077    @Override
078    public boolean isRequired()
079    {
080        return true;
081    }
082
083    @Override
084    protected void processSubmission(String controlName)
085    {
086        String userValue = request.getParameter(controlName);
087
088        validationTracker.recordInput(this, userValue);
089
090        if (TapestryInternalUtils.isEqual(image.getCaptchaText(), userValue))
091            return;
092
093        validationTracker.recordError(this, messages.get("tapestry-incorrect-captcha"));
094    }
095
096    @SuppressWarnings("rawtypes")
097    boolean beginRender(MarkupWriter writer)
098    {
099        writer.element("input",
100
101                "type", visible ? "text" : "password",
102
103                "id", getClientId(),
104
105                "name", getControlName(),
106
107                "value", visible ? validationTracker.getInput(this) : "");
108
109        resources.renderInformalParameters(writer);
110
111        FieldValidator fieldValidator = fieldValidatorSource.createValidator(this, "required", null);
112
113        fieldValidator.render(writer);
114
115        writer.end();
116
117        return false;
118    }
119}