001/** 002 * 003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. 004 * 005 * This library is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU Lesser General Public 007 * License as published by the Free Software Foundation; either 008 * version 2.1 of the License, or (at your option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 * Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public 016 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 017 * 018 **/ 019package lucee.runtime.functions.decision; 020 021import lucee.runtime.PageContext; 022import lucee.runtime.exp.ExpressionException; 023import lucee.runtime.exp.FunctionException; 024import lucee.runtime.exp.PageException; 025import lucee.runtime.ext.function.Function; 026import lucee.runtime.op.Caster; 027import lucee.runtime.op.Decision; 028 029import org.apache.oro.text.regex.MalformedPatternException; 030import org.apache.oro.text.regex.Pattern; 031import org.apache.oro.text.regex.PatternMatcherInput; 032import org.apache.oro.text.regex.Perl5Compiler; 033import org.apache.oro.text.regex.Perl5Matcher; 034 035/** 036 * 037 */ 038public final class IsValid implements Function { 039 040 private static final long serialVersionUID = -1383105304624662986L; 041 042 /** 043 * check for many diff types 044 * @param pc 045 * @param type 046 * @param value 047 * @return 048 * @throws ExpressionException 049 */ 050 public static boolean call(PageContext pc, String type, Object value) throws ExpressionException { 051 type=type.trim(); 052 053 if("range".equalsIgnoreCase(type)) 054 throw new FunctionException(pc,"isValid",1,"type","for [range] you have to define a min and max value"); 055 056 if("regex".equalsIgnoreCase(type) || "regular_expression".equalsIgnoreCase(type)) 057 throw new FunctionException(pc,"isValid",1,"type","for [regex] you have to define a pattern"); 058 059 return Decision.isValid(type, value); 060 } 061 062 /** 063 * regex check 064 * @param pc 065 * @param type 066 * @param value 067 * @param objPattern 068 * @return 069 * @throws PageException 070 */ 071 public static boolean call(PageContext pc, String type, Object value, Object objPattern) throws PageException { 072 type=type.trim(); 073 074 if(!"regex".equalsIgnoreCase(type) && !"regular_expression".equalsIgnoreCase(type)) 075 throw new FunctionException(pc,"isValid",1,"type","wrong attribute count for type ["+type+"]"); 076 077 return regex(Caster.toString(value,null),Caster.toString(objPattern)); 078 } 079 080 081 082 083 public static boolean regex(String value,String strPattern) { 084 if(value==null) 085 return false; 086 087 try { 088 Pattern pattern = new Perl5Compiler().compile(strPattern, Perl5Compiler.MULTILINE_MASK); 089 PatternMatcherInput input = new PatternMatcherInput(value); 090 return new Perl5Matcher().matches(input, pattern); 091 } catch (MalformedPatternException e) { 092 return false; 093 } 094 } 095 096 public static boolean call(PageContext pc, String type, Object value, Object objMin, Object objMax) throws PageException { 097 098 // for named argument calls 099 if(objMax==null) { 100 if(objMin==null) return call(pc, type, value); 101 return call(pc, type, value, objMin); 102 } 103 104 type=type.trim().toLowerCase(); 105 106 // numeric 107 if("range".equals(type) || "integer".equals(type) || "float".equals(type) || "numeric".equals(type) || "number".equals(type) ) { 108 109 double number=Caster.toDoubleValue(value,true,Double.NaN); 110 if(!Decision.isValid(number)) return false; 111 112 double min=toRangeNumber(pc,objMin,3,"min"); 113 double max=toRangeNumber(pc,objMax,4,"max"); 114 115 116 return number>=min && number<=max; 117 } 118 else if("string".equals(type)){ 119 String str=Caster.toString(value,null); 120 if(str==null) return false; 121 122 double min=toRangeNumber(pc,objMin,3,"min"); 123 double max=toRangeNumber(pc,objMax,4,"max"); 124 125 return str.length()>=min && str.length()<=max; 126 } 127 128 else 129 throw new FunctionException(pc,"isValid",1,"type","wrong attribute count for type ["+type+"]"); 130 131 } 132 133 private static double toRangeNumber(PageContext pc,Object objMin, int index,String name) throws FunctionException { 134 double d=Caster.toDoubleValue(objMin,false,Double.NaN); 135 if(!Decision.isValid(d)) 136 throw new FunctionException(pc,"isValid",index,name,"value must be numeric"); 137 return d; 138 } 139}