$rc = new RequestCleaner('POST', RequestCleaner::USE_HTMLENTITIES | RequestCleaner::USE_NL2BR, RequestCleaner::THROW_EXCEPTION); To get a 'cleaned' query parameter, use '$rc->parm', where _parm_ is the parameter name. For example, if 'foo' is a POST parameter, then '$rc->foo' will return the value of 'foo' from after running the 'cleaning' routines on it. h3. Fine points All Cleaned data is cached in a RequestCleaner Class Variable, as are the sources, use and error modes. This means that a top level PHP program can set up the method of cleaning and allowed sources and all included code which uses _any_ instance of a RequestCleaner will use the same methods and cache. Consequently, you can either create a RequestCleaner instance at top level OR in any included or required file which needs to access query parameters. It doesn't matter. Attempts to access undefined attributes generate an error - as specified by _error_mode_. Query parameters which return arrays - as in <input type=... name="foo[]" ...> - are turned into arrays of cleaned strings which can be processed using normal loops and array_...() functions. Extensive use of Magic Methods are used to implement the following operations [presume that $rc is an instance of RequestCleaner]: * $rc->foo - returns the cleaned value of the request parameter _foo_ if it exists. It is cached, if not already cached, to make lookeup and cleaning more efficient. The cleaning is as is implemented in the First instantiaion of RequestCleaner [normally in the controller] If _foo_ is not defined, then the failure method chosen when _this_ instance of RequestCleaner was created is invoked. * $rc->foo = bar - generates an error return - using the method specified for this instance of _rc_ * unset($rc->foo) - removes _foo_ from the cache; attempts to remove _foo_ from the source variable arrays [$_POST, $_GET, $_REQUEST] [which will fail as of PHP 5.2.9]; removes _foo_ from $GLOBALS; and marks _foo_ as 'unset' in a local array so it will not be retrieved in future invocations of $rc->foo [attempting to retrieve $rc->foo will result in the action specified for any other no-existant parameter] * isset($rc->foo) - returns TRUE if $rc->foo will return something; FALSE if it will invoke the failure method specified. h3. Instance Methods * dump() - returns a string giving all passed parameters - after cleaning - in the form of 'parameter => value' * param_array(names = NULL) - returns an associative array of EITHER all the parameters or those specified in _names_. _names_ may be an array of key names or a comma separated list in a string. The returned set is trimmed to only those parameters which actually exist, so optional parameters may be specified without causing an error. #end-doc */ /** * RequestCleaner(sources = NULL) - where sources defines a comma separated list of Super Globals * for attribute values. Legal names are: POST, GET, and REQUEST */ class RequestCleaner { const ERROR_MODE_MASK = 3; const RETURN_NULL = 1; const RETURN_FALSE = 2; const THROW_EXCEPTION = 3; const CLEANER_MODE_MASK = 0x07; // IMPORTANT: Change This as you ADD USE_modes const USE_HTMLENTITIES = 1; const USE_HTMLSPECIALCHARS = 2; const USE_NL2BR = 4; private static $use_modes = array( RequestCleaner::USE_HTMLENTITIES => 'htmlentities()', RequestCleaner::USE_HTMLSPECIALCHARS => 'htmlspecialchars()', RequestCleaner::USE_NL2BR => 'nl2br()', ); private static $error_modes = array( RequestCleaner::RETURN_NULL => 'return NULL', RequestCleaner::RETURN_FALSE => 'return FALSE', RequestCleaner::THROW_EXCEPTION => 'throw Exception' ); private static $sources = NULL; private static $source_names = array(); private static $error_mode = NULL; private static $use_mode = NULL; private static $cache = array(); private static $unset_variables = array(); function __construct($sources = array('GET', 'POST'), $use_mode = RequestCleaner::USE_HTMLENTITIES, $error_mode = RequestCleaner::RETURN_NULL) { if (!RequestCleaner::$sources) { if ($sources) { RequestCleaner::$sources = array(); if (is_string($sources)) { $sources = preg_split("/,\s*/", trim($sources)); } foreach ($sources as $src) { RequestCleaner::$source_names[] = $src; switch (strtoupper($src)) { case 'POST': RequestCleaner::$sources[] = $_POST; break; case 'GET': RequestCleaner::$sources[] = $_GET; break; case 'REQUEST': RequestCleaner::$sources[] = $_REQUEST; break; default: throw new Exception("RequestCleaner::__construct($sources): Illegal Source: $tmp"); } } } else { RequestCleaner::$sources = array($_POST, $_GET); } // this is a Set Once hack to make sure cleaning is consistent with the Original Instantiation // We have to do this to keep the cache consistent. if (!RequestCleaner::$use_mode && (RequestCleaner::CLEANER_MODE_MASK & $use_mode)) { RequestCleaner::$use_mode = RequestCleaner::CLEANER_MODE_MASK & $use_mode; } // This allows local control over error handling if (RequestCleaner::ERROR_MODE_MASK & $error_mode) { RequestCleaner::$error_mode = RequestCleaner::ERROR_MODE_MASK & $error_mode; } } } private function stringCleaner($x) { if (RequestCleaner::$use_mode & RequestCleaner::USE_HTMLSPECIALCHARS) { $x = htmlspecialchars($x); } if (RequestCleaner::$use_mode & RequestCleaner::USE_HTMLENTITIES) { $x = htmlentities($x); } if (RequestCleaner::$use_mode & RequestCleaner::USE_NL2BR) { $x = nl2br($x); } return $x; } // end of arrayHelper() private function useModesToString() { $ar = array(); foreach (array(RequestCleaner::USE_HTMLENTITIES, RequestCleaner::USE_NL2BR, RequestCleaner::USE_HTMLSPECIALCHARS) as $mode) { if (RequestCleaner::$use_mode & $mode) { $ar[] = RequestCleaner::$use_modes[$mode]; } } return implode(',', $ar); } // end of useModeToString() public function __toString() { return "RequestCleaner: examining " . implode(', ', RequestCleaner::$source_names) . " Using " . $this->useModesToString() . " / Exit Mode: " . RequestCleaner::$error_modes[RequestCleaner::$error_mode]; } // end of __toString() public function __get($name) { if (array_key_exists($name, RequestCleaner::$cache)) { return RequestCleaner::$cache[$name]; } // extract from a source array if variable has not been unset() if (!array_key_exists($name, RequestCleaner::$unset_variables)) { foreach (RequestCleaner::$sources as $source) { if (array_key_exists($name, $source)) { $val = $source[$name]; if (is_string($val)) { return (RequestCleaner::$cache[$name] = RequestCleaner::stringCleaner($val)); } elseif (is_array($val)) { return (RequestCleaner::$cache[$name] = array_map(array('RequestCleaner', 'stringCleaner'), $val)); } } } } switch (RequestCleaner::$error_mode) { case RequestCleaner::RETURN_NULL: return NULL; case RequestCleaner::RETURN_FALSE: return FALSE; case RequestCleaner::THROW_EXCEPTION: throw new Exception("RequestCleaner::__get($name): Value Not Defined"); default: throw new Exception("RequestCleaner::__get($name): ERROR: Value Not Defined / Illegal Error Mode"); } return NULL; } // end of __get() public function __set($name, $value) { switch (RequestCleaner::$error_mode) { case RequestCleaner::RETURN_NULL: return NULL; case RequestCleaner::RETURN_FALSE: return FALSE; case RequestCleaner::THROW_EXCEPTION: throw new Exception("RequestCleaner::__set($name, $value): Setting Attributes Not Allowed"); default: throw new Exception("RequestCleaner::__set($name, $value): Setting Attributes Not Allowed / Illegal Error Mode"); } } // end of __set() public function __unset($name) { if (array_key_exists($name, RequestCleaner::$cache)) { unset(RequestCleaner::$cache[$name]); } foreach (RequestCleaner::$sources as $source) { if (array_key_exists($name, $source)) { unset($source[$name]); } } if (array_key_exists($name, $GLOBALS)) { unset($GLOBALS[$name]); } RequestCleaner::$unset_variables[$name] = TRUE; } // end of __set() public function __isset($name) { if (array_key_exists($name, RequestCleaner::$cache)) { return TRUE; } if (array_key_exists($name, RequestCleaner::$unset_variables)) { return FALSE; } foreach (RequestCleaner::$sources as $source) { if (array_key_exists($name, $source)) { return TRUE; } } return FALSE; } // end of __isset() private function all_keys() { $keys = array(); foreach (RequestCleaner::$sources as $source) { $keys = array_merge($keys, array_keys($source)); } $keys = array_diff($keys, array_keys(RequestCleaner::$unset_variables)); sort($keys); return $keys; } // end of all_keys() public function dump() { $ar = array(); foreach ($this->all_keys() as $key) { $ar[] = "$key => '{$this->$key}'"; } return implode("\n", $ar) . "\n"; } // end of dump_all() public function param_array($names = NULL) { $ar = array(); if (!$names) { $keys = $this->all_keys(); } elseif (is_string($names)) { $names = preg_split('/,\s*/', $names); $keys = array_intersect($this->all_keys(), $names); } elseif (is_array($names)) { $keys = array_intersect($this->all_keys(), $names); } else { switch (RequestCleaner::$error_mode) { case RequestCleaner::RETURN_NULL: return NULL; case RequestCleaner::RETURN_FALSE: return FALSE; case RequestCleaner::THROW_EXCEPTION: default: throw new Exception("RequestCleaner::param_array($names): Illegal Argument"); } } foreach ($keys as $key) { $ar[$key] = $this->$key; } return $ar; } // end of extract() } // end class definitions ?>