Source for file XSSFilter.class.php

Documentation is available at XSSFilter.class.php

  1. <?php
  2. /**
  3.  * Simple configurable data filter.
  4.  * Note that it is not perfect but should provide a good starting point for
  5.  * filtering input.
  6.  *
  7.  * LICENSE: LGPLv3+
  8.  *
  9.  * Example:
  10.  * <code>
  11.  * // The params for XSSFilter are: remove_html, remove_javascript,
  12.  * //     escape_html, urlencode_html, extended_return
  13.  * // For more information on what each does see the code docs in the class
  14.  * 
  15.  * $f = new XSSFilter(True, True, False, True, True);
  16.  * $safer = $f->filter($_GET);
  17.  *
  18.  * $f = new XSSFilter(True, True, False, True, True);
  19.  * $result = $f->filter($input);
  20.  * if ($result->changes) {
  21.  *     print('Your input has been modified');
  22.  * }
  23.  * return $result->data;
  24.  * </code>
  25.  *
  26.  * @author Steve 'Ashcrow' Milner
  27.  * @author Lisa Lu
  28.  * @category security
  29.  * @license LGPLv3+
  30.  * @link http://bitbucket.org/ashcrow/php-xssfilter
  31.  * @package XSSFilter
  32.  * @version 1.0.1
  33.  */
  34.  
  35.  
  36. /**
  37.  * Array wrapper for safe arrays.
  38.  */
  39. class ExtendedResponseArray extends ArrayObject {
  40.  
  41.     /**
  42.      * Class variable noting if the data had been changed.
  43.      * @var bool 
  44.      */
  45.     private $changes;
  46.  
  47.     /**
  48.      * Extended response of filtered array data.
  49.      * @param data array input array which is already safe.
  50.      * @param changes bool if changes had to be made.
  51.      */
  52.     function __construct(Array $data$changes)
  53.     {
  54.         $this->changes $changes;
  55.         foreach($data as $key => $value{
  56.             $this->offsetSet($key$value);
  57.         }
  58.     }
  59.  
  60.     /**
  61.      * Converts the instance to a String.
  62.      */
  63.     function __toString()
  64.     {
  65.         return 'Array';
  66.     }
  67.  
  68.     /**
  69.      * Used to return data requested.
  70.      * @param property string requested attribute.
  71.      */
  72.     function __get($property)
  73.     {
  74.         if ($property == 'changes'{
  75.             return $this->changes;
  76.         elseif ($property == 'data'{
  77.             return $this->getArrayCopy();
  78.         }
  79.     }
  80. }
  81.  
  82.  
  83. /**
  84.  * String wrapper for safer strings.
  85.  */
  86.  
  87.     /**
  88.      * Class variable noting if the data had been changed.
  89.      * @var bool 
  90.      */
  91.     private $changes;
  92.     /**
  93.      * Class variable holding the data directly.
  94.      * @var string 
  95.      */
  96.     private $data;
  97.  
  98.     /**
  99.      * Extended response of filtered string data.
  100.      * @param string data input array which is already safe.
  101.      * @param bool change if changes had to be made.
  102.      */
  103.     function __construct($data$changes)
  104.     {
  105.         $this->data $data;
  106.         $this->changes $changes;
  107.     }
  108.  
  109.     /**
  110.      * Converts instance to a String.
  111.      * @return string 
  112.      */
  113.     function __toString()
  114.     {
  115.         return (string) $this->data;
  116.     }
  117.  
  118.     /**
  119.      * Used to return data requested.
  120.      * @param string property requested attribute.
  121.      * @return string 
  122.      */
  123.     function __get($property)
  124.     {
  125.         if ($property == 'changes'{
  126.             return $this->changes;
  127.         elseif ($property == 'data'{
  128.             return $this->__toString();
  129.         }
  130.     }
  131. }
  132.  
  133.  
  134. /**
  135.  * Configurable XSSFilter for use by developers.
  136.  */
  137. class XSSFilter {
  138.  
  139.     /**
  140.      * Class variable noting if html should be removed.
  141.      * @var bool 
  142.      */
  143.     public $remove_html;
  144.     /**
  145.      * Class variable noting if javascript should be removed.
  146.      * @var bool 
  147.      */
  148.     public $remove_javascript;
  149.     /**
  150.      * Class variable noting if html should be escaped.
  151.      * @var bool 
  152.      */
  153.     public $escape_html;
  154.     /**
  155.      * Class variable noting if html should be urlencoded.
  156.      * @var bool 
  157.      */
  158.     public $urlencode_html;
  159.     /**
  160.      * Class variable noting if the return value should be a structure
  161.      * which includes the scrubbed data and a boolean noting if the data
  162.      * was modified or not.
  163.      * A return of False means no changes, True means changes.
  164.      * @var bool 
  165.      */
  166.     public $extended_return;
  167.  
  168.  
  169.     /**
  170.      * A filter object that attempts to strip out evil data.
  171.      * @param bool remove_html if html should be removed.
  172.      * @param bool remove_javascript if javascript should be removed.
  173.      * @param bool escape_html if html should be escaped.
  174.      * @param bool urlencode_html if html should be urlencoded.
  175.      * @param bool extended_return if an extended object should be used.
  176.      */
  177.     function __construct($remove_html=False$remove_javascript=False,
  178.         $escape_html=True$urlencode_html=False$extended_return=False{
  179.         $this->remove_html = $remove_html;
  180.         $this->remove_javascript = $remove_javascript;
  181.         $this->escape_html = $escape_html;
  182.         $this->urlencode_html = $urlencode_html;
  183.         $this->extended_return = $extended_return;
  184.     }
  185.  
  186.     /**
  187.      * Forward method for filtering input.
  188.      * @param string data the data to filter.
  189.      */
  190.     function filter($data{
  191.         if (is_array($data)) {
  192.             return $this->filter_array($data);
  193.         }
  194.         return $this->filter_string($data);
  195.     }
  196.  
  197.     /**
  198.      * Filters a single input item
  199.      * @param string data the data to filter.
  200.      * @return string a safer string.
  201.      */
  202.     function filter_string($data{
  203.         $original_data $data;
  204.         if ($this->remove_javascript{
  205.             $data preg_replace(
  206.                 "@<script[^>]*?>.*?</script[^>]*?>@si"""$data);
  207.         }
  208.         if ($this->remove_html{
  209.             // The regex should catch it all, but can't hurt to double check it
  210.             $data strip_tags(preg_replace(
  211.                 "@<.*[^>]*?>.*?</.*>@si"""$data));
  212.         }
  213.         if ($this->escape_html{
  214.             $data htmlspecialchars($data);
  215.         }
  216.         if ($this->urlencode_html{
  217.             $data urlencode($data);
  218.         }
  219.         if ($this->extended_return{
  220.             return new ExtendedResponseString(
  221.                 $data$original_data != $data True False);
  222.         }
  223.         return $data;
  224.     }
  225.  
  226.     /**
  227.      * Filters a single level array.
  228.      * @param array data the data filled array to filter.
  229.      * @return array a safer array.
  230.      */
  231.     function filter_array($data{
  232.         $safe array();
  233.         $changes False;
  234.         foreach ($data as $key => $value{
  235.             $result $this->filter($value);
  236.             if ($this->extended_return{
  237.                 $safe[$key$result->data;
  238.                 $result->changes and $changes True;
  239.             else {
  240.                 $safe[$key$result;
  241.             }
  242.         }
  243.         if ($this->extended_return{
  244.             return new ExtendedResponseArray($safe$changes);
  245.         }
  246.         return $safe;
  247.     }
  248. }
  249. ?>

Documentation generated on Mon, 01 Nov 2010 10:59:03 -0400 by phpDocumentor 1.4.3