Verileri doğrulamak için PHP ile filtreleme işlemleri
Bazı bölümleri ingilizce bir makaledir.
Security becomes the top priority (or activity) of many PHP developers. Its place and importance keeps growing in every single project, open source or commercial. Every conference provides a talk about security and you can read PHP security on the magazine cover pages.
Security in PHP application is a large topic. This article explains one of the most important part of any security policy: the input or data filtering.
General security topics like XSS, SQL injections and other dangerous attacks will not be discussed here, take a look at the end of this article for a small list of resources.
Asla Yabancı Bilgiye Güvenmeyin
Practically all applications (web, desktop, console) depend on external input to create output or to start an action. This input comes from a user or another application (web services clients, bots, scanner, etc.). The rule #1 of every developer (you all know it, but it does not hurt to write it down once more) should be:
Filter All Foreign Data
Input filtering is one of the cornerstones of any application security, independently of the language or environment. PHP provides a wide range of tools and functions to filter or validate data, but unlike other languages, it does not have any standard functions to filter data (like cgi for perl). The new Filter extension fills this gap.
Yabancı Bilgi Nedir?
- Anything from a form
- Anything from $_GET, $_POST, $_REQUEST
- Cookies ($_COOKIES)
- Web services data
- Files
- Some server variables (e.g. $_SERVER['SERVER_NAME'])
- Environment variables
- Database query results
Filter supports get, post, cookies, server and environment variables as well as defined variables (server and env support may not work in all sapi, for filter 0.11.0 or php 5.2.0).
Neden Filitre Kullanmalı?
To test, validate and filter user input or custom data can rapidly be annoying and repetitive task. It is easy to forget a test or write an incomplete regular expression. The Filter extension aims to make data filtering less painful as this simple example shows:
Check two integer _GET input values:
if (isset($_GET['mode'])) {
if (!is_numeric($_GET['mode'])) {
echo "The 'mode' argument must be a valid integer.<br />";
exit();
}
$mode = (int)$_GET['mode'];
} else {
echo "The 'mode' argument is missing.<br />";
exit();
}
if (isset($_GET['type'])) {
$type = (int)$_GET['type'];
if (!is_numeric($_GET['type']) ||
(is_numeric($_GET['type']) && $type >= 3 && $type <= 10)) {
echo "The 'type' argument must be an integer between 3 and 10.<br />";
exit();
} else {
}
$mode = $_GET['type'];
} else {
echo "The 'type' argument is missing.<br />";
exit();
}
echo "Ok.<br />";
?>
and using Filter's filter_input:
$mode = filter_input(INPUT_GET, 'mode', FILTER_VALIDATE_INT);
$type = filter_input(INPUT_GET, 'type', FILTER_VALIDATE_INT, array('options'=>array('min_range'=>3, 'max_range'=>10)));
if (is_null($mode)) {
echo "The 'mode' argument is missing.<br />";
exit();
} elseif ($mode === false) {
echo "The 'mode' argument must be a valid integer.<br />";
exit();
} else {
echo "mode is: $mode.<br />";
}
if (is_null($type)) {
echo "The 'type' argument is missing.<br />";
exit();
} elseif ($type === false) {
echo "The 'type' argument must be an integer between 3 and 10.<br />";
exit();
} else {
echo "type is: $type.<br />";
}
?>
Çalışma Mantığı Nedir?
The process to transform an input request to a set of user land variables is done by the SAPI layer. Without going into the details, the SAPI layer is the interface between the wild world and the PHP engine. The engine fetches external data (ENV, SERVER, COOKIE, GET or POST) from the SAPI and transforms them into the well known super global or uses them in the related functions like getenv.
Filter is active both at the SAPI level and in the engine. SAPI supports custom filtering operation, Filter functions are called for each external data being processed by the Engine. It is done before the script gets the hand on it. How the SAPI filter will process the data is defined by the default filter, configurable using your php.ini.
Given a simple POST request like:
POST /myform.php?myfield=<script>hola</script>
The diagrams below explain the difference between a normal operation (like php 5.1, without Filter enabled) and a PHP including Filter support:
Genel Filitre Tanımı
İki çeşit Filitreleme vardır
- Santizing filters
- Allow or disallow characters in a string
- Does not care about the data format
- It always returns a string
- Validate filters
- Strong analysis of the data
- Knows the formats
- Returns the expected type on success
Filtreler bu işlevlerden birini kullanarak çağrılır:
- filer_input, bir giriş değişkeni için
- filter_input_array, Tek bir çağrı ile birçok girdi değişkenleni çeker
- filter_var, bir değişken için filtre
- filter_var_array, Tek bir çağrı ile birçok değişken için filitre
The value is returned filtered and using the right type on success, FALSE if the filter fails (bad chars, out of range, ...) and NULL if the variable is not set. Using the optional flag FILTER_NULL_ON_FAILURE, the behavior can be reversed, it will return NULL on failure and FALSE if the variable is not set.
With these three different states, it becomes easy to get rid of the isset or is_numeric mess.
A simple form using logical filter
<head></head>
<body
<form action="example04.php" method="post" >
Enter your age: <input name="age" size="2">
<input type="submit" name="submit" value="Go">
</form>
</body>
</html>
And the little script to process it:
if (!filter_has_var(INPUT_POST, 'submit')) {
echo "form";
// include the form.
}
$age = filter_input(INPUT_POST, 'age', FILTER_VALIDATE_INT);
if (is_null($age)) {
echo "The 'age' field is required.<br />";
} elseif ($age === FALSE) {
echo "Please enter a valid age.<br />";
} else {
echo "Welcome.<br/>";
}
?>
filter_has_var tests if a given variable is set or not. It does not make any validation but only tells whether a variable is set.
It is the equivalent of isset($_POST['submit'])
. filter_input fetches one single value and returns it filtered.
In this example an integer is expected.
If this script displays the last "Tintin" cartoon, the age must be between 7 and 77 :). The numeric filters options accept a minimum and maximum range:
if (!filter_has_var(INPUT_POST, 'submit')) {
echo "form";
// include the form.
}
$options = array('options'=> array('min_range'=>7, 'max_range'=>77));
$age = filter_input(INPUT_POST, 'age', FILTER_VALIDATE_INT, $options);
if (is_null($age)) {
echo "The 'age' field is required.<br />";
} elseif ($age === FALSE) {
echo "You must be enter a valid age and be between 7 and 77 years old.<br />";
} else {
echo "Welcome.<br/>";
}
?>
To add another field for example an email, the procedure is identical:
Just like the other field, $email will be FALSE if the email is invalid and NULL if the email field is missing (for example a lazy spam bot did not detect it).
A simple form using a sanitizing filter
<head></head>
<body
<form action="example05.php" method="post" >
Enter your name: <input name="name" size="50">
<input type="submit" name="submit" value="Go">
</form>
</body>
</html>
The following filter_input call will clean up the "name" variable and returns it useable :
if (!filter_has_var(INPUT_POST, 'submit')) {
echo "form";
// include the form.
}
$name = filter_input(INPUT_POST, 'name', FILTER_SANITIZE_SPECIAL_CHARS);
if (is_null($name)) {
echo "The 'name' field is required.<br />";
} else {
echo "Hello $name.<br/>";
}
?>
If the "name" contains a value similar to:
Johnny Weißmüller <b>Jr</b>
FILTER_SANITIZE_SPECIAL_CHARS will return:
Hello Johnny Weißmüller <b>Jr</b>.
A nicer filter for this field would be:
'name',
FILTER_SANITIZE_STRING,
FILTER_FLAG_ENCODE_HIGH|FILTER_FLAG_ENCODE_LOW);
and it returns
Hello Johnny Weißmüller Jr.
The sanitizing filters accept many options and flags. In this example, we use the "string" filter (also called "stripped") which accepts low or high values stripping. A complete list of filters and flags is available in the Filter manual.
Bir Çağrıda Tüm Değişkenleri Filitreleme
<head></head>
<body
<form action="example07.php" method="post" >
Name: <input name="name" size="50"><br />
Email: <input name="email" size="50"><br />
Homepage: <input name="homepage" size="50"><br />
Age: <input name="age" size="4"><br />
Income: <input name="income" size="50"><br />
Your two favourites languages:
<select name="favourites[]" size="6" multiple>
<option value="haskell">haskell</option>
<option value="r">R</option>
<option value="lua">Lua</option>
<option value="pike">Pike</option>
<option value="rebol">Rebol</option>
<option value="php">PHP</option>
</select><br />
<input type="submit" name="submit" value="Go">
</form>
</body>
</html>
and the script to process it:
if (!filter_has_var(INPUT_POST, 'submit')) {
echo "form";
// include the form.
}
$defs = array(
'name' => array('filter'=>FILTER_SANITIZE_STRING,
'flags' => FILTER_FLAG_ENCODE_HIGH|FILTER_FLAG_ENCODE_LOW),
'email' => FILTER_VALIDATE_EMAIL,
'homepage' => FILTER_VALIDATE_URL,
'age' => array( 'filter' => FILTER_VALIDATE_INT,
'options'=> array('min_range'=>7, 'min_range'=>77)),
'income' => FILTER_VALIDATE_FLOAT,
'favourites' => array(
'filter' => FILTER_SANITIZE_STRING,
'flags' => FILTER_REQUIRE_ARRAY
),
);
$input = filter_input_array(INPUT_POST, $defs);
if ($input['age'] === FALSE) {
exit("You must be between 7 and 77 years old.");
}
if (is_null($input['favourites'])) {
exit("You have to choose two or more languages.");
}
if (!in_array('PHP', $input['favourites'])) {
exit("You don't like PHP!");
}
/*Other checks for required values */
?>
As the script shows, fetching all values you need is as easy as fetching a single value. The only difference is how options or flags are given. An array must be used as soon as you need options or flags.
It can look overkilled to use such array, but it amazingly increases the readability of the input parsing code in a script. Adding, removing or editing input rules can be done in seconds.
Örnek 2:
<body>
<form method="post">
<input type="text" name="id[]" value="1">
<input type="text" name="id[]" value="2">
<input type="text" name="id[]" value="3">
<input type="submit">
</form>
</body>
</html>
<?php
if (filter_has_var(INPUT_POST, 'product_id')) {
$args = array(
'product_id' => FILTER_SANITIZE_ENCODED,
'component' => array('filter' => FILTER_VALIDATE_INT,
'flags' => FILTER_REQUIRE_ARRAY,
'options' => array('min_range' => 1, 'max_range' => 10)
),
'versions' => FILTER_SANITIZE_ENCODED,
'doesnotexist' => FILTER_VALIDATE_INT,
'id' => array(
'filter' => FILTER_VALIDATE_INT,
'flags' => FILTER_REQUIRE_ARRAY,
),
'testarray' => array(
'filter' => FILTER_VALIDATE_INT,
'flags' => FILTER_REQUIRE_ARRAY,
)
);
$myinputs = filter_input_array(INPUT_POST, $args);
print_r($myinputs);
}
Callback Kullanarak Karmaşık Filitreleme İşlemleri
Instead of doing a simple string validation for the "favourites", a user function will be used. The "options" argument is used to define the callback using the same syntax as the PHP call_user_func.
class language {
function __construct($name) {
$this->name = $name;
}
}
function check_languages($var) {
static $called = 0;
$called++;
echo "called: $called: $var<br />";
$var = filter_var($var, FILTER_SANITIZE_STRIPPED);
$l = new language($var);
return $l;
}
if (!filter_has_var(INPUT_POST, 'submit')) {
echo "form";
// include the form.
}
$defs = array(
'name' => array('filter'=>FILTER_SANITIZE_STRING,
'flags' => FILTER_FLAG_ENCODE_HIGH|FILTER_FLAG_ENCODE_LOW),
'email' => FILTER_VALIDATE_EMAIL,
'homepage' => FILTER_VALIDATE_URL,
'age' => FILTER_VALIDATE_INT,
'income' => FILTER_VALIDATE_FLOAT,
'favourites' => array(
'filter' => FILTER_CALLBACK,
'options' => 'check_languages'
),
);
$input = filter_input_array(INPUT_POST, $defs);
if ($input['age'] === FALSE) {
exit("You must be between 7 and 77 years old.");
}
if (is_null($input['favourites'])) {
exit("You have to choose two or more languages.");
}
echo "Your favourite languages:<br /><ul>";
foreach ($input['favourites'] as $l) echo '<li>' . $l->name . "</li>";
echo '</ul>';
?>
The function will be called once if the variable is a scalar; if the variable is an array, it will be called once for each element.
Filter does not sanitize or validate the input before or after the callback. But filter_var can be used inside your callback function or method as shown in this example.
Başka bir Örnek:
return preg_replace("/[^A-z0-9_,.]/", NULL, $Kim);
}
define("REGEXP_MULTIPLE_NAMES", "/^[a-zA-Zs-]+$/i");
define("REGEXP_SAYI", "/^[0-9]+$/s");
$Filitrelenecek = array(
'kart_turu' => FILTER_VALIDATE_INT,
'odenecek_tutar' => FILTER_VALIDATE_FLOAT,
'kart_sahibi' => array(
'filter' => FILTER_VALIDATE_REGEXP,
'options' => array(
"regexp" => REGEXP_SAYI
)),
'kart_sahibi' => array('filter' => FILTER_SANITIZE_STRING,
'flags' => FILTER_FLAG_STRIP_HIGH | FILTER_FLAG_STRIP_LOW | FILTER_),
'kart_sahibi' => array('filter' => FILTER_CALLBACK, 'options' => array($FN, 'Filitrem')),
'kart_sahibi' => array('filter' => FILTER_SANITIZE_STRING,
'flags' => FILTER_FLAG_STRIP_HIGH | FILTER_FLAG_STRIP_LOW | FILTER_SANITIZE_FULL_SPECIAL_CHARS),
'kart_numarasi' => FILTER_VALIDATE_INT,
'son_kullanim_ay' => FILTER_VALIDATE_INT,
'son_kullanim_yil' => FILTER_VALIDATE_INT,
'cvv' => array('filter' => FILTER_SANITIZE_STRING,
'flags' => FILTER_FLAG_STRIP_HIGH | FILTER_FLAG_STRIP_LOW),
'taksit' => array('filter' => FILTER_SANITIZE_STRING,
'flags' => FILTER_FLAG_ENCODE_HIGH | FILTER_FLAG_ENCODE_LOW)
);
$Fi = filter_input_array(INPUT_POST, $Filitrelenecek);
Why no OO?
Filter does not provide any object oriented interface. The current API is flexible enough to add any kind of filters, support unicode (more on this topic in another article) or to integrate into your favourite framework or MVC application.
If someone wrote a generic OO wrapper for the filter function, I would be happy to include it in the examples directory, but do not wait an OO interface, it is not going to come anytime soon.
Default filter, PHP 5.1.x and shared host
The default filter is set to unsafe_raw in PHP 5.2.0 or later. It will not be set to any other default filter by default. An attempt has been made to set it to string, but it breaks way too much applications and it makes the migration process a pain. If you plan to use it, be sure to have first fixed all your applications or loudly warned your users.
Filter works out of the box on PHP 5.1.x. I would recommend to install it by default on any PHP 5.1.0 (without default filter). I'm sure all applications will soon rely on it. It does not solve all security issues but it gets rid of all common mistakes or bad usages.
What is a PHP Filter
One of the greatest strengths of PHP is its ease of use. Unfortunately this same benifit has worked against PHP as many new coders have forgotten any security measures or lack the expertise to create a class to validate their variables from end users. PHP provides an extension to help with this process. There are many validation classes out there, some better than others, with an equal number of methods for doing the same task. The PHP filter extension has many of the functions needed for checking many types of user input. Handled locally this provides a standard method of filtering data. This makes for easier to read code as we will all be using the same functions rather than having to create our own. This will bring PHP security to fore with programmers able to easily implement simple, yet robust, filtering of data. Never again do we need to see code like this below.
include($_GET['filename']);
?>
Or, even more common is database queries like this one...
mysql_query("INSERT INTO table (field_one, field_two) VALUES ({$_POST['var1']}, {$_POST['var2']})";
?>
Getting Started
To get a look at what the filter extension has to offer, we can easily list all the available filters with the input_filters_list() function. Lets put it to work.
<tr><td>Filter Name</td><td>Filter ID</td></tr>
<?php
foreach(filter_list() as $id =>$filter){
echo '<tr><td>'.$filter.'</td><td>'.filter_id($filter).'</td></tr>'."n";
}
?>
</table>
The above code will produce a table like the one below.
Filter Name | Filter ID |
int | 257 |
boolean | 258 |
float | 259 |
validate_regexp | 272 |
validate_url | 273 |
validate_email | 274 |
validate_ip | 275 |
string | 513 |
stripped | 513 |
encoded | 514 |
special_chars | 515 |
unsafe_raw | 516 |
517 | |
url | 518 |
number_int | 519 |
number_float | 520 |
magic_quotes | 521 |
callback | 1024 |
This is quite an impressive list and more will be added in time. Note also that each filter has its own Filter ID, this will become useful as we progress through this tutorial. Each of these filters can be used with the filter_var() function and here we will step through each one show how it works. Note that the string and stripped have the same ID. This is because they are the same.
Filtering Variables
The actual filtering of variables is done with the filter_var() function. Lets start with a simple integer filter to see how it works.
/*** an integer to check ***/
$int = 1234;
/*** validate the integer ***/
echo filter_var($int, FILTER_VALIDATE_INT);
?>
The above code will echo 1234. The filter_var() function will return INT(1234) because the input has validated as an integer. Lets change the $int variable to a non int value and see the results.
/*** an integer to check ***/
$int = 'abc1234';
/*** validate the integer ***/
echo filter_var($int, FILTER_VALIDATE_INT);
?>
Now we see a different result. No display is made because the variable $int has failed validation and the filter_var() function has returned bool(false). Also note that if the variable is set to $int='' then it will again return bool(false). Consider this code..
/*** an integer to check ***/
$int = '';
/*** validate the integer ***/
echo filter_var($int, FILTER_VALIDATE_INT);
?>
As you can see if you run the above snippet of code, the result is once again a blank page. From here we can continue with INTEGER validation as the filter_var() function has some amazing properties to allow us to do many of the validation tasks we once had to write ourselves.
Validating INTEGERS
As we saw in the previous section, validating a variable as type INT is simple with the filter_var() function. But wait, theres more. FILTER_VALIDATE_INT also allows us to specify a range for our integer variable. This is most excellent when we need to check if a variable is both of type INT and between 1 and 100. Lets see some code.
<?php
/*** an integer to check ***/
$int = 42;
/*** lower limit of the int ***/
$min = 50;
/*** upper limit of the int ***/
$max = 100;
/*** validate the integer ***/
echo filter_var($int, FILTER_VALIDATE_INT, array("min_range"=>$min, "max_range"=>$max));
?>
WTF!... Above we have tried to validate an interger that must be in the range of 50 and 100. The number 42 clearly is not within this range, yet it passes the validation. What has happened here is we have incorrectly specified the options for min_range and max_range. Although this looks correct, and no error is generated the filter simply falls back to being FILTER_VALIDATE_INT and the number 42 passes. Below we show how to correctly specify the options array.
<?php
/*** an integer to check ***/
$int = 42;
/*** lower limit of the int ***/
$min = 50;
/*** upper limit of the int ***/
$max = 100;
/*** validate the integer ***/
echo filter_var($int, FILTER_VALIDATE_INT, array("options" => array("min_range"=>$min, "max_range"=>$max)));
?>
Now we see a different behaviour when the options array is correctly specified as above. We havetried to validate an INT(42), checking that it is both of the type INT and it is within the range of 50 and 100. The above code will return boolean FALSE as the interger 42 is not withing the range specified. Note also that this will work for negative values. Consider this next block of code.
<?php
/*** an integer to check ***/
$int = -2;
/*** lower limit of the int ***/
$min = -10;
/*** upper limit of the int ***/
$max = 100;
/*** validate the integer ***/
echo filter_var($int, FILTER_VALIDATE_INT, array("options" => array("min_range"=>$min, "max_range"=>$max)));
?>
The above code will echo -2 as it is both of type INT and within the range of -10 to 100. We could also validate our integer by specifying only a min_range or a max_range. This can prove helpful if we need a number to be no less than 10 for example. Lets see it in action.
<?php
/*** an integer to check ***/
$int = 12;
/*** lower limit of the int ***/
$min = 10;
/*** validate the integer ***/
echo filter_var($int, FILTER_VALIDATE_INT,array('options'=>array('min_range'=>$min)));
?>
The above code now correctly validates an integer that must not be less than, or equal to 10. Now we can move on a little. We have seen how we can validate a single INT, but we can go further and validate an array of values. To validate an array of values, in this case integers, we use the filter_var_array() function. This function alone makes the whole filter extension worth the effort. The filter_var_array() function allows us to filter or validate many different data types. But for now, lets simply stick with INTs. Lets code it up and see.
<?php
/*** an array of values to filter ***/
$arr = array(10,"109","", "-1234", "some text", "asdf234asdfgs", array());
/*** create an array of filtered values ***/
$filtered_array = filter_var_array($arr, FILTER_VALIDATE_INT);
/*** print out the results ***/
foreach($filtered_array as $key=>$value)
{
echo $key.' -- '.$value.'<br />';
}
?>
The above code will print out the array. It should look like this
0 -- 10
1 -- 109
2 --
3 -- -1234
4 --
5 --
6 -- Array
As you can see, it has printed out the values that are of type INT. We note that 4 and 5 in the list are blank as the filter_var() function has return bool(false) here. Finally we see the last type is merely an array. This type of flexibility is makes the filter extension a great improvement over having to code up all this validation yourself. There is no longer any excuse for sloppy security practices.
Moving on from validating an array of values, the FILTER_VALIDATE_INT filter allows us to also validate INTEGERS of the type OCTAL and HEX. Clever stuff, and will save a bundle of time as we no longer need to code up endless hex and octal arrays. Two flags are currently available for this type of checking. They are:
- FILTER_FLAG_ALLOW_HEX
- FILTER_FLAG_ALLOW_OCTAL
Once again the filter uses an array to hold the flags, be sure to correctly specify them as shown here with the flags array. Lets see how we go with a hex value.
<?php
/*** a hex value to check ***/
$hex = "0xff";
/*** filter with HEX flag ***/
echo filter_var($hex, FILTER_VALIDATE_INT, array("flags"=>FILTER_FLAG_ALLOW_HEX));
?>
The above code will correctly echoes 255. The filter has successfully validated the HEX value and returned that value. If validation fails with a non-hex value it will return bool(false). Of course, hex values are not case sensitive so 0Xff or 0xFF would validate also. As we mentioned earlier, we can also use an OCTAL value in the same way.
<?php
/*** an OCTAL value to check ***/
$octal = 0666;
/*** validate with the OCTAL flag ***/
if(filter_var($octal, FILTER_VALIDATE_INT, array("flags"=>FILTER_FLAG_ALLOW_OCTAL)) === FALSE)
{
echo "Value is not OCTAL!";
}
else
{
echo "$octal is a valid OCTAL number";
}
?>
Validate Boolean
Along with the amazing INTEGER validation PHP also provides a similar method of validating BOOLEAN values. Here we see how easy it is to check for a BOOLEAN value.
<?php
/*** test for a boolean value ***/
echo filter_var("true", FILTER_VALIDATE_BOOLEAN);
?>
The above code will echo 1. This is because the BOOLEAN filter has found a valid boolean value. Other acceptable boolean values that return TRUE are listed here.
- 1
- "1"
- "yes"
- "true"
- "on"
- TRUE
These values are not case sensitive so that true and TrUe are the same. Values that return false are listed below here.
- 0
- "0"
- "no"
- "false"
- "off"
- ""
- NULL
- FALSE
The BOOLEAN filter will also allow us to evaluate code within the filter itself to test for values. Consider the below code using the ternary operator.
<?php
/*** a simple array ***/
$array = array(1,2,3,4,5);
/*** test for a boolean value ***/
echo filter_var(in_array(3, $array), FILTER_VALIDATE_BOOLEAN) ? "TRUE" : "FALSE";
?>
The above code will echo TRUE as it has tested the result of the in_array() function and has found the return value to be bool(true). Not to be forgotten here is that we can use an array of values to test for boolean values also. Lets see how.
<?php
/*** a multi dimensional array ***/
$array = array(0,1,2,3,4, array(0,1,2,3,4));
/*** create the list of values ***/
$values = filter_var($array, FILTER_VALIDATE_BOOLEAN, FILTER_REQUIRE_ARRAY);
/*** dump the values ***/
var_dump($values);
?>
The above code will produce something like this..
- array(6) {
- [0]=> bool(false)
- [1]=> bool(true)
- [2]=> bool(false)
- [3]=> bool(false)
- [4]=> bool(false)
- [5]=> array(5) {
-
- [0]=> bool(false)
- [1]=> bool(true)
- [2]=> bool(false)
- [3]=> bool(false)
- [4]=> bool(false)
- }
- }
As you can see above, the filter has recursively iterated over the array and returned the a boolean value depending on the array members value.
Validate FLOAT
There are of course times we need to validate a floating point number and once again this is simply done as the rest.
<?php
/*** an FLOAT value to check ***/
$float = 22.42;
/*** validate with the FLOAT flag ***/
if(filter_var($float, FILTER_VALIDATE_FLOAT) === false)
{
echo "$float is not valid!";
}
else
{
echo "$float is a valid floating point number";
}
?>
Like other validation options we can still validate an array of floats. Similar to how we validated an array of boolean values, we apply the same principles, and flags, to the float filter. We can also use negative values.
<?php
/*** an array of values ***/
$array = array(1.2,"1.7","", "-12345.678", "some text", "abcd4.2efgh", array());
/*** validate the array ***/
$validation_array = filter_var($array, FILTER_VALIDATE_FLOAT, FILTER_REQUIRE_ARRAY);
/*** dump the array of validated data ***/
var_dump($validation_array);
?>
The above code will return a list something like this
- array(7) {
- [0]=> float(1.2)
- [1]=> float(1.7)
- [2]=> bool(false)
- [3]=> float(-23234.123)
- [4]=> bool(false)
- [5]=> bool(false)
- [6]=> array(0) { }
- }
The filter will also allow us to filter an array with a user specified seperator. So that a float like 1,234 can be accepted.
<?php
/*** an array of floats with seperators ***/
$floats = array(
"1,234" => ",",
"1.234" => "..",
"1.2e3" => ","
);
/*** validate the floats against the user defined decimal seperators ***/
foreach ($floats as $float => $dec_sep)
{
$out = filter_var($float, FILTER_VALIDATE_FLOAT, array("options"=>array("decimal" => $dec_sep)));
/*** dump the results ***/
var_dump($out);
}
?>
From the code above we get the output as follows..
- float(1.234)
- Warning: filter_var() [function.filter-var]: decimal separator must be one char in /www/filter.php on line 13
- bool(false)
- bool(false)
Lets step through this for a minute. The first value has used a comma as a decimal seperator. Normally this would be invalid and be regarded as a thousands seperator. However we have specified the comma as the decimal seperator and so it remains valid and the filter replaces the decimal seperator with a dot and returns 1.234. Next we have a Warning due to the use of a double dot as a decimal seperator. This is nvalid as a decimal seperator must be one character only. Following this, the filter returns bool(false) for that value. The final value also returns bool(false) as the decimal seperators do not match.
Validate REGEX
If you are unfamiliar with regex then it is highly recommended you begin with the phPRO Introduction to PHP Regular Expressions. This should put you in good condition for the following. For those adept at regex, then read on. Validating by regex is something we do commonly for information that should fit a pattern. The filter extension allows us to validate variables in the same manner as we have seen previously. First we will attempt a simple pattern match to see if a string begins with the letter and then we will try to match an email address.
<?php
/*** the string we wish to match ***/
$string = "Try to match me";
/*** try to validate with the regex pattern ***/
if(filter_var($string, FILTER_VALIDATE_REGEXP, array("options"=>array("regexp"=>"/^T(.*)/"))) === false)
{
/*** if there is no match ***/
echo "Sorry, no match";
}
else
{
/*** if we match the pattern ***/
echo "The string begins with T";
}
?>
From the above code we see the string does match the pattern and a bool(false) is not returned. If the pattern does match the string value is returned just as with all the previous validation types. Lets see a little more complex regex to try to match an email address.
<?php
/*** an email address ***/
$email = "hatemail@phpro.org";
/*** the pattern we wish to match against ***/
$pattern = "/^S+@[wd.-]{2,}.[w]{2,6}$/iU";
/*** try to validate with the regex pattern ***/
if(filter_var($email, FILTER_VALIDATE_REGEXP, array("options"=>array("regexp"=>$pattern))) === false)
{
/*** if there is no match ***/
echo "Sorry, no match";
}
else
{
/*** if we match the pattern ***/
echo "The email address is valid";
}
?>
So, the above code will match the email address and print the line
The email address is valid
Normally you would not use this method of email checking for email addresses as the filter extension provides checking for this purpose, but more on that later. Should you accidently omit the regex in your checking an E_WARNING is generated and the filter will return bool FALSE.
Validate a URL
URLs can be tricky to deal with. there is no maximum length defined in the rfc and you would be totally amazed at just how many different variations and formats a URL can be in. Recommended reading is RFC 1738 which explains all you need to know about URL validation. You could then write up your own class with which to validate all your ipv4 and ipv6 URLs etc. Or, you can simply use FILTER_VALIDATE_URL in filter_var(). Lets see how it works in its simplest form.
<?php
/*** a rfc compliant web address ***/
$url = "http://www.phpro.org";
/*** try to validate the URL ***/
if(filter_var($url, FILTER_VALIDATE_URL) === FALSE)
{
/*** if there is no match ***/
echo "Sorry, $url is not valid!";
}
else
{
/*** if we match the pattern ***/
echo "The URL, $url is valid!<br />";
}
?>
Above we see, like in the examples previous, a simple check of the variable with an if statement tells us the url value is valid. But not all URLs are in this form. According to the rfc, a URL can take many forms. The URL may be in the form of an IP address, or have a QUERY string attached to it. This is why URLs have been so difficult to validate in the past. Several flags have been provided with the URL validation filter to check for some of these occurances and to validate against them. They are listed here.
- FILTER_FLAG_SCHEME_REQUIRED
- FILTER_FLAG_HOST_REQUIRED
- FILTER_FLAG_PATH_REQUIRED
- FILTER_FLAG_QUERY_REQUIRED
We will begin at the top here and check for flag scheme.
<?php
/*** a non rfc compliant URL ***/
$url = "index.php";
/*** try to validate the URL ***/
if(filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED) === FALSE)
{
/*** if there is no match ***/
echo "Sorry, $url is not valid!";
}
else
{
/*** if the URL is valid ***/
echo "The URL, $url is valid!";
}
?>
We see from above that the URL supplied does not validate against the FILTER_FLAG_SCHEME_REQUIRED flag. The URL needs to be properly formatted to fit the required scheme. Lets try again with a different URL.
<?php
/*** a rfc compliant URL ***/
$url = "http://foo";
/*** try to validate the URL ***/
if(filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED) === FALSE)
{
/*** if there is no match ***/
echo "Sorry, $url is not valid!";
}
else
{
/*** if the URL is valid ***/
echo "The URL, $url is valid!";
}
?>
Now we see that the URL validates against the scheme. The return values are bool(false) if the validation fails, or if it passes validation the URL string is returned. Lets continue with the other flags and FLAG_HOST_REQUIRED. If we were to alter the above filter flag from FILTER_FLAG_SCHEME_REQUIRED to FILTER_FLAG_HOST_REQUIRED it would still validate as the URL http://foo has the host name of "foo". Lets try with an invalid host name.
<?php
/*** a path with no host name ***/
$url = "/path/to/foo";
/*** try to the validate the URL ***/
if(filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_HOST_REQUIRED) === FALSE)
{
/*** if there is no match ***/
echo "Sorry, $url is not valid!";
}
else
{
/*** if the URL is valid ***/
echo "The URL, $url is valid!";
}
?>
Now we see that the missing hostname does not validate against the required flag and returns bool(false). What would happen if you tried a URL like http:// one wonders. It is left as an excercise for the reader to try. To enable correct validation the FILTER_FLAG_HOST_REQUIRED flag must be satisified such as the example below.
<?php
/*** a path with no host name ***/
$url = "http://phpro.org";
/*** try to the validate the URL ***/
if(filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_HOST_REQUIRED) === FALSE)
{
/*** if there is no match ***/
echo "Sorry, $url is not valid!";
}
else
{
/*** if the URL is valid ***/
echo "The URL, $url is valid!";
}
?>
Of course now, the code above validates the URL as we have now supplied a value that satisfies the FILTER_FLAG_HOST_REQUIRED flag. Next we see the FILTER_FLAG_PATH_REQUIRED flag. This flag as the name suggests tells the URL validator that a path is required within the url for it to validate. Lets see it in action.
<?php
/*** a URL with a path ***/
$url = "http://phpro.org/path/to/foo";
/*** try to the validate the URL ***/
if(filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_PATH_REQUIRED) === FALSE)
{
/*** if there is no match ***/
echo "Sorry, $url is not valid!";
}
else
{
/*** if the URL is valid ***/
echo "The URL, $url is valid!";
}
?>
We see from the above code that the URL is valid because it contains a path after the host name. Should the path be missing and the URL was simply http://www.phpro.org then it would fail validation and return bool(false). Next we see the FILTER_FLAG_QUERY_REQUIRED flag. You should now have no problems implementing this as it follows the same convention as the previous flags. As the name suggests, this flag requires the URL to have a query string of type file.php?var=foo&var2=bar. The use is exactly the same as before.
<?php
/*** a URL with a query string ***/
$url = "http://phpro.org/index.php?var=foo&var2=bar";
/*** try to the validate the URL ***/
if(filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_QUERY_REQUIRED) === FALSE)
{
/*** if there is no match ***/
echo "Sorry, $url is not valid!";
}
else
{
/*** if the URL is valid ***/
echo "The URL, $url is valid!";
}
?>
Filter IP Address
Following on from validation of URLs, we often find we need to validate an IP Address. Of course, and IP address may be of different formats for ipv4 and ipv6. An IP address may also need to be within a range of private or reserved ranges. The filter extension makes it possible to discern these differences and to validate an IP address to fit most needs. In its simplest form the validation of a url will look like this.
<?php
/*** an IP address ***/
$ip = "192.168.0.1";
if(filter_var($ip, FILTER_VALIDATE_IP) === FALSE)
{
echo "$ip is not a valid IP";
}
else
{
echo "$ip is valid";
}
?>
As we have supplied the above with a valid IP address it validates and all is well. But now we may wish to validate an IPV6 address or an address with a private range. The IP filter has several flag with which to validate an IP address with. Listed here.
- FILTER_FLAG_IPV4
- FILTER_FLAG_IPV6
- FILTER_FLAG_NO_PRIV_RANGE
- FILTER_FLAG_NO_RES_RANGE
Starting at the top we will check to see if an IP is a valid IPV4 address.
<?php
/*** an IP address ***/
$ip = "192.168.0";
/*** try to validate as IPV4 address ***/
if(filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) === FALSE)
{
echo "$ip is not a valid IP";
}
else
{
echo "$ip is valid";
}
?>
In the above example the IP address has failed to validate as it is not a complete IPV4 address. It would need to be of the form of the example that preceded it, 192.168.0.1 to validate. This is fine, but growth of the net has seen us run out of IPV4 addresses and so we need to validate against IPV6 addresses also. Here we show the use of the FILTER_FLAG_IPV6 flag.
<?php
/*** an IP address ***/
$ip = "2001:0db8:85a3:08d3:1319:8a2e:0370:7334";
/*** try to validate as IPV6 address ***/
if(filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) === FALSE)
{
echo "$ip is not a valid IP";
}
else
{
echo "$ip is valid";
}
?>
Above we see that the IPV6 address is a valid form of IP and passes validation. Next we see if an IP falls within a private range.
<?php
/*** an IP address ***/
$ip = "192.168.0.1";
/*** try to validate a private range address ***/
if(filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE) === FALSE)
{
echo "$ip is within a private range";
}
else
{
echo "$ip is not a private IP";
}
?>
The above code will print the line
192.168.0.1 is within a private range
because the IP address is within the range of private IP address as specified in the RFC. Try changing the IP to a public IP address, that is one used over the internet, and see the results.
The FILTER_FLAG_NO_RES_RANGE, as the name suggests, will allow no reserved range IP addresses. Only valid non-reserved address will pass validation here.
<?php
/*** an IP address ***/
$ip = "255.255.255.255";
/*** try to validate a non reserve range address ***/
if(filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE) === FALSE)
{
echo "$ip is within a reserved range";
}
else
{
echo "$ip is not within a reserved range";
}
?>
Of course, the IP address 255.255.255.255 is within a reserved range and it fails to validate against the FILTER_FLAG_NO_RES_RANGE flag and returns bool FALSE. The filter will take an IPV4 or IPV6 IP address. Try this simple script with some other IP addresses such as:
66.163.161.117
2001:0db8:85a3:08d3:1319:8a2e:0370:7334
and see this in action.
Validate Email Address
What validation suite would be complete without the ability to validate an email address. Almost everybody has their own function and regex for this and many holy wars have been fought over the "correct" method of doing it. We saw earlier how we could do this with the FILTER_VALIDATE_REGEXP filter and supplying a REGEX to the filter. Of course, everybody has their own REGEX that is better than everybody elses. Now we have a standard way that everybody can use. Lets put it to work.
<?php
/*** an email address ***/
$email = "kevin@foo.bar.net";
/*** try to validate the email ***/
if(filter_var($email, FILTER_VALIDATE_EMAIL) === FALSE)
{
/*** if it fails validation ***/
echo "$email is invalid";
}
else
{
/*** if the address passes validation ***/
echo "$email is valid";
}
?>
So, there you have the email validated and the world is a better place having saved many kittens. This filter takes no addition flags or options, it simply validates the email.
Sanitizing Variables
Whilst it is well to be able to validate the data we use, it is equally important to be able to clean up any data that may come to our scripts, especially data from user land. The filter_var() function also contains filters for many data types that will clean up data for use in our scripts. Here we will show their uses in a simple context.
Sanitize A String
The FILTER_SANITIZE_STRING filter allows us to filter various information from a string to allow us to safely use the data within for our applications. Lets look at the possible flags for FILTER_SANITIZE_STRING. You can use this to strip tags, unwanted characters or even encode them.
- FILTER_FLAG_NO_ENCODE_QUOTES
- FILTER_FLAG_STRIP_LOW
- FILTER_FLAG_STRIP_HIGH
- FILTER_FLAG_ENCODE_LOW
- FILTER_FLAG_ENCODE_HIGH
- FILTER_FLAG_ENCODE_AMP
These flags perform various sanitizing functions on a string. Without them the FILTER_SANITIZE_STRING works in this way.
<?php
/*** a string with tags ***/
$string = "<script>foo</script>";
/*** sanitize the string ***/
echo filter_var($string, FILTER_SANITIZE_STRING);
?>
We see from the above code that the <script></script> tags have been removed leaving only the "foo" text. Using the optional flags we can gain a little more control of this behaviour. Lets modify our string variable a little to include some quotes.
<?php
/*** a string with tags ***/
$string = "<script>"'foo'"</script>";
/*** sanitize the string ***/
echo filter_var($string, FILTER_SANITIZE_STRING);
?>
If we look at the HTML source produced from the above code, we we see that we now have the <script></script> tags remove and the quotes have been encoded to produce a string like "'foo'"
Should we wish to keep the quotes the FILTER_FLAG_NO_ENCODE_QUOTES flag can help us.
<?php
/*** a string with tags ***/
$string = "<script>"'foo'"</script>";
/*** sanitize the string ***/
echo filter_var($string, FILTER_SANITIZE_STRING, FILTER_FLAG_NO_ENCODE_QUOTES);
?>
Now we see from the above code, the quotes have not been encoded and are returned without their HTML entity values. We can gain a little more control of the characters we wish to encode with the filter by stipping or encoding only the high, or low characters. High and low characters are defined as those with an ASCII value below 32 or above 32. Lets code up some chars and put the required flags to work.
<?php
/*** a string with tags ***/
$string = "<li><script>!@#$%^&*foo</script><br><p /><li />";
/*** sanitize the string ***/
echo filter_var($string, FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW)
?>
The companion flag to this is of course FILTER_FLAG_STRIP_HIGH, which strips all other characters. It is used in the same manner.
<?php
/*** a string with tags ***/
$string = "<li><script>!@#$%^&*foo</script><br><p /><li />";
/*** sanitize the string ***/
echo filter_var($string, FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_HIGH)
?>
This is all well for stripping out unwanted characters, but does not address the issue of keeping them. To this end we use the encoding functions in the same way.
<?php
/*** a string with tags ***/
$string = "<li><script>!@#$%^&*foo</script><br><p /><li />";
/*** sanitize the string ***/
echo filter_var($string, FILTER_SANITIZE_STRING, FILTER_FLAG_ENCODE_LOW)
?>
By now you should be getting into the swing of the filter functions and flags. It should be quite easy to see the companian flag to the code above and how FILTER_FLAG_ENCODE_HIGH works. It will encode ASCII characters over 32.
<?php
/*** a string with tags ***/
$string = "<li><script>!@#$%^&*foo</script><br><p /><li />";
/*** sanitize the string ***/
echo filter_var($string, FILTER_SANITIZE_STRING, FILTER_FLAG_ENCODE_HIGH);
?>
Lastly in this section is the FILTER_FLAG_ENCODE_AMP. No prizes for guessing this one. It encodes the & character to &
<?php
/*** a string with an ampersand ***/
$string = "http://phpro.org/file.php?foo=1&bar=2";
/*** sanitize the string ***/
echo filter_var($string, FILTER_SANITIZE_STRING, FILTER_FLAG_ENCODE_AMP);
?>
The resulting string will look the same in the browser, however, if you view the source you will see the ampersand has been correctly encode to look like
http://phpro.org/file.php?foo=1&bar=2
The FILTER_SANITIZE_STRING (string) filter has an alias called FILTER_SANITIZE_STRIPPED (stripped). I have no idea why it is there and suggest it dies a slow painful death as it can only lead to confustion.
URL Encode
The ability to url encode data has previously fallen to the urlencode() function. This functionality has been embrace by the filter extension and provides more features than previously. We can now URL encode a string and optionally strip or encode special characters. Lets see it in action.
<?php
/*** a url string ***/
$url = "http://phpro.org/a dir!/file.php?foo=1&bar=2";
/*** sanitize (url encode) the url ***/
echo filter_var($url, FILTER_SANITIZE_ENCODED);
?>
The above code will produce a string like this
http%3A%2F%2Fphpro.org%2Fa%20dir%21%2Ffile.php%3Ffoo%3D1%26bar%3D2
As you can see, the spaces and special chars have been encoded for use in urls. Like the string filter, the encoded filter has HIGH and LOW filtering options with flags that can be set. The LOW filter deals with special chars below ASCII 32 and the HIGH deals with the rest.The flags allow the filtering or sanitizing of the input string. The flags should look familiar by now and are listed below.
- FILTER_FLAG_STRIP_LOW
- FILTER_FLAG_STRIP_HIGH
- FILTER_FLAG_ENCODE_LOW
- FILTER_FLAG_ENCODE_HIGH
Lets put them each through thier paces to see how each works.
<?php
/*** a url string ***/
$url = "http://phpro.org/a dir!/file.php?foo=1&bar=2";
/*** echo our string with the stripped chars ***/
echo filter_var($url, FILTER_SANITIZE_ENCODED, FILTER_FLAG_STRIP_LOW);
?>
Any characters below ASCII 32 will be stripped from the URL variable above. Of course, we can strip all characters above ASCII 32 with FILTER_FLAG_STRIP_HIGH as shown below.
<?php
/*** a url string ***/
$url = "http://phpro.org/a dir!/file.php?foo=1&bar=2";
/*** echo our string with the stripped chars ***/
echo filter_var($url, FILTER_SANITIZE_ENCODED, FILTER_FLAG_STRIP_HIGH);
?>
Rather than strip the any ASCII chars from a url we could encode them instead using FILTER_FLAG_ENCODE_HIGH or FILTER_FLAG_ENCODE_LOW.
<?php
/*** a url string ***/
$url = "one two&three";
/*** echo and encode the string ***/
echo filter_var($url, FILTER_SANITIZE_ENCODED, FILTER_FLAG_ENCODE_LOW)
?>
The same again but encoding the HIGH characters.
<?php
/*** a url string ***/
$url = "one two&three";
/*** echo and encode the string ***/
echo filter_var($url, FILTER_SANITIZE_ENCODED, FILTER_FLAG_ENCODE_HIGH)
?>
Sanitize Special Chars
This filter option allows us to HTML-escape '"<>& and characters with ASCII value less than 32. Because of this there is no FILTER_FLAG_ENCODE_LOW flag. The available flags are listed here
- FILTER_FLAG_STRIP_LOW
- FILTER_FLAG_STRIP_HIGH
- FILTER_FLAG_ENCODE_HIGH
<?php
/*** our string ***/
$string = "?><!@#$%^&*()}{~bobthebuilder";
/*** echo the sanitized string ***/
echo filter_var($string, FILTER_SANITIZE_SPECIAL_CHARS)
?>
If we view the result in our browser and view the source, the result from the above code will look this:
?><!@#$%^&*()}{~bobthebuilder
As you can see, it has seized on the several characters and HTML encoded them. Next we will see how it works with the FILTER_FLAG_STRIP_LOW flag.
<?php
/*** our string ***/
$string = "?????????";
/*** echo the sanitized string ***/
echo filter_var($string, FILTER_SANITIZE_SPECIAL_CHARS, FILTER_FLAG_STRIP_LOW);
?>
The sanitized string from above should look a little like this:
кириллица
funky....
We can of course choose to strip the HIGH ASCII values like this:
<?php
/*** our string ***/
$string = "foo?????????bar";
/*** echo the sanitized string ***/
echo filter_var($string, FILTER_SANITIZE_SPECIAL_CHARS, FILTER_FLAG_STRIP_HIGH);
?>
Finally, we can encode the high chars
<?php
/*** our string ***/
$string = "foo?????????bar&fubar";
/*** echo the sanitized string ***/
echo filter_var($string, FILTER_SANITIZE_SPECIAL_CHARS, FILTER_FLAG_ENCODE_HIGH);
?>
In the above code, the foo and the bar remain, whilst the characters between foo and bar have been sanitized, whilst the ampersand has been encoded.
Filter Unsafe RAW
This is perhaps the oddest of the filters. The PHP manual quotes it as "Do nothing, optionally strip or encode special characters." Well, doing nothing is what I do best. Not to be out-performed it still keeps all the flags as listed below.
- FILTER_FLAG_STRIP_LOW
- FILTER_FLAG_STRIP_HIGH
- FILTER_FLAG_ENCODE_LOW
- FILTER_FLAG_ENCODE_HIGH
- FILTER_FLAG_ENCODE_AMP
You should by now know how to use the STRIP and ENCODE flags. If you do not, return to the top of this document and start from their. Here we will show only the FILTER_FLAG_ENCODE_AMP flag in use.
<?php
/*** our string ***/
$string = "Bed & Breakfast";
/*** echo the sanitized string ***/
echo filter_var($string, FILTER_UNSAFE_RAW, FILTER_FLAG_ENCODE_AMP);
?>
The code above will print the following line
Bed & Breakfast
As you can see,the ampersand is now encoded as the flag dictates.
Sanitize an Email Address
Earlier we saw how to filter and validate an email address. Here we can take the email address and sanitize it. That is, remove illegal or unwanted characters from it. It is surprising the amount of characters that are allowed in a valid email address. They are:
All letters, digits and $-_.+!*'(),{}|^~[]`<>#%";/?:@&=.
Lets put it to the test.
<?php
/*** an email address ***/
$email = "kevin&friends@(foo).example.com";
/*** sanitize the email address ***/
echo filter_var($email, FILTER_SANITIZE_EMAIL);
?>
The above code will produce the output:
kevin∓friends@foo.example.com
The ampersand has remained but the () and the three backslashes have been removed, leaving us with a usable, or sanitized, email address.
Sanitize a URL
Unlike the FILTER_SANITIZE_ENCODED filter that encodes URL strings, or the FILTER_VALIDATE_URL which checks if a URL is valid, the FILTER_SANITIZE_URL will strip out illegal characters. The characters that are not removed are letters and digits and the following:
$ - _ . + ! * ' ( ) , { } | ^ ~ [ ] ` > < # % " ; / ? : @ & = .
To see it in action is simple as this filter takes no flags.
<?php
/*** a URL ***/
$url = "http://www.phÆpro.o?rg";
/*** sanitize the URL ***/
echo filter_var($url, FILTER_SANITIZE_URL);
?>
The url string above contains 2 utf-8 characters (your browser may not show these, check source) which are illegal in urls. The FILTER_SANITIZE_URL filter has stripped these characters from the string leaving us with a valid URL.
Sanitize an Integer
To sanitize an Integer is simple with the FILTER_SANITIZE_INT filter. This filter strips out all characters except for digits and . + -
It is simple to use and we no longer need to boggle our minds with regular expressions.
<?php
/*** an interger ***/
$int = "abc40def+;2";
/*** sanitize the integer ***/
echo filter_var($int, FILTER_SANITIZE_NUMBER_INT);
?>
The above code produces an output of 40+2 as the none INT values, as specified by the filter, have been removed.
Sanitize a Float
Sanitizing a float is a little more playful and as FILTER_SANITIZE_NUMBER_FLOAT filter takes 3 flags.
- FILTER_FLAG_ALLOW_FRACTION
- FILTER_FLAG_ALLOW_THOUSAND
- FILTER_FLAG_ALLOW_SCIENTIFIC
These flags are self explanatory and are easy to use as shown below. First we will put the FILTER_SANITIZE_NUMBER_FLOAT filter to the test without any flags.
<?php
/*** a floating point number ***/
$float = "abc40.4def+;2";
/*** sanitize the float ***/
echo filter_var($float, FILTER_SANITIZE_NUMBER_FLOAT);
?>
Like the previous example this filter has stripped out all chacaracters except for digits and the + and - characters. The dot character is removed with this filter. Optionally would could keep the .(dot) character with the optional FILTER_FLAG_ALLOW_FRACTION flag.
<?php
/*** a floating point number ***/
$float = "abc40.4def+;2";
/*** sanitize the float ***/
echo filter_var($float, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION);
?>
Above we now see that the script returns
40.4+2
as we have now allowed fractional notation. We could also allow thousand seperators with the FILTER_FLAG_ALLOW_THOUSAND flag as demonstrated below.
<?php
/*** a floating point number ***/
$float = "abc40.,000+;2";
/*** sanitize the float ***/
echo filter_var($float, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_THOUSAND);
?>
Now the script above returns
40,000+2
because we have allowed the use of the thousand seperator in the string. If we wished to use scientific notation we can also allow the use of the characters e and E as we see below here.
<?php
/*** a floating point number ***/
$float = "abc40+;4.2e";
/*** sanitize the float ***/
echo filter_var($float, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_SCIENTIFIC);
?>
This should now be rather self explanatory as we see the flag allowing scientific notation and the script returns
40+42e
Note the the decimal seperator has been removed also.
Magic Quotes
The use of magic quotes in PHP has been a contentious issue from its inception. The removal of magic quotes in favour of user defined escaping of characters makes a lot of sense. Here we can impliment the functionality of magic quotes without having them force upon us by php.ini settings which may vary from server to server. The FILTER_SANITIZE_MAGIC_QUOTES filter applies the addslashes function to a string, thus providing us with an escaped string for use in our applications.
<?php
/*** a string ***/
$string = "test'test2'test3'' test'"test5";
/*** sanitize the float ***/
echo filter_var($string, FILTER_SANITIZE_MAGIC_QUOTES)
?>
As we can see, this above script returns
test'test2'test3'' test'"test5
as the addslashes() function has been applied to the string and escaped the characters that need to be escaped.
Callback Filter
The FILTER_CALLBACK filter does exactly what it says. Calls a user-defined function to filter our data. This functionality permits us full control of the filtering of data. Here we will begin with a simple user defined function that converts spaces to underscores.
<?php
/**
* Callback function
* Convert spaces to underscores
*
* @param $string
*
* @return string
*
**/
function space2underscore($string) {
return str_replace(" ", "_", $string);
}
$string = "This is not a love song";
echo filter_var($string, FILTER_CALLBACK, array("options"=>"space2underscore"));
?>
We see the filter has used our space2underscore() function as a callback and converted the spaces in the string so that it now returns
This_is_not_a_love_song.
We could use a PHP function rather than our own as demonstrated here
<?php
/*** a string ***/
$string = "This is not a love song";
/*** use a PHP defined function as callback ***/
echo filter_var($string, FILTER_CALLBACK, array("options"=>"ucwords"));
?>
Now we see that using a simple PHP callback function is simple on our string and the return value is
This Is Not A Love Song
. If a non-existant function is used an error an error is generated as shown below.
<?php
/*** a string ***/
$string = "phpro.org";
/*** a callback without a declared function ***/
filter_var($string, FILTER_CALLBACK, array("options"=>"non_existant_function"));
?>
The above script will produce an error like
Warning: filter_var() [function.filter-var]: First argument is expected to be a valid callback in /www/fil.php on line 6
We have seen above the use of several functions to use as a callback. But what if we wanted to use several functions for our callback array. Lets put it to the test.
<?php
/*** a string ***/
$string = "This is not a love song";
/*** use a PHP defined function as callback ***/
echo filter_var($string, FILTER_CALLBACK, array("options"=>array("ucwords", "strtolower")));
?>
GRIM...
We see above that the use of mulitple callbacks is not permitted and will generate an error as follows:
Warning: filter_var() [function.filter-var]: First argument is expected to be a valid callback in /home/kevin/html/fil.php on line 7.
We can however, call a class method as shown below here.
<?php
/*** class method callback ***/
class my_class{
/**
* Callback method
* Convert spaces to underscores
*
* @param $string
*
* @return string
*
**/
function space2underscore($string) {
return str_replace(" ", "_", $string);
}
}/*** end of class ***/
$string = "This is not a love song";
echo filter_var($string, FILTER_CALLBACK, array("options"=>array("my_class", "space2underscore")));
?>
Moving on from the above class we can also use a call back with a thown exception like this..
<?php
/* thrown exception in the callback */
function check_num(&$num) {
if($num != 4)
{
throw new Exception("This is an exception error message");
}
}
/*** declare a number variable ***/
$num = 3;
try {
filter_var($num, FILTER_CALLBACK, array("options"=>"check_num"));
}
catch (Exception $e)
{
echo $e->getMessage();
}
?>
From the above code we see that the $num variable does not match the value in the check_num() method and so an exception is thrown. The exception is then caught as usual in the first catch block and the error messages is displayed.
The INPUT Filter
As the name suggests, the input filter gets input from outside our script and can then filter it. The function used for this is the filter_input() function. With this we can validate our variables as the come in from userland and be sure they are dealt with before we start using them. This ensures we have some semblance of a security model in place. If you are not moving to this architecture then you are letting yourself, and your customers, down. The input filter can gather data from several sources.
- INPUT_GET
- INPUT_POST
- INPUT_COOKIE
- INPUT_ENV
- INPUT_SERVER
- INPUT_SESSION (Not yet implemented)
- INPUT_REQUEST (Not yet implemented)
Here follows a simple example of using the filter_input() function to deal with GET variables. Lets assume you have a URL of the the type http://www.example.com?num=7
Lets see how we can validate this using our input filter.
<?php
/*** filter the input number from GET ***/
if(filter_input(INPUT_GET, 'num', FILTER_VALIDATE_INT, array("options" => array("min_range"=>1, "max_range"=>10))) != FALSE)
{
echo $_GET['num'].' is valid';
}
else
{
echo 'Invalid number supplied';
}
?>
As seen with earlier use of the FILTER_VALIDATE_INT filter, we are able to validate that the supplied value is a digit and that it is with the range of 1 to 10. Should an invalid value be supplied the filter_input will return bool(false). The INPUT_GET parameter tells the filter_input that the value is coming from GET.
In the same manner as we validated the Integer above, we can do the same for any value. Here we show the filter_input in use with a different filter.
<?php
/*** filter the GET text variable with a value of <kevin> ***/
echo filter_input(INPUT_GET, 'text', FILTER_SANITIZE_SPECIAL_CHARS);
?>
The above code uses the FILTER_SANITIZE_SPECIAL_CHARS filter to check the value of the GET variable named text. When if finds special chars it converts them for use like this
↦#62;kevin<
Of course we can use any of our filters in this way, here we use the FILTER_SANITIZE_ENCODED filter to encode the variable for use in a url. We use a url of the type filter.php?text=php pro
<?php
/*** input url is filter.php?text=php pro ***/
/*** fiter and encode the GET text variable for use in a url ***/
$url = filter_input(INPUT_GET, 'text', FILTER_SANITIZE_ENCODED);
/*** echo the encoded url ***/
echo '<a href="?text='.$url.'">Link</a>';
?>
From the code above we get the encoded url value like this
<a href="?text=php%20pro">Link</a>
Note that the space has been converted to a HTML special char for use in the url.
So, lets assume we are recieving our data from a form and we need to access the POST array. This is done in the same mammer as accessing GET variables with INPUT_POST as we show here.
<form method="post">
<input type="text" name="number" value="123blah456" />
<input type="submit" />
</form>
<?php
/*** echo number from form ***/
echo filter_input(INPUT_POST, "number", FILTER_SANITIZE_NUMBER_INT);
?>
If we use the form above we find INPUT_POST applies the FILTER_SANITIZE_NUMBER_INT filter to the $_POST['number'] variable. It strips out the characters that are not digits which we can then use in our applications. With this sort of flexibility in use of the various filters, it is a small step to use any filter by applying the same methods. Here we show a simple form POST and a callback to prepare data for INSERTing into a MySQL database.
<input type="text" name="answer" value="123bla''h456" />
<input type="submit" />
</form>
/*** use a callback filter to mysql_real_escape_string ***/
$answer = filter_input(INPUT_POST, "answer", FILTER_CALLBACK, array("options"=>"mysql_real_escape_string"));
/*** create an sql query ***/
$sql = "INSERT INTO quiz (answers) VALUES ('{$answer}')";
/*** echo the query ***/
echo $sql;
?>
The code above demonstrates how flexible the filter extension is. We could of course use $_SERVER or $_SESSION as the INPUTs and the functionality would remain the same.
Filter an Array
Up till now we have focused on validation of variables from various sources. Here we show how the filters can be used on an array of values. This is done using the filter_var_array() function. We will show here a simulated POST array that could come from a form and how to apply different filters to the various array members.
<?php
/**
* Callback function
* @format a name
* @param string $name
* @return string formated name
**/
function formatName($name){
return ucwords(strtolower($name));
}
/*** simulated POST array ***/
$_POST = array(
"name" => "KeViN WatersoN",
"age" => "42",
"email" => "example@phpro.org",
);
/*** an array of filters ***/
$filters = array(
"name" => array("filter"=>FILTER_CALLBACK, "flags"=>FILTER_FLAG_ARRAY, "options"=>"formatName"),
"age" => array("filter"=>FILTER_VALIDATE_INT, "flags"=>FILTER_FLAG_ARRAY, "options"=>array("min_range" => 1, "max_range" => 100)),
"email" => FILTER_VALIDATE_EMAIL,
);
/*** apply the filters to the array ***/
$filtered_array = filter_var_array($_POST, $filters);
/*** loop and display keys and values ***/
foreach($filtered_array as $k=>$v)
{
echo $k." - ".$v."<br />";
}
?>
Lets step through the above code to see what we have done here. The output will be like:
name - Kevin Waterson
age - 42
email - example@phpro.org
We began with a simple callback function that we use to apply later in the script. Next we created a simulated POST array to simulate the data coming from a form, or possibly CURL. We then create an array of filters we wish to supply to each of the POST variables. It is then a simple matter for us to apply the filters array to the POST array with the filter_var_array() function. We loop over our filtered_array and see the values. This is by far a superior method of handling variables from users. Of course the POST data could be any array of data. You may be able to see how helpful the callback filter will be when used on POST data intended for INSERTing into a database. A simple callback to a function such as mysql_real_escape_string(), as seen previously, would make life a lot simpler for some.
As mentioned, any array could be used. A POST array was used above as an example, but there is a better way to hand inputs using the filter_input_array. Like the filter_input() function, the filter_input_array() function takes it array of values from inputs as follows
- INPUT_GET
- INPUT_POST
- INPUT_COOKIE
- INPUT_SERVER
- INPUT_ENV
- INPUT_SESSION
- INPUT_REQUEST
<form method="post">
<input type="text" name="name" value="Kevin" /><br />
<input type="text" name="age" value="42" /><br />
<input type="text" name="email" value="example@phpro.org" /><br />
<input type="submit" />
</form>
<?php
$filters = array(
"age" =>array("filter"=>FILTER_VALIDATE_INT, "flags"=>FILTER_FLAG_ARRAY|FILTER_NULL_ON_FAILURE, "options"=>array("min_range"=>0, "max_range"=>100)),
"name" => FILTER_SANITIZE_SPECIAL_CHARS,
"email" => FILTER_SANITIZE_EMAIL,
"notset"=> FILTER_VALIDATE_INT
);
/*** apply the filters to the POST array ***/
$filtered = filter_input_array(INPUT_POST, $filters);
/*** echo the filtered array members ***/
echo $filtered['name'] .'<br />'. $filtered['age'] .'<br />'. $filtered['email'].'<br />';
/*** check for the notset variable ***/
if(filter_has_var(INPUT_POST, "notset") !== false)
{
echo 'Variable is in filter';
}
else
{
var_dump($filtered["notset"]);
}
?>
Stepping through this code we see some familiar filters and some new introductions. When using the FILTER_VALIDATE_INT for the age variable we have added the flag constant FILTER_NULL_ON_FAILURE. This flag tells the filter engine to return NULL rather than bool(false) if the filter fails. This can be handy if we wish to INSERT into a database or something. Wehave used the filter_input_array() function to apply the filters to their respective POST variables much the same as we did with the filter_var_array() function earlier. From there it is simple to echo the filtered array members, or if our program dictated, we may have other uses for them.
At the very last we have used the filter_has_var() function to check if the variable notset is in the INPUT_POST filter. As it is not it returns NULL as seen with the var_dump().
Filter an Array with CALLBACK
Of course, not all arrays come from outside our scripts. Quite often we need to perform operations on our own arrays. Previously, if we wanted to use a callback would would have used array_walk() to apply a callback function. The filter extension deals with this just as simply as with any array. In the following example we will do something useful. The task of hiding email addresses from spam bots is an age old task and many have taken to use ASCII values instead to print thier mails. Latter day spambots read these also, but it makes for a good callback example to iterate over each character of an email address and convert it to its ASCII value using the PHP ord() function.
<?php
echo encodeEmail('example@phpro.org');
/**
*
* Return ASCII value web use
*
* @param string
*
* @return string
*
*/
function makeASCII($char=0){
return '&#'.ord($char).';';
}
/**
*
* @Encode an email to ascii
*
* @parma string
*
* @return string
*
*/
function encodeEmail($email){
/*** check if the filter has a var ***/
if(filter_var($email, FILTER_VALIDATE_EMAIL) !== FALSE)
{
/*** split the email into single chars ***/
$charArray = str_split($email);
/*** apply a callback funcion to each array member ***/
$encodedArray = filter_var($charArray, FILTER_CALLBACK, array('options'=>"makeASCII"));
/*** put the string back together ***/
$encodedString = implode('',$encodedArray);
return '<a href="mailto:'.$encodedString.'">'.$encodedString.'</a>';
}
else
{
return false;
}
}
?>
The string resulting from this will be an ASCII encode mail address for use on a web page like this
<a href="mailto:kevin@phpro.org">kevin@phpro.org<a>
More importantly, what we have done is used the filter_var() function on an array, just as we would a string. The same principles apply and the filter will apply the callback function to each member of the array. It does'nt get any easier than this.
A Real World Example
We have seen above many ways in which we can use the filter extension to improve our script. The use in the real world will not differ greatly from what you have seen here, but will have different value for different applications. With the focus on security, this section has blossomed into its own tutorial which is available at http://www.phpro.org/tutorials/PHP-Security.html. This tutorialis highly recommended for those wishing to use the filter functions for input validation and sanitation.
Credits
Many thanks to Derick Rethans and Pierre for their help with the code in this tutorial and quick fixes to bugs in the PHP 5.2.0 core as we came across them. Pierre and Derick are PHP core developers and the creators of the filter extenstion. You can catch the latest from Pierre on his blog at http://blog.thepimp.net.
Sanitizing
Sanitizing data allows you to remove or encode characters within the context of what you need returned.
FILTER_SANITIZE_STRING
Performs a basic string sanitize. Removes <>?
$san_string = filter_var($string, FILTER_SANITIZE_STRING);
FILTER_SANITIZE_ENCODED
Encodes `~!@#$%^&*()=+[{]};:'".?/| to %hex
$san_enc = filter_var($string, FILTER_SANITIZE_ENCODED);
FILTER_SANITIZE_SPECIAL_CHARS
Encodes <>&" into &type;
$san_spc = filter_var($string, FILTER_SANITIZE_SPECIAL_CHARS);
FILTER_SANITIZE_EMAIL
Removes ();:<>,”
$san_email = filter_var($string, FILTER_SANITIZE_EMAIL);
FILTER_SANITIZE_URL
Only allows a-zA-Z0-9`~!@#$%^&*()-_=+[{]};:'"<,>.?/|
$san_url = filter_var($string, FILTER_SANITIZE_URL);
FILTER_SANITIZE_NUMBER_INT
Only allows 1234567890-+
$san_int = filter_var($string, FILTER_SANITIZE_NUMBER_INT);
FILTER_SANITIZE_NUMBER_FLOAT
Only allows 1234567890-+.
$san_float = filter_var($string, FILTER_SANITIZE_NUMBER_FLOAT);
FILTER_SANITIZE_MAGIC_QUOTES
Escapes '”, the same way magic quotes does.
$mquotes = filter_var($string, FILTER_SANITIZE_MAGIC_QUOTES);
Flags
Flags are additional options for filters. Most flags only work within a certain validate/sanitize mode.
FILTER_FLAG_ALLOW_OCTAL (*_INT filters only)
Allows octals for *_INT flags
$allow_octal = filter_var($int_octal, FILTER_SANITIZE_NUMBER_INT, FILTER_FLAG_ALLOW_OCTAL);
FILTER_FLAG_ALLOW_HEX (*_INT filters only)
Allows hex for *_INT flags
$allow_hex = filter_var($int_hex, FILTER_SANITIZE_NUMBER_INT, FILTER_FLAG_ALLOW_HEX);
FILTER_FLAG_STRIP_LOW
Strip all characters lower than 32 in ASCII
$strip_low = filter_var($string, FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW);
FILTER_FLAG_STRIP_HIGH
Strip all characters higher than 127 in ASCII
$strip_high = filter_var($string, FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_HIGH);
FILTER_FLAG_ENCODE_LOW
Encodes all characters lower than 32 in ASCII
$enc_low = filter_var($string, FILTER_SANITIZE_STRING, FILTER_FLAG_ENCODE_LOW);
FILTER_FLAG_ENCODE_HIGH
Encodes all characters higher than 127 in ASCII
$enc_high = filter_var($string, FILTER_SANITIZE_STRING, FILTER_FLAG_ENCODE_HIGH);
FILTER_FLAG_NO_ENCODE_QUOTES
Ignores encoding ' and “
$deq = filter_var($string, FILTER_SANITIZE_STRING, FILTER_FLAG_NO_ENCODE_QUOTES);
FILTER_FLAG_ALLOW_FRACTION (*_NUMBER_FLOAT filters only)
Only allows 1234567890-+.
$fract = filter_var($string, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION);
FILTER_FLAG_ALLOW_THOUSAND (*_NUMBER_FLOAT filters only)
Only allows 1234567890-+,
$thous = filter_var($string, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_THOUSAND);
FILTER_FLAG_ALLOW_SCIENTIFIC (*_NUMBER_FLOAT filters only)
Only allows eE1234567890-+
$scient = filter_var($string, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_SCIENTIFIC);
FILTER_FLAG_SCHEME_REQUIRED (VALIDATE_URL filter only)
Require that a URL scheme is present
$schemer = filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED);
if ($schemer !== false)
{
// valid
} else {
// invalid
}
FILTER_FLAG_HOST_REQUIRED (VALIDATE_URL filter only)
Require that a URL host is present
$hostr = filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_HOST_REQUIRED);
if ($hostr !== false)
{
// valid
} else {
// invalid
}
FILTER_FLAG_PATH_REQUIRED (VALIDATE_URL filter only)
Require that a URL path is present
$pathr = filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_PATH_REQUIRED);
if ($pathr !== false)
{
// valid
} else {
// invalid
}
FILTER_FLAG_QUERY_REQUIRED (VALIDATE_URL filter only)
Require that a URL query is present
$queryr = filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_QUERY_REQUIRED);
if ($queryr !== false)
{
// valid
} else {
// invalid
}
FILTER_FLAG_IPV4 (VALIDATE_IP filter only)
Require that the IP address be IPV4
$ipv4r = filter_var($ipaddr, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4);
if ($ipv4r !== false)
{
// valid
} else {
// invalid
}
FILTER_FLAG_IPV6 (VALIDATE_IP filter only)
Require that the IP address be IPV6
$ipv6r = filter_var($ipv6addr, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6);
if ($ipv6r !== false)
{
// valid
} else {
// invalid
}
FILTER_FLAG_NO_RES_RANGE (VALIDATE_IP filter only)
Require that the IP address not be in a reserved range
$iprr = filter_var($ipres, FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE);
if ($iprr !== false)
{
// valid
} else {
// invalid
}
FILTER_FLAG_NO_PRIV_RANGE (VALIDATE_IP filter only)
Require that the IP address not be in a private range
$ippr = filter_var($ipres, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE);
if ($ippr !== false)
{
// valid
} else {
// invalid
}
FILTER_NULL_ON_FAILURE
Returns null instead of empty when a validate or flag fails
$ippr = filter_var($ipres, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE, FILTER_NULL_ON_FAILURE);
ID | Name | Options | Flags | Description |
---|---|---|---|---|
FILTER_VALIDATE_BOOLEAN |
"boolean" | default |
FILTER_NULL_ON_FAILURE |
Returns If |
FILTER_VALIDATE_EMAIL |
"validate_email" | default |
Validates value as e-mail. | |
FILTER_VALIDATE_FLOAT |
"float" | default , decimal |
FILTER_FLAG_ALLOW_THOUSAND |
Validates value as float. |
FILTER_VALIDATE_INT |
"int" | default , min_range , max_range |
FILTER_FLAG_ALLOW_OCTAL , FILTER_FLAG_ALLOW_HEX |
Validates value as integer, optionally from the specified range. |
FILTER_VALIDATE_IP |
"validate_ip" | default |
FILTER_FLAG_IPV4 , FILTER_FLAG_IPV6 , FILTER_FLAG_NO_PRIV_RANGE , FILTER_FLAG_NO_RES_RANGE |
Validates value as IP address, optionally only IPv4 or IPv6 or not from private or reserved ranges. |
FILTER_VALIDATE_REGEXP |
"validate_regexp" | default , regexp |
Validates value against regexp , a Perl-compatible regular expression. |
|
FILTER_VALIDATE_URL |
"validate_url" | default |
FILTER_FLAG_PATH_REQUIRED , FILTER_FLAG_QUERY_REQUIRED |
Validates value as URL (according to » http://www.faqs.org/rfcs/rfc2396), optionally with required components. Beware a valid URL may not specify the HTTP protocol
|
ID | Name | Options | Flags | Description |
---|---|---|---|---|
FILTER_SANITIZE_EMAIL |
"email" | Remove all characters except letters, digits and !#$%&'*+-/=?^_`{|}~@.[]. | ||
FILTER_SANITIZE_ENCODED |
"encoded" | FILTER_FLAG_STRIP_LOW , FILTER_FLAG_STRIP_HIGH , FILTER_FLAG_ENCODE_LOW , FILTER_FLAG_ENCODE_HIGH |
URL-encode string, optionally strip or encode special characters. | |
FILTER_SANITIZE_MAGIC_QUOTES |
"magic_quotes" | Apply addslashes(). | ||
FILTER_SANITIZE_NUMBER_FLOAT |
"number_float" | FILTER_FLAG_ALLOW_FRACTION , FILTER_FLAG_ALLOW_THOUSAND , FILTER_FLAG_ALLOW_SCIENTIFIC |
Remove all characters except digits, +- and optionally .,eE. | |
FILTER_SANITIZE_NUMBER_INT |
"number_int" | Remove all characters except digits, plus and minus sign. | ||
FILTER_SANITIZE_SPECIAL_CHARS |
"special_chars" | FILTER_FLAG_STRIP_LOW , FILTER_FLAG_STRIP_HIGH , FILTER_FLAG_ENCODE_HIGH |
HTML-escape '"<>& and characters with ASCII value less than 32, optionally strip or encode other special characters. | |
FILTER_SANITIZE_FULL_SPECIAL_CHARS |
"full_special_chars" | FILTER_FLAG_NO_ENCODE_QUOTES , |
Equivalent to calling htmlspecialchars() with ENT_QUOTES set. Encoding quotes can be disabled by setting FILTER_FLAG_NO_ENCODE_QUOTES . Like htmlspecialchars(), this filter is aware of the default_charset and if a sequence of bytes is detected that makes up an invalid character in the current character set then the entire string is rejected resulting in a 0-length string. When using this filter as a default filter, see the warning below about setting the default flags to 0. |
|
FILTER_SANITIZE_STRING |
"string" | FILTER_FLAG_NO_ENCODE_QUOTES , FILTER_FLAG_STRIP_LOW , FILTER_FLAG_STRIP_HIGH , FILTER_FLAG_ENCODE_LOW , FILTER_FLAG_ENCODE_HIGH , FILTER_FLAG_ENCODE_AMP |
Strip tags, optionally strip or encode special characters. | |
FILTER_SANITIZE_STRIPPED |
"stripped" | Alias of "string" filter. | ||
FILTER_SANITIZE_URL |
"url" | Remove all characters except letters, digits and $-_.+!*'(),{}|^~[]`<>#%";/?:@&=. | ||
FILTER_UNSAFE_RAW |
"unsafe_raw" | FILTER_FLAG_STRIP_LOW , FILTER_FLAG_STRIP_HIGH , FILTER_FLAG_ENCODE_LOW , FILTER_FLAG_ENCODE_HIGH , FILTER_FLAG_ENCODE_AMP |
Do nothing, optionally strip or encode special characters. This filter is also aliased to FILTER_DEFAULT . |
ID | Name | Options | Flags | Description |
---|---|---|---|---|
FILTER_CALLBACK |
"callback" | callable function or method | Call user-defined function to filter data. |
ID | Used with | Description |
---|---|---|
FILTER_FLAG_STRIP_LOW |
FILTER_SANITIZE_ENCODED , FILTER_SANITIZE_SPECIAL_CHARS , FILTER_SANITIZE_STRING , FILTER_UNSAFE_RAW |
Strips characters that has a numerical value <32. |
FILTER_FLAG_STRIP_HIGH |
FILTER_SANITIZE_ENCODED , FILTER_SANITIZE_SPECIAL_CHARS , FILTER_SANITIZE_STRING , FILTER_UNSAFE_RAW |
Strips characters that has a numerical value >127. |
FILTER_FLAG_ALLOW_FRACTION |
FILTER_SANITIZE_NUMBER_FLOAT |
Allows a period (.) as a fractional separator in numbers. |
FILTER_FLAG_ALLOW_THOUSAND |
FILTER_SANITIZE_NUMBER_FLOAT , FILTER_VALIDATE_FLOAT |
Allows a comma (,) as a thousands separator in numbers. |
FILTER_FLAG_ALLOW_SCIENTIFIC |
FILTER_SANITIZE_NUMBER_FLOAT |
Allows an e or E for scientific notation in numbers. |
FILTER_FLAG_NO_ENCODE_QUOTES |
FILTER_SANITIZE_STRING |
If this flag is present, single (') and double (") quotes will not be encoded. |
FILTER_FLAG_ENCODE_LOW |
FILTER_SANITIZE_ENCODED , FILTER_SANITIZE_STRING , FILTER_SANITIZE_RAW |
Encodes all characters with a numerical value <32. |
FILTER_FLAG_ENCODE_HIGH |
FILTER_SANITIZE_ENCODED , FILTER_SANITIZE_SPECIAL_CHARS , FILTER_SANITIZE_STRING , FILTER_SANITIZE_RAW |
Encodes all characters with a numerical value >127. |
FILTER_FLAG_ENCODE_AMP |
FILTER_SANITIZE_STRING , FILTER_SANITIZE_RAW |
Encodes ampersands (&). |
FILTER_NULL_ON_FAILURE |
FILTER_VALIDATE_BOOLEAN |
Returns NULL for unrecognized boolean values. |
FILTER_FLAG_ALLOW_OCTAL |
FILTER_VALIDATE_INT |
Regards inputs starting with a zero (0) as octal numbers. This only allows the succeeding digits to be 0-7. |
FILTER_FLAG_ALLOW_HEX |
FILTER_VALIDATE_INT |
Regards inputs starting with 0x or 0X as hexadecimal numbers. This only allows succeeding characters to be a-fA-F0-9. |
FILTER_FLAG_IPV4 |
FILTER_VALIDATE_IP |
Allows the IP address to be in IPv4 format. |
FILTER_FLAG_IPV6 |
FILTER_VALIDATE_IP |
Allows the IP address to be in IPv6 format. |
FILTER_FLAG_NO_PRIV_RANGE |
FILTER_VALIDATE_IP |
Fails validation for the following private IPv4 ranges: 10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16. Fails validation for the IPv6 addresses starting with FD or FC. |
FILTER_FLAG_NO_RES_RANGE |
FILTER_VALIDATE_IP |
Fails validation for the following reserved IPv4 ranges: 0.0.0.0/8, 169.254.0.0/16, 192.0.2.0/24 and 224.0.0.0/4. This flag does not apply to IPv6 addresses. |
FILTER_FLAG_PATH_REQUIRED |
FILTER_VALIDATE_URL |
Requires the URL to contain a path part. |
FILTER_FLAG_QUERY_REQUIRED |
FILTER_VALIDATE_URL |
Requires the URL to contain a query string. |
Kaynak:
- www.php.net/manual/en/filter.constants.php
- devzone.zend.com/node/view/id/1113
- www.phpro.org/tutorials/Filtering-Data-with-PHP.html#1
- www.devolio.com/blog/archives/413-Data-Filtering-Using-PHPs-Filter-Functions-Part-one.html
- www.php-editors.com/php_manual/ref.filter.html