/** @class: InputFilter; * @project: Filter User Input Source; * @date: 18-03-2005; * @version: 1.1.1_php5; * @author: Daniel Morris; * @copyright: Daniel Morris; * @email: dan@rootcube.com; * @license: GNU General Public License (GPL); */ class InputFilter { // class config vars private $tagsArray; // required private $attrArray; // default = empty array private $tagsMethod; // default = 0 private $attrMethod; // default = 0
/** * Constructor for inputFilter class. Only first parameter is required. * @access constructor * @param Array $tagsArray - list of user-defined tags * @param Array $attrArray - list of user-defined attributes * @param int $tagsMethod - 0= allow just user-defined, 1= allow all but user-defined * @param int $attrMethod - 0= allow just user-defined, 1= allow all but user-defined */ public function __construct($tagsArray, $attrArray = array(), $tagsMethod = 0, $attrMethod = 0) { $this->tagsArray = $tagsArray; $this->attrArray = $attrArray; $this->tagsMethod = $tagsMethod; $this->attrMethod = $attrMethod; }
/** * Method to be called by another php script. * @access public * @param Mixed $source - input string/array-of-string to be 'cleaned' * @return String $source - 'cleaned' version of input parameter */ public function process($source) { if (is_array($source)) { // clean all elements in this array for ($i = 0; $i < count($source); $i++) if (is_string($source[$i])) $source[$i] = $this->remove($source[$i]); return $source; } else if (is_string($source)) return $this->remove($source); // clean this string else return $source; // return parameter as given }
/** * Internal method to iteratively remove all unwanted tags and attributes * @access private * @param String $source - input string to be 'cleaned' * @return String $source - 'cleaned' version of input parameter */ private function remove($source) { $loopCounter=0; // provides nested-tag protection while($source != $this->filterTags($source)) { $source = $this->filterTags($source); $loopCounter++; } return $source; } /** * Internal method to strip a string of certain tags * @access private * @param String $source - input string to be 'cleaned' * @return String $source - 'cleaned' version of input parameter */ private function filterTags($source) { // filter pass setup $preTag = NULL; $postTag = $source; // find initial tag's position $tagOpen_start = strpos($source, '<'); // interate through string until no tags left while($tagOpen_start !== FALSE) { // tag setup $fromTagOpen = substr($postTag, $tagOpen_start); $tagOpen_end = strpos($fromTagOpen, '>'); $tagOpen_nested = (strpos(substr($fromTagOpen, 1), '<')+1); $tagOpen_length = $tagOpen_end - 1; $currentTag = substr($fromTagOpen, 1, $tagOpen_length); // iterate through tag finding attribute pairs - setup $tagLeft = $currentTag; $attrSet = array(); $currentSpace = strpos($tagLeft, ' '); // is end tag if (substr($currentTag, 0, 1) == "/") { $isCloseTag = TRUE; list($tagName) = explode(' ', $currentTag); $tagName = substr($tagName, 1); // is start tag } else { $isCloseTag = FALSE; list($tagName) = explode(' ', $currentTag); }
// this while is needed to support attribute values with spaces in! while ($currentSpace !== FALSE) { $fromSpace = substr($tagLeft, ($currentSpace+1)); $nextSpace = strpos($fromSpace, ' '); $openQuotes = strpos($fromSpace, '"'); $closeQuotes = strpos(substr($fromSpace, ($openQuotes+1)), '"') + $openQuotes + 1; // another equals exists if (strpos($fromSpace, '=') !== FALSE) { // opening and closing quotes exists if (($openQuotes !== FALSE) && (strpos(substr($fromSpace, ($openQuotes+1)), '"') !== FALSE)) $attr = substr($fromSpace, 0, ($closeQuotes+1)); // one or neither exist else $attr = substr($fromSpace, 0, $nextSpace); // no more equals exist } else $attr = substr($fromSpace, 0, $nextSpace); // last attr pair if (!$attr) $attr = $fromSpace; // add to attribute pairs array $attrSet[] = $attr; // next inc $tagLeft = substr($fromSpace, strlen($attr)); $currentSpace = strpos($tagLeft, ' '); } // deals with nexted tags if (($tagOpen_nested < $tagOpen_end) && ($fromTagOpen[$tagOpen_nested] == '<')) { $preTag .= substr($postTag, 0, ($tagOpen_start + ($tagOpen_end - $tagOpen_nested) - 1)); $postTag = substr($fromTagOpen, $tagOpen_nested); $tagOpen_start = strpos($postTag, '<'); continue; // doesn't contain nested tag } else $preTag .= substr($postTag, 0, $tagOpen_start); // appears in array specified by user $tagFound = in_array(strtolower($tagName), $this->tagsArray); // remove this tag on condition if ((!$tagFound && $this->tagsMethod) || ($tagFound && !$this->tagsMethod)) { // reconstruct tag with allowed attributes if (!$isCloseTag) { $attrSet = $this->filterAttr($attrSet); $preTag .= '<' . $tagName; for ($i = 0; $i < count($attrSet); $i++) $preTag .= ' ' . $attrSet[$i]; // reformat single tags to XHTML if (strpos($fromTagOpen, "</" . $tagName)) $preTag .= '>'; else $preTag .= ' />'; // just the tagname } else $preTag .= '</' . $tagName . '>'; } // find next tag's start $postTag = substr($postTag, ($tagOpen_start + $tagOpen_length + 2)); $tagOpen_start = strpos($postTag, '<'); } // append any code after end of tags $preTag .= $postTag; return $preTag; }
/** * Internal method to strip a tag of certain attributes * @access private * @param Array $attrSet * @return Array $newSet */ private function filterAttr($attrSet) { $newSet = array(); // has attributes for ($i = 0; $i <count($attrSet); $i++) { $attrSubSet = explode('=', $attrSet[$i]); list($attrSubSet[0]) = explode(' ', $attrSubSet[0]); $attrFound = in_array(strtolower($attrSubSet[0]), $this->attrArray); // keep this attr on condition if ((!$attrFound && $this->attrMethod) || ($attrFound && !$this->attrMethod)) { // attr has value if ($attrSubSet[1]) $newSet[] = $attrSubSet[0] . '=' . $attrSubSet[1]; // reformat single attributes to XHTML else $newSet[] = $attrSubSet[0] . '="' . $attrSubSet[0] . '"'; } } return $newSet; } }