Friday, 10 August 2018

PHP5 Filter Functions


The filter functions are part of the PECL library and should come as standard on most PHP 5 installs. If they aren't there then ask your server administrator to install them.
The filter functions where created to avoid developers having to write lots of unmaintainable code in order to check the validity of variables and to sanitize these variables once validated. So rather than using many different functions and regular expressions to tell if a value is a number, a boolean or even a URL, you can just use these filter fucntions.
The main functions that you might be interested in are filter_var() and filter_input(). The filter_var() function is used to validate a single input, the parameters are:
  • Varaible: The variable to be tested.
  • Filter: The filter to test the variable against.
  • Options (optional): Associative array of options or bitwise disjunction of flags.
To use the filter_var() function you just pass it a variable and an appropriate filter. So to test if a variable is a number you just pass in the filter called FILTER_VALIDATE_INT.
  1. $int = 746;
  2. if ( filter_var($int, FILTER_VALIDATE_INT) ) {
  3. echo 'Value is an integer';
  4. }else{
  5. echo 'Value is not and integer';
  6. }
Testing to see if a user has put in a correctly formated email address is a common task, and to do this just use the FILTER_VALIDATE_EMAIL filter.
  1. $email = 'email@example.com';
  2. if ( filter_var($email,FILTER_VALIDATE_EMAIL) ) {
  3. echo 'Email passed';
  4. }else{
  5. echo 'Invalid Email';
  6. };
The same thing can be done with a URL.
  1. $url = 'http://www.hashbangcode.com';
  2. if( filter_var($url, FILTER_VALIDATE_URL) ) {
  3. echo 'Valid URL';
  4. }else{
  5. echo 'Not a valid URL';
  6. };
The options parameter can be used for a number of circumstances. Validating that a variable is a number is fine, but a more useful way of validating a number is to use a range. To create a range for the FILTER_VALIDATE_INT filter you need to use an associative array built like this.
  1. $int_options = array('options' => array(
  2. 'min_range' => 0,
  3. 'max_range' => 256)
  4. );
Which can then be fed into the filter_var() funtion like this.
  1. $int=123;
  2. if(filter_var($int, FILTER_VALIDATE_INT, $int_options)){
  3. echo 'Integer within range';
  4. }else{
  5. echo 'Integer outside range';
  6. }
The filter_input() function is used in much the same way, but in this case there is an additional first parameter. This tells PHP where to get the variable from, which can be one of INPUT_GET, INPUT_POST, INPUT_COOKIE, INPUT_SERVER, INPUT_ENV.
For example, to filter a $_POST request all you need to do is drop in the INPUT_POST type and then name the $_POST globals array parameter that you want to test.
  1. if ( filter_input(INPUT_GET, 'test', FILTER_VALIDATE_INT) ) {
  2. echo 'Test is integer';
  3. }else{
  4. echo 'Test is NOT integer';
  5. };
You can check to see that a variable is present in the parameter type by using the filter_has_var() function.
  1. if ( filter_has_var(INPUT_POST, 'url') ) {
  2. echo 'Input not found.';
  3. }
However, this is not the only use of the filter functions, they can also be used to sanitize input. For example, a common practice is to convert HTML tags so that they are correctly displayed, using the FILTER_SANITIZE_SPECIAL_CHARS filter on a string with the filer_var function will convert all HTML specific characters to their ASCII encoding value.
  1. $test = '<strong>Test Text!</strong>';
  2. echo filter_var($test, FILTER_SANITIZE_SPECIAL_CHARS);
Will print...
&#60;strong&#62;Test Text!&#60;/strong&#62;
These functions are filter_var_array() and filter_input_array().
They work in much the same way as filter_var() and filter_input() but they accept an array as the input. This enables you to sanitize or validate many different variables at the same time.
The first step in using these functions is to create a argument array. This is an associative array of data identifiers that allow you to set filter and sanitizer flags for different values. For example, assume that the following array is going to be used..
  1. $data = array(
  2. 'rowid' => '10',
  3. 'level' => '23',
  4. 'text' => 'some text',
  5. 'dataAray' => array('2', '23', '10', '12'),
  6. );
To ensure that the rowid is always an integer the filter flag FILTER_VALIDATE_INT is used in the argument array like this.
$args = array('rowid' => FILTER_VALIDATE_INT);
The same thing needs to be done to the level value in the array. However, I also need to make sure that the value is between a certain range. This is done using an inner array containing the arguments filter (to validate the integer) and options (to define a minimum and maximum range).
  1. $args = array(
  2. 'rowid' => FILTER_VALIDATE_INT,
  3. 'level' => array(
  4. 'filter' => FILTER_VALIDATE_INT,
  5. 'options' => array(
  6. 'min_range' => 1,
  7. 'max_range' => 30
  8. )
  9. )
  10. );
Anything that isn't included in this argument array is not returned from the functions. So at the moment the functions would completely miss out the text and dataArray parts of the array. As the text variable has some HTML in it I want to use the FILTER_SANITIZE_SPECIAL_CHARS to turn this into character encoded text. The dataArray has to be all integers and I want to force this to be an array, even if it isn't. Even if the variable is an array the FILTER_VALIDATE_INT filter will
  1. $args = array(
  2. 'rowid' => FILTER_VALIDATE_INT,
  3. 'level' => array(
  4. 'filter' => FILTER_VALIDATE_INT,
  5. 'options' => array(
  6. 'min_range' => 1,
  7. 'max_range' => 30
  8. )
  9. ),
  10. 'text' => FILTER_SANITIZE_ENCODED,
  11. 'dataAray' => array(
  12. 'filter' => FILTER_VALIDATE_INT,
  13. 'flags' => FILTER_FORCE_ARRAY,
  14. )
  15. );
With the array in place we can now put it into the filter_var_array() and filter/sanitize the data.
  1. $myinputs = filter_var_array($data, $args);
  2.  
  3. var_dump($myinputs);
This produces the following result.
  1. array(4) {
  2. ["rowid"]=>
  3. int(10)
  4. ["text"]=>
  5. string(42) "some <strong>text</strong>"
  6. ["level"]=>
  7. int(23)
  8. ["dataAray"]=>
  9. array(4) {
  10. [0]=>
  11. int(2)
  12. [1]=>
  13. int(23)
  14. [2]=>
  15. int(10)
  16. [3]=>
  17. int(12)
  18. }
  19. }
Using this with the filter_input_array() function is just the same, but in this case instead of the data as the first parameter we use one of INPUT_GET, INPUT_POST, INPUT_COOKIE, INPUT_SERVER, INPUT_ENV, INPUT_SESSION, or INPUT_REQUEST. The following example uses INPUT_POST to retrieve the data from a post request.
  1. $myinputs = filter_input_array(INPUT_POST, $args);
  2.  
  3. var_dump($myinputs);
The callback filters can be used to change data from one form into another, basically creating your own sanitizers. Lets say that we had a HTML string, but that we only wanted to change three characters from their non-encoded forms to their encoded forms. These characters are and ", which translate into <, > and " respectively.
To run a callback function via a filter we use the FILTER_CALLBACK flag with an options array that points to the function we want to run.
  1. function replaceTags($html){
  2. return str_replace(array('', '"'),array('<', '>', '"'),$html);
  3. }
  4.  
  5. $html = 'Some <strong style="padding:10px;">text</strong>';
  6.  
  7. echo filter_var($html,FILTER_CALLBACK,array('options'=>'replaceTags'));
When the filter_var() function is run in this bit of code it replaces the three characters in the HTML with their encoded equivalents.
Although there is plenty of information available on the php.net site there is a fantastic page at phpro.org that has examples on every filter and sanitizer used with the filtering functions.

To see a full list of the filters and sanitizer flags available take a look at the filter page on the PHP website.

0 comments:

Post a Comment