{ $thisval = $match[1]; if ( in_array(strtolower($attrname), $uris) ) $thisval = wp_kses_bad_protocol($thisval, $allowed_protocols); if(false === array_key_exists($attrname, $attrarr)) { $attrarr[$attrname] = array ('name' => $attrname, 'value' => $thisval, 'whole' => "$attrname='$thisval'", 'vless' => 'n'); } $working = 1; $mode = 0; $attr = preg_replace("/^'[^']*'(\s+|$)/", '', $attr); break; } if (preg_match("%^([^\s\"']+)(\s+|/?$)%", $attr, $match)) // value { $thisval = $match[1]; if ( in_array(strtolower($attrname), $uris) ) $thisval = wp_kses_bad_protocol($thisval, $allowed_protocols); if(false === array_key_exists($attrname, $attrarr)) { $attrarr[$attrname] = array ('name' => $attrname, 'value' => $thisval, 'whole' => "$attrname=\"$thisval\"", 'vless' => 'n'); } // We add quotes to conform to W3C's HTML spec. $working = 1; $mode = 0; $attr = preg_replace("%^[^\s\"']+(\s+|$)%", '', $attr); } break; } // switch if ($working == 0) // not well formed, remove and try again { $attr = wp_kses_html_error($attr); $mode = 0; } } // while if ($mode == 1 && false === array_key_exists($attrname, $attrarr)) // special case, for when the attribute list ends with a valueless // attribute like "selected" $attrarr[$attrname] = array ('name' => $attrname, 'value' => '', 'whole' => $attrname, 'vless' => 'y'); return $attrarr; } /** * Finds all attributes of an HTML element. * * Does not modify input. May return "evil" output. * * Based on wp_kses_split2() and wp_kses_attr() * * @since 4.2.3 * * @param string $element HTML element/tag * @return array|bool List of attributes found in $element. Returns false on failure. */ function wp_kses_attr_parse( $element ) { $valid = preg_match('%^(<\s*)(/\s*)?([a-zA-Z0-9]+\s*)([^>]*)(>?)$%', $element, $matches); if ( 1 !== $valid ) { return false; } $begin = $matches[1]; $slash = $matches[2]; $elname = $matches[3]; $attr = $matches[4]; $end = $matches[5]; if ( '' !== $slash ) { // Closing elements do not get parsed. return false; } // Is there a closing XHTML slash at the end of the attributes? if ( 1 === preg_match( '%\s*/\s*$%', $attr, $matches ) ) { $xhtml_slash = $matches[0]; $attr = substr( $attr, 0, -strlen( $xhtml_slash ) ); } else { $xhtml_slash = ''; } // Split it $attrarr = wp_kses_hair_parse( $attr ); if ( false === $attrarr ) { return false; } // Make sure all input is returned by adding front and back matter. array_unshift( $attrarr, $begin . $slash . $elname ); array_push( $attrarr, $xhtml_slash . $end ); return $attrarr; } /** * Builds an attribute list from string containing attributes. * * Does not modify input. May return "evil" output. * In case of unexpected input, returns false instead of stripping things. * * Based on wp_kses_hair() but does not return a multi-dimensional array. * * @since 4.2.3 * * @param string $attr Attribute list from HTML element to closing HTML element tag * @return array|bool List of attributes found in $attr. Returns false on failure. */ function wp_kses_hair_parse( $attr ) { if ( '' === $attr ) { return array(); } $regex = '(?:' . '[-a-zA-Z:]+' // Attribute name. . '|' . '\[\[?[^\[\]]+\]\]?' // Shortcode in the name position implies unfiltered_html. . ')' . '(?:' // Attribute value. . '\s*=\s*' // All values begin with '=' . '(?:' . '"[^"]*"' // Double-quoted . '|' . "'[^']*'" // Single-quoted . '|' . '[^\s"\']+' // Non-quoted . '(?:\s|$)' // Must have a space . ')' . '|' . '(?:\s|$)' // If attribute has no value, space is required. . ')' . '\s*'; // Trailing space is optional except as mentioned above. // Although it is possible to reduce this procedure to a single regexp, // we must run that regexp twice to get exactly the expected result. $validation = "%^($regex)+$%"; $extraction = "%$regex%"; if ( 1 === preg_match( $validation, $attr ) ) { preg_match_all( $extraction, $attr, $attrarr ); return $attrarr[0]; } else { return false; } } /** * Performs different checks for attribute values. * * The currently implemented checks are "maxlen", "minlen", "maxval", "minval" * and "valueless". * * @since 1.0.0 * * @param string $value Attribute value * @param string $vless Whether the value is valueless. Use 'y' or 'n' * @param string $checkname What $checkvalue is checking for. * @param mixed $checkvalue What constraint the value should pass * @return bool Whether check passes */ function wp_kses_check_attr_val($value, $vless, $checkname, $checkvalue) { $ok = true; switch (strtolower($checkname)) { case 'maxlen' : // The maxlen check makes sure that the attribute value has a length not // greater than the given value. This can be used to avoid Buffer Overflows // in WWW clients and various Internet servers. if (strlen($value) > $checkvalue) $ok = false; break; case 'minlen' : // The minlen check makes sure that the attribute value has a length not // smaller than the given value. if (strlen($value) < $checkvalue) $ok = false; break; case 'maxval' : // The maxval check does two things: it checks that the attribute value is // an integer from 0 and up, without an excessive amount of zeroes or // whitespace (to avoid Buffer Overflows). It also checks that the attribute // value is not greater than the given value. // This check can be used to avoid Denial of Service attacks. if (!preg_match('/^\s{0,6}[0-9]{1,6}\s{0,6}$/', $value)) $ok = false; if ($value > $checkvalue) $ok = false; break; case 'minval' : // The minval check makes sure that the attribute value is a positive integer, // and that it is not smaller than the given value. if (!preg_match('/^\s{0,6}[0-9]{1,6}\s{0,6}$/', $value)) $ok = false; if ($value < $checkvalue) $ok = false; break; case 'valueless' : // The valueless check makes sure if the attribute has a value // (like ) or not (