Filter


Filters - 图1

Overview

Sanitizing user input is a critical part of software development. Trusting or neglecting to sanitize user input could lead to unauthorized access to the content of your application, mainly user data, or even the server your application is hosted on.

Filters - 图2

Full image on XKCD

Sanitizing content can be achieved using the Phalcon\Filter and Phalcon\Filter\FilterFactory classes.

FilterFactory

This component creates a new locator with predefined filters attached to it. Each filter is lazy loaded for maximum performance. To instantiate the factory and retrieve the Phalcon\Filter with the preset sanitizers you need to call newInstance()

  1. <?php
  2. use Phalcon\Filter\FilterFactory;
  3. $factory = new FilterFactory();
  4. $locator = $factory->newInstance();

You can now use the locator wherever you need and sanitize content as per the needs of your application.

Filter

The Phalcon\Filter component implements a locator service and can be used as a stand alone component, without initializing the built-in filters.

  1. <?php
  2. use MyApp\Sanitizers\HelloSanitizer;
  3. use Phalcon\Filter;
  4. $services = [
  5. 'hello' => HelloSanitizer::class,
  6. ];
  7. $locator = new Filter($services);
  8. $text = $locator->hello('World');

The Phalcon\Di\FactoryDefault container already has a Phalcon\Filter object loaded with the predefined sanitizers. The component can be accessed using the filter name.

Built-in

Where appropriate, the sanitizers will cast the value to the type expected. For example the absint sanitizer will remove all non numeric characters from the input, cast the input to an integer and return its absolute value.

The following are the built-in filters provided by this component:

absint

  1. AbsInt( mixed $input ): int

Removes any non numeric characters, casts the value to integer and returns its absolute value. Internally it uses [filter_var] for the integer part, intval for casting and absint.

alnum

  1. Alnum( mixed $input ): string | array

Removes all characters that are not numbers or characters of the alphabet. It uses preg_replace which can also accept arrays of strings as the parameters.

alpha

  1. Alpha( mixed $input ): string | array

Removes all characters that are not characters of the alphabet. It uses preg_replace which can also accept arrays of strings as the parameters.

bool

  1. BoolVal( mixed $input ): bool

Casts the value to a boolean.

It also returns true if the value is:

  • true
  • on
  • yes
  • y
  • 1It also returns false if the value is:

  • false

  • off
  • no
  • n
  • 0

email

  1. Email( mixed $input ): string

Removes all characters except letters, digits and !#$%&*+-/=?^`{|}<a href=”https://docs.phalcon.io/cdn-cgi/l/email-protection“ class=”_cf_email“ data-cfemail=”7e003e50”>[email protected][]. Internally it uses filter_var.

float

  1. FloatVal( mixed $input ): float

Removes all characters except digits, dot, plus and minus sign and casts the value as a double. Internally it uses filter_var and (double).

int

  1. IntVal( mixed $input ): int

Remove all characters except digits, plus and minus sign abd casts the value as an integer. Internally it uses filter_var and (int).

lower

  1. Lower( mixed $input ): string

Converts all characters to lowercase. If the mbstring extension is loaded, it will use mb_convert_case to perform the transformation. As a fallback it uses the strtolower PHP function, with utf8_decode.

lowerFirst

  1. LowerFirst( mixed $input ): string

Converts the first character of the input to lower case. Internally it uses lcfirst.

regex

  1. Regex( mixed $input, mixed $pattern, mixed $replace ): string

Performs a regex replacement on the input using a pattern and the replace parameter. Internally it uses preg_replace.

remove

  1. Remove( mixed $input, mixed $remove ): string

Performs a replacement on the input, replacing the replace parameter with an empty string, effectively removing it. Internally it uses str_replace.

replace

  1. Replace( mixed $input, mixed $from, mixed $to ): string

Performs a replacement on the input based on the from and to passed parameters. Internally it uses str_replace.

special

  1. Special( mixed $input ): string

Escapes all HTML characters of the input, as well as '"<>& and characters with ASCII value less than 32. Internally it uses filter_var.

specialFull

  1. SpecialFull( mixed $input ): string

Converts all the special characters of the input to HTML entities (both double and single quotes). Internally it uses filter_var.

string

  1. StringVal( mixed $input ): string

Strip tags and encode HTML entities, including single and double quotes. Internally it uses filter_var.

striptags

  1. StripTags( mixed $input ): int

Removes all HTML and PHP tags from the input. Internally it uses strip_tags.

trim

  1. Trim( mixed $input ): string

Removes all leading and trailing whitespace from the input. Internally it uses trim.

upper

  1. Upper( mixed $input ): string

Converts all characters to uppercase. If the mbstring extension is loaded, it will use mb_convert_case to perform the transformation. As a fallback it uses the strtoupper PHP function, with utf8_decode.

upperFirst

  1. UpperFirst( mixed $input ): string

Converts the first character of the input to upper case. Internally it uses ucfirst.

upperWords

  1. UpperWords( mixed $input ): string

Converts into uppercase the first character of each word from the input. Internally it uses ucwords.

url

  1. Url( mixed $input ): string

Constants are available and can be used to define the type of sanitizing required:

  1. <?php
  2. const FILTER_ABSINT = 'absint';
  3. const FILTER_ALNUM = 'alnum';
  4. const FILTER_ALPHA = 'alpha';
  5. const FILTER_BOOL = 'bool';
  6. const FILTER_EMAIL = 'email';
  7. const FILTER_FLOAT = 'float';
  8. const FILTER_INT = 'int';
  9. const FILTER_LOWER = 'lower';
  10. const FILTER_LOWERFIRST = 'lowerFirst';
  11. const FILTER_REGEX = 'regex';
  12. const FILTER_REMOVE = 'remove';
  13. const FILTER_REPLACE = 'replace';
  14. const FILTER_SPECIAL = 'special';
  15. const FILTER_SPECIALFULL = 'specialFull';
  16. const FILTER_STRING = 'string';
  17. const FILTER_STRIPTAGS = 'striptags';
  18. const FILTER_TRIM = 'trim';
  19. const FILTER_UPPER = 'upper';
  20. const FILTER_UPPERFIRST = 'upperFirst';
  21. const FILTER_UPPERWORDS = 'upperWords';
  22. const FILTER_URL = 'url';

Sanitizing data

Sanitizing is the process which removes specific characters from a value, that are not required or desired by the user or application. By sanitizing input we ensure that application integrity will be intact.

  1. <?php
  2. use Phalcon\Filter\FilterFactory;
  3. $factory = new FilterFactory();
  4. $locator = $factory->newInstance();
  5. // '[email protected]'
  6. $locator->sanitize('some(one)@exa\mple.com', 'email');
  7. // 'hello'
  8. $locator->sanitize('hello<<', 'string');
  9. // '100019'
  10. $locator->sanitize('!100a019', 'int');
  11. // '100019.01'
  12. $locator->sanitize('!100a019.01a', 'float');

Controllers

You can access the Phalcon\Filter object from your controllers when accessing GET or POST input data (through the request object). The first parameter is the name of the variable to be obtained; the second is the sanitizer to be applied on it. The second parameter can also be an array with any number of sanitizers that you want to apply.

  1. <?php
  2. use Phalcon\Filter;
  3. use Phalcon\Http\Request;
  4. use Phalcon\Mvc\Controller;
  5. /**
  6. * Class ProductsController
  7. *
  8. * @property Request $request
  9. */
  10. class ProductsController extends Controller
  11. {
  12. public function saveAction()
  13. {
  14. if (true === $this->request->isPost()) {
  15. // Sanitizing price from input
  16. $price = $this->request->getPost('price', 'double');
  17. // Sanitizing email from input
  18. $email = $this->request->getPost(
  19. 'customerEmail',
  20. Filter::FILTER_EMAIL
  21. );
  22. }
  23. }
  24. }

Action Parameters

If you have used the Phalcon\Di\FactoryDefault as your DI container, the Phalcon\Filter is already registered for you with the default sanitizers. To access it we can use the name filter. If you do not use the Phalcon\Di\FactoryDefault container, you will need to set the service up in it, so that it can be accessible in your controllers.

We can sanitize values passed into controller actions as follows:

  1. <?php
  2. use Phalcon\Filter;
  3. use Phalcon\Mvc\Controller;
  4. /**
  5. * Class ProductsController
  6. *
  7. * @property Filter $filter
  8. */
  9. class ProductsController extends Controller
  10. {
  11. public function showAction($productId)
  12. {
  13. $productId = $this->filter->sanitize($productId, 'absint');
  14. }
  15. }

Filtering data

The Phalcon\Filter both filters and sanitizes data, depending on the sanitizers used. For instance the trim sanitizer will remove all leading and trailing whitespace, leaving the remaining input unchanged. The description of each sanitizer (see Built-in Sanitizers) can help you to understand and use the sanitizers according to your needs.

  1. <?php
  2. use Phalcon\Filter\FilterFactory;
  3. $factory = new FilterFactory();
  4. $locator = $factory->newInstance();
  5. // 'Hello'
  6. $locator->sanitize('<h1>Hello</h1>', 'striptags');
  7. // 'Hello'
  8. $locator->sanitize(' Hello ', 'trim');

Adding sanitizers

You can add your own sanitizers to Phalcon\Filter. The sanitizer can be an anonymous function when initializing the locator:

  1. <?php
  2. use Phalcon\Filter;
  3. $services = [
  4. 'md5' => function ($input) {
  5. return md5($input);
  6. },
  7. ];
  8. $locator = new Filter($services);
  9. $sanitized = $locator->sanitize($value, 'md5');

If you already have an instantiated filter locator object (for instance if you have used the Phalcon\Filter\FilterFactory and newInstance()), then you can simply add the custom filter:

  1. <?php
  2. use Phalcon\Filter\FilterFactory;
  3. $factory = new FilterFactory();
  4. $locator = $factory->newInstance();
  5. $locator->set(
  6. 'md5',
  7. function ($input) {
  8. return md5($input);
  9. }
  10. );
  11. $sanitized = $locator->sanitize($value, 'md5');

Or, if you prefer, you can implement the filter in a class:

  1. <?php
  2. use Phalcon\Filter\FilterFactory;
  3. class IPv4
  4. {
  5. public function __invoke($value)
  6. {
  7. return filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4);
  8. }
  9. }
  10. $factory = new FilterFactory();
  11. $locator = $factory->newInstance();
  12. $locator->set(
  13. 'ipv4',
  14. function () {
  15. return new Ipv4();
  16. }
  17. );
  18. // Sanitize with the 'ipv4' filter
  19. $filteredIp = $locator->sanitize('127.0.0.1', 'ipv4');

Combining Sanitizers

There are times where one sanitizer is not enough for your data. For instance a very common usage is the striptags and trim sanitizers for text input. The Phalcon\Filter component offers the ability to accept an array of names for sanitizers to be applied on the input value. The following example demonstrates this:

  1. <?php
  2. use Phalcon\Filter\FilterFactory;
  3. $factory = new FilterFactory();
  4. $locator = $factory->newInstance();
  5. // Returns 'Hello'
  6. $locator->sanitize(
  7. ' <h1> Hello </h1> ',
  8. [
  9. 'striptags',
  10. 'trim',
  11. ]
  12. );

Note that this feature also works on the Phalcon\Http\Request object, when calling methods to retrieve data from GET and POST, namely getQuery() and getPost().

  1. <?php
  2. use Phalcon\Filter;
  3. use Phalcon\Http\Request;
  4. use Phalcon\Mvc\Controller;
  5. /**
  6. * Class ProductsController
  7. *
  8. * @property Request $request
  9. */
  10. class ProductsController extends Controller
  11. {
  12. public function saveAction()
  13. {
  14. if (true === $this->request->isPost()) {
  15. $message = $this->request->getPost(
  16. ' <h1> Hello </h1> ',
  17. [
  18. 'striptags',
  19. 'trim',
  20. ]
  21. );
  22. }
  23. }
  24. }

Custom Sanitizer

A custom sanitizer can be implemented as as an anonymous function. If however you prefer to use a class per sanitizer, all you need to do is make it a callable by implementing the __invoke method with the relevant parameters.

  1. <?php
  2. use Phalcon\Filter\FilterFactory;
  3. $factory = new FilterFactory();
  4. $locator = $factory->newInstance();
  5. $locator->set(
  6. 'md5',
  7. function ($input) {
  8. return md5($input);
  9. }
  10. );
  11. $sanitized = $locator->sanitize($value, 'md5');

Or, if you prefer, you can implement the sanitizer in a class:

  1. <?php
  2. use Phalcon\Filter\FilterFactory;
  3. class IPv4
  4. {
  5. public function __invoke($value)
  6. {
  7. return filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4);
  8. }
  9. }
  10. $factory = new FilterFactory();
  11. $locator = $factory->newInstance();
  12. $locator->set(
  13. 'ipv4',
  14. function () {
  15. return new Ipv4();
  16. }
  17. );
  18. // Sanitize with the 'ipv4' filter
  19. $filteredIp = $locator->sanitize('127.0.0.1', 'ipv4');