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 }