<?php
// ValidateParam.php
// Copyright P.Kassel, M.Seliger, G.Trietsch, all Rights Reserved
namespace Docuform\Lib;use DateTimeImmutable;use DateTimeInterface;use DateTimeZone;class ValidateParam{public const HOSTNAME=1;public const IP=2;public const IP_OR_HOSTNAME=3;public const MAC=4;public const UUID=5;public const EMAIL=6;public const BOOL_STRICT=7;public const BOOL_LAZY=8;public const BOOL_STRING=9;public const DATE_ISO8601=10;public const STRINGLIST=11;public const STRING_ASCII=12;public static function checkIntegerRange(int $value,?int $min=null,?int $max=null):bool{$bOk=false;if(($min===null||$value>=$min)&&($max===null||$value<=$max)){$bOk=true;}return $bOk;}public static function checkParameters(array $params,array $constraints){$result=true;if(count($constraints)){foreach($constraints as $info){if(!empty($info['name'])||(isset($info['name'])&&$info['name']===false)){$name=$info['name'];$param=null;unset($param);if(is_array($name)){if(isset($params[key($name)][current($name)]))$param=$params[key($name)][current($name)];$name=key($name).'/'.current($name);}elseif(isset($params[$name])){$param=$params[$name];}$bIsEmpty=(!isset($param)||(is_string($param)&&$param==='')||(is_array($param)&&count($param)===0));$bRequired=(!empty($info['required'])&&$info['required']===true);if($bIsEmpty&&!(isset($param)&&$param===false)&&$bRequired===true){$result=$name;}if($result===true&&!$bIsEmpty){if(is_array($param)){$name=key($param).'/'.current($param);}else{$param=[$name=>$param];}foreach($param as $value){if(!empty($info['minLength'])&&strlen($value)<(int)$info['minLength']){$result=$name;break;}if(!empty($info['maxLength'])&&strlen($value)>(int)$info['maxLength']){$result=$name;break;}if(!empty($info['type'])&&!self::isValid($value,$info['type'])){$result=$name;break;}if(isset($info['min'])||isset($info['max'])){if(!self::checkIntegerRange($value,$info['min']?? null,$info['max']?? null)){$result=$name;break;}}if(!empty($info['invalidChars'])&&self::containsCharacters($value,$info['invalidChars'])){$result=$name;break;}if(!empty($info['invalidContent'])&&self::isContained($value,$info['invalidContent'])){$result=$name;break;}if(!empty($info['allowedContent'])){if(!empty($info['type'])&&$info['type']===self::STRINGLIST)$value=explode(',',$value);if(self::isContained($value,$info['allowedContent'])===false){$result=$name;break;}}if(!empty($info['callback'])&&is_array($info['callback'])){if($info['callback']($value)===false){$result=$name;break;}}}}}}}return $result;}public static function isContained($value,$content):bool{$contained=0;if(!is_array($value)){$value=array($value);}if(!is_array($content)){$content=array($content);}foreach($value as $v){foreach($content as $c){if((is_string($v)&&strtolower($v)===strtolower($c))||($v===$c)){$contained++;}}}return($contained===count($value));}public static function containsCharacters(string $string,string $chars):bool{$bOk=false;if(!empty($string)&&!empty($chars)){$len=strlen($chars);for($i=0;!$bOk&&$i<$len;$i++){if(strpos($string,$chars[$i])!==false){$bOk=true;}}}return $bOk;}public static function isValid($value,$flag,$bAllowEmpty=true):bool{$bOk=false;if(!empty($value)||$value===false){switch($flag){case self::IP:if(filter_var($value,FILTER_VALIDATE_IP)){$bOk=true;}break;case self::HOSTNAME:if(filter_var($value,FILTER_VALIDATE_DOMAIN,FILTER_FLAG_HOSTNAME)){$bOk=true;}break;case self::IP_OR_HOSTNAME:$Dirty=$value;$Clean=str_replace("_","",$Dirty);if(filter_var($Clean,FILTER_VALIDATE_IP)||filter_var($Clean,FILTER_VALIDATE_DOMAIN,FILTER_FLAG_HOSTNAME)){$bOk=true;}break;case self::MAC:$value=str_replace(':','-',$value);if(filter_var($value,FILTER_VALIDATE_MAC)||filter_var(MacAddress::toString($value),FILTER_VALIDATE_MAC)){$bOk=true;}break;case self::UUID:$UuidPattern='/^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i';if(preg_match($UuidPattern,$value)){$bOk=true;}break;case self::EMAIL:if(filter_var($value,FILTER_VALIDATE_EMAIL)){$bOk=true;}break;case self::BOOL_STRICT:if($value===true||$value===false){$bOk=true;}break;case self::BOOL_LAZY:if(filter_var($value,FILTER_VALIDATE_BOOLEAN,FILTER_NULL_ON_FAILURE)!==null){$bOk=true;}break;case self::BOOL_STRING:if(is_string($value)){if(strtolower($value)==='true'){$value=true;}elseif(strtolower($value)==='false'){$value=false;}else{$value=null;}}else{$value=null;}if($value!==null){$bOk=true;}break;case self::DATE_ISO8601:if(self::isValidDate($value)){$bOk=true;}break;case self::STRINGLIST:if(is_string($value))$bOk=true;break;case self::STRING_ASCII:if(is_string($value)&&preg_match('/[^\x20-\x7e]/',$value)!==1)$bOk=true;break;}}else{$bOk=$bAllowEmpty?true:false;}return $bOk;}private static function isValidDate($isoDateTime):bool{$dateTime=DateTimeImmutable::createFromFormat(DateTimeInterface::ATOM,$isoDateTime,new DateTimeZone('UTC'));$errors=DateTimeImmutable::getLastErrors();return $dateTime!==false&&($errors===false||($errors['warning_count']===0&&$errors['error_count']===0));}}