Exemplo n.º 1
0
 /**
  * _filter_xss_attributes private method
  * @param  string $attr attributes string
  * @return array        filtered attributes array
  */
 private static function _filter_xss_attributes($attr)
 {
     $attrarr = array();
     $mode = 0;
     $attrname = '';
     while (strlen($attr) != 0) {
         // Was the last operation successful?
         $working = 0;
         switch ($mode) {
             case 0:
                 // Attribute name, href for instance.
                 if (preg_match('/^([-a-zA-Z]+)/', $attr, $match)) {
                     $attrname = strtolower($match[1]);
                     $skip = $attrname == 'style' || substr($attrname, 0, 2) == 'on';
                     $working = $mode = 1;
                     $attr = preg_replace('/^[-a-zA-Z]+/', '', $attr);
                 }
                 break;
             case 1:
                 // Equals sign or valueless ("selected").
                 if (preg_match('/^\\s*=\\s*/', $attr)) {
                     $working = 1;
                     $mode = 2;
                     $attr = preg_replace('/^\\s*=\\s*/', '', $attr);
                     break;
                 }
                 if (preg_match('/^\\s+/', $attr)) {
                     $working = 1;
                     $mode = 0;
                     if (!$skip) {
                         $attrarr[] = $attrname;
                     }
                     $attr = preg_replace('/^\\s+/', '', $attr);
                 }
                 break;
             case 2:
                 // Attribute value, a URL after href= for instance.
                 if (preg_match('/^"([^"]*)"(\\s+|$)/', $attr, $match)) {
                     $thisval = cs_form::_filter_xss_bad_protocol($match[1]);
                     if (!$skip) {
                         $attrarr[] = "{$attrname}=\"{$thisval}\"";
                     }
                     $working = 1;
                     $mode = 0;
                     $attr = preg_replace('/^"[^"]*"(\\s+|$)/', '', $attr);
                     break;
                 }
                 if (preg_match("/^'([^']*)'(\\s+|\$)/", $attr, $match)) {
                     $thisval = cs_form::_filter_xss_bad_protocol($match[1]);
                     if (!$skip) {
                         $attrarr[] = "{$attrname}='{$thisval}'";
                     }
                     $working = 1;
                     $mode = 0;
                     $attr = preg_replace("/^'[^']*'(\\s+|\$)/", '', $attr);
                     break;
                 }
                 if (preg_match("%^([^\\s\"']+)(\\s+|\$)%", $attr, $match)) {
                     $thisval = cs_form::_filter_xss_bad_protocol($match[1]);
                     if (!$skip) {
                         $attrarr[] = "{$attrname}=\"{$thisval}\"";
                     }
                     $working = 1;
                     $mode = 0;
                     $attr = preg_replace("%^[^\\s\"']+(\\s+|\$)%", '', $attr);
                 }
                 break;
         }
         if ($working == 0) {
             // Not well formed; remove and try again.
             $attr = preg_replace('/
       ^
       (
       "[^"]*("|$)     # - a string that starts with a double quote, up until the next double quote or the end of the string
       |               # or
       \'[^\']*(\'|$)| # - a string that starts with a quote, up until the next quote or the end of the string
       |               # or
       \\S              # - a non-whitespace character
       )*              # any number of the above three
       \\s*             # any number of whitespaces
       /x', '', $attr);
             $mode = 0;
         }
     }
     // The attribute list ends with a valueless attribute like "selected".
     if ($mode == 1 && !$skip) {
         $attrarr[] = $attrname;
     }
     return $attrarr;
 }