PHP Developers Network

A community of PHP developers offering assistance, advice, discussion, and friendship.
 
Loading
It is currently Wed Jun 26, 2019 8:10 pm

All times are UTC - 5 hours




Post new topic Reply to topic  [ 6 posts ] 
Author Message
PostPosted: Wed Apr 19, 2006 1:14 pm 
Offline
Breakbeat Nuttzer
User avatar

Joined: Wed Mar 24, 2004 8:57 am
Posts: 13098
Location: Melbourne, Australia
Sticking this here since I think it may be useful to someone, somewhere. Drafted together as a result of a thread in Theory/Design about spoofing POST data. Added functionality to fetch the raw POST data as per Jcart's suggestion in said thread.

Instead if working directly with $_GET, $_POST etc you pass it an array of items you're expecting to receive on a page, along with their types (int, numeric, float, string, array...). You can optionally pass it a PCRE pattern to match and a specific location to look in (GET, POST...). The default is to look in REQUEST (yuck).

If values do not satisfy the requirements you asked for they are nulled, but can still be accessed by getRaw('variable_name'). Access items normally using getVar('variable_name');

Pass a multidimensional array to expectData() like this:

array (
array( string varName, string varType [, string match [, string requestLocation] ] )
)


This would be easy to convert to PHP4 since the construct does nothing here and the private/public keywords can be adjusted accordingly.

Syntax: [ Download ] [ Hide ]
<?php



/*

 A basic class for sanitizing data being received over HTTP

   in PHP Super Globals.



 Author: d11wtq (Chris Corbyn)

 Date: 2006-04-19



 License: None.  You can use it freely, edit it, sell it, print it,

     burn it, feed it to your cat... I don't care

 

 */




class htDataHandler

{



        private

       

        $htVars = array(),

        $rawVars = array(),

        $expectVars = array(), //Variable names

        $expectLocs = array(), //POST, GET, COOKIE, REQUEST, SESSION

        $expectTypes = array(), //Data types

        $expectMatches = array(); //PCRE

       

        public function __construct()

        {

                //

        }



        public function expectData($array)

        {

                foreach ($array as $k => $a)

                {

                        if (is_array($a) && sizeof($a) >= 2)

                        {

                                $params = array_values($a);

                                $this->addVar($params, $k);

                                $this->addLoc($params, $k);

                                $this->addMatch($params, $k);

                                $this->addType($params, $k);

                        }

                }

                $this->validate();

        }



        public function getVar($v)

        {

                if (isset($this->htVars[$v])) return $this->htVars[$v];

        }



        public function getRaw($v)

        {

                if (isset($this->rawVars[$v])) return $this->rawVars[$v];

        }



        private function validate()

        {

                foreach ($this->expectVars as $k => $v)

                {

                        //It seems this is needed for variable variable in the superglobal scope

                        global ${$this->expectLocs[$k]};

                       

                        if (isset(${$this->expectLocs[$k]}[$v]))

                        {

                                $tmp = ${$this->expectLocs[$k]}[$v]; //Read it but don't use it yet

                                $this->rawVars[$v] = $tmp;

                               

                                if ($this->expectTypes[$k] && !$this->checkType($tmp, $this->expectTypes[$k])) $tmp = null;

                                if ($this->expectMatches[$k] && !$this->checkMatch($tmp, $this->expectMatches[$k])) $tmp = null;

                               

                                $this->htVars[$v] = $tmp;

                        }

                        else

                        {

                                $this->htVars[$v] = null;

                                $this->rawVars[$v] = null;

                        }

                }

        }



        private function checkType($v, $type)

        {

                switch (strtolower($type))

                {

                        case 'str':

                        case 'string': return is_string($v);

                        case 'int':

                        case 'integer': return is_int($v);

                        case 'float': return is_float($v);

                        case 'double': return is_double($v);

                        case 'array': return is_array($v);

                        case 'object': return is_object($v);

                        case 'numeric': return is_numeric($v);

                }

                return false;

        }



        private function checkMatch($v, $pattern)

        {

                if (preg_match($pattern, $v)) return true;

                else return false;

        }



        private function addVar($a, $k)

        {

                if (isset($a[0])) $this->expectVars[$k] = $a[0];

                else $this->expectVars[$k] = null;

        }



        private function addType($a, $k)

        {

                if (isset($a[1])) $this->expectTypes[$k] = $a[1];

                else $this->expectTypes[$k] = null;

        }



        private function addMatch($a, $k)

        {

                if (!empty($a[2])) $this->expectMatches[$k] = $a[2];

                else $this->expectMatches[$k] = null;

        }



        private function addLoc($a, $k)

        {

                if (!empty($a[3])) $this->expectLocs[$k] = $this->getLocation($a[3]);

                else $this->expectLocs[$k] = $this->getLocation(0);

        }



        private function getLocation($loc)

        {

                switch (strtolower($loc))

                {

                        case 'get':

                        case '$_get':

                        case '_get': return '_GET';

                        //

                        case 'post':

                        case '$_post':

                        case '_post': return '_POST';

                        //

                        case 'cookie':

                        case '$_cookie':

                        case '_cookie': return '_COOKIE';

                        //

                        case 'session':

                        case '$_session':

                        case '_session': return '_SESSION';

                        //

                        case 'request':

                        case '$_request':

                        case '_request':

                        default: return '_REQUEST';

                }

        }



}



?>


Usage:
Syntax: [ Download ] [ Hide ]
/*

 array (

        array( string varName, string varType [, string match [, string requestLocation] ] )

 )

 */


$a = array(

        array('foo', 'string', '/^foo\d{2}$/i', 'get'),

        array('bar', 'numeric')

);



$handler = new htDataHandler;



$handler->expectData($a);



echo $handler->getVar('foo');

echo $handler->getVar('bar');



echo $handler->getRaw('foo');


Top
 Profile  
 
 Post subject:
PostPosted: Wed Apr 19, 2006 2:25 pm 
Offline
Site Administrator
User avatar

Joined: Wed Aug 25, 2004 7:54 pm
Posts: 13590
Location: New York, NY, US
Nice. This looks like a middle ground between something like Zend's Input_Filter and the Request/FilterChain/Validator style.

Input_Filter is procedural something like:
Syntax: [ Download ] [ Hide ]
$filter = new Zend_InputFilter($_REQUEST);

$foo = $filter->testString('foo');

$foo = $filter->testPattern('foo', '/^foo\d{2}$/i');

$bar = $filter->testNumeric('bar');


Your Data Handler:
Syntax: [ Download ] [ Hide ]
a = array(

        array('foo', 'string', '/^foo\d{2}$/i', 'get'),

        array('bar', 'numeric')

);



$handler = new htDataHandler;



$handler->expectData($a);



echo $handler->getVar('foo');

echo $handler->getVar('bar');



echo $handler->getRaw('foo');


And the Request/FilterChain/Validator style:
Syntax: [ Download ] [ Hide ]
$request = new Request();



$filterchain = new FilterChain();

$filterchain->add('foo', new FilterString());

$filterchain->add('foo', new FilterNumeric());

$filterchain->run($request);



$validator = new Validator ();

$validator->add('foo', new RuleRegexp('/^foo\d{2}$/i'));

$validator->run($request);

if ($validator->isValid()) {

// request ok

    echo $request->get('foo');

    echo $request->get('bar');

} else {

// request errors

    echo $validator->getErrorMessages()

}

_________________
(#10850)


Top
 Profile  
 
 Post subject:
PostPosted: Wed Apr 19, 2006 6:38 pm 
Offline
Breakbeat Nuttzer
User avatar

Joined: Wed Mar 24, 2004 8:57 am
Posts: 13098
Location: Melbourne, Australia
arborint wrote:
Nice. This looks like a middle ground between something like Zend's Input_Filter and the Request/FilterChain/Validator style.


How interesting. I hadn't actually looked at those before... I guess it's quite a natural way to handle this in any case :)


Top
 Profile  
 
 Post subject:
PostPosted: Wed Apr 19, 2006 7:23 pm 
Offline
Site Administrator
User avatar

Joined: Wed Aug 25, 2004 7:54 pm
Posts: 13590
Location: New York, NY, US
In looking at it again (I just typed it in earlier without thinking much about it) you can see the actual data move from vars, to properties, to a container. Three levels of complexity -- all filtering which is a Good Thing.

_________________
(#10850)


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 20, 2006 2:33 am 
Offline
Admin
User avatar

Joined: Wed Aug 13, 2003 7:02 am
Posts: 4522
Location: York, UK
Looks d11wtq!


Top
 Profile  
 
 Post subject:
PostPosted: Thu Oct 05, 2006 10:42 am 
Offline
Forum Contributor
User avatar

Joined: Thu Oct 20, 2005 7:01 pm
Posts: 127
I took your code and made some minor changes to it. What do you think?
Syntax: [ Download ] [ Hide ]
/*

    Usage:

        $var_handler->pushData('var', 'type', 'where', 'legnth', 'regex');

        $var_handler->pushData('foo', 'string', 'get', '4', '/^foo\d{2}$/i');

        $var_handler->getData();

        $var_handler->getVar('foo');

*/




//Orginal Author: d11wtq (Chris Corbyn)

class variables

{



    var $Vars           = array();

    var $rawVars        = array();

    var $expectVars     = array(); //Variable names

    var $expectLocs     = array(); //POST, GET, COOKIE, REQUEST, SESSION

    var $expectTypes    = array(); //Data types

    var $expectMatches  = array(); //PCRE

    var $expectLength   = array(); //Lengthy

    var $dataArray      = array();

   

    //Constructor

    function variables() { }



    function getData() {

        if (is_array($this->dataArray)) {

            foreach ($this->dataArray as $k => $a) {

                if (is_array($a) && sizeof($a) >= 2) {

                    $params = array_values($a);

                    $this->_addVar($params, $k);

                    $this->_addLoc($params, $k);

                    $this->_addMatch($params, $k);

                    $this->_addType($params, $k);

                    $this->_addLen($params, $k);

                }

            }

            $this->_validate();

        } else {

            die('getData() Error');

        }

    }



    function getRaw($v) {

        if (isset($this->rawVars[$v])) return $this->rawVars[$v];

    }

   

    function getVar($v) {

        if (isset($this->Vars[$v])) return $this->Vars[$v];

    }

   

    function pushData($var, $type, $loc, $len='', $regex='') {

        if (!empty($var)) {

            $this->dataArray[] = array($var, $type, $regex, $loc, $len);

        } else {

            die('pushData() Error');

        }

    }

   

    function fixQuotes($string) {

        if (!is_numeric($string)) {

            $string = str_replace('%27', "'", $string);

            return (version_compare(phpversion(), '4.3.0', '>=')) ? mysql_real_escape_string($string) : mysql_escape_string($string);

        }

        return $string;

    }



   function _addLen($a, $k) {

        if (isset($a[4]) && (!empty($a[4]) || $a[4] == 0) && $this->_checkType($a[0], 'int')) {

            $this->expectLength[$k] = $a[4];

        } else {

            $this->expectLength[$k] = null;

        }

    }



    function _addLoc($a, $k) {

        if (isset($a[3]) && (!empty($a[3]))) {

            $this->expectLocs[$k] = $this->_getLocation($a[3]);

        } else {

            $this->expectLocs[$k] = $this->_getLocation(0);

        }

    }

   

    function _addMatch($a, $k) {

        if (isset($a[2]) && (!empty($a[2]))) {

            $this->expectMatches[$k] = $a[2];

        } else {

            $this->expectMatches[$k] = null;

        }

    }

   

    function _addType($a, $k) {

        if (isset($a[1]) && (isset($a[1]))) {

            $this->expectTypes[$k] = $a[1];

        } else {

            $this->expectTypes[$k] = null;

        }

    }

   

    function _addVar($a, $k) {

        if (isset($a[0]) && (isset($a[0]))) {

            $this->expectVars[$k] = $a[0];

        } else {

            $this->expectVars[$k] = null;

        }

    }

   

    function _checkType($v, $type) {

        switch (strtolower($type)) {

            case 'str':

            case 'string':  return is_string($v);

            //

            case 'int':

            case 'integer': return (is_numeric($v) ? ((int)$v) == $v : false);

            //

            case 'double':

            case 'float':   return (is_numeric($v) ? ((float)$v) == $v : false);

            //

            case 'array':   return is_array($v);

            case 'object':  return is_object($v);

            case 'numeric': return is_numeric($v);

        }

        return false;

    }



    function _checkMatch($v, $pattern) {

        return (preg_match($pattern, $v)) ? true : false;

    }

   

    function _checkLen($v, $len) {

        return (strlen($v) <= ((int) $len) ) ? true : false;

    }



    function _getLocation($loc)

    {

        switch (strtolower($loc))

        {

            case 'get':

            case '$_get':

            case '_get':        return '_GET';

            //

            case 'post':

            case '$_post':

            case '_post':       return '_POST';

            //

            case 'cookie':

            case '$_cookie':

            case '_cookie':     return '_COOKIE';

            //

            case 'session':

            case '$_session':

            case '_session':    return '_SESSION';

            //

            case 'request':

            case '$_request':

            case '_request':

            default:            return '_REQUEST';

        }

    }

   

    function _stripslashes_array($data) {

        return is_array($data) ? array_map('stripslashes', $data) : stripslashes($data);

    }



    function _undoMagic($data) {

        static $magic_quotes;

       

        if (empty($data)) return null;

       

        //Replace with STRIP

        if (!isset($magic_quotes)) $magic_quotes = get_magic_quotes_gpc();

        return ($magic_quotes) ? $this->_stripslashes_array($data) : $data;

    }

   

    function _validate() {

        if (is_array($this->expectVars)) {

            foreach ($this->expectVars as $k => $v) {

                //It seems this is needed for variable variable in the superglobal scope

                global ${$this->expectLocs[$k]};

               

                if (isset(${$this->expectLocs[$k]}[$v])) {

                    $tmp = ${$this->expectLocs[$k]}[$v]; //Read it but don't use it yet

                    $this->rawVars[$v] = $tmp;

                   

                    if ($this->expectTypes[$k] && !$this->_checkType($tmp, $this->expectTypes[$k])) $tmp = null;

                    if ($this->expectMatches[$k] && !$this->_checkMatch($tmp, $this->expectMatches[$k])) $tmp = null;

                    if ($this->expectLength[$k] && !$this->_checkLen($tmp, $this->expectLength[$k])) $tmp = null;

                   

                    $this->Vars[$v] = $this->_undoMagic($tmp);

                } else {

                    $this->Vars[$v] = null;

                    $this->rawVars[$v] = null;

                }

            }

        } else {

            die('_validate() Error');

        }

    }

}


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 posts ] 

All times are UTC - 5 hours


Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Jump to:  
Powered by phpBB® Forum Software © phpBB Group