/** * Copyright (c) 2011-2017, James Zhan 詹波 (jfinal@126.com). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.jfinal.validate; import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; import java.text.SimpleDateFormat; import java.util.Date; import java.util.regex.Matcher; import java.util.regex.Pattern; import com.jfinal.aop.Interceptor; import com.jfinal.aop.Invocation; import com.jfinal.core.Controller; import com.jfinal.kit.LogKit; import com.jfinal.kit.StrKit; /** * Validator. */ public abstract class Validator implements Interceptor { protected Controller controller; protected Invocation invocation; protected boolean shortCircuit = false; protected boolean invalid = false; protected String datePattern = null; // TODO set the DEFAULT_DATE_PATTERN in Const and config it in Constants. TypeConverter do the same thing. protected static final String DEFAULT_DATE_PATTERN = "yyyy-MM-dd"; protected static final String emailAddressPattern = "\\b(^['_A-Za-z0-9-]+(\\.['_A-Za-z0-9-]+)*@([A-Za-z0-9-])+(\\.[A-Za-z0-9-]+)*((\\.[A-Za-z0-9]{2,})|(\\.[A-Za-z0-9]{2,}\\.[A-Za-z0-9]{2,}))$)\\b"; protected void setShortCircuit(boolean shortCircuit) { this.shortCircuit = shortCircuit; } protected void setDatePattern(String datePattern) { this.datePattern = datePattern; } protected String getDatePattern() { return (datePattern != null ? datePattern : DEFAULT_DATE_PATTERN); } final public void intercept(Invocation invocation) { Validator validator = null; try { validator = getClass().newInstance(); } catch (Exception e) { throw new RuntimeException(e); } validator.controller = invocation.getController(); validator.invocation = invocation; try { validator.validate(validator.controller); } catch (ValidateException e) { // should not be throw, short circuit validate need this LogKit.logNothing(e); } if (validator.invalid) { validator.handleError(validator.controller); } else { invocation.invoke(); } } /** * Use validateXxx method to validate the parameters of this action. */ protected abstract void validate(Controller c); /** * Handle the validate error. * Example:<br> * controller.keepPara();<br> * controller.render("register.html"); */ protected abstract void handleError(Controller c); /** * Add message when validate failure. */ protected void addError(String errorKey, String errorMessage) { invalid = true; controller.setAttr(errorKey, errorMessage); if (shortCircuit) { throw new ValidateException(); } } /** * Return the controller of this action. */ protected Controller getController() { return controller; } /** * Return the action key of this action. */ protected String getActionKey() { return invocation.getActionKey(); } /** * Return the controller key of this action. */ protected String getControllerKey() { return invocation.getControllerKey(); } /** * Return the method of this action. */ protected Method getActionMethod() { return invocation.getMethod(); } /** * Return the method name of this action. */ protected String getActionMethodName() { return invocation.getMethodName(); } /** * Return view path of this controller. */ protected String getViewPath() { return invocation.getViewPath(); } /** * Validate Required. Allow space characters. */ protected void validateRequired(String field, String errorKey, String errorMessage) { String value = controller.getPara(field); if (value == null || "".equals(value)) { // 经测试,form表单域无输入时值为"",跳格键值为"\t",输入空格则为空格" " addError(errorKey, errorMessage); } } /** * Validate Required for urlPara. */ protected void validateRequired(int index, String errorKey, String errorMessage) { String value = controller.getPara(index); if (value == null /* || "".equals(value) */) { addError(errorKey, errorMessage); } } /** * Validate required string. */ protected void validateRequiredString(String field, String errorKey, String errorMessage) { if (StrKit.isBlank(controller.getPara(field))) { addError(errorKey, errorMessage); } } /** * Validate required string for urlPara. */ protected void validateRequiredString(int index, String errorKey, String errorMessage) { if (StrKit.isBlank(controller.getPara(index))) { addError(errorKey, errorMessage); } } /** * Validate integer. */ protected void validateInteger(String field, int min, int max, String errorKey, String errorMessage) { validateIntegerValue(controller.getPara(field), min, max, errorKey, errorMessage); } /** * Validate integer for urlPara. */ protected void validateInteger(int index, int min, int max, String errorKey, String errorMessage) { String value = controller.getPara(index); if (value != null && (value.startsWith("N") || value.startsWith("n"))) { value = "-" + value.substring(1); } validateIntegerValue(value, min, max, errorKey, errorMessage); } private void validateIntegerValue(String value, int min, int max, String errorKey, String errorMessage) { if (StrKit.isBlank(value)) { addError(errorKey, errorMessage); return ; } try { int temp = Integer.parseInt(value.trim()); if (temp < min || temp > max) { addError(errorKey, errorMessage); } } catch (Exception e) { addError(errorKey, errorMessage); } } /** * Validate integer. */ protected void validateInteger(String field, String errorKey, String errorMessage) { validateIntegerValue(controller.getPara(field), errorKey, errorMessage); } /** * Validate integer for urlPara. */ protected void validateInteger(int index, String errorKey, String errorMessage) { String value = controller.getPara(index); if (value != null && (value.startsWith("N") || value.startsWith("n"))) { value = "-" + value.substring(1); } validateIntegerValue(value, errorKey, errorMessage); } private void validateIntegerValue(String value, String errorKey, String errorMessage) { if (StrKit.isBlank(value)) { addError(errorKey, errorMessage); return ; } try { Integer.parseInt(value.trim()); } catch (Exception e) { addError(errorKey, errorMessage); } } /** * Validate long. */ protected void validateLong(String field, long min, long max, String errorKey, String errorMessage) { validateLongValue(controller.getPara(field), min, max, errorKey, errorMessage); } /** * Validate long for urlPara. */ protected void validateLong(int index, long min, long max, String errorKey, String errorMessage) { String value = controller.getPara(index); if (value != null && (value.startsWith("N") || value.startsWith("n"))) { value = "-" + value.substring(1); } validateLongValue(value, min, max, errorKey, errorMessage); } private void validateLongValue(String value, long min, long max, String errorKey, String errorMessage) { if (StrKit.isBlank(value)) { addError(errorKey, errorMessage); return ; } try { long temp = Long.parseLong(value.trim()); if (temp < min || temp > max) { addError(errorKey, errorMessage); } } catch (Exception e) { addError(errorKey, errorMessage); } } /** * Validate long. */ protected void validateLong(String field, String errorKey, String errorMessage) { validateLongValue(controller.getPara(field), errorKey, errorMessage); } /** * Validate long for urlPara. */ protected void validateLong(int index, String errorKey, String errorMessage) { String value = controller.getPara(index); if (value != null && (value.startsWith("N") || value.startsWith("n"))) { value = "-" + value.substring(1); } validateLongValue(value, errorKey, errorMessage); } private void validateLongValue(String value, String errorKey, String errorMessage) { if (StrKit.isBlank(value)) { addError(errorKey, errorMessage); return ; } try { Long.parseLong(value.trim()); } catch (Exception e) { addError(errorKey, errorMessage); } } /** * Validate double. */ protected void validateDouble(String field, double min, double max, String errorKey, String errorMessage) { String value = controller.getPara(field); if (StrKit.isBlank(value)) { addError(errorKey, errorMessage); return ; } try { double temp = Double.parseDouble(value.trim()); if (temp < min || temp > max) { addError(errorKey, errorMessage); } } catch (Exception e) { addError(errorKey, errorMessage); } } /** * Validate double. */ protected void validateDouble(String field, String errorKey, String errorMessage) { String value = controller.getPara(field); if (StrKit.isBlank(value)) { addError(errorKey, errorMessage); return ; } try { Double.parseDouble(value.trim()); } catch (Exception e) { addError(errorKey, errorMessage); } } /** * Validate date. Date formate: yyyy-MM-dd */ protected void validateDate(String field, String errorKey, String errorMessage) { String value = controller.getPara(field); if (StrKit.isBlank(value)) { addError(errorKey, errorMessage); return ; } try { new SimpleDateFormat(getDatePattern()).parse(value.trim()); // Date temp = Date.valueOf(value); 为了兼容 64位 JDK } catch (Exception e) { addError(errorKey, errorMessage); } } /** * Validate date. */ protected void validateDate(String field, Date min, Date max, String errorKey, String errorMessage) { String value = controller.getPara(field); if (StrKit.isBlank(value)) { addError(errorKey, errorMessage); return ; } try { Date temp = new SimpleDateFormat(getDatePattern()).parse(value.trim()); // Date temp = Date.valueOf(value); 为了兼容 64位 JDK if (temp.before(min) || temp.after(max)) { addError(errorKey, errorMessage); } } catch (Exception e) { addError(errorKey, errorMessage); } } /** * Validate date. Date formate: yyyy-MM-dd */ protected void validateDate(String field, String min, String max, String errorKey, String errorMessage) { // validateDate(field, Date.valueOf(min), Date.valueOf(max), errorKey, errorMessage); 为了兼容 64位 JDK try { SimpleDateFormat sdf = new SimpleDateFormat(getDatePattern()); validateDate(field, sdf.parse(min.trim()), sdf.parse(max.trim()), errorKey, errorMessage); } catch (Exception e) { addError(errorKey, errorMessage); } } /** * Validate equal field. Usually validate password and password again */ protected void validateEqualField(String field_1, String field_2, String errorKey, String errorMessage) { String value_1 = controller.getPara(field_1); String value_2 = controller.getPara(field_2); if (value_1 == null || value_2 == null || (! value_1.equals(value_2))) { addError(errorKey, errorMessage); } } /** * Validate equal string. */ protected void validateEqualString(String s1, String s2, String errorKey, String errorMessage) { if (s1 == null || s2 == null || (! s1.equals(s2))) { addError(errorKey, errorMessage); } } /** * Validate equal integer. */ protected void validateEqualInteger(Integer i1, Integer i2, String errorKey, String errorMessage) { if (i1 == null || i2 == null || (i1.intValue() != i2.intValue())) { addError(errorKey, errorMessage); } } /** * Validate email. */ protected void validateEmail(String field, String errorKey, String errorMessage) { validateRegex(field, emailAddressPattern, false, errorKey, errorMessage); } /** * Validate URL. */ protected void validateUrl(String field, String errorKey, String errorMessage) { String value = controller.getPara(field); if (StrKit.isBlank(value)) { addError(errorKey, errorMessage); return ; } try { value = value.trim(); if (value.startsWith("https://")) { value = "http://" + value.substring(8); // URL doesn't understand the https protocol, hack it } new URL(value); } catch (MalformedURLException e) { addError(errorKey, errorMessage); } } /** * Validate regular expression. */ protected void validateRegex(String field, String regExpression, boolean isCaseSensitive, String errorKey, String errorMessage) { String value = controller.getPara(field); if (value == null) { addError(errorKey, errorMessage); return ; } Pattern pattern = isCaseSensitive ? Pattern.compile(regExpression) : Pattern.compile(regExpression, Pattern.CASE_INSENSITIVE); Matcher matcher = pattern.matcher(value); if (!matcher.matches()) { addError(errorKey, errorMessage); } } /** * Validate regular expression and case sensitive. */ protected void validateRegex(String field, String regExpression, String errorKey, String errorMessage) { validateRegex(field, regExpression, true, errorKey, errorMessage); } /** * Validate string. */ protected void validateString(String field, int minLen, int maxLen, String errorKey, String errorMessage) { validateStringValue(controller.getPara(field), minLen, maxLen, errorKey, errorMessage); } /** * Validate string for urlPara */ protected void validateString(int index, int minLen, int maxLen, String errorKey, String errorMessage) { validateStringValue(controller.getPara(index), minLen, maxLen, errorKey, errorMessage); } private void validateStringValue(String value, int minLen, int maxLen, String errorKey, String errorMessage) { if (StrKit.isBlank(value)) { addError(errorKey, errorMessage); return ; } if (value.length() < minLen || value.length() > maxLen) { addError(errorKey, errorMessage); } } /** * Validate token created by Controller.createToken(String). */ protected void validateToken(String tokenName, String errorKey, String errorMessage) { if (controller.validateToken(tokenName) == false) { addError(errorKey, errorMessage); } } /** * Validate token created by Controller.createToken(). */ protected void validateToken(String errorKey, String errorMessage) { if (controller.validateToken() == false) { addError(errorKey, errorMessage); } } /** * validate boolean. */ protected void validateBoolean(String field, String errorKey, String errorMessage) { validateBooleanValue(controller.getPara(field), errorKey, errorMessage); } /** * validate boolean for urlPara. */ protected void validateBoolean(int index, String errorKey, String errorMessage) { validateBooleanValue(controller.getPara(index), errorKey, errorMessage); } private void validateBooleanValue(String value, String errorKey, String errorMessage) { if (StrKit.isBlank(value)) { addError(errorKey, errorMessage); return ; } value = value.trim().toLowerCase(); if ("1".equals(value) || "true".equals(value)) { return ; } else if ("0".equals(value) || "false".equals(value)) { return ; } addError(errorKey, errorMessage); } protected void validateCaptcha(String field, String errorKey, String errorMessage) { if (getController().validateCaptcha(field) == false) { addError(errorKey, errorMessage); } } }