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