[ Index ]

PHP Cross Reference of YOURLS

title

Body

[close]

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

   1  <?php
   2  /**
   3   * YOURLS modification of a small subset from WordPress' KSES implementation.
   4   * Straight from the Let's Not Reinvent The Wheel department.
   5   */
   6  
   7  /**
   8   * kses 0.2.2 - HTML/XHTML filter that only allows some elements and attributes
   9   * Copyright (C) 2002, 2003, 2005  Ulf Harnhammar
  10   *
  11   * This program is free software and open source software; you can redistribute
  12   * it and/or modify it under the terms of the GNU General Public License as
  13   * published by the Free Software Foundation; either version 2 of the License,
  14   * or (at your option) any later version.
  15   *
  16   * This program is distributed in the hope that it will be useful, but WITHOUT
  17   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  18   * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  19   * more details.
  20   *
  21   * You should have received a copy of the GNU General Public License along
  22   * with this program; if not, write to the Free Software Foundation, Inc.,
  23   * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  24   * http://www.gnu.org/licenses/gpl.html
  25   *
  26   * [kses strips evil scripts!]
  27   *
  28   * @version 0.2.2
  29   * @copyright (C) 2002, 2003, 2005
  30   * @author Ulf Harnhammar <http://advogato.org/person/metaur/>
  31   *
  32   * @package External
  33   * @subpackage KSES
  34   *
  35   */
  36  
  37  /* NOTE ABOUT GLOBALS
  38   * Two globals are defined: $yourls_allowedentitynames and $yourls_allowedprotocols
  39   * - $yourls_allowedentitynames is used internally in KSES functions to sanitize HTML entities
  40   * - $yourls_allowedprotocols is used in various parts of YOURLS, not just in KSES, albeit being defined here
  41   * Two globals are not defined and unused at this moment: $yourls_allowedtags_all and $yourls_allowedtags
  42   * The code for these vars is here and ready for any future use
  43   */
  44  
  45  // Populate after plugins have loaded to allow user defined values
  46  yourls_add_action( 'plugins_loaded', 'yourls_kses_init' );
  47  
  48  /**
  49   * Init KSES globals if not already defined (by a plugin)
  50   *
  51   * @since 1.6
  52   * @return void
  53   */
  54  function yourls_kses_init() {
  55      global $yourls_allowedentitynames, $yourls_allowedprotocols;
  56  
  57      if( ! $yourls_allowedentitynames ) {
  58          $yourls_allowedentitynames = yourls_apply_filter( 'kses_allowed_entities', yourls_kses_allowed_entities() );
  59      }
  60  
  61      if( ! $yourls_allowedprotocols ) {
  62          $yourls_allowedprotocols   = yourls_apply_filter( 'kses_allowed_protocols', yourls_kses_allowed_protocols() );
  63      }
  64  
  65      /** See NOTE ABOUT GLOBALS **
  66  
  67      if( ! $yourls_allowedtags_all ) {
  68          $yourls_allowedtags_all = yourls_kses_allowed_tags_all();
  69          $yourls_allowedtags_all = array_map( '_yourls_add_global_attributes', $yourls_allowedtags_all );
  70          $yourls_allowedtags_all = yourls_apply_filter( 'kses_allowed_tags_all', $yourls_allowedtags_all );
  71      } else {
  72          // User defined: let's sanitize
  73          $yourls_allowedtags_all = yourls_kses_array_lc( $yourls_allowedtags_all );
  74      }
  75  
  76      if( ! $yourls_allowedtags ) {
  77          $yourls_allowedtags = yourls_kses_allowed_tags();
  78          $yourls_allowedtags = array_map( '_yourls_add_global_attributes', $yourls_allowedtags );
  79          $yourls_allowedtags = yourls_apply_filter( 'kses_allowed_tags', $yourls_allowedtags );
  80      } else {
  81          // User defined: let's sanitize
  82          $yourls_allowedtags = yourls_kses_array_lc( $yourls_allowedtags );
  83      }
  84  
  85      /**/
  86  }
  87  
  88  /**
  89   * Kses global for all allowable HTML tags.
  90   *
  91   * Complete (?) list of HTML tags. Keep this function available for any plugin or
  92   * future feature that will want to display lots of HTML.
  93   *
  94   * @since 1.6
  95   *
  96   * @return array All tags
  97   */
  98  function yourls_kses_allowed_tags_all() {
  99      return array(
 100          'address' => array(),
 101          'a' => array(
 102              'href' => true,
 103              'rel' => true,
 104              'rev' => true,
 105              'name' => true,
 106              'target' => true,
 107          ),
 108          'abbr' => array(),
 109          'acronym' => array(),
 110          'area' => array(
 111              'alt' => true,
 112              'coords' => true,
 113              'href' => true,
 114              'nohref' => true,
 115              'shape' => true,
 116              'target' => true,
 117          ),
 118          'article' => array(
 119              'align' => true,
 120              'dir' => true,
 121              'lang' => true,
 122              'xml:lang' => true,
 123          ),
 124          'aside' => array(
 125              'align' => true,
 126              'dir' => true,
 127              'lang' => true,
 128              'xml:lang' => true,
 129          ),
 130          'b' => array(),
 131          'big' => array(),
 132          'blockquote' => array(
 133              'cite' => true,
 134              'lang' => true,
 135              'xml:lang' => true,
 136          ),
 137          'br' => array(),
 138          'button' => array(
 139              'disabled' => true,
 140              'name' => true,
 141              'type' => true,
 142              'value' => true,
 143          ),
 144          'caption' => array(
 145              'align' => true,
 146          ),
 147          'cite' => array(
 148              'dir' => true,
 149              'lang' => true,
 150          ),
 151          'code' => array(),
 152          'col' => array(
 153              'align' => true,
 154              'char' => true,
 155              'charoff' => true,
 156              'span' => true,
 157              'dir' => true,
 158              'valign' => true,
 159              'width' => true,
 160          ),
 161          'del' => array(
 162              'datetime' => true,
 163          ),
 164          'dd' => array(),
 165          'details' => array(
 166              'align' => true,
 167              'dir' => true,
 168              'lang' => true,
 169              'open' => true,
 170              'xml:lang' => true,
 171          ),
 172          'div' => array(
 173              'align' => true,
 174              'dir' => true,
 175              'lang' => true,
 176              'xml:lang' => true,
 177          ),
 178          'dl' => array(),
 179          'dt' => array(),
 180          'em' => array(),
 181          'fieldset' => array(),
 182          'figure' => array(
 183              'align' => true,
 184              'dir' => true,
 185              'lang' => true,
 186              'xml:lang' => true,
 187          ),
 188          'figcaption' => array(
 189              'align' => true,
 190              'dir' => true,
 191              'lang' => true,
 192              'xml:lang' => true,
 193          ),
 194          'font' => array(
 195              'color' => true,
 196              'face' => true,
 197              'size' => true,
 198          ),
 199          'footer' => array(
 200              'align' => true,
 201              'dir' => true,
 202              'lang' => true,
 203              'xml:lang' => true,
 204          ),
 205          'form' => array(
 206              'action' => true,
 207              'accept' => true,
 208              'accept-charset' => true,
 209              'enctype' => true,
 210              'method' => true,
 211              'name' => true,
 212              'target' => true,
 213          ),
 214          'h1' => array(
 215              'align' => true,
 216          ),
 217          'h2' => array(
 218              'align' => true,
 219          ),
 220          'h3' => array(
 221              'align' => true,
 222          ),
 223          'h4' => array(
 224              'align' => true,
 225          ),
 226          'h5' => array(
 227              'align' => true,
 228          ),
 229          'h6' => array(
 230              'align' => true,
 231          ),
 232          'header' => array(
 233              'align' => true,
 234              'dir' => true,
 235              'lang' => true,
 236              'xml:lang' => true,
 237          ),
 238          'hgroup' => array(
 239              'align' => true,
 240              'dir' => true,
 241              'lang' => true,
 242              'xml:lang' => true,
 243          ),
 244          'hr' => array(
 245              'align' => true,
 246              'noshade' => true,
 247              'size' => true,
 248              'width' => true,
 249          ),
 250          'i' => array(),
 251          'img' => array(
 252              'alt' => true,
 253              'align' => true,
 254              'border' => true,
 255              'height' => true,
 256              'hspace' => true,
 257              'longdesc' => true,
 258              'vspace' => true,
 259              'src' => true,
 260              'usemap' => true,
 261              'width' => true,
 262          ),
 263          'ins' => array(
 264              'datetime' => true,
 265              'cite' => true,
 266          ),
 267          'kbd' => array(),
 268          'label' => array(
 269              'for' => true,
 270          ),
 271          'legend' => array(
 272              'align' => true,
 273          ),
 274          'li' => array(
 275              'align' => true,
 276          ),
 277          'map' => array(
 278              'name' => true,
 279          ),
 280          'menu' => array(
 281              'type' => true,
 282          ),
 283          'nav' => array(
 284              'align' => true,
 285              'dir' => true,
 286              'lang' => true,
 287              'xml:lang' => true,
 288          ),
 289          'p' => array(
 290              'align' => true,
 291              'dir' => true,
 292              'lang' => true,
 293              'xml:lang' => true,
 294          ),
 295          'pre' => array(
 296              'width' => true,
 297          ),
 298          'q' => array(
 299              'cite' => true,
 300          ),
 301          's' => array(),
 302          'span' => array(
 303              'dir' => true,
 304              'align' => true,
 305              'lang' => true,
 306              'xml:lang' => true,
 307          ),
 308          'section' => array(
 309              'align' => true,
 310              'dir' => true,
 311              'lang' => true,
 312              'xml:lang' => true,
 313          ),
 314          'small' => array(),
 315          'strike' => array(),
 316          'strong' => array(),
 317          'sub' => array(),
 318          'summary' => array(
 319              'align' => true,
 320              'dir' => true,
 321              'lang' => true,
 322              'xml:lang' => true,
 323          ),
 324          'sup' => array(),
 325          'table' => array(
 326              'align' => true,
 327              'bgcolor' => true,
 328              'border' => true,
 329              'cellpadding' => true,
 330              'cellspacing' => true,
 331              'dir' => true,
 332              'rules' => true,
 333              'summary' => true,
 334              'width' => true,
 335          ),
 336          'tbody' => array(
 337              'align' => true,
 338              'char' => true,
 339              'charoff' => true,
 340              'valign' => true,
 341          ),
 342          'td' => array(
 343              'abbr' => true,
 344              'align' => true,
 345              'axis' => true,
 346              'bgcolor' => true,
 347              'char' => true,
 348              'charoff' => true,
 349              'colspan' => true,
 350              'dir' => true,
 351              'headers' => true,
 352              'height' => true,
 353              'nowrap' => true,
 354              'rowspan' => true,
 355              'scope' => true,
 356              'valign' => true,
 357              'width' => true,
 358          ),
 359          'textarea' => array(
 360              'cols' => true,
 361              'rows' => true,
 362              'disabled' => true,
 363              'name' => true,
 364              'readonly' => true,
 365          ),
 366          'tfoot' => array(
 367              'align' => true,
 368              'char' => true,
 369              'charoff' => true,
 370              'valign' => true,
 371          ),
 372          'th' => array(
 373              'abbr' => true,
 374              'align' => true,
 375              'axis' => true,
 376              'bgcolor' => true,
 377              'char' => true,
 378              'charoff' => true,
 379              'colspan' => true,
 380              'headers' => true,
 381              'height' => true,
 382              'nowrap' => true,
 383              'rowspan' => true,
 384              'scope' => true,
 385              'valign' => true,
 386              'width' => true,
 387          ),
 388          'thead' => array(
 389              'align' => true,
 390              'char' => true,
 391              'charoff' => true,
 392              'valign' => true,
 393          ),
 394          'title' => array(),
 395          'tr' => array(
 396              'align' => true,
 397              'bgcolor' => true,
 398              'char' => true,
 399              'charoff' => true,
 400              'valign' => true,
 401          ),
 402          'tt' => array(),
 403          'u' => array(),
 404          'ul' => array(
 405              'type' => true,
 406          ),
 407          'ol' => array(
 408              'start' => true,
 409              'type' => true,
 410          ),
 411          'var' => array(),
 412      );
 413  }
 414  
 415  /**
 416   * Kses global for default allowable HTML tags. TODO: trim down to necessary only.
 417   *
 418   * Short list of HTML tags used in YOURLS core for display
 419   *
 420   * @since 1.6
 421   *
 422   * @return array Allowed tags
 423   */
 424  function yourls_kses_allowed_tags() {
 425      return array(
 426          'a' => array(
 427              'href' => true,
 428              'title' => true,
 429          ),
 430          'abbr' => array(
 431              'title' => true,
 432          ),
 433          'acronym' => array(
 434              'title' => true,
 435          ),
 436          'b' => array(),
 437          'blockquote' => array(
 438              'cite' => true,
 439          ),
 440          'cite' => array(),
 441          'code' => array(),
 442          'del' => array(
 443              'datetime' => true,
 444          ),
 445          'em' => array(),
 446          'i' => array(),
 447          'q' => array(
 448              'cite' => true,
 449          ),
 450          'strike' => array(),
 451          'strong' => array(),
 452      );
 453  }
 454  
 455  /**
 456   * Kses global for allowable HTML entities.
 457   *
 458   * @since 1.6
 459   *
 460   * @return array Allowed entities
 461   */
 462  function yourls_kses_allowed_entities() {
 463      return array(
 464          'nbsp',    'iexcl',  'cent',    'pound',  'curren', 'yen',
 465          'brvbar',  'sect',   'uml',     'copy',   'ordf',   'laquo',
 466          'not',     'shy',    'reg',     'macr',   'deg',    'plusmn',
 467          'acute',   'micro',  'para',    'middot', 'cedil',  'ordm',
 468          'raquo',   'iquest', 'Agrave',  'Aacute', 'Acirc',  'Atilde',
 469          'Auml',    'Aring',  'AElig',   'Ccedil', 'Egrave', 'Eacute',
 470          'Ecirc',   'Euml',   'Igrave',  'Iacute', 'Icirc',  'Iuml',
 471          'ETH',     'Ntilde', 'Ograve',  'Oacute', 'Ocirc',  'Otilde',
 472          'Ouml',    'times',  'Oslash',  'Ugrave', 'Uacute', 'Ucirc',
 473          'Uuml',    'Yacute', 'THORN',   'szlig',  'agrave', 'aacute',
 474          'acirc',   'atilde', 'auml',    'aring',  'aelig',  'ccedil',
 475          'egrave',  'eacute', 'ecirc',   'euml',   'igrave', 'iacute',
 476          'icirc',   'iuml',   'eth',     'ntilde', 'ograve', 'oacute',
 477          'ocirc',   'otilde', 'ouml',    'divide', 'oslash', 'ugrave',
 478          'uacute',  'ucirc',  'uuml',    'yacute', 'thorn',  'yuml',
 479          'quot',    'amp',    'lt',      'gt',     'apos',   'OElig',
 480          'oelig',   'Scaron', 'scaron',  'Yuml',   'circ',   'tilde',
 481          'ensp',    'emsp',   'thinsp',  'zwnj',   'zwj',    'lrm',
 482          'rlm',     'ndash',  'mdash',   'lsquo',  'rsquo',  'sbquo',
 483          'ldquo',   'rdquo',  'bdquo',   'dagger', 'Dagger', 'permil',
 484          'lsaquo',  'rsaquo', 'euro',    'fnof',   'Alpha',  'Beta',
 485          'Gamma',   'Delta',  'Epsilon', 'Zeta',   'Eta',    'Theta',
 486          'Iota',    'Kappa',  'Lambda',  'Mu',     'Nu',     'Xi',
 487          'Omicron', 'Pi',     'Rho',     'Sigma',  'Tau',    'Upsilon',
 488          'Phi',     'Chi',    'Psi',     'Omega',  'alpha',  'beta',
 489          'gamma',   'delta',  'epsilon', 'zeta',   'eta',    'theta',
 490          'iota',    'kappa',  'lambda',  'mu',     'nu',     'xi',
 491          'omicron', 'pi',     'rho',     'sigmaf', 'sigma',  'tau',
 492          'upsilon', 'phi',    'chi',     'psi',    'omega',  'thetasym',
 493          'upsih',   'piv',    'bull',    'hellip', 'prime',  'Prime',
 494          'oline',   'frasl',  'weierp',  'image',  'real',   'trade',
 495          'alefsym', 'larr',   'uarr',    'rarr',   'darr',   'harr',
 496          'crarr',   'lArr',   'uArr',    'rArr',   'dArr',   'hArr',
 497          'forall',  'part',   'exist',   'empty',  'nabla',  'isin',
 498          'notin',   'ni',     'prod',    'sum',    'minus',  'lowast',
 499          'radic',   'prop',   'infin',   'ang',    'and',    'or',
 500          'cap',     'cup',    'int',     'sim',    'cong',   'asymp',
 501          'ne',      'equiv',  'le',      'ge',     'sub',    'sup',
 502          'nsub',    'sube',   'supe',    'oplus',  'otimes', 'perp',
 503          'sdot',    'lceil',  'rceil',   'lfloor', 'rfloor', 'lang',
 504          'rang',    'loz',    'spades',  'clubs',  'hearts', 'diams',
 505      );
 506  }
 507  
 508  /**
 509   * Kses global for allowable protocols.
 510   *
 511   * @since 1.6
 512   *
 513   * @return array Allowed protocols
 514   */
 515  function yourls_kses_allowed_protocols() {
 516      // More or less common stuff in links. From http://en.wikipedia.org/wiki/URI_scheme
 517      return array(
 518          // Common
 519          'http://', 'https://', 'ftp://',
 520          'file://', 'smb://',
 521          'sftp://',
 522          'feed:', 'feed://',
 523          'mailto:',
 524          'news:', 'nntp://',
 525  
 526          // Old school bearded geek
 527          'gopher://', 'telnet://', 'finger://',
 528          'nntp://', 'worldwind://',
 529  
 530          // Dev
 531          'ssh://', 'svn://', 'svn+ssh://', 'git://', 'cvs://',
 532          'apt:',
 533          'market://', // Google Play
 534          'view-source:',
 535  
 536          // P2P
 537          'ed2k://', 'magnet:', 'udp://',
 538  
 539          // Streaming stuff
 540          'mms://', 'lastfm://', 'spotify:', 'rtsp://',
 541  
 542          // Text & voice
 543          'aim:', 'facetime://', 'gtalk:', 'xmpp:',
 544          'irc://', 'ircs://', 'mumble://',
 545          'callto:', 'skype:', 'sip:',
 546          'teamspeak://', 'tel:', 'ventrilo://', 'xfire:',
 547          'ymsgr:', 'tg://', 'whatsapp://',
 548  
 549          // Misc
 550          'steam:', 'steam://',
 551          'bitcoin:',
 552          'ldap://', 'ldaps://',
 553  
 554          // Purposedly removed for security
 555          /*
 556          'about:', 'chrome://', 'chrome-extension://',
 557          'javascript:',
 558          'data:',
 559          */
 560      );
 561  }
 562  
 563  
 564  /**
 565   * Converts and fixes HTML entities.
 566   *
 567   * This function normalizes HTML entities. It will convert "AT&T" to the correct
 568   * "AT&amp;T", "&#00058;" to "&#58;", "&#XYZZY;" to "&amp;#XYZZY;" and so on.
 569   *
 570   * @since 1.6
 571   *
 572   * @param string $string Content to normalize entities
 573   * @return string Content with normalized entities
 574   */
 575  function yourls_kses_normalize_entities($string) {
 576      # Disarm all entities by converting & to &amp;
 577  
 578      $string = str_replace('&', '&amp;', $string);
 579  
 580      # Change back the allowed entities in our entity whitelist
 581  
 582      $string = preg_replace_callback('/&amp;([A-Za-z]{2,8});/', 'yourls_kses_named_entities', $string);
 583      $string = preg_replace_callback('/&amp;#(0*[0-9]{1,7});/', 'yourls_kses_normalize_entities2', $string);
 584      $string = preg_replace_callback('/&amp;#[Xx](0*[0-9A-Fa-f]{1,6});/', 'yourls_kses_normalize_entities3', $string);
 585  
 586      return $string;
 587  }
 588  
 589  /**
 590   * Callback for yourls_kses_normalize_entities() regular expression.
 591   *
 592   * This function only accepts valid named entity references, which are finite,
 593   * case-sensitive, and highly scrutinized by HTML and XML validators.
 594   *
 595   * @since 1.6
 596   *
 597   * @param array $matches preg_replace_callback() matches array
 598   * @return string Correctly encoded entity
 599   */
 600  function yourls_kses_named_entities($matches) {
 601      global $yourls_allowedentitynames;
 602  
 603      if ( empty($matches[1]) )
 604          return '';
 605  
 606      // KSES globals are normally populated on the 'plugins_loaded' action. This can run
 607      // earlier though (eg yourls_die() on a DB connection error, before plugins load), so
 608      // make sure the allowed entity names are available.
 609      if ( ! is_array($yourls_allowedentitynames) ) {
 610          yourls_kses_init();
 611      }
 612  
 613      $i = $matches[1];
 614      return ( ( ! in_array($i, $yourls_allowedentitynames) ) ? "&amp;$i;" : "&$i;" );
 615  }
 616  
 617  /**
 618   * Callback for yourls_kses_normalize_entities() regular expression.
 619   *
 620   * This function helps yourls_kses_normalize_entities() to only accept 16-bit values
 621   * and nothing more for &#number; entities.
 622   *
 623   * @access private
 624   * @since 1.6
 625   *
 626   * @param array $matches preg_replace_callback() matches array
 627   * @return string Correctly encoded entity
 628   */
 629  function yourls_kses_normalize_entities2($matches) {
 630      if ( empty($matches[1]) )
 631          return '';
 632  
 633      $i = $matches[1];
 634      if (yourls_valid_unicode($i)) {
 635          $i = str_pad(ltrim($i,'0'), 3, '0', STR_PAD_LEFT);
 636          $i = "&#$i;";
 637      } else {
 638          $i = "&amp;#$i;";
 639      }
 640  
 641      return $i;
 642  }
 643  
 644  /**
 645   * Callback for yourls_kses_normalize_entities() for regular expression.
 646   *
 647   * This function helps yourls_kses_normalize_entities() to only accept valid Unicode
 648   * numeric entities in hex form.
 649   *
 650   * @access private
 651   * @since 1.6
 652   *
 653   * @param array $matches preg_replace_callback() matches array
 654   * @return string Correctly encoded entity
 655   */
 656  function yourls_kses_normalize_entities3($matches) {
 657      if ( empty($matches[1]) )
 658          return '';
 659  
 660      $hexchars = $matches[1];
 661      return ( ( ! yourls_valid_unicode(hexdec($hexchars)) ) ? "&amp;#x$hexchars;" : '&#x'.ltrim($hexchars,'0').';' );
 662  }
 663  
 664  /**
 665   * Helper function to add global attributes to a tag in the allowed html list.
 666   *
 667   * @since 1.6
 668   * @access private
 669   *
 670   * @param array $value An array of attributes.
 671   * @return array The array of attributes with global attributes added.
 672   */
 673  function _yourls_add_global_attributes( $value ) {
 674      $global_attributes = array(
 675          'class' => true,
 676          'id' => true,
 677          'style' => true,
 678          'title' => true,
 679      );
 680  
 681      if ( true === $value )
 682          $value = array();
 683  
 684      if ( is_array( $value ) )
 685          return array_merge( $value, $global_attributes );
 686  
 687      return $value;
 688  }
 689  
 690  /**
 691   * Helper function to determine if a Unicode value is valid.
 692   *
 693   * @since 1.6
 694   *
 695   * @param int $i Unicode value
 696   * @return bool True if the value was a valid Unicode number
 697   */
 698  function yourls_valid_unicode($i) {
 699      return ( $i == 0x9 || $i == 0xa || $i == 0xd ||
 700              ($i >= 0x20 && $i <= 0xd7ff) ||
 701              ($i >= 0xe000 && $i <= 0xfffd) ||
 702              ($i >= 0x10000 && $i <= 0x10ffff) );
 703  }
 704  
 705  /**
 706   * Goes through an array and changes the keys to all lower case.
 707   *
 708   * @since 1.6
 709   *
 710   * @param array $inarray Unfiltered array
 711   * @return array Fixed array with all lowercase keys
 712   */
 713  function yourls_kses_array_lc($inarray) {
 714      $outarray = array ();
 715  
 716      foreach ( (array) $inarray as $inkey => $inval) {
 717          $outkey = strtolower($inkey);
 718          $outarray[$outkey] = array ();
 719  
 720          foreach ( (array) $inval as $inkey2 => $inval2) {
 721              $outkey2 = strtolower($inkey2);
 722              $outarray[$outkey][$outkey2] = $inval2;
 723          } # foreach $inval
 724      } # foreach $inarray
 725  
 726      return $outarray;
 727  }
 728  
 729  /**
 730   * Convert all entities to their character counterparts.
 731   *
 732   * This function decodes numeric HTML entities (&#65; and &#x41;). It doesn't do
 733   * anything with other entities like &auml;, but we don't need them in the URL
 734   * protocol whitelisting system anyway.
 735   *
 736   * @since 1.6
 737   *
 738   * @param string $string Content to change entities
 739   * @return string Content after decoded entities
 740   */
 741  function yourls_kses_decode_entities($string) {
 742      $string = preg_replace_callback('/&#([0-9]+);/', '_yourls_kses_decode_entities_chr', $string);
 743      $string = preg_replace_callback('/&#[Xx]([0-9A-Fa-f]+);/', '_yourls_kses_decode_entities_chr_hexdec', $string);
 744  
 745      return $string;
 746  }
 747  
 748  /**
 749   * Regex callback for yourls_kses_decode_entities()
 750   *
 751   * @since 1.6
 752   *
 753   * @param array $match preg match
 754   * @return string
 755   */
 756  function _yourls_kses_decode_entities_chr( $match ) {
 757      return chr( $match[1] );
 758  }
 759  
 760  /**
 761   * Regex callback for yourls_kses_decode_entities()
 762   *
 763   * @since 1.6
 764   *
 765   * @param array $match preg match
 766   * @return string
 767   */
 768  function _yourls_kses_decode_entities_chr_hexdec( $match ) {
 769      return chr( hexdec( $match[1] ) );
 770  }
 771  
 772  /**
 773   * Removes any null characters in $string.
 774   *
 775   * @since 1.6
 776   *
 777   * @param string $string
 778   * @return string
 779   */
 780  function yourls_kses_no_null($string) {
 781      $string = preg_replace( '/\0+/', '', $string );
 782      $string = preg_replace( '/(\\\\0)+/', '', $string );
 783  
 784      return $string;
 785  }


Generated: Sun Aug 9 05:10:27 2026 Cross-referenced by PHPXref 0.7.1