Input Validation - Average to Expert

Results 1 to 4 of 4
  1. #1
    Member RavenGamers is offline
    MemberRank
    Nov 2011 Join Date
    87Posts

    big grin Input Validation - Average to Expert

    Greetings,
    I am developing a new Web Engine and I wanted to release a php class from the Engine for `input validation`, in my opinion you need to be an average to expert in php in order to understand this class. This class can be used for any website. It is a very good security layer to valid any input coming from the client and anyone can use it, even newbie php developers/coders. It might need some work but I hope you like it.
    Feel free to ask any question :)

    //input.class.php
    PHP Code:
    <?php

    class input {

        
    //Every input should include: name, some features like type and the data itself
        
    private $_inputs = array( );
        private 
    $_number 0;
        private 
    $_errors = array( );

        function 
    __construct(array $inputs NULL)
        {
            
    $this->_inputs = (is_array($inputs)) ? $inputs : array( );
        }

        public function 
    addError($name$type$message)
        {
            
    $this->_errors[$name] = array('type' => $type'message' => $message);
        }

        public function 
    addInput($input)
        {
            if(
    $input['name'] && is_array($input)) {
                
    $this->_inputs[$input['name']] = $input;
                
    $this->_number++;
                return 
    true;
            } else {
                return 
    false;
            }
        }

        public function 
    addInputs($inputs)
        {
            if(!
    is_array($inputs)) return false;
            for(
    $i 0$i count($inputs); $i++) {
                if(
    $inputs[$i]['name']) {
                    
    $this->_inputs[$inputs[$i]['name']] = $inputs[$i];
                    
    $this->_number++;
                } else {
                    return 
    false;
                    break;
                }
            }
        }

        private function 
    dataType($type)
        {
            
    $regex false;
            switch(
    $type)
            {
                case 
    'CHAR':
                    
    $regex '^[a-zA-Z]+$';
                    break;

                case 
    'NAME':
                    
    $regex '^[a-zA-Z0-9]+$';
                    break;

                case 
    'PASSWORD':
                    
    $regex '^[a-zA-Z0-9\'\/~`\!@#\$%\^&\*\(\)_\-\+=\{\}\[\]\|;:"\<\>,\.\?\\\]+$';
                    break;

                case 
    'EMAIL':
                    
    $regex '^[[^@\s<&>]+@([-a-z0-9]+\.)+[a-z]{2,}]$';
                    break;

                case 
    'URL':
                    
    $regex '^[(http|https|ftp)\://[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(:[a-zA-Z0-9]*)?/?([a-zA-Z0-9\-\._\?\,\'/\\\+&amp;%\$#\=~])*[^\.\,\)\(\s]]$';
                    break;

                case 
    'IP':
                    
    $regex '^[(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])]$';
                    break;

                case 
    'INT':
                    
    $regex '^[0-9]+$';
                    break;

                case 
    'FLOAT':
                    
    $regex '^[[-+]?\d*\.?\d]*$';
                    break;
            }
            return 
    $regex;
        }

        private function 
    dataType_var($type)
        {
            switch(
    $type){
                case 
    'BOOLEAN':
                    
    $type FILTER_VALIDATE_BOOLEAN;
                    break;
                case 
    'EMAIL':
                    
    $type FILTER_VALIDATE_EMAIL;
                    break;
                case 
    'FLOAT':
                    
    $type FILTER_VALIDATE_FLOAT;
                    break;
                case 
    'INT':
                    
    $type FILTER_VALIDATE_INT;
                    break;
                case 
    'IP':
                    
    $type FILTER_VALIDATE_IP;
                    break;
                case 
    'REGEXP':
                    
    $type FILTER_VALIDATE_REGEXP;
                    break;
                case 
    'URL':
                    
    $type FILTER_VALIDATE_URL;
                    break;
                case 
    'BOOLEAN_S':
                    
    $type FILTER_SANITIZE_BOOLEAN;
                    break;
                case 
    'EMAIL_S':
                    
    $type FILTER_SANITIZE_EMAIL;
                    break;
                case 
    'FLOAT_S':
                    
    $type FILTER_SANITIZE_FLOAT;
                    break;
                case 
    'INT_S':
                    
    $type FILTER_SANITIZE_INT;
                    break;
                case 
    'IP_S':
                    
    $type FILTER_SANITIZE_IP;
                    break;
                case 
    'REGEXP_S':
                    
    $type FILTER_SANITIZE_REGEXP;
                    break;
                case 
    'URL_S':
                    
    $type FILTER_SANITIZE_URL;
                    break;
            }
            return 
    $type;
        }

        private function 
    pregMatch($data$type)
        {
            return (
    preg_match("/"$type ."/"$data)) ? 0;
        }

        private function 
    filterVar($data$type)
        {
            return (
    filter_var($data$type)) ? 0;
        }

        private function 
    isEmpty($data)
        {
            return (
    strlen(trim($data)) == || trim($data) == null || trim($data) == '' || empty($data) === true) ? 0;
        }

        private function 
    dataLength($data$min$max)
        {
            
    $error false;
            if(
    strlen($data) < $min) {
                
    $error 'toShort';
            } else if(
    strlen($data) > $max) {
                
    $error 'toLong';
            }

            return 
    $error;
        }

        private function 
    dataStrength($data$strongLen)
        {
            
    $score 0;

            if (
    strlen($data) >= $strongLen) {
                
    $score 1;
            }

            if (
    preg_match("/[a-z]/"$data) && preg_match("/[A-Z]/"$data)) {
                
    $score++;
            }

            if (
    preg_match("/[0-9]/"$data)) {
                
    $score++;
            }

            if (
    preg_match("/.[!,@,#,$,%,^,&,*,?,_,~,-,?,(,)]/"$data)) {
                
    $score++;
            }

            return 
    $score;
        }

        private function 
    filterData($data$type$replace)
        {
            if(
    $replace === true){
                
    $type str_replace('^[''[^'$type);
                
    $type str_replace(']+$'']'$type);
                
    $type str_replace(']$'']'$type);
            }
            return 
    preg_replace('/'$type .'/'''$data);
        }

        private function 
    render()
        {
            return (
    count($this->_errors) != 0) ? $this->_errors false;
        }

        public function 
    validation()
        {
            if(!
    is_array($this->_inputs)) return false;
            
    $inputs $this->_inputs;

            foreach(
    $inputs as $name => $input) {
                foreach(
    $input as $key => $value) {
                    switch(
    $key) {
                        case 
    'type':
                            if(
    array_key_exists('length'$input) && $input['length']['empty'] && empty($input['data'])) {

                            } else {
                                if (
    $value == 'EMAIL') {
                                    if (!
    $this->filterVar($input['data'], $this->dataType_var($value))) {
                                        
    $this->addError('dataType''default''invalid');
                                    }
                                } else {
                                    if (!
    $this->pregMatch($input['data'], $this->dataType($value))) {
                                        
    $this->addError('dataType''default''invalid');
                                    }
                                }
                            }
                            break;

                        case 
    'length':
                            
    $min = (array_key_exists('min'$value)) ? $value['min'] : 0;
                            
    $max = (array_key_exists('max'$value)) ? $value['max'] : 0;

                            if(!
    $value['empty'] && $this->isEmpty($input['data'])) {
                                
    $this->addError('emptyData''default''empty');
                            } else if(
    $this->dataLength($input['data'], $min$max) !== false) {
                                
    $this->addError('dataLength''default'$this->dataLength($input['data'], $min$max));
                            }
                            break;

                        case 
    'strength':
                            
    $array = array("very weak""weak""medium""strong""very strong");
                            
    $minLength = ($value['minLength']) ? $value['minLength'] : 0;
                            
    $minStrength = ($value['minStrength']) ? $value['minStrength'] : 0;

                            if(
    $this->dataStrength($input['data'], $minLength) < $minStrength) {
                                
    $curr $array[$this->dataStrength($input['data'], $minLength)];
                                
    $allowed $array[$minStrength];
                                
    $message 'The '$input['name'] .' is '$curr .', it must be '$allowed .'.';
                                
    $this->addError('dataStrength''default'$message);
                            }
                            break;

                        default:
                            break;
                    }
                }
                
    //$inputs[$name]['data'] = $this->filterData($inputs[$name]['data'], $this->dataType($inputs[$name]['type']), true);
            
    }
            return (
    $this->render() !== false) ? $this->render() : true;
        }
    }
    //input validation example
    PHP Code:
    <?php
    //Input validation system
    require_once('input.class.php');
    $input = new input();

    $username = array(
        
    'name' => 'username',
        
    'type' => 'NAME',
        
    'length' => array(
            
    'empty' => false,
            
    'min' => 4,
            
    'max' => 10
        
    ),
        
    'data' => 'WebDeveloper'
    );
    $input->addInput($username);
    $errors $input->validation();

    echo (
    is_array($errors) && !empty($errors)) ? '<pre>'print_r($errorstrue) .'</pre>' 'Input is valid.';
    //another example (password)
    PHP Code:
    <?php
    //Input validation system
    require_once('input.class.php');
    $input = new input();

    $password = array(
        
    'name' => 'password',
        
    'type' => 'PASSWORD',
        
    'length' => array(
            
    'empty' => false,
            
    'min' => 6,
            
    'max' => 18
        
    ),
        
    'strength' => array(
            
    'minLength' => 6,
            
    'minStrength' => 3,
        ),
        
    'data' => 'Qweasd123'
    );
    $input->addInput($password);
    $errors $input->validation();

    echo (
    is_array($errors) && !empty($errors)) ? '<pre>'print_r($errorstrue) .'</pre>' 'Input is valid.';


  2. #2
    Digital Horizon KristiansJ is offline
    MemberRank
    Jul 2012 Join Date
    203Posts

    Re: Input Validation - Average to Expert

    i was working for something similar, not perfect, but still
    PHP Code:
    <?php/*

     */

    declare(strict_types 1);

    namespace 
    System\Components
    {
        use 
    System\Exceptions\CompileException;
        use 
    System\Kernel\Container;

        
    /**
         * Class Validator
         *
         * @package System\Components
         */
        
    class Validator extends Container
        
    {
            const 
    TYPECAST_INT          0;
            const 
    TYPECAST_STRING       1;
            const 
    TYPECAST_FLOAT        2;
            const 
    TYPECAST_BOOL         3;

            const 
    CHECK_STRING_EMAIL    0;
            const 
    CHECK_STRING_IP       1;
            const 
    CHECK_STRING_ALPHNUM  2;
            const 
    CHECK_STRING_LOWER    3;
            const 
    CHECK_STRING_TEXT     4;

            
    /**
             *  [MENTION=1333430648]Var[/MENTION] array
             */
            
    private $rules = array();

            
    /**
             * Validates if object value can be casted other types.
             *
             *  [MENTION=2000183830]para[/MENTION]m string $object
             *  [MENTION=2000183830]para[/MENTION]m int    $castTo
             *
             *  [MENTION=850422]return[/MENTION] bool
             */
            
    public function canCastInput(string $objectint $castTo): bool
            
    {
                if(
    $castTo == Validator::TYPECAST_INT)
                {
                    if(!
    ctype_digit($object))
                    {
                        return 
    false;
                    }
                }
                elseif(
    $castTo == Validator::TYPECAST_FLOAT)
                {
                    
    $floatVal floatval($object);
                    if(!
    $floatVal && intval($floatVal) == $floatVal)
                    {
                        return 
    false;
                    }
                }
                elseif(
    $castTo == Validator::TYPECAST_BOOL)
                {
                    if(
    $object !== 'false' OR $object !== 'true')
                    {
                        return 
    false;
                    }
                }
                elseif(
    $castTo == Validator::TYPECAST_BOOL)
                {
                    if(
    $object !== 'false' OR $object !== 'true')
                    {
                        return 
    false;
                    }
                }
                return 
    true;
            }

            
    /**
             * Validates string value to match required pattern.
             *
             *  [MENTION=2000183830]para[/MENTION]m     $object Object to check value from
             *  [MENTION=2000183830]para[/MENTION]m int $check  Option to check what
             *
             *  [MENTION=850422]return[/MENTION] bool true if value matches, false on failure
             */
            
    public function validateStringValue($objectint $check): bool
            
    {
                if(
    $check == Validator::CHECK_STRING_EMAIL)
                {
                    if(
    filter_var($objectFILTER_VALIDATE_EMAIL))
                    {
                        return 
    true;
                    }
                }
                elseif(
    $check == Validator::CHECK_STRING_IP)
                {
                    if(
    filter_var($objectFILTER_VALIDATE_IP))
                    {
                        return 
    true;
                    }
                }
                elseif(
    $check == Validator::CHECK_STRING_ALPHNUM)
                {
                    if(
    ctype_alnum($object))
                    {
                        return 
    true;
                    }
                }
                elseif(
    $check == Validator::CHECK_STRING_LOWER)
                {
                    if(
    ctype_lower($object))
                    {
                        return 
    true;
                    }
                }
                elseif(
    $check == Validator::CHECK_STRING_TEXT)
                {
                    
    $lower_case "abcdefghijklmnopqrstuvwxyz";
                    
    $numbers   "0123456789";
                    
    $other        ".@,?!:)(";

                    
    $allowed   $lower_case.strtoupper($lower_case).$numbers.$other;

                    
    $gama     $this->convertStringToArray($allowed);
                    
    $chars        $this->convertStringToArray($object);

                    foreach(
    $chars as $char)
                    {
                        if(
    in_array($char$gama)==false)
                        {
                            return 
    false;
                        }
                    }
                    return 
    true;
                }
                return 
    false;
            }

            
    /**
             * Converts multi byte string to character array
             *
             *  [MENTION=2000183830]para[/MENTION]m string $string
             *
             *  [MENTION=850422]return[/MENTION] array
             */
            
    public function convertStringToArray(string $string)
            {
                
    mb_internal_encoding("UTF-8");
                
    $chars = array();

                for (
    $i 0$i mb_strlen($string); $i++ )
                {
                    
    $chars[] = mb_substr($string$i1);
                }

                return 
    $chars;
            }

            
    /**
             * Sets validation rules
             *
             *  [MENTION=2000183830]para[/MENTION]m array $rules
             */
            
    public function setRules(array $rules)
            {
                
    $this->rules $rules;
            }

            
    /**
             * Validates and casts user input to valid format.
             * Original array will be affected.
             *
             *  [MENTION=2000183830]para[/MENTION]m array $inputData
             *
             *  [MENTION=850422]return[/MENTION] array|null
             *  [MENTION=2000032449]Throws[/MENTION] CompileException
             */
            
    public function validateAndCast(array &$inputData)
            {
                
    $errorList NULL;

                
    $castList = array
                (
                    
    'int'   => Validator::TYPECAST_INT,
                    
    'string'=> Validator::TYPECAST_STRING,
                    
    'float' => Validator::TYPECAST_FLOAT,
                    
    'bool'  => Validator::TYPECAST_BOOL,
                );

                
    $stringContainsList = array
                (
                    
    'email'     => Validator::CHECK_STRING_EMAIL,
                    
    'ip'        => Validator::CHECK_STRING_IP,
                    
    'alphanum'  => Validator::CHECK_STRING_ALPHNUM,
                    
    'lower'     => Validator::CHECK_STRING_LOWER,
                    
    'text'      => Validator::CHECK_STRING_TEXT,
                );

                foreach(
    $inputData as $item => $value)
                {
                    if(isset(
    $this->rules[$item]))
                    {
                        
    $itemRules $this->rules[$item];

                        if(
    $itemRules['allowSpaces'] == false)
                        {
                            if(
    strpos($value" ") !== false)
                            {
                                
    $errorList[] = $itemRules['optionName']." cannot contain any spaces!";
                            }
                        }

                        if(isset(
    $itemRules['length']))
                        {
                            
    $length mb_strlen($value);
                            if(!(
    $length >= $itemRules['length'][0] && $length <= $itemRules['length'][1]))
                            {
                                
    $errorList[] = $itemRules['optionName']." must be at least ".$itemRules['length'][0]." characters long at most ".$itemRules['length'][1]." characters long";;
                            }
                        }

                        if(isset(
    $itemRules['convert']))
                        {
                            if(isset(
    $castList[$itemRules['convert']]))
                            {
                                
    $castListName array_flip($castList);

                                if(
    $this->canCastInput($value,$castList[$itemRules['convert']]))
                                {
                                    switch(
    $itemRules['convert'])
                                    {
                                        case 
    'int':
                                            
    $inputData[$item] = (int)$value;
                                        break;
                                        case 
    'string':
                                            if(isset(
    $itemRules['contains']))
                                            {
                                                if(isset(
    $stringContainsList[$itemRules['contains']]))
                                                {
                                                    if(!
    $this->validateStringValue($value,$stringContainsList[$itemRules['contains']]))
                                                    {
                                                        
    $errorList[] = $itemRules['optionName']." is not valid {$itemRules['contains']}!";
                                                    }
                                                }
                                                else
                                                {
                                                    throw new 
    CompileException("Validator {$itemRules['optionName']} string value check type ({$itemRules['contains']}) not found!");
                                                }

                                                
    $inputData[$item] = (string)filter_var($value,FILTER_SANITIZE_STRING);
                                            }
                                        break;
                                        case 
    'bool':
                                            if(
    $value == 'true')
                                            {
                                                
    $inputData[$item] = true;
                                            }
                                            elseif(
    $value == 'false')
                                            {
                                                
    $inputData[$item] = false;
                                            }
                                        break;
                                        case 
    'float':
                                                
    $inputData[$item] = (float)$value;
                                        break;
                                    }
                                }
                                else
                                {
                                    
    $errorList[] = $itemRules['optionName']." is not valid {$itemRules['convert']} value!";
                                }
                            }
                            else
                            {
                                throw new 
    CompileException("Validator {$itemRules['optionName']} casting type ({$itemRules['convert']}) not found or not possible to perform!");
                            }

                            return 
    $errorList;
                        }
                    }
                    else
                    {
                        
    $errorList[] = $itemRules['optionName']." cannot be empty value!";
                    }


                }

            }

        }
    }

  3. #3
    Enthusiast Eric Bulba is offline
    MemberRank
    Nov 2015 Join Date
    31Posts

    Re: Input Validation - Average to Expert

    you don't need to be smarter than intermediate with php, cuz i don't think i'm expert but it's pretty simple system at least for me.

  4. #4
    Moderator GigaToni is offline
    ModeratorRank
    Aug 2009 Join Date
    GER / FRLocation
    2,329Posts

    Re: Input Validation - Average to Expert

    Quote Originally Posted by Eric Bulba View Post
    you don't need to be smarter than intermediate with php, cuz i don't think i'm expert but it's pretty simple system at least for me.
    Why not use filter_var?



Advertisement