    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
    015    package org.apache.tapestry5.kaptcha.components;
    016
    017    import org.apache.tapestry5.*;
    018    import org.apache.tapestry5.annotations.Environmental;
    019    import org.apache.tapestry5.annotations.Import;
    020    import org.apache.tapestry5.annotations.Parameter;
    021    import org.apache.tapestry5.annotations.SupportsInformalParameters;
    022    import org.apache.tapestry5.corelib.base.AbstractField;
    023    import org.apache.tapestry5.internal.TapestryInternalUtils;
    024    import org.apache.tapestry5.ioc.Messages;
    025    import org.apache.tapestry5.ioc.annotations.Inject;
    026    import org.apache.tapestry5.kaptcha.KaptchaSymbolConstants;
    027    import org.apache.tapestry5.services.FieldValidatorSource;
    028    import 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")
    039    public 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    }