function _filter_xss_attributes

Processes a string of HTML attributes.

Return value

Cleaned up version of the HTML attributes.

Related topics

1 call to _filter_xss_attributes()
_filter_xss_split in includes/common.inc
Processes an HTML tag.

File

includes/common.inc, line 1651

Code

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' || substr($attrname, 0, 1) == '-' || strlen($attrname) > 96;
                    $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 = 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 = 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 = 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;
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.