[ Index ]

PHP Cross Reference of WordPress

title

Body

[close]

/wp-includes/ -> kses.php (source)

   1  <?php
   2  /**
   3   * kses 0.2.2 - HTML/XHTML filter that only allows some elements and attributes
   4   * Copyright (C) 2002, 2003, 2005  Ulf Harnhammar
   5   *
   6   * This program is free software and open source software; you can redistribute
   7   * it and/or modify it under the terms of the GNU General Public License as
   8   * published by the Free Software Foundation; either version 2 of the License,
   9   * or (at your option) any later version.
  10   *
  11   * This program is distributed in the hope that it will be useful, but WITHOUT
  12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13   * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  14   * more details.
  15   *
  16   * You should have received a copy of the GNU General Public License along
  17   * with this program; if not, write to the Free Software Foundation, Inc.,
  18   * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  19   * http://www.gnu.org/licenses/gpl.html
  20   *
  21   * [kses strips evil scripts!]
  22   *
  23   * Added wp_ prefix to avoid conflicts with existing kses users
  24   *
  25   * @version 0.2.2
  26   * @copyright (C) 2002, 2003, 2005
  27   * @author Ulf Harnhammar <http://advogato.org/person/metaur/>
  28   *
  29   * @package External
  30   * @subpackage KSES
  31   */
  32  
  33  /**
  34   * Specifies the default allowable HTML tags.
  35   *
  36   * Using `CUSTOM_TAGS` is not recommended and should be considered deprecated. The
  37   * {@see 'wp_kses_allowed_html'} filter is more powerful and supplies context.
  38   *
  39   * @see wp_kses_allowed_html()
  40   * @since 1.2.0
  41   *
  42   * @var array[]|bool Array of default allowable HTML tags, or false to use the defaults.
  43   */
  44  if ( ! defined( 'CUSTOM_TAGS' ) ) {
  45      define( 'CUSTOM_TAGS', false );
  46  }
  47  
  48  // Ensure that these variables are added to the global namespace
  49  // (e.g. if using namespaces / autoload in the current PHP environment).
  50  global $allowedposttags, $allowedtags, $allowedentitynames;
  51  
  52  if ( ! CUSTOM_TAGS ) {
  53      /**
  54       * KSES global for default allowable HTML tags.
  55       *
  56       * Can be overridden with the `CUSTOM_TAGS` constant.
  57       *
  58       * @var array[] $allowedposttags Array of default allowable HTML tags.
  59       * @since 2.0.0
  60       */
  61      $allowedposttags = array(
  62          'address'    => array(),
  63          'a'          => array(
  64              'href'     => true,
  65              'rel'      => true,
  66              'rev'      => true,
  67              'name'     => true,
  68              'target'   => true,
  69              'download' => array(
  70                  'valueless' => 'y',
  71              ),
  72          ),
  73          'abbr'       => array(),
  74          'acronym'    => array(),
  75          'area'       => array(
  76              'alt'    => true,
  77              'coords' => true,
  78              'href'   => true,
  79              'nohref' => true,
  80              'shape'  => true,
  81              'target' => true,
  82          ),
  83          'article'    => array(
  84              'align'    => true,
  85              'dir'      => true,
  86              'lang'     => true,
  87              'xml:lang' => true,
  88          ),
  89          'aside'      => array(
  90              'align'    => true,
  91              'dir'      => true,
  92              'lang'     => true,
  93              'xml:lang' => true,
  94          ),
  95          'audio'      => array(
  96              'autoplay' => true,
  97              'controls' => true,
  98              'loop'     => true,
  99              'muted'    => true,
 100              'preload'  => true,
 101              'src'      => true,
 102          ),
 103          'b'          => array(),
 104          'bdo'        => array(
 105              'dir' => true,
 106          ),
 107          'big'        => array(),
 108          'blockquote' => array(
 109              'cite'     => true,
 110              'lang'     => true,
 111              'xml:lang' => true,
 112          ),
 113          'br'         => array(),
 114          'button'     => array(
 115              'disabled' => true,
 116              'name'     => true,
 117              'type'     => true,
 118              'value'    => true,
 119          ),
 120          'caption'    => array(
 121              'align' => true,
 122          ),
 123          'cite'       => array(
 124              'dir'  => true,
 125              'lang' => true,
 126          ),
 127          'code'       => array(),
 128          'col'        => array(
 129              'align'   => true,
 130              'char'    => true,
 131              'charoff' => true,
 132              'span'    => true,
 133              'dir'     => true,
 134              'valign'  => true,
 135              'width'   => true,
 136          ),
 137          'colgroup'   => array(
 138              'align'   => true,
 139              'char'    => true,
 140              'charoff' => true,
 141              'span'    => true,
 142              'valign'  => true,
 143              'width'   => true,
 144          ),
 145          'del'        => array(
 146              'datetime' => true,
 147          ),
 148          'dd'         => array(),
 149          'dfn'        => array(),
 150          'details'    => array(
 151              'align'    => true,
 152              'dir'      => true,
 153              'lang'     => true,
 154              'open'     => true,
 155              'xml:lang' => true,
 156          ),
 157          'div'        => array(
 158              'align'    => true,
 159              'dir'      => true,
 160              'lang'     => true,
 161              'xml:lang' => true,
 162          ),
 163          'dl'         => array(),
 164          'dt'         => array(),
 165          'em'         => array(),
 166          'fieldset'   => array(),
 167          'figure'     => array(
 168              'align'    => true,
 169              'dir'      => true,
 170              'lang'     => true,
 171              'xml:lang' => true,
 172          ),
 173          'figcaption' => array(
 174              'align'    => true,
 175              'dir'      => true,
 176              'lang'     => true,
 177              'xml:lang' => true,
 178          ),
 179          'font'       => array(
 180              'color' => true,
 181              'face'  => true,
 182              'size'  => true,
 183          ),
 184          'footer'     => array(
 185              'align'    => true,
 186              'dir'      => true,
 187              'lang'     => true,
 188              'xml:lang' => true,
 189          ),
 190          'h1'         => array(
 191              'align' => true,
 192          ),
 193          'h2'         => array(
 194              'align' => true,
 195          ),
 196          'h3'         => array(
 197              'align' => true,
 198          ),
 199          'h4'         => array(
 200              'align' => true,
 201          ),
 202          'h5'         => array(
 203              'align' => true,
 204          ),
 205          'h6'         => array(
 206              'align' => true,
 207          ),
 208          'header'     => array(
 209              'align'    => true,
 210              'dir'      => true,
 211              'lang'     => true,
 212              'xml:lang' => true,
 213          ),
 214          'hgroup'     => array(
 215              'align'    => true,
 216              'dir'      => true,
 217              'lang'     => true,
 218              'xml:lang' => true,
 219          ),
 220          'hr'         => array(
 221              'align'   => true,
 222              'noshade' => true,
 223              'size'    => true,
 224              'width'   => true,
 225          ),
 226          'i'          => array(),
 227          'img'        => array(
 228              'alt'      => true,
 229              'align'    => true,
 230              'border'   => true,
 231              'height'   => true,
 232              'hspace'   => true,
 233              'longdesc' => true,
 234              'vspace'   => true,
 235              'src'      => true,
 236              'usemap'   => true,
 237              'width'    => true,
 238          ),
 239          'ins'        => array(
 240              'datetime' => true,
 241              'cite'     => true,
 242          ),
 243          'kbd'        => array(),
 244          'label'      => array(
 245              'for' => true,
 246          ),
 247          'legend'     => array(
 248              'align' => true,
 249          ),
 250          'li'         => array(
 251              'align' => true,
 252              'value' => true,
 253          ),
 254          'map'        => array(
 255              'name' => true,
 256          ),
 257          'mark'       => array(),
 258          'menu'       => array(
 259              'type' => true,
 260          ),
 261          'nav'        => array(
 262              'align'    => true,
 263              'dir'      => true,
 264              'lang'     => true,
 265              'xml:lang' => true,
 266          ),
 267          'p'          => array(
 268              'align'    => true,
 269              'dir'      => true,
 270              'lang'     => true,
 271              'xml:lang' => true,
 272          ),
 273          'pre'        => array(
 274              'width' => true,
 275          ),
 276          'q'          => array(
 277              'cite' => true,
 278          ),
 279          's'          => array(),
 280          'samp'       => array(),
 281          'span'       => array(
 282              'dir'      => true,
 283              'align'    => true,
 284              'lang'     => true,
 285              'xml:lang' => true,
 286          ),
 287          'section'    => array(
 288              'align'    => true,
 289              'dir'      => true,
 290              'lang'     => true,
 291              'xml:lang' => true,
 292          ),
 293          'small'      => array(),
 294          'strike'     => array(),
 295          'strong'     => array(),
 296          'sub'        => array(),
 297          'summary'    => array(
 298              'align'    => true,
 299              'dir'      => true,
 300              'lang'     => true,
 301              'xml:lang' => true,
 302          ),
 303          'sup'        => array(),
 304          'table'      => array(
 305              'align'       => true,
 306              'bgcolor'     => true,
 307              'border'      => true,
 308              'cellpadding' => true,
 309              'cellspacing' => true,
 310              'dir'         => true,
 311              'rules'       => true,
 312              'summary'     => true,
 313              'width'       => true,
 314          ),
 315          'tbody'      => array(
 316              'align'   => true,
 317              'char'    => true,
 318              'charoff' => true,
 319              'valign'  => true,
 320          ),
 321          'td'         => array(
 322              'abbr'    => true,
 323              'align'   => true,
 324              'axis'    => true,
 325              'bgcolor' => true,
 326              'char'    => true,
 327              'charoff' => true,
 328              'colspan' => true,
 329              'dir'     => true,
 330              'headers' => true,
 331              'height'  => true,
 332              'nowrap'  => true,
 333              'rowspan' => true,
 334              'scope'   => true,
 335              'valign'  => true,
 336              'width'   => true,
 337          ),
 338          'textarea'   => array(
 339              'cols'     => true,
 340              'rows'     => true,
 341              'disabled' => true,
 342              'name'     => true,
 343              'readonly' => true,
 344          ),
 345          'tfoot'      => array(
 346              'align'   => true,
 347              'char'    => true,
 348              'charoff' => true,
 349              'valign'  => true,
 350          ),
 351          'th'         => array(
 352              'abbr'    => true,
 353              'align'   => true,
 354              'axis'    => true,
 355              'bgcolor' => true,
 356              'char'    => true,
 357              'charoff' => true,
 358              'colspan' => true,
 359              'headers' => true,
 360              'height'  => true,
 361              'nowrap'  => true,
 362              'rowspan' => true,
 363              'scope'   => true,
 364              'valign'  => true,
 365              'width'   => true,
 366          ),
 367          'thead'      => array(
 368              'align'   => true,
 369              'char'    => true,
 370              'charoff' => true,
 371              'valign'  => true,
 372          ),
 373          'title'      => array(),
 374          'tr'         => array(
 375              'align'   => true,
 376              'bgcolor' => true,
 377              'char'    => true,
 378              'charoff' => true,
 379              'valign'  => true,
 380          ),
 381          'track'      => array(
 382              'default' => true,
 383              'kind'    => true,
 384              'label'   => true,
 385              'src'     => true,
 386              'srclang' => true,
 387          ),
 388          'tt'         => array(),
 389          'u'          => array(),
 390          'ul'         => array(
 391              'type' => true,
 392          ),
 393          'ol'         => array(
 394              'start'    => true,
 395              'type'     => true,
 396              'reversed' => true,
 397          ),
 398          'var'        => array(),
 399          'video'      => array(
 400              'autoplay' => true,
 401              'controls' => true,
 402              'height'   => true,
 403              'loop'     => true,
 404              'muted'    => true,
 405              'poster'   => true,
 406              'preload'  => true,
 407              'src'      => true,
 408              'width'    => true,
 409          ),
 410      );
 411  
 412      /**
 413       * @var array[] $allowedtags Array of KSES allowed HTML elements.
 414       * @since 1.0.0
 415       */
 416      $allowedtags = array(
 417          'a'          => array(
 418              'href'  => true,
 419              'title' => true,
 420          ),
 421          'abbr'       => array(
 422              'title' => true,
 423          ),
 424          'acronym'    => array(
 425              'title' => true,
 426          ),
 427          'b'          => array(),
 428          'blockquote' => array(
 429              'cite' => true,
 430          ),
 431          'cite'       => array(),
 432          'code'       => array(),
 433          'del'        => array(
 434              'datetime' => true,
 435          ),
 436          'em'         => array(),
 437          'i'          => array(),
 438          'q'          => array(
 439              'cite' => true,
 440          ),
 441          's'          => array(),
 442          'strike'     => array(),
 443          'strong'     => array(),
 444      );
 445  
 446      /**
 447       * @var string[] $allowedentitynames Array of KSES allowed HTML entitity names.
 448       * @since 1.0.0
 449       */
 450      $allowedentitynames = array(
 451          'nbsp',
 452          'iexcl',
 453          'cent',
 454          'pound',
 455          'curren',
 456          'yen',
 457          'brvbar',
 458          'sect',
 459          'uml',
 460          'copy',
 461          'ordf',
 462          'laquo',
 463          'not',
 464          'shy',
 465          'reg',
 466          'macr',
 467          'deg',
 468          'plusmn',
 469          'acute',
 470          'micro',
 471          'para',
 472          'middot',
 473          'cedil',
 474          'ordm',
 475          'raquo',
 476          'iquest',
 477          'Agrave',
 478          'Aacute',
 479          'Acirc',
 480          'Atilde',
 481          'Auml',
 482          'Aring',
 483          'AElig',
 484          'Ccedil',
 485          'Egrave',
 486          'Eacute',
 487          'Ecirc',
 488          'Euml',
 489          'Igrave',
 490          'Iacute',
 491          'Icirc',
 492          'Iuml',
 493          'ETH',
 494          'Ntilde',
 495          'Ograve',
 496          'Oacute',
 497          'Ocirc',
 498          'Otilde',
 499          'Ouml',
 500          'times',
 501          'Oslash',
 502          'Ugrave',
 503          'Uacute',
 504          'Ucirc',
 505          'Uuml',
 506          'Yacute',
 507          'THORN',
 508          'szlig',
 509          'agrave',
 510          'aacute',
 511          'acirc',
 512          'atilde',
 513          'auml',
 514          'aring',
 515          'aelig',
 516          'ccedil',
 517          'egrave',
 518          'eacute',
 519          'ecirc',
 520          'euml',
 521          'igrave',
 522          'iacute',
 523          'icirc',
 524          'iuml',
 525          'eth',
 526          'ntilde',
 527          'ograve',
 528          'oacute',
 529          'ocirc',
 530          'otilde',
 531          'ouml',
 532          'divide',
 533          'oslash',
 534          'ugrave',
 535          'uacute',
 536          'ucirc',
 537          'uuml',
 538          'yacute',
 539          'thorn',
 540          'yuml',
 541          'quot',
 542          'amp',
 543          'lt',
 544          'gt',
 545          'apos',
 546          'OElig',
 547          'oelig',
 548          'Scaron',
 549          'scaron',
 550          'Yuml',
 551          'circ',
 552          'tilde',
 553          'ensp',
 554          'emsp',
 555          'thinsp',
 556          'zwnj',
 557          'zwj',
 558          'lrm',
 559          'rlm',
 560          'ndash',
 561          'mdash',
 562          'lsquo',
 563          'rsquo',
 564          'sbquo',
 565          'ldquo',
 566          'rdquo',
 567          'bdquo',
 568          'dagger',
 569          'Dagger',
 570          'permil',
 571          'lsaquo',
 572          'rsaquo',
 573          'euro',
 574          'fnof',
 575          'Alpha',
 576          'Beta',
 577          'Gamma',
 578          'Delta',
 579          'Epsilon',
 580          'Zeta',
 581          'Eta',
 582          'Theta',
 583          'Iota',
 584          'Kappa',
 585          'Lambda',
 586          'Mu',
 587          'Nu',
 588          'Xi',
 589          'Omicron',
 590          'Pi',
 591          'Rho',
 592          'Sigma',
 593          'Tau',
 594          'Upsilon',
 595          'Phi',
 596          'Chi',
 597          'Psi',
 598          'Omega',
 599          'alpha',
 600          'beta',
 601          'gamma',
 602          'delta',
 603          'epsilon',
 604          'zeta',
 605          'eta',
 606          'theta',
 607          'iota',
 608          'kappa',
 609          'lambda',
 610          'mu',
 611          'nu',
 612          'xi',
 613          'omicron',
 614          'pi',
 615          'rho',
 616          'sigmaf',
 617          'sigma',
 618          'tau',
 619          'upsilon',
 620          'phi',
 621          'chi',
 622          'psi',
 623          'omega',
 624          'thetasym',
 625          'upsih',
 626          'piv',
 627          'bull',
 628          'hellip',
 629          'prime',
 630          'Prime',
 631          'oline',
 632          'frasl',
 633          'weierp',
 634          'image',
 635          'real',
 636          'trade',
 637          'alefsym',
 638          'larr',
 639          'uarr',
 640          'rarr',
 641          'darr',
 642          'harr',
 643          'crarr',
 644          'lArr',
 645          'uArr',
 646          'rArr',
 647          'dArr',
 648          'hArr',
 649          'forall',
 650          'part',
 651          'exist',
 652          'empty',
 653          'nabla',
 654          'isin',
 655          'notin',
 656          'ni',
 657          'prod',
 658          'sum',
 659          'minus',
 660          'lowast',
 661          'radic',
 662          'prop',
 663          'infin',
 664          'ang',
 665          'and',
 666          'or',
 667          'cap',
 668          'cup',
 669          'int',
 670          'sim',
 671          'cong',
 672          'asymp',
 673          'ne',
 674          'equiv',
 675          'le',
 676          'ge',
 677          'sub',
 678          'sup',
 679          'nsub',
 680          'sube',
 681          'supe',
 682          'oplus',
 683          'otimes',
 684          'perp',
 685          'sdot',
 686          'lceil',
 687          'rceil',
 688          'lfloor',
 689          'rfloor',
 690          'lang',
 691          'rang',
 692          'loz',
 693          'spades',
 694          'clubs',
 695          'hearts',
 696          'diams',
 697          'sup1',
 698          'sup2',
 699          'sup3',
 700          'frac14',
 701          'frac12',
 702          'frac34',
 703          'there4',
 704      );
 705  
 706      $allowedposttags = array_map( '_wp_add_global_attributes', $allowedposttags );
 707  } else {
 708      $allowedtags     = wp_kses_array_lc( $allowedtags );
 709      $allowedposttags = wp_kses_array_lc( $allowedposttags );
 710  }
 711  
 712  /**
 713   * Filters text content and strips out disallowed HTML.
 714   *
 715   * This function makes sure that only the allowed HTML element names, attribute
 716   * names, attribute values, and HTML entities will occur in the given text string.
 717   *
 718   * This function expects unslashed data.
 719   *
 720   * @see wp_kses_post() for specifically filtering post content and fields.
 721   * @see wp_allowed_protocols() for the default allowed protocols in link URLs.
 722   *
 723   * @since 1.0.0
 724   *
 725   * @param string         $string            Text content to filter.
 726   * @param array[]|string $allowed_html      An array of allowed HTML elements and attributes, or a
 727   *                                          context name such as 'post'.
 728   * @param string[]       $allowed_protocols Array of allowed URL protocols.
 729   * @return string Filtered content containing only the allowed HTML.
 730   */
 731  function wp_kses( $string, $allowed_html, $allowed_protocols = array() ) {
 732      if ( empty( $allowed_protocols ) ) {
 733          $allowed_protocols = wp_allowed_protocols();
 734      }
 735      $string = wp_kses_no_null( $string, array( 'slash_zero' => 'keep' ) );
 736      $string = wp_kses_normalize_entities( $string );
 737      $string = wp_kses_hook( $string, $allowed_html, $allowed_protocols );
 738      return wp_kses_split( $string, $allowed_html, $allowed_protocols );
 739  }
 740  
 741  /**
 742   * Filters one HTML attribute and ensures its value is allowed.
 743   *
 744   * This function can escape data in some situations where `wp_kses()` must strip the whole attribute.
 745   *
 746   * @since 4.2.3
 747   *
 748   * @param string $string  The 'whole' attribute, including name and value.
 749   * @param string $element The HTML element name to which the attribute belongs.
 750   * @return string Filtered attribute.
 751   */
 752  function wp_kses_one_attr( $string, $element ) {
 753      $uris              = wp_kses_uri_attributes();
 754      $allowed_html      = wp_kses_allowed_html( 'post' );
 755      $allowed_protocols = wp_allowed_protocols();
 756      $string            = wp_kses_no_null( $string, array( 'slash_zero' => 'keep' ) );
 757  
 758      // Preserve leading and trailing whitespace.
 759      $matches = array();
 760      preg_match( '/^\s*/', $string, $matches );
 761      $lead = $matches[0];
 762      preg_match( '/\s*$/', $string, $matches );
 763      $trail = $matches[0];
 764      if ( empty( $trail ) ) {
 765          $string = substr( $string, strlen( $lead ) );
 766      } else {
 767          $string = substr( $string, strlen( $lead ), -strlen( $trail ) );
 768      }
 769  
 770      // Parse attribute name and value from input.
 771      $split = preg_split( '/\s*=\s*/', $string, 2 );
 772      $name  = $split[0];
 773      if ( count( $split ) == 2 ) {
 774          $value = $split[1];
 775  
 776          // Remove quotes surrounding $value.
 777          // Also guarantee correct quoting in $string for this one attribute.
 778          if ( '' == $value ) {
 779              $quote = '';
 780          } else {
 781              $quote = $value[0];
 782          }
 783          if ( '"' == $quote || "'" == $quote ) {
 784              if ( substr( $value, -1 ) != $quote ) {
 785                  return '';
 786              }
 787              $value = substr( $value, 1, -1 );
 788          } else {
 789              $quote = '"';
 790          }
 791  
 792          // Sanitize quotes, angle braces, and entities.
 793          $value = esc_attr( $value );
 794  
 795          // Sanitize URI values.
 796          if ( in_array( strtolower( $name ), $uris ) ) {
 797              $value = wp_kses_bad_protocol( $value, $allowed_protocols );
 798          }
 799  
 800          $string = "$name=$quote$value$quote";
 801          $vless  = 'n';
 802      } else {
 803          $value = '';
 804          $vless = 'y';
 805      }
 806  
 807      // Sanitize attribute by name.
 808      wp_kses_attr_check( $name, $value, $string, $vless, $element, $allowed_html );
 809  
 810      // Restore whitespace.
 811      return $lead . $string . $trail;
 812  }
 813  
 814  /**
 815   * Returns an array of allowed HTML tags and attributes for a given context.
 816   *
 817   * @since 3.5.0
 818   * @since 5.0.1 `form` removed as allowable HTML tag.
 819   *
 820   * @global array $allowedposttags
 821   * @global array $allowedtags
 822   * @global array $allowedentitynames
 823   *
 824   * @param string|array $context The context for which to retrieve tags. Allowed values are 'post',
 825   *                              'strip', 'data', 'entities', or the name of a field filter such as
 826   *                              'pre_user_description'.
 827   * @return array Array of allowed HTML tags and their allowed attributes.
 828   */
 829  function wp_kses_allowed_html( $context = '' ) {
 830      global $allowedposttags, $allowedtags, $allowedentitynames;
 831  
 832      if ( is_array( $context ) ) {
 833          /**
 834           * Filters the HTML that is allowed for a given context.
 835           *
 836           * @since 3.5.0
 837           *
 838           * @param array[]|string $context      Context to judge allowed tags by.
 839           * @param string         $context_type Context name.
 840           */
 841          return apply_filters( 'wp_kses_allowed_html', $context, 'explicit' );
 842      }
 843  
 844      switch ( $context ) {
 845          case 'post':
 846              /** This filter is documented in wp-includes/kses.php */
 847              $tags = apply_filters( 'wp_kses_allowed_html', $allowedposttags, $context );
 848  
 849              // 5.0.1 removed the `<form>` tag, allow it if a filter is allowing it's sub-elements `<input>` or `<select>`.
 850              if ( ! CUSTOM_TAGS && ! isset( $tags['form'] ) && ( isset( $tags['input'] ) || isset( $tags['select'] ) ) ) {
 851                  $tags = $allowedposttags;
 852  
 853                  $tags['form'] = array(
 854                      'action'         => true,
 855                      'accept'         => true,
 856                      'accept-charset' => true,
 857                      'enctype'        => true,
 858                      'method'         => true,
 859                      'name'           => true,
 860                      'target'         => true,
 861                  );
 862  
 863                  /** This filter is documented in wp-includes/kses.php */
 864                  $tags = apply_filters( 'wp_kses_allowed_html', $tags, $context );
 865              }
 866  
 867              return $tags;
 868  
 869          case 'user_description':
 870          case 'pre_user_description':
 871              $tags             = $allowedtags;
 872              $tags['a']['rel'] = true;
 873              /** This filter is documented in wp-includes/kses.php */
 874              return apply_filters( 'wp_kses_allowed_html', $tags, $context );
 875  
 876          case 'strip':
 877              /** This filter is documented in wp-includes/kses.php */
 878              return apply_filters( 'wp_kses_allowed_html', array(), $context );
 879  
 880          case 'entities':
 881              /** This filter is documented in wp-includes/kses.php */
 882              return apply_filters( 'wp_kses_allowed_html', $allowedentitynames, $context );
 883  
 884          case 'data':
 885          default:
 886              /** This filter is documented in wp-includes/kses.php */
 887              return apply_filters( 'wp_kses_allowed_html', $allowedtags, $context );
 888      }
 889  }
 890  
 891  /**
 892   * You add any KSES hooks here.
 893   *
 894   * There is currently only one KSES WordPress hook, {@see 'pre_kses'}, and it is called here.
 895   * All parameters are passed to the hooks and expected to receive a string.
 896   *
 897   * @since 1.0.0
 898   *
 899   * @param string          $string            Content to filter through KSES.
 900   * @param array[]|string  $allowed_html      List of allowed HTML elements.
 901   * @param string[]        $allowed_protocols Array of allowed URL protocols.
 902   * @return string Filtered content through {@see 'pre_kses'} hook.
 903   */
 904  function wp_kses_hook( $string, $allowed_html, $allowed_protocols ) {
 905      /**
 906       * Filters content to be run through kses.
 907       *
 908       * @since 2.3.0
 909       *
 910       * @param string          $string            Content to run through KSES.
 911       * @param array[]|string  $allowed_html      Allowed HTML elements.
 912       * @param string[]        $allowed_protocols Array of allowed URL protocols.
 913       */
 914      return apply_filters( 'pre_kses', $string, $allowed_html, $allowed_protocols );
 915  }
 916  
 917  /**
 918   * Returns the version number of KSES.
 919   *
 920   * @since 1.0.0
 921   *
 922   * @return string KSES version number.
 923   */
 924  function wp_kses_version() {
 925      return '0.2.2';
 926  }
 927  
 928  /**
 929   * Searches for HTML tags, no matter how malformed.
 930   *
 931   * It also matches stray `>` characters.
 932   *
 933   * @since 1.0.0
 934   *
 935   * @global array $pass_allowed_html
 936   * @global array $pass_allowed_protocols
 937   *
 938   * @param string   $string            Content to filter.
 939   * @param array    $allowed_html      Allowed HTML elements.
 940   * @param string[] $allowed_protocols Array of allowed URL protocols.
 941   * @return string Content with fixed HTML tags
 942   */
 943  function wp_kses_split( $string, $allowed_html, $allowed_protocols ) {
 944      global $pass_allowed_html, $pass_allowed_protocols;
 945      $pass_allowed_html      = $allowed_html;
 946      $pass_allowed_protocols = $allowed_protocols;
 947      return preg_replace_callback( '%(<!--.*?(-->|$))|(<[^>]*(>|$)|>)%', '_wp_kses_split_callback', $string );
 948  }
 949  
 950  /**
 951   * Helper function listing HTML attributes containing a URL.
 952   *
 953   * This function returns a list of all HTML attributes that must contain
 954   * a URL according to the HTML specification.
 955   *
 956   * This list includes URI attributes both allowed and disallowed by KSES.
 957   *
 958   * @link https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes
 959   *
 960   * @since 5.0.1
 961   *
 962   * @return array HTML attributes that must include a URL.
 963   */
 964  function wp_kses_uri_attributes() {
 965      $uri_attributes = array(
 966          'action',
 967          'archive',
 968          'background',
 969          'cite',
 970          'classid',
 971          'codebase',
 972          'data',
 973          'formaction',
 974          'href',
 975          'icon',
 976          'longdesc',
 977          'manifest',
 978          'poster',
 979          'profile',
 980          'src',
 981          'usemap',
 982          'xmlns',
 983      );
 984  
 985      /**
 986       * Filters the list of attributes that are required to contain a URL.
 987       *
 988       * Use this filter to add any `data-` attributes that are required to be
 989       * validated as a URL.
 990       *
 991       * @since 5.0.1
 992       *
 993       * @param array $uri_attributes HTML attributes requiring validation as a URL.
 994       */
 995      $uri_attributes = apply_filters( 'wp_kses_uri_attributes', $uri_attributes );
 996  
 997      return $uri_attributes;
 998  }
 999  
1000  /**
1001   * Callback for `wp_kses_split()`.
1002   *
1003   * @since 3.1.0
1004   * @access private
1005   * @ignore
1006   *
1007   * @global array $pass_allowed_html
1008   * @global array $pass_allowed_protocols
1009   *
1010   * @return string
1011   */
1012  function _wp_kses_split_callback( $match ) {
1013      global $pass_allowed_html, $pass_allowed_protocols;
1014      return wp_kses_split2( $match[0], $pass_allowed_html, $pass_allowed_protocols );
1015  }
1016  
1017  /**
1018   * Callback for `wp_kses_split()` for fixing malformed HTML tags.
1019   *
1020   * This function does a lot of work. It rejects some very malformed things like
1021   * `<:::>`. It returns an empty string, if the element isn't allowed (look ma, no
1022   * `strip_tags()`!). Otherwise it splits the tag into an element and an attribute
1023   * list.
1024   *
1025   * After the tag is split into an element and an attribute list, it is run
1026   * through another filter which will remove illegal attributes and once that is
1027   * completed, will be returned.
1028   *
1029   * @access private
1030   * @ignore
1031   * @since 1.0.0
1032   *
1033   * @param string   $string            Content to filter.
1034   * @param array    $allowed_html      Allowed HTML elements.
1035   * @param string[] $allowed_protocols Array of allowed URL protocols.
1036   * @return string Fixed HTML element
1037   */
1038  function wp_kses_split2( $string, $allowed_html, $allowed_protocols ) {
1039      $string = wp_kses_stripslashes( $string );
1040  
1041      // It matched a ">" character.
1042      if ( substr( $string, 0, 1 ) != '<' ) {
1043          return '&gt;';
1044      }
1045  
1046      // Allow HTML comments.
1047      if ( '<!--' == substr( $string, 0, 4 ) ) {
1048          $string = str_replace( array( '<!--', '-->' ), '', $string );
1049          while ( $string != ( $newstring = wp_kses( $string, $allowed_html, $allowed_protocols ) ) ) {
1050              $string = $newstring;
1051          }
1052          if ( $string == '' ) {
1053              return '';
1054          }
1055          // prevent multiple dashes in comments
1056          $string = preg_replace( '/--+/', '-', $string );
1057          // prevent three dashes closing a comment
1058          $string = preg_replace( '/-$/', '', $string );
1059          return "<!--{$string}-->";
1060      }
1061  
1062      // It's seriously malformed.
1063      if ( ! preg_match( '%^<\s*(/\s*)?([a-zA-Z0-9-]+)([^>]*)>?$%', $string, $matches ) ) {
1064          return '';
1065      }
1066  
1067      $slash    = trim( $matches[1] );
1068      $elem     = $matches[2];
1069      $attrlist = $matches[3];
1070  
1071      if ( ! is_array( $allowed_html ) ) {
1072          $allowed_html = wp_kses_allowed_html( $allowed_html );
1073      }
1074  
1075      // They are using a not allowed HTML element.
1076      if ( ! isset( $allowed_html[ strtolower( $elem ) ] ) ) {
1077          return '';
1078      }
1079  
1080      // No attributes are allowed for closing elements.
1081      if ( $slash != '' ) {
1082          return "</$elem>";
1083      }
1084  
1085      return wp_kses_attr( $elem, $attrlist, $allowed_html, $allowed_protocols );
1086  }
1087  
1088  /**
1089   * Removes all attributes, if none are allowed for this element.
1090   *
1091   * If some are allowed it calls `wp_kses_hair()` to split them further, and then
1092   * it builds up new HTML code from the data that `kses_hair()` returns. It also
1093   * removes `<` and `>` characters, if there are any left. One more thing it does
1094   * is to check if the tag has a closing XHTML slash, and if it does, it puts one
1095   * in the returned code as well.
1096   *
1097   * @since 1.0.0
1098   *
1099   * @param string   $element           HTML element/tag.
1100   * @param string   $attr              HTML attributes from HTML element to closing HTML element tag.
1101   * @param array    $allowed_html      Allowed HTML elements.
1102   * @param string[] $allowed_protocols Array of allowed URL protocols.
1103   * @return string Sanitized HTML element.
1104   */
1105  function wp_kses_attr( $element, $attr, $allowed_html, $allowed_protocols ) {
1106      if ( ! is_array( $allowed_html ) ) {
1107          $allowed_html = wp_kses_allowed_html( $allowed_html );
1108      }
1109  
1110      // Is there a closing XHTML slash at the end of the attributes?
1111      $xhtml_slash = '';
1112      if ( preg_match( '%\s*/\s*$%', $attr ) ) {
1113          $xhtml_slash = ' /';
1114      }
1115  
1116      // Are any attributes allowed at all for this element?
1117      $element_low = strtolower( $element );
1118      if ( empty( $allowed_html[ $element_low ] ) || true === $allowed_html[ $element_low ] ) {
1119          return "<$element$xhtml_slash>";
1120      }
1121  
1122      // Split it
1123      $attrarr = wp_kses_hair( $attr, $allowed_protocols );
1124  
1125      // Go through $attrarr, and save the allowed attributes for this element
1126      // in $attr2
1127      $attr2 = '';
1128      foreach ( $attrarr as $arreach ) {
1129          if ( wp_kses_attr_check( $arreach['name'], $arreach['value'], $arreach['whole'], $arreach['vless'], $element, $allowed_html ) ) {
1130              $attr2 .= ' ' . $arreach['whole'];
1131          }
1132      }
1133  
1134      // Remove any "<" or ">" characters
1135      $attr2 = preg_replace( '/[<>]/', '', $attr2 );
1136  
1137      return "<$element$attr2$xhtml_slash>";
1138  }
1139  
1140  /**
1141   * Determines whether an attribute is allowed.
1142   *
1143   * @since 4.2.3
1144   * @since 5.0.0 Add support for `data-*` wildcard attributes.
1145   *
1146   * @param string $name         The attribute name. Passed by reference. Returns empty string when not allowed.
1147   * @param string $value        The attribute value. Passed by reference. Returns a filtered value.
1148   * @param string $whole        The `name=value` input. Passed by reference. Returns filtered input.
1149   * @param string $vless        Whether the attribute is valueless. Use 'y' or 'n'.
1150   * @param string $element      The name of the element to which this attribute belongs.
1151   * @param array  $allowed_html The full list of allowed elements and attributes.
1152   * @return bool Whether or not the attribute is allowed.
1153   */
1154  function wp_kses_attr_check( &$name, &$value, &$whole, $vless, $element, $allowed_html ) {
1155      $allowed_attr = $allowed_html[ strtolower( $element ) ];
1156  
1157      $name_low = strtolower( $name );
1158      if ( ! isset( $allowed_attr[ $name_low ] ) || '' == $allowed_attr[ $name_low ] ) {
1159          /*
1160           * Allow `data-*` attributes.
1161           *
1162           * When specifying `$allowed_html`, the attribute name should be set as
1163           * `data-*` (not to be mixed with the HTML 4.0 `data` attribute, see
1164           * https://www.w3.org/TR/html40/struct/objects.html#adef-data).
1165           *
1166           * Note: the attribute name should only contain `A-Za-z0-9_-` chars,
1167           * double hyphens `--` are not accepted by WordPress.
1168           */
1169          if ( strpos( $name_low, 'data-' ) === 0 && ! empty( $allowed_attr['data-*'] ) && preg_match( '/^data(?:-[a-z0-9_]+)+$/', $name_low, $match ) ) {
1170              /*
1171               * Add the whole attribute name to the allowed attributes and set any restrictions
1172               * for the `data-*` attribute values for the current element.
1173               */
1174              $allowed_attr[ $match[0] ] = $allowed_attr['data-*'];
1175          } else {
1176              $name  = '';
1177              $value = '';
1178              $whole = '';
1179              return false;
1180          }
1181      }
1182  
1183      if ( 'style' == $name_low ) {
1184          $new_value = safecss_filter_attr( $value );
1185  
1186          if ( empty( $new_value ) ) {
1187              $name  = '';
1188              $value = '';
1189              $whole = '';
1190              return false;
1191          }
1192  
1193          $whole = str_replace( $value, $new_value, $whole );
1194          $value = $new_value;
1195      }
1196  
1197      if ( is_array( $allowed_attr[ $name_low ] ) ) {
1198          // there are some checks
1199          foreach ( $allowed_attr[ $name_low ] as $currkey => $currval ) {
1200              if ( ! wp_kses_check_attr_val( $value, $vless, $currkey, $currval ) ) {
1201                  $name  = '';
1202                  $value = '';
1203                  $whole = '';
1204                  return false;
1205              }
1206          }
1207      }
1208  
1209      return true;
1210  }
1211  
1212  /**
1213   * Builds an attribute list from string containing attributes.
1214   *
1215   * This function does a lot of work. It parses an attribute list into an array
1216   * with attribute data, and tries to do the right thing even if it gets weird
1217   * input. It will add quotes around attribute values that don't have any quotes
1218   * or apostrophes around them, to make it easier to produce HTML code that will
1219   * conform to W3C's HTML specification. It will also remove bad URL protocols
1220   * from attribute values. It also reduces duplicate attributes by using the
1221   * attribute defined first (`foo='bar' foo='baz'` will result in `foo='bar'`).
1222   *
1223   * @since 1.0.0
1224   *
1225   * @param string   $attr              Attribute list from HTML element to closing HTML element tag.
1226   * @param string[] $allowed_protocols Array of allowed URL protocols.
1227   * @return array[] Array of attribute information after parsing.
1228   */
1229  function wp_kses_hair( $attr, $allowed_protocols ) {
1230      $attrarr  = array();
1231      $mode     = 0;
1232      $attrname = '';
1233      $uris     = wp_kses_uri_attributes();
1234  
1235      // Loop through the whole attribute list
1236  
1237      while ( strlen( $attr ) != 0 ) {
1238          $working = 0; // Was the last operation successful?
1239  
1240          switch ( $mode ) {
1241              case 0:
1242                  if ( preg_match( '/^([-a-zA-Z:]+)/', $attr, $match ) ) {
1243                      $attrname = $match[1];
1244                      $working  = 1;
1245                      $mode     = 1;
1246                      $attr     = preg_replace( '/^[-a-zA-Z:]+/', '', $attr );
1247                  }
1248  
1249                  break;
1250  
1251              case 1:
1252                  if ( preg_match( '/^\s*=\s*/', $attr ) ) { // equals sign
1253                      $working = 1;
1254                      $mode    = 2;
1255                      $attr    = preg_replace( '/^\s*=\s*/', '', $attr );
1256                      break;
1257                  }
1258  
1259                  if ( preg_match( '/^\s+/', $attr ) ) { // valueless
1260                      $working = 1;
1261                      $mode    = 0;
1262                      if ( false === array_key_exists( $attrname, $attrarr ) ) {
1263                          $attrarr[ $attrname ] = array(
1264                              'name'  => $attrname,
1265                              'value' => '',
1266                              'whole' => $attrname,
1267                              'vless' => 'y',
1268                          );
1269                      }
1270                      $attr = preg_replace( '/^\s+/', '', $attr );
1271                  }
1272  
1273                  break;
1274  
1275              case 2:
1276                  if ( preg_match( '%^"([^"]*)"(\s+|/?$)%', $attr, $match ) ) {
1277                      // "value"
1278                      $thisval = $match[1];
1279                      if ( in_array( strtolower( $attrname ), $uris ) ) {
1280                          $thisval = wp_kses_bad_protocol( $thisval, $allowed_protocols );
1281                      }
1282  
1283                      if ( false === array_key_exists( $attrname, $attrarr ) ) {
1284                          $attrarr[ $attrname ] = array(
1285                              'name'  => $attrname,
1286                              'value' => $thisval,
1287                              'whole' => "$attrname=\"$thisval\"",
1288                              'vless' => 'n',
1289                          );
1290                      }
1291                      $working = 1;
1292                      $mode    = 0;
1293                      $attr    = preg_replace( '/^"[^"]*"(\s+|$)/', '', $attr );
1294                      break;
1295                  }
1296  
1297                  if ( preg_match( "%^'([^']*)'(\s+|/?$)%", $attr, $match ) ) {
1298                      // 'value'
1299                      $thisval = $match[1];
1300                      if ( in_array( strtolower( $attrname ), $uris ) ) {
1301                          $thisval = wp_kses_bad_protocol( $thisval, $allowed_protocols );
1302                      }
1303  
1304                      if ( false === array_key_exists( $attrname, $attrarr ) ) {
1305                          $attrarr[ $attrname ] = array(
1306                              'name'  => $attrname,
1307                              'value' => $thisval,
1308                              'whole' => "$attrname='$thisval'",
1309                              'vless' => 'n',
1310                          );
1311                      }
1312                      $working = 1;
1313                      $mode    = 0;
1314                      $attr    = preg_replace( "/^'[^']*'(\s+|$)/", '', $attr );
1315                      break;
1316                  }
1317  
1318                  if ( preg_match( "%^([^\s\"']+)(\s+|/?$)%", $attr, $match ) ) {
1319                      // value
1320                      $thisval = $match[1];
1321                      if ( in_array( strtolower( $attrname ), $uris ) ) {
1322                          $thisval = wp_kses_bad_protocol( $thisval, $allowed_protocols );
1323                      }
1324  
1325                      if ( false === array_key_exists( $attrname, $attrarr ) ) {
1326                          $attrarr[ $attrname ] = array(
1327                              'name'  => $attrname,
1328                              'value' => $thisval,
1329                              'whole' => "$attrname=\"$thisval\"",
1330                              'vless' => 'n',
1331                          );
1332                      }
1333                      // We add quotes to conform to W3C's HTML spec.
1334                      $working = 1;
1335                      $mode    = 0;
1336                      $attr    = preg_replace( "%^[^\s\"']+(\s+|$)%", '', $attr );
1337                  }
1338  
1339                  break;
1340          } // switch
1341  
1342          if ( $working == 0 ) { // not well formed, remove and try again
1343              $attr = wp_kses_html_error( $attr );
1344              $mode = 0;
1345          }
1346      } // while
1347  
1348      if ( $mode == 1 && false === array_key_exists( $attrname, $attrarr ) ) {
1349          // special case, for when the attribute list ends with a valueless
1350          // attribute like "selected"
1351          $attrarr[ $attrname ] = array(
1352              'name'  => $attrname,
1353              'value' => '',
1354              'whole' => $attrname,
1355              'vless' => 'y',
1356          );
1357      }
1358  
1359      return $attrarr;
1360  }
1361  
1362  /**
1363   * Finds all attributes of an HTML element.
1364   *
1365   * Does not modify input.  May return "evil" output.
1366   *
1367   * Based on `wp_kses_split2()` and `wp_kses_attr()`.
1368   *
1369   * @since 4.2.3
1370   *
1371   * @param string $element HTML element.
1372   * @return array|bool List of attributes found in the element. Returns false on failure.
1373   */
1374  function wp_kses_attr_parse( $element ) {
1375      $valid = preg_match( '%^(<\s*)(/\s*)?([a-zA-Z0-9]+\s*)([^>]*)(>?)$%', $element, $matches );
1376      if ( 1 !== $valid ) {
1377          return false;
1378      }
1379  
1380      $begin  = $matches[1];
1381      $slash  = $matches[2];
1382      $elname = $matches[3];
1383      $attr   = $matches[4];
1384      $end    = $matches[5];
1385  
1386      if ( '' !== $slash ) {
1387          // Closing elements do not get parsed.
1388          return false;
1389      }
1390  
1391      // Is there a closing XHTML slash at the end of the attributes?
1392      if ( 1 === preg_match( '%\s*/\s*$%', $attr, $matches ) ) {
1393          $xhtml_slash = $matches[0];
1394          $attr        = substr( $attr, 0, -strlen( $xhtml_slash ) );
1395      } else {
1396          $xhtml_slash = '';
1397      }
1398  
1399      // Split it
1400      $attrarr = wp_kses_hair_parse( $attr );
1401      if ( false === $attrarr ) {
1402          return false;
1403      }
1404  
1405      // Make sure all input is returned by adding front and back matter.
1406      array_unshift( $attrarr, $begin . $slash . $elname );
1407      array_push( $attrarr, $xhtml_slash . $end );
1408  
1409      return $attrarr;
1410  }
1411  
1412  /**
1413   * Builds an attribute list from string containing attributes.
1414   *
1415   * Does not modify input.  May return "evil" output.
1416   * In case of unexpected input, returns false instead of stripping things.
1417   *
1418   * Based on `wp_kses_hair()` but does not return a multi-dimensional array.
1419   *
1420   * @since 4.2.3
1421   *
1422   * @param string $attr Attribute list from HTML element to closing HTML element tag.
1423   * @return array|bool List of attributes found in $attr. Returns false on failure.
1424   */
1425  function wp_kses_hair_parse( $attr ) {
1426      if ( '' === $attr ) {
1427          return array();
1428      }
1429  
1430      // phpcs:disable Squiz.Strings.ConcatenationSpacing.PaddingFound -- don't remove regex indentation
1431      $regex =
1432      '(?:'
1433      .     '[-a-zA-Z:]+'   // Attribute name.
1434      . '|'
1435      .     '\[\[?[^\[\]]+\]\]?' // Shortcode in the name position implies unfiltered_html.
1436      . ')'
1437      . '(?:'               // Attribute value.
1438      .     '\s*=\s*'       // All values begin with '='
1439      .     '(?:'
1440      .         '"[^"]*"'   // Double-quoted
1441      .     '|'
1442      .         "'[^']*'"   // Single-quoted
1443      .     '|'
1444      .         '[^\s"\']+' // Non-quoted
1445      .         '(?:\s|$)'  // Must have a space
1446      .     ')'
1447      . '|'
1448      .     '(?:\s|$)'      // If attribute has no value, space is required.
1449      . ')'
1450      . '\s*';              // Trailing space is optional except as mentioned above.
1451      // phpcs:enable
1452  
1453      // Although it is possible to reduce this procedure to a single regexp,
1454      // we must run that regexp twice to get exactly the expected result.
1455  
1456      $validation = "%^($regex)+$%";
1457      $extraction = "%$regex%";
1458  
1459      if ( 1 === preg_match( $validation, $attr ) ) {
1460          preg_match_all( $extraction, $attr, $attrarr );
1461          return $attrarr[0];
1462      } else {
1463          return false;
1464      }
1465  }
1466  
1467  /**
1468   * Performs different checks for attribute values.
1469   *
1470   * The currently implemented checks are "maxlen", "minlen", "maxval", "minval",
1471   * and "valueless".
1472   *
1473   * @since 1.0.0
1474   *
1475   * @param string $value      Attribute value.
1476   * @param string $vless      Whether the attribute is valueless. Use 'y' or 'n'.
1477   * @param string $checkname  What $checkvalue is checking for.
1478   * @param mixed  $checkvalue What constraint the value should pass.
1479   * @return bool Whether check passes.
1480   */
1481  function wp_kses_check_attr_val( $value, $vless, $checkname, $checkvalue ) {
1482      $ok = true;
1483  
1484      switch ( strtolower( $checkname ) ) {
1485          case 'maxlen':
1486              // The maxlen check makes sure that the attribute value has a length not
1487              // greater than the given value. This can be used to avoid Buffer Overflows
1488              // in WWW clients and various Internet servers.
1489  
1490              if ( strlen( $value ) > $checkvalue ) {
1491                  $ok = false;
1492              }
1493              break;
1494  
1495          case 'minlen':
1496              // The minlen check makes sure that the attribute value has a length not
1497              // smaller than the given value.
1498  
1499              if ( strlen( $value ) < $checkvalue ) {
1500                  $ok = false;
1501              }
1502              break;
1503  
1504          case 'maxval':
1505              // The maxval check does two things: it checks that the attribute value is
1506              // an integer from 0 and up, without an excessive amount of zeroes or
1507              // whitespace (to avoid Buffer Overflows). It also checks that the attribute
1508              // value is not greater than the given value.
1509              // This check can be used to avoid Denial of Service attacks.
1510  
1511              if ( ! preg_match( '/^\s{0,6}[0-9]{1,6}\s{0,6}$/', $value ) ) {
1512                  $ok = false;
1513              }
1514              if ( $value > $checkvalue ) {
1515                  $ok = false;
1516              }
1517              break;
1518  
1519          case 'minval':
1520              // The minval check makes sure that the attribute value is a positive integer,
1521              // and that it is not smaller than the given value.
1522  
1523              if ( ! preg_match( '/^\s{0,6}[0-9]{1,6}\s{0,6}$/', $value ) ) {
1524                  $ok = false;
1525              }
1526              if ( $value < $checkvalue ) {
1527                  $ok = false;
1528              }
1529              break;
1530  
1531          case 'valueless':
1532              // The valueless check makes sure if the attribute has a value
1533              // (like `<a href="blah">`) or not (`<option selected>`). If the given value
1534              // is a "y" or a "Y", the attribute must not have a value.
1535              // If the given value is an "n" or an "N", the attribute must have a value.
1536  
1537              if ( strtolower( $checkvalue ) != $vless ) {
1538                  $ok = false;
1539              }
1540              break;
1541      } // switch
1542  
1543      return $ok;
1544  }
1545  
1546  /**
1547   * Sanitizes a string and removed disallowed URL protocols.
1548   *
1549   * This function removes all non-allowed protocols from the beginning of the
1550   * string. It ignores whitespace and the case of the letters, and it does
1551   * understand HTML entities. It does its work recursively, so it won't be
1552   * fooled by a string like `javascript:javascript:alert(57)`.
1553   *
1554   * @since 1.0.0
1555   *
1556   * @param string   $string            Content to filter bad protocols from.
1557   * @param string[] $allowed_protocols Array of allowed URL protocols.
1558   * @return string Filtered content.
1559   */
1560  function wp_kses_bad_protocol( $string, $allowed_protocols ) {
1561      $string     = wp_kses_no_null( $string );
1562      $iterations = 0;
1563  
1564      do {
1565          $original_string = $string;
1566          $string          = wp_kses_bad_protocol_once( $string, $allowed_protocols );
1567      } while ( $original_string != $string && ++$iterations < 6 );
1568  
1569      if ( $original_string != $string ) {
1570          return '';
1571      }
1572  
1573      return $string;
1574  }
1575  
1576  /**
1577   * Removes any invalid control characters in a text string.
1578   *
1579   * Also removes any instance of the `\0` string.
1580   *
1581   * @since 1.0.0
1582   *
1583   * @param string $string  Content to filter null characters from.
1584   * @param array  $options Set 'slash_zero' => 'keep' when '\0' is allowed. Default is 'remove'.
1585   * @return string Filtered content.
1586   */
1587  function wp_kses_no_null( $string, $options = null ) {
1588      if ( ! isset( $options['slash_zero'] ) ) {
1589          $options = array( 'slash_zero' => 'remove' );
1590      }
1591  
1592      $string = preg_replace( '/[\x00-\x08\x0B\x0C\x0E-\x1F]/', '', $string );
1593      if ( 'remove' == $options['slash_zero'] ) {
1594          $string = preg_replace( '/\\\\+0+/', '', $string );
1595      }
1596  
1597      return $string;
1598  }
1599  
1600  /**
1601   * Strips slashes from in front of quotes.
1602   *
1603   * This function changes the character sequence `\"` to just `"`. It leaves all other
1604   * slashes alone. The quoting from `preg_replace(//e)` requires this.
1605   *
1606   * @since 1.0.0
1607   *
1608   * @param string $string String to strip slashes from.
1609   * @return string Fixed string with quoted slashes.
1610   */
1611  function wp_kses_stripslashes( $string ) {
1612      return preg_replace( '%\\\\"%', '"', $string );
1613  }
1614  
1615  /**
1616   * Converts the keys of an array to lowercase.
1617   *
1618   * @since 1.0.0
1619   *
1620   * @param array $inarray Unfiltered array.
1621   * @return array Fixed array with all lowercase keys.
1622   */
1623  function wp_kses_array_lc( $inarray ) {
1624      $outarray = array();
1625  
1626      foreach ( (array) $inarray as $inkey => $inval ) {
1627          $outkey              = strtolower( $inkey );
1628          $outarray[ $outkey ] = array();
1629  
1630          foreach ( (array) $inval as $inkey2 => $inval2 ) {
1631              $outkey2                         = strtolower( $inkey2 );
1632              $outarray[ $outkey ][ $outkey2 ] = $inval2;
1633          }
1634      }
1635  
1636      return $outarray;
1637  }
1638  
1639  /**
1640   * Handles parsing errors in `wp_kses_hair()`.
1641   *
1642   * The general plan is to remove everything to and including some whitespace,
1643   * but it deals with quotes and apostrophes as well.
1644   *
1645   * @since 1.0.0
1646   *
1647   * @param string $string
1648   * @return string
1649   */
1650  function wp_kses_html_error( $string ) {
1651      return preg_replace( '/^("[^"]*("|$)|\'[^\']*(\'|$)|\S)*\s*/', '', $string );
1652  }
1653  
1654  /**
1655   * Sanitizes content from bad protocols and other characters.
1656   *
1657   * This function searches for URL protocols at the beginning of the string, while
1658   * handling whitespace and HTML entities.
1659   *
1660   * @since 1.0.0
1661   *
1662   * @param string   $string            Content to check for bad protocols.
1663   * @param string[] $allowed_protocols Array of allowed URL protocols.
1664   * @return string Sanitized content.
1665   */
1666  function wp_kses_bad_protocol_once( $string, $allowed_protocols, $count = 1 ) {
1667      $string2 = preg_split( '/:|&#0*58;|&#x0*3a;/i', $string, 2 );
1668      if ( isset( $string2[1] ) && ! preg_match( '%/\?%', $string2[0] ) ) {
1669          $string   = trim( $string2[1] );
1670          $protocol = wp_kses_bad_protocol_once2( $string2[0], $allowed_protocols );
1671          if ( 'feed:' == $protocol ) {
1672              if ( $count > 2 ) {
1673                  return '';
1674              }
1675              $string = wp_kses_bad_protocol_once( $string, $allowed_protocols, ++$count );
1676              if ( empty( $string ) ) {
1677                  return $string;
1678              }
1679          }
1680          $string = $protocol . $string;
1681      }
1682  
1683      return $string;
1684  }
1685  
1686  /**
1687   * Callback for `wp_kses_bad_protocol_once()` regular expression.
1688   *
1689   * This function processes URL protocols, checks to see if they're in the
1690   * whitelist or not, and returns different data depending on the answer.
1691   *
1692   * @access private
1693   * @ignore
1694   * @since 1.0.0
1695   *
1696   * @param string   $string            URI scheme to check against the whitelist.
1697   * @param string[] $allowed_protocols Array of allowed URL protocols.
1698   * @return string Sanitized content.
1699   */
1700  function wp_kses_bad_protocol_once2( $string, $allowed_protocols ) {
1701      $string2 = wp_kses_decode_entities( $string );
1702      $string2 = preg_replace( '/\s/', '', $string2 );
1703      $string2 = wp_kses_no_null( $string2 );
1704      $string2 = strtolower( $string2 );
1705  
1706      $allowed = false;
1707      foreach ( (array) $allowed_protocols as $one_protocol ) {
1708          if ( strtolower( $one_protocol ) == $string2 ) {
1709              $allowed = true;
1710              break;
1711          }
1712      }
1713  
1714      if ( $allowed ) {
1715          return "$string2:";
1716      } else {
1717          return '';
1718      }
1719  }
1720  
1721  /**
1722   * Converts and fixes HTML entities.
1723   *
1724   * This function normalizes HTML entities. It will convert `AT&T` to the correct
1725   * `AT&amp;T`, `&#00058;` to `&#58;`, `&#XYZZY;` to `&amp;#XYZZY;` and so on.
1726   *
1727   * @since 1.0.0
1728   *
1729   * @param string $string Content to normalize entities.
1730   * @return string Content with normalized entities.
1731   */
1732  function wp_kses_normalize_entities( $string ) {
1733      // Disarm all entities by converting & to &amp;
1734      $string = str_replace( '&', '&amp;', $string );
1735  
1736      // Change back the allowed entities in our entity whitelist
1737      $string = preg_replace_callback( '/&amp;([A-Za-z]{2,8}[0-9]{0,2});/', 'wp_kses_named_entities', $string );
1738      $string = preg_replace_callback( '/&amp;#(0*[0-9]{1,7});/', 'wp_kses_normalize_entities2', $string );
1739      $string = preg_replace_callback( '/&amp;#[Xx](0*[0-9A-Fa-f]{1,6});/', 'wp_kses_normalize_entities3', $string );
1740  
1741      return $string;
1742  }
1743  
1744  /**
1745   * Callback for `wp_kses_normalize_entities()` regular expression.
1746   *
1747   * This function only accepts valid named entity references, which are finite,
1748   * case-sensitive, and highly scrutinized by HTML and XML validators.
1749   *
1750   * @since 3.0.0
1751   *
1752   * @global array $allowedentitynames
1753   *
1754   * @param array $matches preg_replace_callback() matches array.
1755   * @return string Correctly encoded entity.
1756   */
1757  function wp_kses_named_entities( $matches ) {
1758      global $allowedentitynames;
1759  
1760      if ( empty( $matches[1] ) ) {
1761          return '';
1762      }
1763  
1764      $i = $matches[1];
1765      return ( ! in_array( $i, $allowedentitynames ) ) ? "&amp;$i;" : "&$i;";
1766  }
1767  
1768  /**
1769   * Callback for `wp_kses_normalize_entities()` regular expression.
1770   *
1771   * This function helps `wp_kses_normalize_entities()` to only accept 16-bit
1772   * values and nothing more for `&#number;` entities.
1773   *
1774   * @access private
1775   * @ignore
1776   * @since 1.0.0
1777   *
1778   * @param array $matches `preg_replace_callback()` matches array.
1779   * @return string Correctly encoded entity.
1780   */
1781  function wp_kses_normalize_entities2( $matches ) {
1782      if ( empty( $matches[1] ) ) {
1783          return '';
1784      }
1785  
1786      $i = $matches[1];
1787      if ( valid_unicode( $i ) ) {
1788          $i = str_pad( ltrim( $i, '0' ), 3, '0', STR_PAD_LEFT );
1789          $i = "&#$i;";
1790      } else {
1791          $i = "&amp;#$i;";
1792      }
1793  
1794      return $i;
1795  }
1796  
1797  /**
1798   * Callback for `wp_kses_normalize_entities()` for regular expression.
1799   *
1800   * This function helps `wp_kses_normalize_entities()` to only accept valid Unicode
1801   * numeric entities in hex form.
1802   *
1803   * @since 2.7.0
1804   * @access private
1805   * @ignore
1806   *
1807   * @param array $matches `preg_replace_callback()` matches array.
1808   * @return string Correctly encoded entity.
1809   */
1810  function wp_kses_normalize_entities3( $matches ) {
1811      if ( empty( $matches[1] ) ) {
1812          return '';
1813      }
1814  
1815      $hexchars = $matches[1];
1816      return ( ! valid_unicode( hexdec( $hexchars ) ) ) ? "&amp;#x$hexchars;" : '&#x' . ltrim( $hexchars, '0' ) . ';';
1817  }
1818  
1819  /**
1820   * Determines if a Unicode codepoint is valid.
1821   *
1822   * @since 2.7.0
1823   *
1824   * @param int $i Unicode codepoint.
1825   * @return bool Whether or not the codepoint is a valid Unicode codepoint.
1826   */
1827  function valid_unicode( $i ) {
1828      return ( $i == 0x9 || $i == 0xa || $i == 0xd ||
1829              ( $i >= 0x20 && $i <= 0xd7ff ) ||
1830              ( $i >= 0xe000 && $i <= 0xfffd ) ||
1831              ( $i >= 0x10000 && $i <= 0x10ffff ) );
1832  }
1833  
1834  /**
1835   * Converts all numeric HTML entities to their named counterparts.
1836   *
1837   * This function decodes numeric HTML entities (`&#65;` and `&#x41;`).
1838   * It doesn't do anything with named entities like `&auml;`, but we don't
1839   * need them in the URL protocol whitelisting system anyway.
1840   *
1841   * @since 1.0.0
1842   *
1843   * @param string $string Content to change entities.
1844   * @return string Content after decoded entities.
1845   */
1846  function wp_kses_decode_entities( $string ) {
1847      $string = preg_replace_callback( '/&#([0-9]+);/', '_wp_kses_decode_entities_chr', $string );
1848      $string = preg_replace_callback( '/&#[Xx]([0-9A-Fa-f]+);/', '_wp_kses_decode_entities_chr_hexdec', $string );
1849  
1850      return $string;
1851  }
1852  
1853  /**
1854   * Regex callback for `wp_kses_decode_entities()`.
1855   *
1856   * @since 2.9.0
1857   * @access private
1858   * @ignore
1859   *
1860   * @param array $match preg match
1861   * @return string
1862   */
1863  function _wp_kses_decode_entities_chr( $match ) {
1864      return chr( $match[1] );
1865  }
1866  
1867  /**
1868   * Regex callback for `wp_kses_decode_entities()`.
1869   *
1870   * @since 2.9.0
1871   * @access private
1872   * @ignore
1873   *
1874   * @param array $match preg match
1875   * @return string
1876   */
1877  function _wp_kses_decode_entities_chr_hexdec( $match ) {
1878      return chr( hexdec( $match[1] ) );
1879  }
1880  
1881  /**
1882   * Sanitize content with allowed HTML KSES rules.
1883   *
1884   * This function expects slashed data.
1885   *
1886   * @since 1.0.0
1887   *
1888   * @param string $data Content to filter, expected to be escaped with slashes.
1889   * @return string Filtered content.
1890   */
1891  function wp_filter_kses( $data ) {
1892      return addslashes( wp_kses( stripslashes( $data ), current_filter() ) );
1893  }
1894  
1895  /**
1896   * Sanitize content with allowed HTML KSES rules.
1897   *
1898   * This function expects unslashed data.
1899   *
1900   * @since 2.9.0
1901   *
1902   * @param string $data Content to filter, expected to not be escaped.
1903   * @return string Filtered content.
1904   */
1905  function wp_kses_data( $data ) {
1906      return wp_kses( $data, current_filter() );
1907  }
1908  
1909  /**
1910   * Sanitizes content for allowed HTML tags for post content.
1911   *
1912   * Post content refers to the page contents of the 'post' type and not `$_POST`
1913   * data from forms.
1914   *
1915   * This function expects slashed data.
1916   *
1917   * @since 2.0.0
1918   *
1919   * @param string $data Post content to filter, expected to be escaped with slashes.
1920   * @return string Filtered post content with allowed HTML tags and attributes intact.
1921   */
1922  function wp_filter_post_kses( $data ) {
1923      return addslashes( wp_kses( stripslashes( $data ), 'post' ) );
1924  }
1925  
1926  /**
1927   * Sanitizes content for allowed HTML tags for post content.
1928   *
1929   * Post content refers to the page contents of the 'post' type and not `$_POST`
1930   * data from forms.
1931   *
1932   * This function expects unslashed data.
1933   *
1934   * @since 2.9.0
1935   *
1936   * @param string $data Post content to filter.
1937   * @return string Filtered post content with allowed HTML tags and attributes intact.
1938   */
1939  function wp_kses_post( $data ) {
1940      return wp_kses( $data, 'post' );
1941  }
1942  
1943  /**
1944   * Navigates through an array, object, or scalar, and sanitizes content for
1945   * allowed HTML tags for post content.
1946   *
1947   * @since 4.4.2
1948   *
1949   * @see map_deep()
1950   *
1951   * @param mixed $data The array, object, or scalar value to inspect.
1952   * @return mixed The filtered content.
1953   */
1954  function wp_kses_post_deep( $data ) {
1955      return map_deep( $data, 'wp_kses_post' );
1956  }
1957  
1958  /**
1959   * Strips all HTML from a text string.
1960   *
1961   * This function expects slashed data.
1962   *
1963   * @since 2.1.0
1964   *
1965   * @param string $data Content to strip all HTML from.
1966   * @return string Filtered content without any HTML.
1967   */
1968  function wp_filter_nohtml_kses( $data ) {
1969      return addslashes( wp_kses( stripslashes( $data ), 'strip' ) );
1970  }
1971  
1972  /**
1973   * Adds all KSES input form content filters.
1974   *
1975   * All hooks have default priority. The `wp_filter_kses()` function is added to
1976   * the 'pre_comment_content' and 'title_save_pre' hooks.
1977   *
1978   * The `wp_filter_post_kses()` function is added to the 'content_save_pre',
1979   * 'excerpt_save_pre', and 'content_filtered_save_pre' hooks.
1980   *
1981   * @since 2.0.0
1982   */
1983  function kses_init_filters() {
1984      // Normal filtering
1985      add_filter( 'title_save_pre', 'wp_filter_kses' );
1986  
1987      // Comment filtering
1988      if ( current_user_can( 'unfiltered_html' ) ) {
1989          add_filter( 'pre_comment_content', 'wp_filter_post_kses' );
1990      } else {
1991          add_filter( 'pre_comment_content', 'wp_filter_kses' );
1992      }
1993  
1994      // Post filtering
1995      add_filter( 'content_save_pre', 'wp_filter_post_kses' );
1996      add_filter( 'excerpt_save_pre', 'wp_filter_post_kses' );
1997      add_filter( 'content_filtered_save_pre', 'wp_filter_post_kses' );
1998  }
1999  
2000  /**
2001   * Removes all KSES input form content filters.
2002   *
2003   * A quick procedural method to removing all of the filters that KSES uses for
2004   * content in WordPress Loop.
2005   *
2006   * Does not remove the `kses_init()` function from {@see 'init'} hook (priority is
2007   * default). Also does not remove `kses_init()` function from {@see 'set_current_user'}
2008   * hook (priority is also default).
2009   *
2010   * @since 2.0.6
2011   */
2012  function kses_remove_filters() {
2013      // Normal filtering
2014      remove_filter( 'title_save_pre', 'wp_filter_kses' );
2015  
2016      // Comment filtering
2017      remove_filter( 'pre_comment_content', 'wp_filter_post_kses' );
2018      remove_filter( 'pre_comment_content', 'wp_filter_kses' );
2019  
2020      // Post filtering
2021      remove_filter( 'content_save_pre', 'wp_filter_post_kses' );
2022      remove_filter( 'excerpt_save_pre', 'wp_filter_post_kses' );
2023      remove_filter( 'content_filtered_save_pre', 'wp_filter_post_kses' );
2024  }
2025  
2026  /**
2027   * Sets up most of the KSES filters for input form content.
2028   *
2029   * First removes all of the KSES filters in case the current user does not need
2030   * to have KSES filter the content. If the user does not have `unfiltered_html`
2031   * capability, then KSES filters are added.
2032   *
2033   * @since 2.0.0
2034   */
2035  function kses_init() {
2036      kses_remove_filters();
2037  
2038      if ( ! current_user_can( 'unfiltered_html' ) ) {
2039          kses_init_filters();
2040      }
2041  }
2042  
2043  /**
2044   * Filters an inline style attribute and removes disallowed rules.
2045   *
2046   * @since 2.8.1
2047   *
2048   * @param string $css        A string of CSS rules.
2049   * @param string $deprecated Not used.
2050   * @return string Filtered string of CSS rules.
2051   */
2052  function safecss_filter_attr( $css, $deprecated = '' ) {
2053      if ( ! empty( $deprecated ) ) {
2054          _deprecated_argument( __FUNCTION__, '2.8.1' ); // Never implemented
2055      }
2056  
2057      $css = wp_kses_no_null( $css );
2058      $css = str_replace( array( "\n", "\r", "\t" ), '', $css );
2059  
2060      $allowed_protocols = wp_allowed_protocols();
2061  
2062      $css_array = explode( ';', trim( $css ) );
2063  
2064      /**
2065       * Filters list of allowed CSS attributes.
2066       *
2067       * @since 2.8.1
2068       * @since 4.4.0 Added support for `min-height`, `max-height`, `min-width`, and `max-width`.
2069       * @since 4.6.0 Added support for `list-style-type`.
2070       * @since 5.0.0 Added support for `background-image`.
2071       * @since 5.1.0 Added support for `text-transform`.
2072       * @since 5.2.0 Added support for `background-position` and `grid-template-columns`
2073       * @since 5.3.0 Added support for `flex`, `flex-grow`, `flex-shrink`, and `flex-basis`.
2074       *
2075       * @param string[] $attr Array of allowed CSS attributes.
2076       */
2077      $allowed_attr = apply_filters(
2078          'safe_style_css',
2079          array(
2080              'background',
2081              'background-color',
2082              'background-image',
2083              'background-position',
2084  
2085              'border',
2086              'border-width',
2087              'border-color',
2088              'border-style',
2089              'border-right',
2090              'border-right-color',
2091              'border-right-style',
2092              'border-right-width',
2093              'border-bottom',
2094              'border-bottom-color',
2095              'border-bottom-style',
2096              'border-bottom-width',
2097              'border-left',
2098              'border-left-color',
2099              'border-left-style',
2100              'border-left-width',
2101              'border-top',
2102              'border-top-color',
2103              'border-top-style',
2104              'border-top-width',
2105  
2106              'border-spacing',
2107              'border-collapse',
2108              'caption-side',
2109  
2110              'color',
2111              'font',
2112              'font-family',
2113              'font-size',
2114              'font-style',
2115              'font-variant',
2116              'font-weight',
2117              'letter-spacing',
2118              'line-height',
2119              'text-align',
2120              'text-decoration',
2121              'text-indent',
2122              'text-transform',
2123  
2124              'height',
2125              'min-height',
2126              'max-height',
2127  
2128              'width',
2129              'min-width',
2130              'max-width',
2131  
2132              'margin',
2133              'margin-right',
2134              'margin-bottom',
2135              'margin-left',
2136              'margin-top',
2137  
2138              'padding',
2139              'padding-right',
2140              'padding-bottom',
2141              'padding-left',
2142              'padding-top',
2143  
2144              'flex',
2145              'flex-grow',
2146              'flex-shrink',
2147              'flex-basis',
2148  
2149              'clear',
2150              'cursor',
2151              'direction',
2152              'float',
2153              'overflow',
2154              'vertical-align',
2155              'list-style-type',
2156              'grid-template-columns',
2157          )
2158      );
2159  
2160      /*
2161       * CSS attributes that accept URL data types.
2162       *
2163       * This is in accordance to the CSS spec and unrelated to
2164       * the sub-set of supported attributes above.
2165       *
2166       * See: https://developer.mozilla.org/en-US/docs/Web/CSS/url
2167       */
2168      $css_url_data_types = array(
2169          'background',
2170          'background-image',
2171  
2172          'cursor',
2173  
2174          'list-style',
2175          'list-style-image',
2176      );
2177  
2178      if ( empty( $allowed_attr ) ) {
2179          return $css;
2180      }
2181  
2182      $css = '';
2183      foreach ( $css_array as $css_item ) {
2184          if ( $css_item == '' ) {
2185              continue;
2186          }
2187  
2188          $css_item        = trim( $css_item );
2189          $css_test_string = $css_item;
2190          $found           = false;
2191          $url_attr        = false;
2192  
2193          if ( strpos( $css_item, ':' ) === false ) {
2194              $found = true;
2195          } else {
2196              $parts        = explode( ':', $css_item, 2 );
2197              $css_selector = trim( $parts[0] );
2198  
2199              if ( in_array( $css_selector, $allowed_attr, true ) ) {
2200                  $found    = true;
2201                  $url_attr = in_array( $css_selector, $css_url_data_types, true );
2202              }
2203          }
2204  
2205          if ( $found && $url_attr ) {
2206              // Simplified: matches the sequence `url(*)`.
2207              preg_match_all( '/url\([^)]+\)/', $parts[1], $url_matches );
2208  
2209              foreach ( $url_matches[0] as $url_match ) {
2210                  // Clean up the URL from each of the matches above.
2211                  preg_match( '/^url\(\s*([\'\"]?)(.*)(\g1)\s*\)$/', $url_match, $url_pieces );
2212  
2213                  if ( empty( $url_pieces[2] ) ) {
2214                      $found = false;
2215                      break;
2216                  }
2217  
2218                  $url = trim( $url_pieces[2] );
2219  
2220                  if ( empty( $url ) || $url !== wp_kses_bad_protocol( $url, $allowed_protocols ) ) {
2221                      $found = false;
2222                      break;
2223                  } else {
2224                      // Remove the whole `url(*)` bit that was matched above from the CSS.
2225                      $css_test_string = str_replace( $url_match, '', $css_test_string );
2226                  }
2227              }
2228          }
2229  
2230          // Remove any CSS containing containing \ ( & } = or comments, except for url() useage checked above.
2231          if ( $found && ! preg_match( '%[\\\(&=}]|/\*%', $css_test_string ) ) {
2232              if ( $css != '' ) {
2233                  $css .= ';';
2234              }
2235  
2236              $css .= $css_item;
2237          }
2238      }
2239  
2240      return $css;
2241  }
2242  
2243  /**
2244   * Helper function to add global attributes to a tag in the allowed html list.
2245   *
2246   * @since 3.5.0
2247   * @since 5.0.0 Add support for `data-*` wildcard attributes.
2248   * @access private
2249   * @ignore
2250   *
2251   * @param array $value An array of attributes.
2252   * @return array The array of attributes with global attributes added.
2253   */
2254  function _wp_add_global_attributes( $value ) {
2255      $global_attributes = array(
2256          'aria-describedby' => true,
2257          'aria-details'     => true,
2258          'aria-label'       => true,
2259          'aria-labelledby'  => true,
2260          'aria-hidden'      => true,
2261          'class'            => true,
2262          'id'               => true,
2263          'style'            => true,
2264          'title'            => true,
2265          'role'             => true,
2266          'data-*'           => true,
2267      );
2268  
2269      if ( true === $value ) {
2270          $value = array();
2271      }
2272  
2273      if ( is_array( $value ) ) {
2274          return array_merge( $value, $global_attributes );
2275      }
2276  
2277      return $value;
2278  }


Generated: Tue Jul 16 01:00:03 2019 Cross-referenced by PHPXref 0.7.1