raw
mp-wp_genesis           1 <?php
mp-wp_genesis 2 /**
mp-wp_genesis 3 * HTML/XHTML filter that only allows some elements and attributes
mp-wp_genesis 4 *
mp-wp_genesis 5 * Added wp_ prefix to avoid conflicts with existing kses users
mp-wp_genesis 6 *
mp-wp_genesis 7 * @version 0.2.2
mp-wp_genesis 8 * @copyright (C) 2002, 2003, 2005
mp-wp_genesis 9 * @author Ulf Harnhammar <metaur@users.sourceforge.net>
mp-wp_genesis 10 *
mp-wp_genesis 11 * @package External
mp-wp_genesis 12 * @subpackage KSES
mp-wp_genesis 13 *
mp-wp_genesis 14 * @internal
mp-wp_genesis 15 * *** CONTACT INFORMATION ***
mp-wp_genesis 16 * E-mail: metaur at users dot sourceforge dot net
mp-wp_genesis 17 * Web page: http://sourceforge.net/projects/kses
mp-wp_genesis 18 * Paper mail: Ulf Harnhammar
mp-wp_genesis 19 * Ymergatan 17 C
mp-wp_genesis 20 * 753 25 Uppsala
mp-wp_genesis 21 * SWEDEN
mp-wp_genesis 22 *
mp-wp_genesis 23 * [kses strips evil scripts!]
mp-wp_genesis 24 */
mp-wp_genesis 25
mp-wp_genesis 26 /**
mp-wp_genesis 27 * You can override this in your my-hacks.php file You can also override this
mp-wp_genesis 28 * in a plugin file. The my-hacks.php is deprecated in its usage.
mp-wp_genesis 29 *
mp-wp_genesis 30 * @since 1.2.0
mp-wp_genesis 31 */
mp-wp_genesis 32 if (!defined('CUSTOM_TAGS'))
mp-wp_genesis 33 define('CUSTOM_TAGS', false);
mp-wp_genesis 34
mp-wp_genesis 35 if (!CUSTOM_TAGS) {
mp-wp_genesis 36 /**
mp-wp_genesis 37 * Kses global for default allowable HTML tags.
mp-wp_genesis 38 *
mp-wp_genesis 39 * Can be override by using CUSTOM_TAGS constant.
mp-wp_genesis 40 *
mp-wp_genesis 41 * @global array $allowedposttags
mp-wp_genesis 42 * @since 2.0.0
mp-wp_genesis 43 */
mp-wp_genesis 44 $allowedposttags = array(
mp-wp_genesis 45 'address' => array(),
mp-wp_genesis 46 'a' => array(
mp-wp_genesis 47 'class' => array (),
mp-wp_genesis 48 'href' => array (),
mp-wp_genesis 49 'id' => array (),
mp-wp_genesis 50 'title' => array (),
mp-wp_genesis 51 'rel' => array (),
mp-wp_genesis 52 'rev' => array (),
mp-wp_genesis 53 'name' => array (),
mp-wp_genesis 54 'target' => array()),
mp-wp_genesis 55 'abbr' => array(
mp-wp_genesis 56 'class' => array (),
mp-wp_genesis 57 'title' => array ()),
mp-wp_genesis 58 'acronym' => array(
mp-wp_genesis 59 'title' => array ()),
mp-wp_genesis 60 'b' => array(),
mp-wp_genesis 61 'big' => array(),
mp-wp_genesis 62 'blockquote' => array(
mp-wp_genesis 63 'id' => array (),
mp-wp_genesis 64 'cite' => array (),
mp-wp_genesis 65 'class' => array(),
mp-wp_genesis 66 'lang' => array(),
mp-wp_genesis 67 'xml:lang' => array()),
mp-wp_genesis 68 'br' => array (
mp-wp_genesis 69 'class' => array ()),
mp-wp_genesis 70 'button' => array(
mp-wp_genesis 71 'disabled' => array (),
mp-wp_genesis 72 'name' => array (),
mp-wp_genesis 73 'type' => array (),
mp-wp_genesis 74 'value' => array ()),
mp-wp_genesis 75 'caption' => array(
mp-wp_genesis 76 'align' => array (),
mp-wp_genesis 77 'class' => array ()),
mp-wp_genesis 78 'cite' => array (
mp-wp_genesis 79 'class' => array(),
mp-wp_genesis 80 'dir' => array(),
mp-wp_genesis 81 'lang' => array(),
mp-wp_genesis 82 'title' => array ()),
mp-wp_genesis 83 'code' => array (
mp-wp_genesis 84 'style' => array()),
mp-wp_genesis 85 'col' => array(
mp-wp_genesis 86 'align' => array (),
mp-wp_genesis 87 'char' => array (),
mp-wp_genesis 88 'charoff' => array (),
mp-wp_genesis 89 'span' => array (),
mp-wp_genesis 90 'dir' => array(),
mp-wp_genesis 91 'style' => array (),
mp-wp_genesis 92 'valign' => array (),
mp-wp_genesis 93 'width' => array ()),
mp-wp_genesis 94 'del' => array(
mp-wp_genesis 95 'datetime' => array ()),
mp-wp_genesis 96 'dd' => array(),
mp-wp_genesis 97 'div' => array(
mp-wp_genesis 98 'align' => array (),
mp-wp_genesis 99 'class' => array (),
mp-wp_genesis 100 'dir' => array (),
mp-wp_genesis 101 'lang' => array(),
mp-wp_genesis 102 'style' => array (),
mp-wp_genesis 103 'xml:lang' => array()),
mp-wp_genesis 104 'dl' => array(),
mp-wp_genesis 105 'dt' => array(),
mp-wp_genesis 106 'em' => array(),
mp-wp_genesis 107 'fieldset' => array(),
mp-wp_genesis 108 'font' => array(
mp-wp_genesis 109 'color' => array (),
mp-wp_genesis 110 'face' => array (),
mp-wp_genesis 111 'size' => array ()),
mp-wp_genesis 112 'form' => array(
mp-wp_genesis 113 'action' => array (),
mp-wp_genesis 114 'accept' => array (),
mp-wp_genesis 115 'accept-charset' => array (),
mp-wp_genesis 116 'enctype' => array (),
mp-wp_genesis 117 'method' => array (),
mp-wp_genesis 118 'name' => array (),
mp-wp_genesis 119 'target' => array ()),
mp-wp_genesis 120 'h1' => array(
mp-wp_genesis 121 'align' => array (),
mp-wp_genesis 122 'class' => array ()),
mp-wp_genesis 123 'h2' => array(
mp-wp_genesis 124 'align' => array (),
mp-wp_genesis 125 'class' => array ()),
mp-wp_genesis 126 'h3' => array(
mp-wp_genesis 127 'align' => array (),
mp-wp_genesis 128 'class' => array ()),
mp-wp_genesis 129 'h4' => array(
mp-wp_genesis 130 'align' => array (),
mp-wp_genesis 131 'class' => array ()),
mp-wp_genesis 132 'h5' => array(
mp-wp_genesis 133 'align' => array (),
mp-wp_genesis 134 'class' => array ()),
mp-wp_genesis 135 'h6' => array(
mp-wp_genesis 136 'align' => array (),
mp-wp_genesis 137 'class' => array ()),
mp-wp_genesis 138 'hr' => array(
mp-wp_genesis 139 'align' => array (),
mp-wp_genesis 140 'class' => array (),
mp-wp_genesis 141 'noshade' => array (),
mp-wp_genesis 142 'size' => array (),
mp-wp_genesis 143 'width' => array ()),
mp-wp_genesis 144 'i' => array(),
mp-wp_genesis 145 'img' => array(
mp-wp_genesis 146 'alt' => array (),
mp-wp_genesis 147 'align' => array (),
mp-wp_genesis 148 'border' => array (),
mp-wp_genesis 149 'class' => array (),
mp-wp_genesis 150 'height' => array (),
mp-wp_genesis 151 'hspace' => array (),
mp-wp_genesis 152 'longdesc' => array (),
mp-wp_genesis 153 'vspace' => array (),
mp-wp_genesis 154 'src' => array (),
mp-wp_genesis 155 'style' => array (),
mp-wp_genesis 156 'width' => array ()),
mp-wp_genesis 157 'ins' => array(
mp-wp_genesis 158 'datetime' => array (),
mp-wp_genesis 159 'cite' => array ()),
mp-wp_genesis 160 'kbd' => array(),
mp-wp_genesis 161 'label' => array(
mp-wp_genesis 162 'for' => array ()),
mp-wp_genesis 163 'legend' => array(
mp-wp_genesis 164 'align' => array ()),
mp-wp_genesis 165 'li' => array (
mp-wp_genesis 166 'align' => array (),
mp-wp_genesis 167 'class' => array ()),
mp-wp_genesis 168 'p' => array(
mp-wp_genesis 169 'class' => array (),
mp-wp_genesis 170 'align' => array (),
mp-wp_genesis 171 'dir' => array(),
mp-wp_genesis 172 'lang' => array(),
mp-wp_genesis 173 'style' => array (),
mp-wp_genesis 174 'xml:lang' => array()),
mp-wp_genesis 175 'pre' => array(
mp-wp_genesis 176 'style' => array(),
mp-wp_genesis 177 'width' => array ()),
mp-wp_genesis 178 'q' => array(
mp-wp_genesis 179 'cite' => array ()),
mp-wp_genesis 180 's' => array(),
mp-wp_genesis 181 'span' => array (
mp-wp_genesis 182 'class' => array (),
mp-wp_genesis 183 'dir' => array (),
mp-wp_genesis 184 'align' => array (),
mp-wp_genesis 185 'lang' => array (),
mp-wp_genesis 186 'style' => array (),
mp-wp_genesis 187 'title' => array (),
mp-wp_genesis 188 'xml:lang' => array()),
mp-wp_genesis 189 'strike' => array(),
mp-wp_genesis 190 'strong' => array(),
mp-wp_genesis 191 'sub' => array(),
mp-wp_genesis 192 'sup' => array(),
mp-wp_genesis 193 'table' => array(
mp-wp_genesis 194 'align' => array (),
mp-wp_genesis 195 'bgcolor' => array (),
mp-wp_genesis 196 'border' => array (),
mp-wp_genesis 197 'cellpadding' => array (),
mp-wp_genesis 198 'cellspacing' => array (),
mp-wp_genesis 199 'class' => array (),
mp-wp_genesis 200 'dir' => array(),
mp-wp_genesis 201 'id' => array(),
mp-wp_genesis 202 'rules' => array (),
mp-wp_genesis 203 'style' => array (),
mp-wp_genesis 204 'summary' => array (),
mp-wp_genesis 205 'width' => array ()),
mp-wp_genesis 206 'tbody' => array(
mp-wp_genesis 207 'align' => array (),
mp-wp_genesis 208 'char' => array (),
mp-wp_genesis 209 'charoff' => array (),
mp-wp_genesis 210 'valign' => array ()),
mp-wp_genesis 211 'td' => array(
mp-wp_genesis 212 'abbr' => array (),
mp-wp_genesis 213 'align' => array (),
mp-wp_genesis 214 'axis' => array (),
mp-wp_genesis 215 'bgcolor' => array (),
mp-wp_genesis 216 'char' => array (),
mp-wp_genesis 217 'charoff' => array (),
mp-wp_genesis 218 'class' => array (),
mp-wp_genesis 219 'colspan' => array (),
mp-wp_genesis 220 'dir' => array(),
mp-wp_genesis 221 'headers' => array (),
mp-wp_genesis 222 'height' => array (),
mp-wp_genesis 223 'nowrap' => array (),
mp-wp_genesis 224 'rowspan' => array (),
mp-wp_genesis 225 'scope' => array (),
mp-wp_genesis 226 'style' => array (),
mp-wp_genesis 227 'valign' => array (),
mp-wp_genesis 228 'width' => array ()),
mp-wp_genesis 229 'textarea' => array(
mp-wp_genesis 230 'cols' => array (),
mp-wp_genesis 231 'rows' => array (),
mp-wp_genesis 232 'disabled' => array (),
mp-wp_genesis 233 'name' => array (),
mp-wp_genesis 234 'readonly' => array ()),
mp-wp_genesis 235 'tfoot' => array(
mp-wp_genesis 236 'align' => array (),
mp-wp_genesis 237 'char' => array (),
mp-wp_genesis 238 'class' => array (),
mp-wp_genesis 239 'charoff' => array (),
mp-wp_genesis 240 'valign' => array ()),
mp-wp_genesis 241 'th' => array(
mp-wp_genesis 242 'abbr' => array (),
mp-wp_genesis 243 'align' => array (),
mp-wp_genesis 244 'axis' => array (),
mp-wp_genesis 245 'bgcolor' => array (),
mp-wp_genesis 246 'char' => array (),
mp-wp_genesis 247 'charoff' => array (),
mp-wp_genesis 248 'class' => array (),
mp-wp_genesis 249 'colspan' => array (),
mp-wp_genesis 250 'headers' => array (),
mp-wp_genesis 251 'height' => array (),
mp-wp_genesis 252 'nowrap' => array (),
mp-wp_genesis 253 'rowspan' => array (),
mp-wp_genesis 254 'scope' => array (),
mp-wp_genesis 255 'valign' => array (),
mp-wp_genesis 256 'width' => array ()),
mp-wp_genesis 257 'thead' => array(
mp-wp_genesis 258 'align' => array (),
mp-wp_genesis 259 'char' => array (),
mp-wp_genesis 260 'charoff' => array (),
mp-wp_genesis 261 'class' => array (),
mp-wp_genesis 262 'valign' => array ()),
mp-wp_genesis 263 'title' => array(),
mp-wp_genesis 264 'tr' => array(
mp-wp_genesis 265 'align' => array (),
mp-wp_genesis 266 'bgcolor' => array (),
mp-wp_genesis 267 'char' => array (),
mp-wp_genesis 268 'charoff' => array (),
mp-wp_genesis 269 'class' => array (),
mp-wp_genesis 270 'style' => array (),
mp-wp_genesis 271 'valign' => array ()),
mp-wp_genesis 272 'tt' => array(),
mp-wp_genesis 273 'u' => array(),
mp-wp_genesis 274 'ul' => array (
mp-wp_genesis 275 'class' => array (),
mp-wp_genesis 276 'style' => array (),
mp-wp_genesis 277 'type' => array ()),
mp-wp_genesis 278 'ol' => array (
mp-wp_genesis 279 'class' => array (),
mp-wp_genesis 280 'start' => array (),
mp-wp_genesis 281 'style' => array (),
mp-wp_genesis 282 'type' => array ()),
mp-wp_genesis 283 'var' => array ());
mp-wp_genesis 284
mp-wp_genesis 285 /**
mp-wp_genesis 286 * Kses allowed HTML elements.
mp-wp_genesis 287 *
mp-wp_genesis 288 * @global array $allowedtags
mp-wp_genesis 289 * @since 1.0.0
mp-wp_genesis 290 */
mp-wp_genesis 291 $allowedtags = array(
mp-wp_genesis 292 'a' => array(
mp-wp_genesis 293 'href' => array (),
mp-wp_genesis 294 'title' => array ()),
mp-wp_genesis 295 'abbr' => array(
mp-wp_genesis 296 'title' => array ()),
mp-wp_genesis 297 'acronym' => array(
mp-wp_genesis 298 'title' => array ()),
mp-wp_genesis 299 'b' => array(),
mp-wp_genesis 300 'blockquote' => array(
mp-wp_genesis 301 'cite' => array ()),
mp-wp_genesis 302 // 'br' => array(),
mp-wp_genesis 303 'cite' => array (),
mp-wp_genesis 304 'code' => array(),
mp-wp_genesis 305 'del' => array(
mp-wp_genesis 306 'datetime' => array ()),
mp-wp_genesis 307 // 'dd' => array(),
mp-wp_genesis 308 // 'dl' => array(),
mp-wp_genesis 309 // 'dt' => array(),
mp-wp_genesis 310 'em' => array (), 'i' => array (),
mp-wp_genesis 311 // 'ins' => array('datetime' => array(), 'cite' => array()),
mp-wp_genesis 312 // 'li' => array(),
mp-wp_genesis 313 // 'ol' => array(),
mp-wp_genesis 314 // 'p' => array(),
mp-wp_genesis 315 'q' => array(
mp-wp_genesis 316 'cite' => array ()),
mp-wp_genesis 317 'strike' => array(),
mp-wp_genesis 318 'strong' => array(),
mp-wp_genesis 319 // 'sub' => array(),
mp-wp_genesis 320 // 'sup' => array(),
mp-wp_genesis 321 // 'u' => array(),
mp-wp_genesis 322 // 'ul' => array(),
mp-wp_genesis 323 );
mp-wp_genesis 324 }
mp-wp_genesis 325
mp-wp_genesis 326 /**
mp-wp_genesis 327 * Filters content and keeps only allowable HTML elements.
mp-wp_genesis 328 *
mp-wp_genesis 329 * This function makes sure that only the allowed HTML element names, attribute
mp-wp_genesis 330 * names and attribute values plus only sane HTML entities will occur in
mp-wp_genesis 331 * $string. You have to remove any slashes from PHP's magic quotes before you
mp-wp_genesis 332 * call this function.
mp-wp_genesis 333 *
mp-wp_genesis 334 * The default allowed protocols are 'http', 'https', 'ftp', 'mailto', 'news',
mp-wp_genesis 335 * 'irc', 'gopher', 'nntp', 'feed', and finally 'telnet. This covers all common
mp-wp_genesis 336 * link protocols, except for 'javascript' which should not be allowed for
mp-wp_genesis 337 * untrusted users.
mp-wp_genesis 338 *
mp-wp_genesis 339 * @since 1.0.0
mp-wp_genesis 340 *
mp-wp_genesis 341 * @param string $string Content to filter through kses
mp-wp_genesis 342 * @param array $allowed_html List of allowed HTML elements
mp-wp_genesis 343 * @param array $allowed_protocols Optional. Allowed protocol in links.
mp-wp_genesis 344 * @return string Filtered content with only allowed HTML elements
mp-wp_genesis 345 */
mp-wp_genesis 346 function wp_kses($string, $allowed_html, $allowed_protocols = array ('http', 'https', 'ftp', 'ftps', 'mailto', 'news', 'irc', 'gopher', 'nntp', 'feed', 'telnet')) {
mp-wp_genesis 347 $string = wp_kses_no_null($string);
mp-wp_genesis 348 $string = wp_kses_js_entities($string);
mp-wp_genesis 349 $string = wp_kses_normalize_entities($string);
mp-wp_genesis 350 $allowed_html_fixed = wp_kses_array_lc($allowed_html);
mp-wp_genesis 351 $string = wp_kses_hook($string, $allowed_html_fixed, $allowed_protocols); // WP changed the order of these funcs and added args to wp_kses_hook
mp-wp_genesis 352 return wp_kses_split($string, $allowed_html_fixed, $allowed_protocols);
mp-wp_genesis 353 }
mp-wp_genesis 354
mp-wp_genesis 355 /**
mp-wp_genesis 356 * You add any kses hooks here.
mp-wp_genesis 357 *
mp-wp_genesis 358 * There is currently only one kses WordPress hook and it is called here. All
mp-wp_genesis 359 * parameters are passed to the hooks and expected to recieve a string.
mp-wp_genesis 360 *
mp-wp_genesis 361 * @since 1.0.0
mp-wp_genesis 362 *
mp-wp_genesis 363 * @param string $string Content to filter through kses
mp-wp_genesis 364 * @param array $allowed_html List of allowed HTML elements
mp-wp_genesis 365 * @param array $allowed_protocols Allowed protocol in links
mp-wp_genesis 366 * @return string Filtered content through 'pre_kses' hook
mp-wp_genesis 367 */
mp-wp_genesis 368 function wp_kses_hook($string, $allowed_html, $allowed_protocols) {
mp-wp_genesis 369 $string = apply_filters('pre_kses', $string, $allowed_html, $allowed_protocols);
mp-wp_genesis 370 return $string;
mp-wp_genesis 371 }
mp-wp_genesis 372
mp-wp_genesis 373 /**
mp-wp_genesis 374 * This function returns kses' version number.
mp-wp_genesis 375 *
mp-wp_genesis 376 * @since 1.0.0
mp-wp_genesis 377 *
mp-wp_genesis 378 * @return string KSES Version Number
mp-wp_genesis 379 */
mp-wp_genesis 380 function wp_kses_version() {
mp-wp_genesis 381 return '0.2.2';
mp-wp_genesis 382 }
mp-wp_genesis 383
mp-wp_genesis 384 /**
mp-wp_genesis 385 * Searches for HTML tags, no matter how malformed.
mp-wp_genesis 386 *
mp-wp_genesis 387 * It also matches stray ">" characters.
mp-wp_genesis 388 *
mp-wp_genesis 389 * @since 1.0.0
mp-wp_genesis 390 *
mp-wp_genesis 391 * @param string $string Content to filter
mp-wp_genesis 392 * @param array $allowed_html Allowed HTML elements
mp-wp_genesis 393 * @param array $allowed_protocols Allowed protocols to keep
mp-wp_genesis 394 * @return string Content with fixed HTML tags
mp-wp_genesis 395 */
mp-wp_genesis 396 function wp_kses_split($string, $allowed_html, $allowed_protocols) {
mp-wp_genesis 397 return preg_replace_callback('%((<!--.*?(-->|$))|(<[^>]*(>|$)|>))%',
mp-wp_genesis 398 function($match) {
mp-wp_genesis 399 return wp_kses_split2($match[1], $allowed_html, $allowed_protocols);
mp-wp_genesis 400 }, $string);
mp-wp_genesis 401 }
mp-wp_genesis 402
mp-wp_genesis 403 /**
mp-wp_genesis 404 * Callback for wp_kses_split for fixing malformed HTML tags.
mp-wp_genesis 405 *
mp-wp_genesis 406 * This function does a lot of work. It rejects some very malformed things like
mp-wp_genesis 407 * <:::>. It returns an empty string, if the element isn't allowed (look ma, no
mp-wp_genesis 408 * strip_tags()!). Otherwise it splits the tag into an element and an attribute
mp-wp_genesis 409 * list.
mp-wp_genesis 410 *
mp-wp_genesis 411 * After the tag is split into an element and an attribute list, it is run
mp-wp_genesis 412 * through another filter which will remove illegal attributes and once that is
mp-wp_genesis 413 * completed, will be returned.
mp-wp_genesis 414 *
mp-wp_genesis 415 * @access private
mp-wp_genesis 416 * @since 1.0.0
mp-wp_genesis 417 * @uses wp_kses_attr()
mp-wp_genesis 418 *
mp-wp_genesis 419 * @param string $string Content to filter
mp-wp_genesis 420 * @param array $allowed_html Allowed HTML elements
mp-wp_genesis 421 * @param array $allowed_protocols Allowed protocols to keep
mp-wp_genesis 422 * @return string Fixed HTML element
mp-wp_genesis 423 */
mp-wp_genesis 424 function wp_kses_split2($string, $allowed_html, $allowed_protocols) {
mp-wp_genesis 425 $string = wp_kses_stripslashes($string);
mp-wp_genesis 426
mp-wp_genesis 427 if (substr($string, 0, 1) != '<')
mp-wp_genesis 428 return '&gt;';
mp-wp_genesis 429 # It matched a ">" character
mp-wp_genesis 430
mp-wp_genesis 431 if (preg_match('%^<!--(.*?)(-->)?$%', $string, $matches)) {
mp-wp_genesis 432 $string = str_replace(array('<!--', '-->'), '', $matches[1]);
mp-wp_genesis 433 while ( $string != $newstring = wp_kses($string, $allowed_html, $allowed_protocols) )
mp-wp_genesis 434 $string = $newstring;
mp-wp_genesis 435 if ( $string == '' )
mp-wp_genesis 436 return '';
mp-wp_genesis 437 // prevent multiple dashes in comments
mp-wp_genesis 438 $string = preg_replace('/--+/', '-', $string);
mp-wp_genesis 439 // prevent three dashes closing a comment
mp-wp_genesis 440 $string = preg_replace('/-$/', '', $string);
mp-wp_genesis 441 return "<!--{$string}-->";
mp-wp_genesis 442 }
mp-wp_genesis 443 # Allow HTML comments
mp-wp_genesis 444
mp-wp_genesis 445 if (!preg_match('%^<\s*(/\s*)?([a-zA-Z0-9]+)([^>]*)>?$%', $string, $matches))
mp-wp_genesis 446 return '';
mp-wp_genesis 447 # It's seriously malformed
mp-wp_genesis 448
mp-wp_genesis 449 $slash = trim($matches[1]);
mp-wp_genesis 450 $elem = $matches[2];
mp-wp_genesis 451 $attrlist = $matches[3];
mp-wp_genesis 452
mp-wp_genesis 453 if (!@isset($allowed_html[strtolower($elem)]))
mp-wp_genesis 454 return '';
mp-wp_genesis 455 # They are using a not allowed HTML element
mp-wp_genesis 456
mp-wp_genesis 457 if ($slash != '')
mp-wp_genesis 458 return "<$slash$elem>";
mp-wp_genesis 459 # No attributes are allowed for closing elements
mp-wp_genesis 460
mp-wp_genesis 461 return wp_kses_attr("$slash$elem", $attrlist, $allowed_html, $allowed_protocols);
mp-wp_genesis 462 }
mp-wp_genesis 463
mp-wp_genesis 464 /**
mp-wp_genesis 465 * Removes all attributes, if none are allowed for this element.
mp-wp_genesis 466 *
mp-wp_genesis 467 * If some are allowed it calls wp_kses_hair() to split them further, and then
mp-wp_genesis 468 * it builds up new HTML code from the data that kses_hair() returns. It also
mp-wp_genesis 469 * removes "<" and ">" characters, if there are any left. One more thing it does
mp-wp_genesis 470 * is to check if the tag has a closing XHTML slash, and if it does, it puts one
mp-wp_genesis 471 * in the returned code as well.
mp-wp_genesis 472 *
mp-wp_genesis 473 * @since 1.0.0
mp-wp_genesis 474 *
mp-wp_genesis 475 * @param string $element HTML element/tag
mp-wp_genesis 476 * @param string $attr HTML attributes from HTML element to closing HTML element tag
mp-wp_genesis 477 * @param array $allowed_html Allowed HTML elements
mp-wp_genesis 478 * @param array $allowed_protocols Allowed protocols to keep
mp-wp_genesis 479 * @return string Sanitized HTML element
mp-wp_genesis 480 */
mp-wp_genesis 481 function wp_kses_attr($element, $attr, $allowed_html, $allowed_protocols) {
mp-wp_genesis 482 # Is there a closing XHTML slash at the end of the attributes?
mp-wp_genesis 483
mp-wp_genesis 484 $xhtml_slash = '';
mp-wp_genesis 485 if (preg_match('%\s/\s*$%', $attr))
mp-wp_genesis 486 $xhtml_slash = ' /';
mp-wp_genesis 487
mp-wp_genesis 488 # Are any attributes allowed at all for this element?
mp-wp_genesis 489
mp-wp_genesis 490 if (@ count($allowed_html[strtolower($element)]) == 0)
mp-wp_genesis 491 return "<$element$xhtml_slash>";
mp-wp_genesis 492
mp-wp_genesis 493 # Split it
mp-wp_genesis 494
mp-wp_genesis 495 $attrarr = wp_kses_hair($attr, $allowed_protocols);
mp-wp_genesis 496
mp-wp_genesis 497 # Go through $attrarr, and save the allowed attributes for this element
mp-wp_genesis 498 # in $attr2
mp-wp_genesis 499
mp-wp_genesis 500 $attr2 = '';
mp-wp_genesis 501
mp-wp_genesis 502 foreach ($attrarr as $arreach) {
mp-wp_genesis 503 if (!@ isset ($allowed_html[strtolower($element)][strtolower($arreach['name'])]))
mp-wp_genesis 504 continue; # the attribute is not allowed
mp-wp_genesis 505
mp-wp_genesis 506 $current = $allowed_html[strtolower($element)][strtolower($arreach['name'])];
mp-wp_genesis 507 if ($current == '')
mp-wp_genesis 508 continue; # the attribute is not allowed
mp-wp_genesis 509
mp-wp_genesis 510 if (!is_array($current))
mp-wp_genesis 511 $attr2 .= ' '.$arreach['whole'];
mp-wp_genesis 512 # there are no checks
mp-wp_genesis 513
mp-wp_genesis 514 else {
mp-wp_genesis 515 # there are some checks
mp-wp_genesis 516 $ok = true;
mp-wp_genesis 517 foreach ($current as $currkey => $currval)
mp-wp_genesis 518 if (!wp_kses_check_attr_val($arreach['value'], $arreach['vless'], $currkey, $currval)) {
mp-wp_genesis 519 $ok = false;
mp-wp_genesis 520 break;
mp-wp_genesis 521 }
mp-wp_genesis 522
mp-wp_genesis 523 if ($ok)
mp-wp_genesis 524 $attr2 .= ' '.$arreach['whole']; # it passed them
mp-wp_genesis 525 } # if !is_array($current)
mp-wp_genesis 526 } # foreach
mp-wp_genesis 527
mp-wp_genesis 528 # Remove any "<" or ">" characters
mp-wp_genesis 529
mp-wp_genesis 530 $attr2 = preg_replace('/[<>]/', '', $attr2);
mp-wp_genesis 531
mp-wp_genesis 532 return "<$element$attr2$xhtml_slash>";
mp-wp_genesis 533 }
mp-wp_genesis 534
mp-wp_genesis 535 /**
mp-wp_genesis 536 * Builds an attribute list from string containing attributes.
mp-wp_genesis 537 *
mp-wp_genesis 538 * This function does a lot of work. It parses an attribute list into an array
mp-wp_genesis 539 * with attribute data, and tries to do the right thing even if it gets weird
mp-wp_genesis 540 * input. It will add quotes around attribute values that don't have any quotes
mp-wp_genesis 541 * or apostrophes around them, to make it easier to produce HTML code that will
mp-wp_genesis 542 * conform to W3C's HTML specification. It will also remove bad URL protocols
mp-wp_genesis 543 * from attribute values. It also reduces duplicate attributes by using the
mp-wp_genesis 544 * attribute defined first (foo='bar' foo='baz' will result in foo='bar').
mp-wp_genesis 545 *
mp-wp_genesis 546 * @since 1.0.0
mp-wp_genesis 547 *
mp-wp_genesis 548 * @param string $attr Attribute list from HTML element to closing HTML element tag
mp-wp_genesis 549 * @param array $allowed_protocols Allowed protocols to keep
mp-wp_genesis 550 * @return array List of attributes after parsing
mp-wp_genesis 551 */
mp-wp_genesis 552 function wp_kses_hair($attr, $allowed_protocols) {
mp-wp_genesis 553 $attrarr = array ();
mp-wp_genesis 554 $mode = 0;
mp-wp_genesis 555 $attrname = '';
mp-wp_genesis 556 $uris = array('xmlns', 'profile', 'href', 'src', 'cite', 'classid', 'codebase', 'data', 'usemap', 'longdesc', 'action');
mp-wp_genesis 557
mp-wp_genesis 558 # Loop through the whole attribute list
mp-wp_genesis 559
mp-wp_genesis 560 while (strlen($attr) != 0) {
mp-wp_genesis 561 $working = 0; # Was the last operation successful?
mp-wp_genesis 562
mp-wp_genesis 563 switch ($mode) {
mp-wp_genesis 564 case 0 : # attribute name, href for instance
mp-wp_genesis 565
mp-wp_genesis 566 if (preg_match('/^([-a-zA-Z]+)/', $attr, $match)) {
mp-wp_genesis 567 $attrname = $match[1];
mp-wp_genesis 568 $working = $mode = 1;
mp-wp_genesis 569 $attr = preg_replace('/^[-a-zA-Z]+/', '', $attr);
mp-wp_genesis 570 }
mp-wp_genesis 571
mp-wp_genesis 572 break;
mp-wp_genesis 573
mp-wp_genesis 574 case 1 : # equals sign or valueless ("selected")
mp-wp_genesis 575
mp-wp_genesis 576 if (preg_match('/^\s*=\s*/', $attr)) # equals sign
mp-wp_genesis 577 {
mp-wp_genesis 578 $working = 1;
mp-wp_genesis 579 $mode = 2;
mp-wp_genesis 580 $attr = preg_replace('/^\s*=\s*/', '', $attr);
mp-wp_genesis 581 break;
mp-wp_genesis 582 }
mp-wp_genesis 583
mp-wp_genesis 584 if (preg_match('/^\s+/', $attr)) # valueless
mp-wp_genesis 585 {
mp-wp_genesis 586 $working = 1;
mp-wp_genesis 587 $mode = 0;
mp-wp_genesis 588 if(FALSE === array_key_exists($attrname, $attrarr)) {
mp-wp_genesis 589 $attrarr[$attrname] = array ('name' => $attrname, 'value' => '', 'whole' => $attrname, 'vless' => 'y');
mp-wp_genesis 590 }
mp-wp_genesis 591 $attr = preg_replace('/^\s+/', '', $attr);
mp-wp_genesis 592 }
mp-wp_genesis 593
mp-wp_genesis 594 break;
mp-wp_genesis 595
mp-wp_genesis 596 case 2 : # attribute value, a URL after href= for instance
mp-wp_genesis 597
mp-wp_genesis 598 if (preg_match('/^"([^"]*)"(\s+|$)/', $attr, $match))
mp-wp_genesis 599 # "value"
mp-wp_genesis 600 {
mp-wp_genesis 601 $thisval = $match[1];
mp-wp_genesis 602 if ( in_array($attrname, $uris) )
mp-wp_genesis 603 $thisval = wp_kses_bad_protocol($thisval, $allowed_protocols);
mp-wp_genesis 604
mp-wp_genesis 605 if(FALSE === array_key_exists($attrname, $attrarr)) {
mp-wp_genesis 606 $attrarr[$attrname] = array ('name' => $attrname, 'value' => $thisval, 'whole' => "$attrname=\"$thisval\"", 'vless' => 'n');
mp-wp_genesis 607 }
mp-wp_genesis 608 $working = 1;
mp-wp_genesis 609 $mode = 0;
mp-wp_genesis 610 $attr = preg_replace('/^"[^"]*"(\s+|$)/', '', $attr);
mp-wp_genesis 611 break;
mp-wp_genesis 612 }
mp-wp_genesis 613
mp-wp_genesis 614 if (preg_match("/^'([^']*)'(\s+|$)/", $attr, $match))
mp-wp_genesis 615 # 'value'
mp-wp_genesis 616 {
mp-wp_genesis 617 $thisval = $match[1];
mp-wp_genesis 618 if ( in_array($attrname, $uris) )
mp-wp_genesis 619 $thisval = wp_kses_bad_protocol($thisval, $allowed_protocols);
mp-wp_genesis 620
mp-wp_genesis 621 if(FALSE === array_key_exists($attrname, $attrarr)) {
mp-wp_genesis 622 $attrarr[$attrname] = array ('name' => $attrname, 'value' => $thisval, 'whole' => "$attrname='$thisval'", 'vless' => 'n');
mp-wp_genesis 623 }
mp-wp_genesis 624 $working = 1;
mp-wp_genesis 625 $mode = 0;
mp-wp_genesis 626 $attr = preg_replace("/^'[^']*'(\s+|$)/", '', $attr);
mp-wp_genesis 627 break;
mp-wp_genesis 628 }
mp-wp_genesis 629
mp-wp_genesis 630 if (preg_match("%^([^\s\"']+)(\s+|$)%", $attr, $match))
mp-wp_genesis 631 # value
mp-wp_genesis 632 {
mp-wp_genesis 633 $thisval = $match[1];
mp-wp_genesis 634 if ( in_array($attrname, $uris) )
mp-wp_genesis 635 $thisval = wp_kses_bad_protocol($thisval, $allowed_protocols);
mp-wp_genesis 636
mp-wp_genesis 637 if(FALSE === array_key_exists($attrname, $attrarr)) {
mp-wp_genesis 638 $attrarr[$attrname] = array ('name' => $attrname, 'value' => $thisval, 'whole' => "$attrname=\"$thisval\"", 'vless' => 'n');
mp-wp_genesis 639 }
mp-wp_genesis 640 # We add quotes to conform to W3C's HTML spec.
mp-wp_genesis 641 $working = 1;
mp-wp_genesis 642 $mode = 0;
mp-wp_genesis 643 $attr = preg_replace("%^[^\s\"']+(\s+|$)%", '', $attr);
mp-wp_genesis 644 }
mp-wp_genesis 645
mp-wp_genesis 646 break;
mp-wp_genesis 647 } # switch
mp-wp_genesis 648
mp-wp_genesis 649 if ($working == 0) # not well formed, remove and try again
mp-wp_genesis 650 {
mp-wp_genesis 651 $attr = wp_kses_html_error($attr);
mp-wp_genesis 652 $mode = 0;
mp-wp_genesis 653 }
mp-wp_genesis 654 } # while
mp-wp_genesis 655
mp-wp_genesis 656 if ($mode == 1 && FALSE === array_key_exists($attrname, $attrarr))
mp-wp_genesis 657 # special case, for when the attribute list ends with a valueless
mp-wp_genesis 658 # attribute like "selected"
mp-wp_genesis 659 $attrarr[$attrname] = array ('name' => $attrname, 'value' => '', 'whole' => $attrname, 'vless' => 'y');
mp-wp_genesis 660
mp-wp_genesis 661 return $attrarr;
mp-wp_genesis 662 }
mp-wp_genesis 663
mp-wp_genesis 664 /**
mp-wp_genesis 665 * Performs different checks for attribute values.
mp-wp_genesis 666 *
mp-wp_genesis 667 * The currently implemented checks are "maxlen", "minlen", "maxval", "minval"
mp-wp_genesis 668 * and "valueless" with even more checks to come soon.
mp-wp_genesis 669 *
mp-wp_genesis 670 * @since 1.0.0
mp-wp_genesis 671 *
mp-wp_genesis 672 * @param string $value Attribute value
mp-wp_genesis 673 * @param string $vless Whether the value is valueless or not. Use 'y' or 'n'
mp-wp_genesis 674 * @param string $checkname What $checkvalue is checking for.
mp-wp_genesis 675 * @param mixed $checkvalue What constraint the value should pass
mp-wp_genesis 676 * @return bool Whether check passes (true) or not (false)
mp-wp_genesis 677 */
mp-wp_genesis 678 function wp_kses_check_attr_val($value, $vless, $checkname, $checkvalue) {
mp-wp_genesis 679 $ok = true;
mp-wp_genesis 680
mp-wp_genesis 681 switch (strtolower($checkname)) {
mp-wp_genesis 682 case 'maxlen' :
mp-wp_genesis 683 # The maxlen check makes sure that the attribute value has a length not
mp-wp_genesis 684 # greater than the given value. This can be used to avoid Buffer Overflows
mp-wp_genesis 685 # in WWW clients and various Internet servers.
mp-wp_genesis 686
mp-wp_genesis 687 if (strlen($value) > $checkvalue)
mp-wp_genesis 688 $ok = false;
mp-wp_genesis 689 break;
mp-wp_genesis 690
mp-wp_genesis 691 case 'minlen' :
mp-wp_genesis 692 # The minlen check makes sure that the attribute value has a length not
mp-wp_genesis 693 # smaller than the given value.
mp-wp_genesis 694
mp-wp_genesis 695 if (strlen($value) < $checkvalue)
mp-wp_genesis 696 $ok = false;
mp-wp_genesis 697 break;
mp-wp_genesis 698
mp-wp_genesis 699 case 'maxval' :
mp-wp_genesis 700 # The maxval check does two things: it checks that the attribute value is
mp-wp_genesis 701 # an integer from 0 and up, without an excessive amount of zeroes or
mp-wp_genesis 702 # whitespace (to avoid Buffer Overflows). It also checks that the attribute
mp-wp_genesis 703 # value is not greater than the given value.
mp-wp_genesis 704 # This check can be used to avoid Denial of Service attacks.
mp-wp_genesis 705
mp-wp_genesis 706 if (!preg_match('/^\s{0,6}[0-9]{1,6}\s{0,6}$/', $value))
mp-wp_genesis 707 $ok = false;
mp-wp_genesis 708 if ($value > $checkvalue)
mp-wp_genesis 709 $ok = false;
mp-wp_genesis 710 break;
mp-wp_genesis 711
mp-wp_genesis 712 case 'minval' :
mp-wp_genesis 713 # The minval check checks that the attribute value is a positive integer,
mp-wp_genesis 714 # and that it is not smaller than the given value.
mp-wp_genesis 715
mp-wp_genesis 716 if (!preg_match('/^\s{0,6}[0-9]{1,6}\s{0,6}$/', $value))
mp-wp_genesis 717 $ok = false;
mp-wp_genesis 718 if ($value < $checkvalue)
mp-wp_genesis 719 $ok = false;
mp-wp_genesis 720 break;
mp-wp_genesis 721
mp-wp_genesis 722 case 'valueless' :
mp-wp_genesis 723 # The valueless check checks if the attribute has a value
mp-wp_genesis 724 # (like <a href="blah">) or not (<option selected>). If the given value
mp-wp_genesis 725 # is a "y" or a "Y", the attribute must not have a value.
mp-wp_genesis 726 # If the given value is an "n" or an "N", the attribute must have one.
mp-wp_genesis 727
mp-wp_genesis 728 if (strtolower($checkvalue) != $vless)
mp-wp_genesis 729 $ok = false;
mp-wp_genesis 730 break;
mp-wp_genesis 731 } # switch
mp-wp_genesis 732
mp-wp_genesis 733 return $ok;
mp-wp_genesis 734 }
mp-wp_genesis 735
mp-wp_genesis 736 /**
mp-wp_genesis 737 * Sanitize string from bad protocols.
mp-wp_genesis 738 *
mp-wp_genesis 739 * This function removes all non-allowed protocols from the beginning of
mp-wp_genesis 740 * $string. It ignores whitespace and the case of the letters, and it does
mp-wp_genesis 741 * understand HTML entities. It does its work in a while loop, so it won't be
mp-wp_genesis 742 * fooled by a string like "javascript:javascript:alert(57)".
mp-wp_genesis 743 *
mp-wp_genesis 744 * @since 1.0.0
mp-wp_genesis 745 *
mp-wp_genesis 746 * @param string $string Content to filter bad protocols from
mp-wp_genesis 747 * @param array $allowed_protocols Allowed protocols to keep
mp-wp_genesis 748 * @return string Filtered content
mp-wp_genesis 749 */
mp-wp_genesis 750 function wp_kses_bad_protocol($string, $allowed_protocols) {
mp-wp_genesis 751 $string = wp_kses_no_null($string);
mp-wp_genesis 752 $string = preg_replace('/\xad+/', '', $string); # deals with Opera "feature"
mp-wp_genesis 753 $string2 = $string.'a';
mp-wp_genesis 754
mp-wp_genesis 755 while ($string != $string2) {
mp-wp_genesis 756 $string2 = $string;
mp-wp_genesis 757 $string = wp_kses_bad_protocol_once($string, $allowed_protocols);
mp-wp_genesis 758 } # while
mp-wp_genesis 759
mp-wp_genesis 760 return $string;
mp-wp_genesis 761 }
mp-wp_genesis 762
mp-wp_genesis 763 /**
mp-wp_genesis 764 * Removes any NULL characters in $string.
mp-wp_genesis 765 *
mp-wp_genesis 766 * @since 1.0.0
mp-wp_genesis 767 *
mp-wp_genesis 768 * @param string $string
mp-wp_genesis 769 * @return string
mp-wp_genesis 770 */
mp-wp_genesis 771 function wp_kses_no_null($string) {
mp-wp_genesis 772 $string = preg_replace('/\0+/', '', $string);
mp-wp_genesis 773 $string = preg_replace('/(\\\\0)+/', '', $string);
mp-wp_genesis 774
mp-wp_genesis 775 return $string;
mp-wp_genesis 776 }
mp-wp_genesis 777
mp-wp_genesis 778 /**
mp-wp_genesis 779 * Strips slashes from in front of quotes.
mp-wp_genesis 780 *
mp-wp_genesis 781 * This function changes the character sequence \" to just ". It leaves all
mp-wp_genesis 782 * other slashes alone. It's really weird, but the quoting from
mp-wp_genesis 783 * preg_replace(//e) seems to require this.
mp-wp_genesis 784 *
mp-wp_genesis 785 * @since 1.0.0
mp-wp_genesis 786 *
mp-wp_genesis 787 * @param string $string String to strip slashes
mp-wp_genesis 788 * @return string Fixed strings with quoted slashes
mp-wp_genesis 789 */
mp-wp_genesis 790 function wp_kses_stripslashes($string) {
mp-wp_genesis 791 return preg_replace('%\\\\"%', '"', $string);
mp-wp_genesis 792 }
mp-wp_genesis 793
mp-wp_genesis 794 /**
mp-wp_genesis 795 * Goes through an array and changes the keys to all lower case.
mp-wp_genesis 796 *
mp-wp_genesis 797 * @since 1.0.0
mp-wp_genesis 798 *
mp-wp_genesis 799 * @param array $inarray Unfiltered array
mp-wp_genesis 800 * @return array Fixed array with all lowercase keys
mp-wp_genesis 801 */
mp-wp_genesis 802 function wp_kses_array_lc($inarray) {
mp-wp_genesis 803 $outarray = array ();
mp-wp_genesis 804
mp-wp_genesis 805 foreach ( (array) $inarray as $inkey => $inval) {
mp-wp_genesis 806 $outkey = strtolower($inkey);
mp-wp_genesis 807 $outarray[$outkey] = array ();
mp-wp_genesis 808
mp-wp_genesis 809 foreach ( (array) $inval as $inkey2 => $inval2) {
mp-wp_genesis 810 $outkey2 = strtolower($inkey2);
mp-wp_genesis 811 $outarray[$outkey][$outkey2] = $inval2;
mp-wp_genesis 812 } # foreach $inval
mp-wp_genesis 813 } # foreach $inarray
mp-wp_genesis 814
mp-wp_genesis 815 return $outarray;
mp-wp_genesis 816 }
mp-wp_genesis 817
mp-wp_genesis 818 /**
mp-wp_genesis 819 * Removes the HTML JavaScript entities found in early versions of Netscape 4.
mp-wp_genesis 820 *
mp-wp_genesis 821 * @since 1.0.0
mp-wp_genesis 822 *
mp-wp_genesis 823 * @param string $string
mp-wp_genesis 824 * @return string
mp-wp_genesis 825 */
mp-wp_genesis 826 function wp_kses_js_entities($string) {
mp-wp_genesis 827 return preg_replace('%&\s*\{[^}]*(\}\s*;?|$)%', '', $string);
mp-wp_genesis 828 }
mp-wp_genesis 829
mp-wp_genesis 830 /**
mp-wp_genesis 831 * Handles parsing errors in wp_kses_hair().
mp-wp_genesis 832 *
mp-wp_genesis 833 * The general plan is to remove everything to and including some whitespace,
mp-wp_genesis 834 * but it deals with quotes and apostrophes as well.
mp-wp_genesis 835 *
mp-wp_genesis 836 * @since 1.0.0
mp-wp_genesis 837 *
mp-wp_genesis 838 * @param string $string
mp-wp_genesis 839 * @return string
mp-wp_genesis 840 */
mp-wp_genesis 841 function wp_kses_html_error($string) {
mp-wp_genesis 842 return preg_replace('/^("[^"]*("|$)|\'[^\']*(\'|$)|\S)*\s*/', '', $string);
mp-wp_genesis 843 }
mp-wp_genesis 844
mp-wp_genesis 845 /**
mp-wp_genesis 846 * Sanitizes content from bad protocols and other characters.
mp-wp_genesis 847 *
mp-wp_genesis 848 * This function searches for URL protocols at the beginning of $string, while
mp-wp_genesis 849 * handling whitespace and HTML entities.
mp-wp_genesis 850 *
mp-wp_genesis 851 * @since 1.0.0
mp-wp_genesis 852 *
mp-wp_genesis 853 * @param string $string Content to check for bad protocols
mp-wp_genesis 854 * @param string $allowed_protocols Allowed protocols
mp-wp_genesis 855 * @return string Sanitized content
mp-wp_genesis 856 */
mp-wp_genesis 857 function wp_kses_bad_protocol_once($string, $allowed_protocols) {
mp-wp_genesis 858 global $_kses_allowed_protocols;
mp-wp_genesis 859 $_kses_allowed_protocols = $allowed_protocols;
mp-wp_genesis 860
mp-wp_genesis 861 $string2 = preg_split('/:|&#58;|&#x3a;/i', $string, 2);
mp-wp_genesis 862 if ( isset($string2[1]) && !preg_match('%/\?%', $string2[0]) )
mp-wp_genesis 863 $string = wp_kses_bad_protocol_once2($string2[0]) . trim($string2[1]);
mp-wp_genesis 864 else
mp-wp_genesis 865 $string = preg_replace_callback('/^((&[^;]*;|[\sA-Za-z0-9])*)'.'(:|&#58;|&#[Xx]3[Aa];)\s*/', 'wp_kses_bad_protocol_once2', $string);
mp-wp_genesis 866
mp-wp_genesis 867 return $string;
mp-wp_genesis 868 }
mp-wp_genesis 869
mp-wp_genesis 870 /**
mp-wp_genesis 871 * Callback for wp_kses_bad_protocol_once() regular expression.
mp-wp_genesis 872 *
mp-wp_genesis 873 * This function processes URL protocols, checks to see if they're in the
mp-wp_genesis 874 * white-list or not, and returns different data depending on the answer.
mp-wp_genesis 875 *
mp-wp_genesis 876 * @access private
mp-wp_genesis 877 * @since 1.0.0
mp-wp_genesis 878 *
mp-wp_genesis 879 * @param mixed $matches string or preg_replace_callback() matches array to check for bad protocols
mp-wp_genesis 880 * @return string Sanitized content
mp-wp_genesis 881 */
mp-wp_genesis 882 function wp_kses_bad_protocol_once2($matches) {
mp-wp_genesis 883 global $_kses_allowed_protocols;
mp-wp_genesis 884
mp-wp_genesis 885 if ( is_array($matches) ) {
mp-wp_genesis 886 if ( ! isset($matches[1]) || empty($matches[1]) )
mp-wp_genesis 887 return '';
mp-wp_genesis 888
mp-wp_genesis 889 $string = $matches[1];
mp-wp_genesis 890 } else {
mp-wp_genesis 891 $string = $matches;
mp-wp_genesis 892 }
mp-wp_genesis 893
mp-wp_genesis 894 $string2 = wp_kses_decode_entities($string);
mp-wp_genesis 895 $string2 = preg_replace('/\s/', '', $string2);
mp-wp_genesis 896 $string2 = wp_kses_no_null($string2);
mp-wp_genesis 897 $string2 = preg_replace('/\xad+/', '', $string2);
mp-wp_genesis 898 # deals with Opera "feature"
mp-wp_genesis 899 $string2 = strtolower($string2);
mp-wp_genesis 900
mp-wp_genesis 901 $allowed = false;
mp-wp_genesis 902 foreach ( (array) $_kses_allowed_protocols as $one_protocol)
mp-wp_genesis 903 if (strtolower($one_protocol) == $string2) {
mp-wp_genesis 904 $allowed = true;
mp-wp_genesis 905 break;
mp-wp_genesis 906 }
mp-wp_genesis 907
mp-wp_genesis 908 if ($allowed)
mp-wp_genesis 909 return "$string2:";
mp-wp_genesis 910 else
mp-wp_genesis 911 return '';
mp-wp_genesis 912 }
mp-wp_genesis 913
mp-wp_genesis 914 /**
mp-wp_genesis 915 * Converts and fixes HTML entities.
mp-wp_genesis 916 *
mp-wp_genesis 917 * This function normalizes HTML entities. It will convert "AT&T" to the correct
mp-wp_genesis 918 * "AT&amp;T", "&#00058;" to "&#58;", "&#XYZZY;" to "&amp;#XYZZY;" and so on.
mp-wp_genesis 919 *
mp-wp_genesis 920 * @since 1.0.0
mp-wp_genesis 921 *
mp-wp_genesis 922 * @param string $string Content to normalize entities
mp-wp_genesis 923 * @return string Content with normalized entities
mp-wp_genesis 924 */
mp-wp_genesis 925 function wp_kses_normalize_entities($string) {
mp-wp_genesis 926 # Disarm all entities by converting & to &amp;
mp-wp_genesis 927
mp-wp_genesis 928 $string = str_replace('&', '&amp;', $string);
mp-wp_genesis 929
mp-wp_genesis 930 # Change back the allowed entities in our entity whitelist
mp-wp_genesis 931
mp-wp_genesis 932 $string = preg_replace('/&amp;([A-Za-z][A-Za-z0-9]{0,19});/', '&\\1;', $string);
mp-wp_genesis 933 $string = preg_replace_callback('/&amp;#0*([0-9]{1,5});/', 'wp_kses_normalize_entities2', $string);
mp-wp_genesis 934 $string = preg_replace_callback('/&amp;#([Xx])0*(([0-9A-Fa-f]{2}){1,2});/', 'wp_kses_normalize_entities3', $string);
mp-wp_genesis 935
mp-wp_genesis 936 return $string;
mp-wp_genesis 937 }
mp-wp_genesis 938
mp-wp_genesis 939 /**
mp-wp_genesis 940 * Callback for wp_kses_normalize_entities() regular expression.
mp-wp_genesis 941 *
mp-wp_genesis 942 * This function helps wp_kses_normalize_entities() to only accept 16 bit values
mp-wp_genesis 943 * and nothing more for &#number; entities.
mp-wp_genesis 944 *
mp-wp_genesis 945 * @access private
mp-wp_genesis 946 * @since 1.0.0
mp-wp_genesis 947 *
mp-wp_genesis 948 * @param array $matches preg_replace_callback() matches array
mp-wp_genesis 949 * @return string Correctly encoded entity
mp-wp_genesis 950 */
mp-wp_genesis 951 function wp_kses_normalize_entities2($matches) {
mp-wp_genesis 952 if ( ! isset($matches[1]) || empty($matches[1]) )
mp-wp_genesis 953 return '';
mp-wp_genesis 954
mp-wp_genesis 955 $i = $matches[1];
mp-wp_genesis 956 return ( ( ! valid_unicode($i) ) || ($i > 65535) ? "&amp;#$i;" : "&#$i;" );
mp-wp_genesis 957 }
mp-wp_genesis 958
mp-wp_genesis 959 /**
mp-wp_genesis 960 * Callback for wp_kses_normalize_entities() for regular expression.
mp-wp_genesis 961 *
mp-wp_genesis 962 * This function helps wp_kses_normalize_entities() to only accept valid Unicode
mp-wp_genesis 963 * numeric entities in hex form.
mp-wp_genesis 964 *
mp-wp_genesis 965 * @access private
mp-wp_genesis 966 *
mp-wp_genesis 967 * @param array $matches preg_replace_callback() matches array
mp-wp_genesis 968 * @return string Correctly encoded entity
mp-wp_genesis 969 */
mp-wp_genesis 970 function wp_kses_normalize_entities3($matches) {
mp-wp_genesis 971 if ( ! isset($matches[2]) || empty($matches[2]) )
mp-wp_genesis 972 return '';
mp-wp_genesis 973
mp-wp_genesis 974 $hexchars = $matches[2];
mp-wp_genesis 975 return ( ( ! valid_unicode(hexdec($hexchars)) ) ? "&amp;#x$hexchars;" : "&#x$hexchars;" );
mp-wp_genesis 976 }
mp-wp_genesis 977
mp-wp_genesis 978 /**
mp-wp_genesis 979 * Helper function to determine if a Unicode value is valid.
mp-wp_genesis 980 *
mp-wp_genesis 981 * @param int $i Unicode value
mp-wp_genesis 982 * @return bool true if the value was a valid Unicode number
mp-wp_genesis 983 */
mp-wp_genesis 984 function valid_unicode($i) {
mp-wp_genesis 985 return ( $i == 0x9 || $i == 0xa || $i == 0xd ||
mp-wp_genesis 986 ($i >= 0x20 && $i <= 0xd7ff) ||
mp-wp_genesis 987 ($i >= 0xe000 && $i <= 0xfffd) ||
mp-wp_genesis 988 ($i >= 0x10000 && $i <= 0x10ffff) );
mp-wp_genesis 989 }
mp-wp_genesis 990
mp-wp_genesis 991 /**
mp-wp_genesis 992 * Convert all entities to their character counterparts.
mp-wp_genesis 993 *
mp-wp_genesis 994 * This function decodes numeric HTML entities (&#65; and &#x41;). It doesn't do
mp-wp_genesis 995 * anything with other entities like &auml;, but we don't need them in the URL
mp-wp_genesis 996 * protocol whitelisting system anyway.
mp-wp_genesis 997 *
mp-wp_genesis 998 * @since 1.0.0
mp-wp_genesis 999 *
mp-wp_genesis 1000 * @param string $string Content to change entities
mp-wp_genesis 1001 * @return string Content after decoded entities
mp-wp_genesis 1002 */
mp-wp_genesis 1003 function wp_kses_decode_entities($string) {
mp-wp_genesis 1004 $string = preg_replace_callback('/&#([0-9]+);/', function($match) {
mp-wp_genesis 1005 return chr($match[1]);
mp-wp_genesis 1006 }, $string);
mp-wp_genesis 1007 $string = preg_replace_callback('/&#[Xx]([0-9A-Fa-f]+);/', function($match) {
mp-wp_genesis 1008 return chr(hexdec($match[1]));
mp-wp_genesis 1009 }, $string);
mp-wp_genesis 1010
mp-wp_genesis 1011 return $string;
mp-wp_genesis 1012 }
mp-wp_genesis 1013
mp-wp_genesis 1014 /**
mp-wp_genesis 1015 * Sanitize content with allowed HTML Kses rules.
mp-wp_genesis 1016 *
mp-wp_genesis 1017 * @since 1.0.0
mp-wp_genesis 1018 * @uses $allowedtags
mp-wp_genesis 1019 *
mp-wp_genesis 1020 * @param string $data Content to filter
mp-wp_genesis 1021 * @return string Filtered content
mp-wp_genesis 1022 */
mp-wp_genesis 1023 function wp_filter_kses($data) {
mp-wp_genesis 1024 global $allowedtags;
mp-wp_genesis 1025 return addslashes( wp_kses(stripslashes( $data ), $allowedtags) );
mp-wp_genesis 1026 }
mp-wp_genesis 1027
mp-wp_genesis 1028 /**
mp-wp_genesis 1029 * Sanitize content for allowed HTML tags for post content.
mp-wp_genesis 1030 *
mp-wp_genesis 1031 * Post content refers to the page contents of the 'post' type and not $_POST
mp-wp_genesis 1032 * data from forms.
mp-wp_genesis 1033 *
mp-wp_genesis 1034 * @since 2.0.0
mp-wp_genesis 1035 * @uses $allowedposttags
mp-wp_genesis 1036 *
mp-wp_genesis 1037 * @param string $data Post content to filter
mp-wp_genesis 1038 * @return string Filtered post content with allowed HTML tags and attributes intact.
mp-wp_genesis 1039 */
mp-wp_genesis 1040 function wp_filter_post_kses($data) {
mp-wp_genesis 1041 global $allowedposttags;
mp-wp_genesis 1042 return addslashes ( wp_kses(stripslashes( $data ), $allowedposttags) );
mp-wp_genesis 1043 }
mp-wp_genesis 1044
mp-wp_genesis 1045 /**
mp-wp_genesis 1046 * Strips all of the HTML in the content.
mp-wp_genesis 1047 *
mp-wp_genesis 1048 * @since 2.1.0
mp-wp_genesis 1049 *
mp-wp_genesis 1050 * @param string $data Content to strip all HTML from
mp-wp_genesis 1051 * @return string Filtered content without any HTML
mp-wp_genesis 1052 */
mp-wp_genesis 1053 function wp_filter_nohtml_kses($data) {
mp-wp_genesis 1054 return addslashes ( wp_kses(stripslashes( $data ), array()) );
mp-wp_genesis 1055 }
mp-wp_genesis 1056
mp-wp_genesis 1057 /**
mp-wp_genesis 1058 * Adds all Kses input form content filters.
mp-wp_genesis 1059 *
mp-wp_genesis 1060 * All hooks have default priority. The wp_filter_kses() function is added to
mp-wp_genesis 1061 * the 'pre_comment_content' and 'title_save_pre' hooks.
mp-wp_genesis 1062 *
mp-wp_genesis 1063 * The wp_filter_post_kses() function is added to the 'content_save_pre',
mp-wp_genesis 1064 * 'excerpt_save_pre', and 'content_filtered_save_pre' hooks.
mp-wp_genesis 1065 *
mp-wp_genesis 1066 * @since 2.0.0
mp-wp_genesis 1067 * @uses add_filter() See description for what functions are added to what hooks.
mp-wp_genesis 1068 */
mp-wp_genesis 1069 function kses_init_filters() {
mp-wp_genesis 1070 // Normal filtering.
mp-wp_genesis 1071 add_filter('pre_comment_content', 'wp_filter_kses');
mp-wp_genesis 1072 add_filter('title_save_pre', 'wp_filter_kses');
mp-wp_genesis 1073
mp-wp_genesis 1074 // Post filtering
mp-wp_genesis 1075 add_filter('content_save_pre', 'wp_filter_post_kses');
mp-wp_genesis 1076 add_filter('excerpt_save_pre', 'wp_filter_post_kses');
mp-wp_genesis 1077 add_filter('content_filtered_save_pre', 'wp_filter_post_kses');
mp-wp_genesis 1078 }
mp-wp_genesis 1079
mp-wp_genesis 1080 /**
mp-wp_genesis 1081 * Removes all Kses input form content filters.
mp-wp_genesis 1082 *
mp-wp_genesis 1083 * A quick procedural method to removing all of the filters that kses uses for
mp-wp_genesis 1084 * content in WordPress Loop.
mp-wp_genesis 1085 *
mp-wp_genesis 1086 * Does not remove the kses_init() function from 'init' hook (priority is
mp-wp_genesis 1087 * default). Also does not remove kses_init() function from 'set_current_user'
mp-wp_genesis 1088 * hook (priority is also default).
mp-wp_genesis 1089 *
mp-wp_genesis 1090 * @since 2.0.6
mp-wp_genesis 1091 */
mp-wp_genesis 1092 function kses_remove_filters() {
mp-wp_genesis 1093 // Normal filtering.
mp-wp_genesis 1094 remove_filter('pre_comment_content', 'wp_filter_kses');
mp-wp_genesis 1095 remove_filter('title_save_pre', 'wp_filter_kses');
mp-wp_genesis 1096
mp-wp_genesis 1097 // Post filtering
mp-wp_genesis 1098 remove_filter('content_save_pre', 'wp_filter_post_kses');
mp-wp_genesis 1099 remove_filter('excerpt_save_pre', 'wp_filter_post_kses');
mp-wp_genesis 1100 remove_filter('content_filtered_save_pre', 'wp_filter_post_kses');
mp-wp_genesis 1101 }
mp-wp_genesis 1102
mp-wp_genesis 1103 /**
mp-wp_genesis 1104 * Sets up most of the Kses filters for input form content.
mp-wp_genesis 1105 *
mp-wp_genesis 1106 * If you remove the kses_init() function from 'init' hook and
mp-wp_genesis 1107 * 'set_current_user' (priority is default), then none of the Kses filter hooks
mp-wp_genesis 1108 * will be added.
mp-wp_genesis 1109 *
mp-wp_genesis 1110 * First removes all of the Kses filters in case the current user does not need
mp-wp_genesis 1111 * to have Kses filter the content. If the user does not have unfiltered html
mp-wp_genesis 1112 * capability, then Kses filters are added.
mp-wp_genesis 1113 *
mp-wp_genesis 1114 * @uses kses_remove_filters() Removes the Kses filters
mp-wp_genesis 1115 * @uses kses_init_filters() Adds the Kses filters back if the user
mp-wp_genesis 1116 * does not have unfiltered HTML capability.
mp-wp_genesis 1117 * @since 2.0.0
mp-wp_genesis 1118 */
mp-wp_genesis 1119 function kses_init() {
mp-wp_genesis 1120 kses_remove_filters();
mp-wp_genesis 1121
mp-wp_genesis 1122 if (current_user_can('unfiltered_html') == false)
mp-wp_genesis 1123 kses_init_filters();
mp-wp_genesis 1124 }
mp-wp_genesis 1125
mp-wp_genesis 1126 add_action('init', 'kses_init');
mp-wp_genesis 1127 add_action('set_current_user', 'kses_init');
mp-wp_genesis 1128 ?>