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.commons.Messages; 024import org.apache.tapestry5.corelib.base.AbstractField; 025import org.apache.tapestry5.internal.TapestryInternalUtils; 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}