web/wp-includes/kses.php
changeset 194 32102edaa81b
parent 136 bde1974c263b
child 204 09a1c134465b
equal deleted inserted replaced
193:2f6f6f7551ca 194:32102edaa81b
     1 <?php
     1 <?php
     2 /**
     2 /**
     3  * HTML/XHTML filter that only allows some elements and attributes
     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!]
     4  *
    22  *
     5  * Added wp_ prefix to avoid conflicts with existing kses users
    23  * Added wp_ prefix to avoid conflicts with existing kses users
     6  *
    24  *
     7  * @version 0.2.2
    25  * @version 0.2.2
     8  * @copyright (C) 2002, 2003, 2005
    26  * @copyright (C) 2002, 2003, 2005
     9  * @author Ulf Harnhammar <metaur@users.sourceforge.net>
    27  * @author Ulf Harnhammar <http://advogato.org/person/metaur/>
    10  *
    28  *
    11  * @package External
    29  * @package External
    12  * @subpackage KSES
    30  * @subpackage KSES
    13  *
    31  *
    14  * @internal
    32  */
    15  * *** CONTACT INFORMATION ***
    33 
    16  * E-mail:      metaur at users dot sourceforge dot net
    34 /**
    17  * Web page:    http://sourceforge.net/projects/kses
    35  * You can override this in a plugin.
    18  * Paper mail:  Ulf Harnhammar
       
    19  *              Ymergatan 17 C
       
    20  *              753 25  Uppsala
       
    21  *              SWEDEN
       
    22  *
       
    23  * [kses strips evil scripts!]
       
    24  */
       
    25 
       
    26 /**
       
    27  * You can override this in your my-hacks.php file You can also override this
       
    28  * in a plugin file. The my-hacks.php is deprecated in its usage.
       
    29  *
    36  *
    30  * @since 1.2.0
    37  * @since 1.2.0
    31  */
    38  */
    32 if (!defined('CUSTOM_TAGS'))
    39 if ( ! defined( 'CUSTOM_TAGS' ) )
    33 	define('CUSTOM_TAGS', false);
    40 	define( 'CUSTOM_TAGS', false );
    34 
    41 
    35 if (!CUSTOM_TAGS) {
    42 if ( ! CUSTOM_TAGS ) {
    36 	/**
    43 	/**
    37 	 * Kses global for default allowable HTML tags.
    44 	 * Kses global for default allowable HTML tags.
    38 	 *
    45 	 *
    39 	 * Can be override by using CUSTOM_TAGS constant.
    46 	 * Can be override by using CUSTOM_TAGS constant.
    40 	 *
    47 	 *
    42 	 * @since 2.0.0
    49 	 * @since 2.0.0
    43 	 */
    50 	 */
    44 	$allowedposttags = array(
    51 	$allowedposttags = array(
    45 		'address' => array(),
    52 		'address' => array(),
    46 		'a' => array(
    53 		'a' => array(
    47 			'class' => array (),
    54 			'class' => true,
    48 			'href' => array (),
    55 			'href' => true,
    49 			'id' => array (),
    56 			'id' => true,
    50 			'title' => array (),
    57 			'title' => true,
    51 			'rel' => array (),
    58 			'rel' => true,
    52 			'rev' => array (),
    59 			'rev' => true,
    53 			'name' => array (),
    60 			'name' => true,
    54 			'target' => array()),
    61 			'target' => true,
       
    62 		),
    55 		'abbr' => array(
    63 		'abbr' => array(
    56 			'class' => array (),
    64 			'class' => true,
    57 			'title' => array ()),
    65 			'title' => true,
       
    66 		),
    58 		'acronym' => array(
    67 		'acronym' => array(
    59 			'title' => array ()),
    68 			'title' => true,
       
    69 		),
       
    70 		'article' => array(
       
    71 			'align' => true,
       
    72 			'class' => true,
       
    73 			'dir' => true,
       
    74 			'lang' => true,
       
    75 			'style' => true,
       
    76 			'xml:lang' => true,
       
    77 		),
       
    78 		'aside' => array(
       
    79 			'align' => true,
       
    80 			'class' => true,
       
    81 			'dir' => true,
       
    82 			'lang' => true,
       
    83 			'style' => true,
       
    84 			'xml:lang' => true,
       
    85 		),
    60 		'b' => array(),
    86 		'b' => array(),
    61 		'big' => array(),
    87 		'big' => array(),
    62 		'blockquote' => array(
    88 		'blockquote' => array(
    63 			'id' => array (),
    89 			'id' => true,
    64 			'cite' => array (),
    90 			'cite' => true,
    65 			'class' => array(),
    91 			'class' => true,
    66 			'lang' => array(),
    92 			'lang' => true,
    67 			'xml:lang' => array()),
    93 			'xml:lang' => true,
       
    94 		),
    68 		'br' => array (
    95 		'br' => array (
    69 			'class' => array ()),
    96 			'class' => true,
       
    97 		),
    70 		'button' => array(
    98 		'button' => array(
    71 			'disabled' => array (),
    99 			'disabled' => true,
    72 			'name' => array (),
   100 			'name' => true,
    73 			'type' => array (),
   101 			'type' => true,
    74 			'value' => array ()),
   102 			'value' => true,
       
   103 		),
    75 		'caption' => array(
   104 		'caption' => array(
    76 			'align' => array (),
   105 			'align' => true,
    77 			'class' => array ()),
   106 			'class' => true,
       
   107 		),
    78 		'cite' => array (
   108 		'cite' => array (
    79 			'class' => array(),
   109 			'class' => true,
    80 			'dir' => array(),
   110 			'dir' => true,
    81 			'lang' => array(),
   111 			'lang' => true,
    82 			'title' => array ()),
   112 			'title' => true,
       
   113 		),
    83 		'code' => array (
   114 		'code' => array (
    84 			'style' => array()),
   115 			'style' => true,
       
   116 		),
    85 		'col' => array(
   117 		'col' => array(
    86 			'align' => array (),
   118 			'align' => true,
    87 			'char' => array (),
   119 			'char' => true,
    88 			'charoff' => array (),
   120 			'charoff' => true,
    89 			'span' => array (),
   121 			'span' => true,
    90 			'dir' => array(),
   122 			'dir' => true,
    91 			'style' => array (),
   123 			'style' => true,
    92 			'valign' => array (),
   124 			'valign' => true,
    93 			'width' => array ()),
   125 			'width' => true,
       
   126 		),
    94 		'del' => array(
   127 		'del' => array(
    95 			'datetime' => array ()),
   128 			'datetime' => true,
       
   129 		),
    96 		'dd' => array(),
   130 		'dd' => array(),
       
   131 		'details' => array(
       
   132 			'align' => true,
       
   133 			'class' => true,
       
   134 			'dir' => true,
       
   135 			'lang' => true,
       
   136 			'open' => true,
       
   137 			'style' => true,
       
   138 			'xml:lang' => true,
       
   139 		),
    97 		'div' => array(
   140 		'div' => array(
    98 			'align' => array (),
   141 			'align' => true,
    99 			'class' => array (),
   142 			'class' => true,
   100 			'dir' => array (),
   143 			'dir' => true,
   101 			'lang' => array(),
   144 			'lang' => true,
   102 			'style' => array (),
   145 			'style' => true,
   103 			'xml:lang' => array()),
   146 			'xml:lang' => true,
       
   147 		),
   104 		'dl' => array(),
   148 		'dl' => array(),
   105 		'dt' => array(),
   149 		'dt' => array(),
   106 		'em' => array(),
   150 		'em' => array(),
   107 		'fieldset' => array(),
   151 		'fieldset' => array(),
       
   152 		'figure' => array(
       
   153 			'align' => true,
       
   154 			'class' => true,
       
   155 			'dir' => true,
       
   156 			'lang' => true,
       
   157 			'style' => true,
       
   158 			'xml:lang' => true,
       
   159 		),
       
   160 		'figcaption' => array(
       
   161 			'align' => true,
       
   162 			'class' => true,
       
   163 			'dir' => true,
       
   164 			'lang' => true,
       
   165 			'style' => true,
       
   166 			'xml:lang' => true,
       
   167 		),
   108 		'font' => array(
   168 		'font' => array(
   109 			'color' => array (),
   169 			'color' => true,
   110 			'face' => array (),
   170 			'face' => true,
   111 			'size' => array ()),
   171 			'size' => true,
       
   172 		),
       
   173 		'footer' => array(
       
   174 			'align' => true,
       
   175 			'class' => true,
       
   176 			'dir' => true,
       
   177 			'lang' => true,
       
   178 			'style' => true,
       
   179 			'xml:lang' => true,
       
   180 		),
   112 		'form' => array(
   181 		'form' => array(
   113 			'action' => array (),
   182 			'action' => true,
   114 			'accept' => array (),
   183 			'accept' => true,
   115 			'accept-charset' => array (),
   184 			'accept-charset' => true,
   116 			'enctype' => array (),
   185 			'enctype' => true,
   117 			'method' => array (),
   186 			'method' => true,
   118 			'name' => array (),
   187 			'name' => true,
   119 			'target' => array ()),
   188 			'target' => true,
       
   189 		),
   120 		'h1' => array(
   190 		'h1' => array(
   121 			'align' => array (),
   191 			'align' => true,
   122 			'class' => array (),
   192 			'class' => true,
   123 			'id'    => array (),
   193 			'id'    => true,
   124 			'style' => array ()),
   194 			'style' => true,
       
   195 		),
   125 		'h2' => array (
   196 		'h2' => array (
   126 			'align' => array (),
   197 			'align' => true,
   127 			'class' => array (),
   198 			'class' => true,
   128 			'id'    => array (),
   199 			'id'    => true,
   129 			'style' => array ()),
   200 			'style' => true,
       
   201 		),
   130 		'h3' => array (
   202 		'h3' => array (
   131 			'align' => array (),
   203 			'align' => true,
   132 			'class' => array (),
   204 			'class' => true,
   133 			'id'    => array (),
   205 			'id'    => true,
   134 			'style' => array ()),
   206 			'style' => true,
       
   207 		),
   135 		'h4' => array (
   208 		'h4' => array (
   136 			'align' => array (),
   209 			'align' => true,
   137 			'class' => array (),
   210 			'class' => true,
   138 			'id'    => array (),
   211 			'id'    => true,
   139 			'style' => array ()),
   212 			'style' => true,
       
   213 		),
   140 		'h5' => array (
   214 		'h5' => array (
   141 			'align' => array (),
   215 			'align' => true,
   142 			'class' => array (),
   216 			'class' => true,
   143 			'id'    => array (),
   217 			'id'    => true,
   144 			'style' => array ()),
   218 			'style' => true,
       
   219 		),
   145 		'h6' => array (
   220 		'h6' => array (
   146 			'align' => array (),
   221 			'align' => true,
   147 			'class' => array (),
   222 			'class' => true,
   148 			'id'    => array (),
   223 			'id'    => true,
   149 			'style' => array ()),
   224 			'style' => true,
       
   225 		),
       
   226 		'header' => array(
       
   227 			'align' => true,
       
   228 			'class' => true,
       
   229 			'dir' => true,
       
   230 			'lang' => true,
       
   231 			'style' => true,
       
   232 			'xml:lang' => true,
       
   233 		),
       
   234 		'hgroup' => array(
       
   235 			'align' => true,
       
   236 			'class' => true,
       
   237 			'dir' => true,
       
   238 			'lang' => true,
       
   239 			'style' => true,
       
   240 			'xml:lang' => true,
       
   241 		),
   150 		'hr' => array (
   242 		'hr' => array (
   151 			'align' => array (),
   243 			'align' => true,
   152 			'class' => array (),
   244 			'class' => true,
   153 			'noshade' => array (),
   245 			'noshade' => true,
   154 			'size' => array (),
   246 			'size' => true,
   155 			'width' => array ()),
   247 			'width' => true,
       
   248 		),
   156 		'i' => array(),
   249 		'i' => array(),
   157 		'img' => array(
   250 		'img' => array(
   158 			'alt' => array (),
   251 			'alt' => true,
   159 			'align' => array (),
   252 			'align' => true,
   160 			'border' => array (),
   253 			'border' => true,
   161 			'class' => array (),
   254 			'class' => true,
   162 			'height' => array (),
   255 			'height' => true,
   163 			'hspace' => array (),
   256 			'hspace' => true,
   164 			'longdesc' => array (),
   257 			'longdesc' => true,
   165 			'vspace' => array (),
   258 			'vspace' => true,
   166 			'src' => array (),
   259 			'src' => true,
   167 			'style' => array (),
   260 			'style' => true,
   168 			'width' => array ()),
   261 			'width' => true,
       
   262 		),
   169 		'ins' => array(
   263 		'ins' => array(
   170 			'datetime' => array (),
   264 			'datetime' => true,
   171 			'cite' => array ()),
   265 			'cite' => true,
       
   266 		),
   172 		'kbd' => array(),
   267 		'kbd' => array(),
   173 		'label' => array(
   268 		'label' => array(
   174 			'for' => array ()),
   269 			'for' => true,
       
   270 		),
   175 		'legend' => array(
   271 		'legend' => array(
   176 			'align' => array ()),
   272 			'align' => true,
       
   273 		),
   177 		'li' => array (
   274 		'li' => array (
   178 			'align' => array (),
   275 			'align' => true,
   179 			'class' => array ()),
   276 			'class' => true,
       
   277 		),
       
   278 		'menu' => array (
       
   279 			'class' => true,
       
   280 			'style' => true,
       
   281 			'type' => true,
       
   282 		),
       
   283 		'nav' => array(
       
   284 			'align' => true,
       
   285 			'class' => true,
       
   286 			'dir' => true,
       
   287 			'lang' => true,
       
   288 			'style' => true,
       
   289 			'xml:lang' => true,
       
   290 		),
   180 		'p' => array(
   291 		'p' => array(
   181 			'class' => array (),
   292 			'class' => true,
   182 			'align' => array (),
   293 			'align' => true,
   183 			'dir' => array(),
   294 			'dir' => true,
   184 			'lang' => array(),
   295 			'lang' => true,
   185 			'style' => array (),
   296 			'style' => true,
   186 			'xml:lang' => array()),
   297 			'xml:lang' => true,
       
   298 		),
   187 		'pre' => array(
   299 		'pre' => array(
   188 			'style' => array(),
   300 			'style' => true,
   189 			'width' => array ()),
   301 			'width' => true,
       
   302 		),
   190 		'q' => array(
   303 		'q' => array(
   191 			'cite' => array ()),
   304 			'cite' => true,
       
   305 		),
   192 		's' => array(),
   306 		's' => array(),
   193 		'span' => array (
   307 		'span' => array (
   194 			'class' => array (),
   308 			'class' => true,
   195 			'dir' => array (),
   309 			'dir' => true,
   196 			'align' => array (),
   310 			'align' => true,
   197 			'lang' => array (),
   311 			'lang' => true,
   198 			'style' => array (),
   312 			'style' => true,
   199 			'title' => array (),
   313 			'title' => true,
   200 			'xml:lang' => array()),
   314 			'xml:lang' => true,
       
   315 		),
       
   316 		'section' => array(
       
   317 			'align' => true,
       
   318 			'class' => true,
       
   319 			'dir' => true,
       
   320 			'lang' => true,
       
   321 			'style' => true,
       
   322 			'xml:lang' => true,
       
   323 		),
   201 		'strike' => array(),
   324 		'strike' => array(),
   202 		'strong' => array(),
   325 		'strong' => array(),
   203 		'sub' => array(),
   326 		'sub' => array(),
       
   327 		'summary' => array(
       
   328 			'align' => true,
       
   329 			'class' => true,
       
   330 			'dir' => true,
       
   331 			'lang' => true,
       
   332 			'style' => true,
       
   333 			'xml:lang' => true,
       
   334 		),
   204 		'sup' => array(),
   335 		'sup' => array(),
   205 		'table' => array(
   336 		'table' => array(
   206 			'align' => array (),
   337 			'align' => true,
   207 			'bgcolor' => array (),
   338 			'bgcolor' => true,
   208 			'border' => array (),
   339 			'border' => true,
   209 			'cellpadding' => array (),
   340 			'cellpadding' => true,
   210 			'cellspacing' => array (),
   341 			'cellspacing' => true,
   211 			'class' => array (),
   342 			'class' => true,
   212 			'dir' => array(),
   343 			'dir' => true,
   213 			'id' => array(),
   344 			'id' => true,
   214 			'rules' => array (),
   345 			'rules' => true,
   215 			'style' => array (),
   346 			'style' => true,
   216 			'summary' => array (),
   347 			'summary' => true,
   217 			'width' => array ()),
   348 			'width' => true,
       
   349 		),
   218 		'tbody' => array(
   350 		'tbody' => array(
   219 			'align' => array (),
   351 			'align' => true,
   220 			'char' => array (),
   352 			'char' => true,
   221 			'charoff' => array (),
   353 			'charoff' => true,
   222 			'valign' => array ()),
   354 			'valign' => true,
       
   355 		),
   223 		'td' => array(
   356 		'td' => array(
   224 			'abbr' => array (),
   357 			'abbr' => true,
   225 			'align' => array (),
   358 			'align' => true,
   226 			'axis' => array (),
   359 			'axis' => true,
   227 			'bgcolor' => array (),
   360 			'bgcolor' => true,
   228 			'char' => array (),
   361 			'char' => true,
   229 			'charoff' => array (),
   362 			'charoff' => true,
   230 			'class' => array (),
   363 			'class' => true,
   231 			'colspan' => array (),
   364 			'colspan' => true,
   232 			'dir' => array(),
   365 			'dir' => true,
   233 			'headers' => array (),
   366 			'headers' => true,
   234 			'height' => array (),
   367 			'height' => true,
   235 			'nowrap' => array (),
   368 			'nowrap' => true,
   236 			'rowspan' => array (),
   369 			'rowspan' => true,
   237 			'scope' => array (),
   370 			'scope' => true,
   238 			'style' => array (),
   371 			'style' => true,
   239 			'valign' => array (),
   372 			'valign' => true,
   240 			'width' => array ()),
   373 			'width' => true,
       
   374 		),
   241 		'textarea' => array(
   375 		'textarea' => array(
   242 			'cols' => array (),
   376 			'cols' => true,
   243 			'rows' => array (),
   377 			'rows' => true,
   244 			'disabled' => array (),
   378 			'disabled' => true,
   245 			'name' => array (),
   379 			'name' => true,
   246 			'readonly' => array ()),
   380 			'readonly' => true,
       
   381 		),
   247 		'tfoot' => array(
   382 		'tfoot' => array(
   248 			'align' => array (),
   383 			'align' => true,
   249 			'char' => array (),
   384 			'char' => true,
   250 			'class' => array (),
   385 			'class' => true,
   251 			'charoff' => array (),
   386 			'charoff' => true,
   252 			'valign' => array ()),
   387 			'valign' => true,
       
   388 		),
   253 		'th' => array(
   389 		'th' => array(
   254 			'abbr' => array (),
   390 			'abbr' => true,
   255 			'align' => array (),
   391 			'align' => true,
   256 			'axis' => array (),
   392 			'axis' => true,
   257 			'bgcolor' => array (),
   393 			'bgcolor' => true,
   258 			'char' => array (),
   394 			'char' => true,
   259 			'charoff' => array (),
   395 			'charoff' => true,
   260 			'class' => array (),
   396 			'class' => true,
   261 			'colspan' => array (),
   397 			'colspan' => true,
   262 			'headers' => array (),
   398 			'headers' => true,
   263 			'height' => array (),
   399 			'height' => true,
   264 			'nowrap' => array (),
   400 			'nowrap' => true,
   265 			'rowspan' => array (),
   401 			'rowspan' => true,
   266 			'scope' => array (),
   402 			'scope' => true,
   267 			'valign' => array (),
   403 			'valign' => true,
   268 			'width' => array ()),
   404 			'width' => true,
       
   405 		),
   269 		'thead' => array(
   406 		'thead' => array(
   270 			'align' => array (),
   407 			'align' => true,
   271 			'char' => array (),
   408 			'char' => true,
   272 			'charoff' => array (),
   409 			'charoff' => true,
   273 			'class' => array (),
   410 			'class' => true,
   274 			'valign' => array ()),
   411 			'valign' => true,
       
   412 		),
   275 		'title' => array(),
   413 		'title' => array(),
   276 		'tr' => array(
   414 		'tr' => array(
   277 			'align' => array (),
   415 			'align' => true,
   278 			'bgcolor' => array (),
   416 			'bgcolor' => true,
   279 			'char' => array (),
   417 			'char' => true,
   280 			'charoff' => array (),
   418 			'charoff' => true,
   281 			'class' => array (),
   419 			'class' => true,
   282 			'style' => array (),
   420 			'style' => true,
   283 			'valign' => array ()),
   421 			'valign' => true,
       
   422 		),
   284 		'tt' => array(),
   423 		'tt' => array(),
   285 		'u' => array(),
   424 		'u' => array(),
   286 		'ul' => array (
   425 		'ul' => array (
   287 			'class' => array (),
   426 			'class' => true,
   288 			'style' => array (),
   427 			'style' => true,
   289 			'type' => array ()),
   428 			'type' => true,
       
   429 		),
   290 		'ol' => array (
   430 		'ol' => array (
   291 			'class' => array (),
   431 			'class' => true,
   292 			'start' => array (),
   432 			'start' => true,
   293 			'style' => array (),
   433 			'style' => true,
   294 			'type' => array ()),
   434 			'type' => true,
   295 		'var' => array ());
   435 		),
       
   436 		'var' => array(),
       
   437 	);
   296 
   438 
   297 	/**
   439 	/**
   298 	 * Kses allowed HTML elements.
   440 	 * Kses allowed HTML elements.
   299 	 *
   441 	 *
   300 	 * @global array $allowedtags
   442 	 * @global array $allowedtags
   301 	 * @since 1.0.0
   443 	 * @since 1.0.0
   302 	 */
   444 	 */
   303 	$allowedtags = array(
   445 	$allowedtags = array(
   304 		'a' => array(
   446 		'a' => array(
   305 			'href' => array (),
   447 			'href' => true,
   306 			'title' => array ()),
   448 			'title' => true,
       
   449 		),
   307 		'abbr' => array(
   450 		'abbr' => array(
   308 			'title' => array ()),
   451 			'title' => true,
       
   452 		),
   309 		'acronym' => array(
   453 		'acronym' => array(
   310 			'title' => array ()),
   454 			'title' => true,
       
   455 		),
   311 		'b' => array(),
   456 		'b' => array(),
   312 		'blockquote' => array(
   457 		'blockquote' => array(
   313 			'cite' => array ()),
   458 			'cite' => true,
       
   459 		),
   314 		//	'br' => array(),
   460 		//	'br' => array(),
   315 		'cite' => array (),
   461 		'cite' => array(),
   316 		'code' => array(),
   462 		'code' => array(),
   317 		'del' => array(
   463 		'del' => array(
   318 			'datetime' => array ()),
   464 			'datetime' => true,
       
   465 		),
   319 		//	'dd' => array(),
   466 		//	'dd' => array(),
   320 		//	'dl' => array(),
   467 		//	'dl' => array(),
   321 		//	'dt' => array(),
   468 		//	'dt' => array(),
   322 		'em' => array (), 'i' => array (),
   469 		'em' => array (), 'i' => array (),
   323 		//	'ins' => array('datetime' => array(), 'cite' => array()),
   470 		//	'ins' => array('datetime' => array(), 'cite' => array()),
   324 		//	'li' => array(),
   471 		//	'li' => array(),
   325 		//	'ol' => array(),
   472 		//	'ol' => array(),
   326 		//	'p' => array(),
   473 		//	'p' => array(),
   327 		'q' => array(
   474 		'q' => array(
   328 			'cite' => array ()),
   475 			'cite' => true,
       
   476 		),
   329 		'strike' => array(),
   477 		'strike' => array(),
   330 		'strong' => array(),
   478 		'strong' => array(),
   331 		//	'sub' => array(),
   479 		//	'sub' => array(),
   332 		//	'sup' => array(),
   480 		//	'sup' => array(),
   333 		//	'u' => array(),
   481 		//	'u' => array(),
   334 		//	'ul' => array(),
   482 		//	'ul' => array(),
   335 	);
   483 	);
       
   484 
       
   485 	$allowedentitynames = array(
       
   486 		'nbsp',    'iexcl',  'cent',    'pound',  'curren', 'yen',
       
   487 		'brvbar',  'sect',   'uml',     'copy',   'ordf',   'laquo',
       
   488 		'not',     'shy',    'reg',     'macr',   'deg',    'plusmn',
       
   489 		'acute',   'micro',  'para',    'middot', 'cedil',  'ordm',
       
   490 		'raquo',   'iquest', 'Agrave',  'Aacute', 'Acirc',  'Atilde',
       
   491 		'Auml',    'Aring',  'AElig',   'Ccedil', 'Egrave', 'Eacute',
       
   492 		'Ecirc',   'Euml',   'Igrave',  'Iacute', 'Icirc',  'Iuml',
       
   493 		'ETH',     'Ntilde', 'Ograve',  'Oacute', 'Ocirc',  'Otilde',
       
   494 		'Ouml',    'times',  'Oslash',  'Ugrave', 'Uacute', 'Ucirc',
       
   495 		'Uuml',    'Yacute', 'THORN',   'szlig',  'agrave', 'aacute',
       
   496 		'acirc',   'atilde', 'auml',    'aring',  'aelig',  'ccedil',
       
   497 		'egrave',  'eacute', 'ecirc',   'euml',   'igrave', 'iacute',
       
   498 		'icirc',   'iuml',   'eth',     'ntilde', 'ograve', 'oacute',
       
   499 		'ocirc',   'otilde', 'ouml',    'divide', 'oslash', 'ugrave',
       
   500 		'uacute',  'ucirc',  'uuml',    'yacute', 'thorn',  'yuml',
       
   501 		'quot',    'amp',    'lt',      'gt',     'apos',   'OElig',
       
   502 		'oelig',   'Scaron', 'scaron',  'Yuml',   'circ',   'tilde',
       
   503 		'ensp',    'emsp',   'thinsp',  'zwnj',   'zwj',    'lrm',
       
   504 		'rlm',     'ndash',  'mdash',   'lsquo',  'rsquo',  'sbquo',
       
   505 		'ldquo',   'rdquo',  'bdquo',   'dagger', 'Dagger', 'permil',
       
   506 		'lsaquo',  'rsaquo', 'euro',    'fnof',   'Alpha',  'Beta',
       
   507 		'Gamma',   'Delta',  'Epsilon', 'Zeta',   'Eta',    'Theta',
       
   508 		'Iota',    'Kappa',  'Lambda',  'Mu',     'Nu',     'Xi',
       
   509 		'Omicron', 'Pi',     'Rho',     'Sigma',  'Tau',    'Upsilon',
       
   510 		'Phi',     'Chi',    'Psi',     'Omega',  'alpha',  'beta',
       
   511 		'gamma',   'delta',  'epsilon', 'zeta',   'eta',    'theta',
       
   512 		'iota',    'kappa',  'lambda',  'mu',     'nu',     'xi',
       
   513 		'omicron', 'pi',     'rho',     'sigmaf', 'sigma',  'tau',
       
   514 		'upsilon', 'phi',    'chi',     'psi',    'omega',  'thetasym',
       
   515 		'upsih',   'piv',    'bull',    'hellip', 'prime',  'Prime',
       
   516 		'oline',   'frasl',  'weierp',  'image',  'real',   'trade',
       
   517 		'alefsym', 'larr',   'uarr',    'rarr',   'darr',   'harr',
       
   518 		'crarr',   'lArr',   'uArr',    'rArr',   'dArr',   'hArr',
       
   519 		'forall',  'part',   'exist',   'empty',  'nabla',  'isin',
       
   520 		'notin',   'ni',     'prod',    'sum',    'minus',  'lowast',
       
   521 		'radic',   'prop',   'infin',   'ang',    'and',    'or',
       
   522 		'cap',     'cup',    'int',     'sim',    'cong',   'asymp',
       
   523 		'ne',      'equiv',  'le',      'ge',     'sub',    'sup',
       
   524 		'nsub',    'sube',   'supe',    'oplus',  'otimes', 'perp',
       
   525 		'sdot',    'lceil',  'rceil',   'lfloor', 'rfloor', 'lang',
       
   526 		'rang',    'loz',    'spades',  'clubs',  'hearts', 'diams',
       
   527 	);
   336 }
   528 }
   337 
   529 
   338 /**
   530 /**
   339  * Filters content and keeps only allowable HTML elements.
   531  * Filters content and keeps only allowable HTML elements.
   340  *
   532  *
   342  * names and attribute values plus only sane HTML entities will occur in
   534  * names and attribute values plus only sane HTML entities will occur in
   343  * $string. You have to remove any slashes from PHP's magic quotes before you
   535  * $string. You have to remove any slashes from PHP's magic quotes before you
   344  * call this function.
   536  * call this function.
   345  *
   537  *
   346  * The default allowed protocols are 'http', 'https', 'ftp', 'mailto', 'news',
   538  * The default allowed protocols are 'http', 'https', 'ftp', 'mailto', 'news',
   347  * 'irc', 'gopher', 'nntp', 'feed', and finally 'telnet. This covers all common
   539  * 'irc', 'gopher', 'nntp', 'feed', 'telnet, 'mms', 'rtsp' and 'svn'. This
   348  * link protocols, except for 'javascript' which should not be allowed for
   540  * covers all common link protocols, except for 'javascript' which should not
   349  * untrusted users.
   541  * be allowed for untrusted users.
   350  *
   542  *
   351  * @since 1.0.0
   543  * @since 1.0.0
   352  *
   544  *
   353  * @param string $string Content to filter through kses
   545  * @param string $string Content to filter through kses
   354  * @param array $allowed_html List of allowed HTML elements
   546  * @param array $allowed_html List of allowed HTML elements
   355  * @param array $allowed_protocols Optional. Allowed protocol in links.
   547  * @param array $allowed_protocols Optional. Allowed protocol in links.
   356  * @return string Filtered content with only allowed HTML elements
   548  * @return string Filtered content with only allowed HTML elements
   357  */
   549  */
   358 function wp_kses($string, $allowed_html, $allowed_protocols = array ('http', 'https', 'ftp', 'ftps', 'mailto', 'news', 'irc', 'gopher', 'nntp', 'feed', 'telnet')) {
   550 function wp_kses($string, $allowed_html, $allowed_protocols = array ()) {
       
   551 	if ( empty( $allowed_protocols ) )
       
   552 		$allowed_protocols = wp_allowed_protocols();
   359 	$string = wp_kses_no_null($string);
   553 	$string = wp_kses_no_null($string);
   360 	$string = wp_kses_js_entities($string);
   554 	$string = wp_kses_js_entities($string);
   361 	$string = wp_kses_normalize_entities($string);
   555 	$string = wp_kses_normalize_entities($string);
   362 	$allowed_html_fixed = wp_kses_array_lc($allowed_html);
   556 	$allowed_html_fixed = wp_kses_array_lc($allowed_html);
   363 	$string = wp_kses_hook($string, $allowed_html_fixed, $allowed_protocols); // WP changed the order of these funcs and added args to wp_kses_hook
   557 	$string = wp_kses_hook($string, $allowed_html_fixed, $allowed_protocols); // WP changed the order of these funcs and added args to wp_kses_hook
   366 
   560 
   367 /**
   561 /**
   368  * You add any kses hooks here.
   562  * You add any kses hooks here.
   369  *
   563  *
   370  * There is currently only one kses WordPress hook and it is called here. All
   564  * There is currently only one kses WordPress hook and it is called here. All
   371  * parameters are passed to the hooks and expected to recieve a string.
   565  * parameters are passed to the hooks and expected to receive a string.
   372  *
   566  *
   373  * @since 1.0.0
   567  * @since 1.0.0
   374  *
   568  *
   375  * @param string $string Content to filter through kses
   569  * @param string $string Content to filter through kses
   376  * @param array $allowed_html List of allowed HTML elements
   570  * @param array $allowed_html List of allowed HTML elements
   407  */
   601  */
   408 function wp_kses_split($string, $allowed_html, $allowed_protocols) {
   602 function wp_kses_split($string, $allowed_html, $allowed_protocols) {
   409 	global $pass_allowed_html, $pass_allowed_protocols;
   603 	global $pass_allowed_html, $pass_allowed_protocols;
   410 	$pass_allowed_html = $allowed_html;
   604 	$pass_allowed_html = $allowed_html;
   411 	$pass_allowed_protocols = $allowed_protocols;
   605 	$pass_allowed_protocols = $allowed_protocols;
   412 	return preg_replace_callback('%((<!--.*?(-->|$))|(<[^>]*(>|$)|>))%',
   606 	return preg_replace_callback( '%(<!--.*?(-->|$))|(<[^>]*(>|$)|>)%', '_wp_kses_split_callback', $string );
   413 		create_function('$match', 'global $pass_allowed_html, $pass_allowed_protocols; return wp_kses_split2($match[1], $pass_allowed_html, $pass_allowed_protocols);'), $string);
   607 }
       
   608 
       
   609 /**
       
   610  * Callback for wp_kses_split.
       
   611  *
       
   612  * @since 3.1.0
       
   613  * @access private
       
   614  */
       
   615 function _wp_kses_split_callback( $match ) {
       
   616 	global $pass_allowed_html, $pass_allowed_protocols;
       
   617 	return wp_kses_split2( $match[0], $pass_allowed_html, $pass_allowed_protocols );
   414 }
   618 }
   415 
   619 
   416 /**
   620 /**
   417  * Callback for wp_kses_split for fixing malformed HTML tags.
   621  * Callback for wp_kses_split for fixing malformed HTML tags.
   418  *
   622  *
   439 
   643 
   440 	if (substr($string, 0, 1) != '<')
   644 	if (substr($string, 0, 1) != '<')
   441 		return '&gt;';
   645 		return '&gt;';
   442 	# It matched a ">" character
   646 	# It matched a ">" character
   443 
   647 
   444 	if (preg_match('%^<!--(.*?)(-->)?$%', $string, $matches)) {
   648 	if ( '<!--' == substr( $string, 0, 4 ) ) {
   445 		$string = str_replace(array('<!--', '-->'), '', $matches[1]);
   649 		$string = str_replace( array('<!--', '-->'), '', $string );
   446 		while ( $string != $newstring = wp_kses($string, $allowed_html, $allowed_protocols) )
   650 		while ( $string != ($newstring = wp_kses($string, $allowed_html, $allowed_protocols)) )
   447 			$string = $newstring;
   651 			$string = $newstring;
   448 		if ( $string == '' )
   652 		if ( $string == '' )
   449 			return '';
   653 			return '';
   450 		// prevent multiple dashes in comments
   654 		// prevent multiple dashes in comments
   451 		$string = preg_replace('/--+/', '-', $string);
   655 		$string = preg_replace('/--+/', '-', $string);
   461 
   665 
   462 	$slash = trim($matches[1]);
   666 	$slash = trim($matches[1]);
   463 	$elem = $matches[2];
   667 	$elem = $matches[2];
   464 	$attrlist = $matches[3];
   668 	$attrlist = $matches[3];
   465 
   669 
   466 	if (!@isset($allowed_html[strtolower($elem)]))
   670 	if ( ! isset($allowed_html[strtolower($elem)]) )
   467 		return '';
   671 		return '';
   468 	# They are using a not allowed HTML element
   672 	# They are using a not allowed HTML element
   469 
   673 
   470 	if ($slash != '')
   674 	if ($slash != '')
   471 		return "<$slash$elem>";
   675 		return "</$elem>";
   472 	# No attributes are allowed for closing elements
   676 	# No attributes are allowed for closing elements
   473 
   677 
   474 	return wp_kses_attr("$slash$elem", $attrlist, $allowed_html, $allowed_protocols);
   678 	return wp_kses_attr( $elem, $attrlist, $allowed_html, $allowed_protocols );
   475 }
   679 }
   476 
   680 
   477 /**
   681 /**
   478  * Removes all attributes, if none are allowed for this element.
   682  * Removes all attributes, if none are allowed for this element.
   479  *
   683  *
   493  */
   697  */
   494 function wp_kses_attr($element, $attr, $allowed_html, $allowed_protocols) {
   698 function wp_kses_attr($element, $attr, $allowed_html, $allowed_protocols) {
   495 	# Is there a closing XHTML slash at the end of the attributes?
   699 	# Is there a closing XHTML slash at the end of the attributes?
   496 
   700 
   497 	$xhtml_slash = '';
   701 	$xhtml_slash = '';
   498 	if (preg_match('%\s/\s*$%', $attr))
   702 	if (preg_match('%\s*/\s*$%', $attr))
   499 		$xhtml_slash = ' /';
   703 		$xhtml_slash = ' /';
   500 
   704 
   501 	# Are any attributes allowed at all for this element?
   705 	# Are any attributes allowed at all for this element?
   502 
   706 	if ( ! isset($allowed_html[strtolower($element)]) || count($allowed_html[strtolower($element)]) == 0 )
   503 	if (@ count($allowed_html[strtolower($element)]) == 0)
       
   504 		return "<$element$xhtml_slash>";
   707 		return "<$element$xhtml_slash>";
   505 
   708 
   506 	# Split it
   709 	# Split it
   507 
       
   508 	$attrarr = wp_kses_hair($attr, $allowed_protocols);
   710 	$attrarr = wp_kses_hair($attr, $allowed_protocols);
   509 
   711 
   510 	# Go through $attrarr, and save the allowed attributes for this element
   712 	# Go through $attrarr, and save the allowed attributes for this element
   511 	# in $attr2
   713 	# in $attr2
   512 
       
   513 	$attr2 = '';
   714 	$attr2 = '';
   514 
   715 
       
   716 	$allowed_attr = $allowed_html[strtolower($element)];
   515 	foreach ($attrarr as $arreach) {
   717 	foreach ($attrarr as $arreach) {
   516 		if (!@ isset ($allowed_html[strtolower($element)][strtolower($arreach['name'])]))
   718 		if ( ! isset( $allowed_attr[strtolower($arreach['name'])] ) )
   517 			continue; # the attribute is not allowed
   719 			continue; # the attribute is not allowed
   518 
   720 
   519 		$current = $allowed_html[strtolower($element)][strtolower($arreach['name'])];
   721 		$current = $allowed_attr[strtolower($arreach['name'])];
   520 		if ($current == '')
   722 		if ( $current == '' )
   521 			continue; # the attribute is not allowed
   723 			continue; # the attribute is not allowed
   522 
   724 
   523 		if (!is_array($current))
   725 		if ( strtolower( $arreach['name'] ) == 'style' ) {
       
   726 			$orig_value = $arreach['value'];
       
   727 			$value = safecss_filter_attr( $orig_value );
       
   728 
       
   729 			if ( empty( $value ) )
       
   730 				continue;
       
   731 
       
   732 			$arreach['value'] = $value;
       
   733 			$arreach['whole'] = str_replace( $orig_value, $value, $arreach['whole'] );
       
   734 		}
       
   735 
       
   736 		if ( ! is_array($current) ) {
   524 			$attr2 .= ' '.$arreach['whole'];
   737 			$attr2 .= ' '.$arreach['whole'];
   525 		# there are no checks
   738 		# there are no checks
   526 
   739 
   527 		else {
   740 		} else {
   528 			# there are some checks
   741 			# there are some checks
   529 			$ok = true;
   742 			$ok = true;
   530 			foreach ($current as $currkey => $currval)
   743 			foreach ($current as $currkey => $currval) {
   531 				if (!wp_kses_check_attr_val($arreach['value'], $arreach['vless'], $currkey, $currval)) {
   744 				if ( ! wp_kses_check_attr_val($arreach['value'], $arreach['vless'], $currkey, $currval) ) {
   532 					$ok = false;
   745 					$ok = false;
   533 					break;
   746 					break;
   534 				}
   747 				}
   535 
       
   536 			if ( $arreach['name'] == 'style' ) {
       
   537 				$orig_value = $arreach['value'];
       
   538 
       
   539 				$value = safecss_filter_attr($orig_value);
       
   540 
       
   541 				if ( empty($value) )
       
   542 					continue;
       
   543 
       
   544 				$arreach['value'] = $value;
       
   545 
       
   546 				$arreach['whole'] = str_replace($orig_value, $value, $arreach['whole']);
       
   547 			}
   748 			}
   548 
   749 
   549 			if ($ok)
   750 			if ( $ok )
   550 				$attr2 .= ' '.$arreach['whole']; # it passed them
   751 				$attr2 .= ' '.$arreach['whole']; # it passed them
   551 		} # if !is_array($current)
   752 		} # if !is_array($current)
   552 	} # foreach
   753 	} # foreach
   553 
   754 
   554 	# Remove any "<" or ">" characters
   755 	# Remove any "<" or ">" characters
   555 
       
   556 	$attr2 = preg_replace('/[<>]/', '', $attr2);
   756 	$attr2 = preg_replace('/[<>]/', '', $attr2);
   557 
   757 
   558 	return "<$element$attr2$xhtml_slash>";
   758 	return "<$element$attr2$xhtml_slash>";
   559 }
   759 }
   560 
   760 
   564  * This function does a lot of work. It parses an attribute list into an array
   764  * This function does a lot of work. It parses an attribute list into an array
   565  * with attribute data, and tries to do the right thing even if it gets weird
   765  * with attribute data, and tries to do the right thing even if it gets weird
   566  * input. It will add quotes around attribute values that don't have any quotes
   766  * input. It will add quotes around attribute values that don't have any quotes
   567  * or apostrophes around them, to make it easier to produce HTML code that will
   767  * or apostrophes around them, to make it easier to produce HTML code that will
   568  * conform to W3C's HTML specification. It will also remove bad URL protocols
   768  * conform to W3C's HTML specification. It will also remove bad URL protocols
   569  * from attribute values.  It also reduces duplicate attributes by using the
   769  * from attribute values. It also reduces duplicate attributes by using the
   570  * attribute defined first (foo='bar' foo='baz' will result in foo='bar').
   770  * attribute defined first (foo='bar' foo='baz' will result in foo='bar').
   571  *
   771  *
   572  * @since 1.0.0
   772  * @since 1.0.0
   573  *
   773  *
   574  * @param string $attr Attribute list from HTML element to closing HTML element tag
   774  * @param string $attr Attribute list from HTML element to closing HTML element tag
   609 
   809 
   610 				if (preg_match('/^\s+/', $attr)) # valueless
   810 				if (preg_match('/^\s+/', $attr)) # valueless
   611 					{
   811 					{
   612 					$working = 1;
   812 					$working = 1;
   613 					$mode = 0;
   813 					$mode = 0;
   614 					if(FALSE === array_key_exists($attrname, $attrarr)) {
   814 					if(false === array_key_exists($attrname, $attrarr)) {
   615 						$attrarr[$attrname] = array ('name' => $attrname, 'value' => '', 'whole' => $attrname, 'vless' => 'y');
   815 						$attrarr[$attrname] = array ('name' => $attrname, 'value' => '', 'whole' => $attrname, 'vless' => 'y');
   616 					}
   816 					}
   617 					$attr = preg_replace('/^\s+/', '', $attr);
   817 					$attr = preg_replace('/^\s+/', '', $attr);
   618 				}
   818 				}
   619 
   819 
   620 				break;
   820 				break;
   621 
   821 
   622 			case 2 : # attribute value, a URL after href= for instance
   822 			case 2 : # attribute value, a URL after href= for instance
   623 
   823 
   624 				if (preg_match('/^"([^"]*)"(\s+|$)/', $attr, $match))
   824 				if (preg_match('%^"([^"]*)"(\s+|/?$)%', $attr, $match))
   625 					# "value"
   825 					# "value"
   626 					{
   826 					{
   627 					$thisval = $match[1];
   827 					$thisval = $match[1];
   628 					if ( in_array($attrname, $uris) )
   828 					if ( in_array(strtolower($attrname), $uris) )
   629 						$thisval = wp_kses_bad_protocol($thisval, $allowed_protocols);
   829 						$thisval = wp_kses_bad_protocol($thisval, $allowed_protocols);
   630 
   830 
   631 					if(FALSE === array_key_exists($attrname, $attrarr)) {
   831 					if(false === array_key_exists($attrname, $attrarr)) {
   632 						$attrarr[$attrname] = array ('name' => $attrname, 'value' => $thisval, 'whole' => "$attrname=\"$thisval\"", 'vless' => 'n');
   832 						$attrarr[$attrname] = array ('name' => $attrname, 'value' => $thisval, 'whole' => "$attrname=\"$thisval\"", 'vless' => 'n');
   633 					}
   833 					}
   634 					$working = 1;
   834 					$working = 1;
   635 					$mode = 0;
   835 					$mode = 0;
   636 					$attr = preg_replace('/^"[^"]*"(\s+|$)/', '', $attr);
   836 					$attr = preg_replace('/^"[^"]*"(\s+|$)/', '', $attr);
   637 					break;
   837 					break;
   638 				}
   838 				}
   639 
   839 
   640 				if (preg_match("/^'([^']*)'(\s+|$)/", $attr, $match))
   840 				if (preg_match("%^'([^']*)'(\s+|/?$)%", $attr, $match))
   641 					# 'value'
   841 					# 'value'
   642 					{
   842 					{
   643 					$thisval = $match[1];
   843 					$thisval = $match[1];
   644 					if ( in_array($attrname, $uris) )
   844 					if ( in_array(strtolower($attrname), $uris) )
   645 						$thisval = wp_kses_bad_protocol($thisval, $allowed_protocols);
   845 						$thisval = wp_kses_bad_protocol($thisval, $allowed_protocols);
   646 
   846 
   647 					if(FALSE === array_key_exists($attrname, $attrarr)) {
   847 					if(false === array_key_exists($attrname, $attrarr)) {
   648 						$attrarr[$attrname] = array ('name' => $attrname, 'value' => $thisval, 'whole' => "$attrname='$thisval'", 'vless' => 'n');
   848 						$attrarr[$attrname] = array ('name' => $attrname, 'value' => $thisval, 'whole' => "$attrname='$thisval'", 'vless' => 'n');
   649 					}
   849 					}
   650 					$working = 1;
   850 					$working = 1;
   651 					$mode = 0;
   851 					$mode = 0;
   652 					$attr = preg_replace("/^'[^']*'(\s+|$)/", '', $attr);
   852 					$attr = preg_replace("/^'[^']*'(\s+|$)/", '', $attr);
   653 					break;
   853 					break;
   654 				}
   854 				}
   655 
   855 
   656 				if (preg_match("%^([^\s\"']+)(\s+|$)%", $attr, $match))
   856 				if (preg_match("%^([^\s\"']+)(\s+|/?$)%", $attr, $match))
   657 					# value
   857 					# value
   658 					{
   858 					{
   659 					$thisval = $match[1];
   859 					$thisval = $match[1];
   660 					if ( in_array($attrname, $uris) )
   860 					if ( in_array(strtolower($attrname), $uris) )
   661 						$thisval = wp_kses_bad_protocol($thisval, $allowed_protocols);
   861 						$thisval = wp_kses_bad_protocol($thisval, $allowed_protocols);
   662 
   862 
   663 					if(FALSE === array_key_exists($attrname, $attrarr)) {
   863 					if(false === array_key_exists($attrname, $attrarr)) {
   664 						$attrarr[$attrname] = array ('name' => $attrname, 'value' => $thisval, 'whole' => "$attrname=\"$thisval\"", 'vless' => 'n');
   864 						$attrarr[$attrname] = array ('name' => $attrname, 'value' => $thisval, 'whole' => "$attrname=\"$thisval\"", 'vless' => 'n');
   665 					}
   865 					}
   666 					# We add quotes to conform to W3C's HTML spec.
   866 					# We add quotes to conform to W3C's HTML spec.
   667 					$working = 1;
   867 					$working = 1;
   668 					$mode = 0;
   868 					$mode = 0;
   677 			$attr = wp_kses_html_error($attr);
   877 			$attr = wp_kses_html_error($attr);
   678 			$mode = 0;
   878 			$mode = 0;
   679 		}
   879 		}
   680 	} # while
   880 	} # while
   681 
   881 
   682 	if ($mode == 1 && FALSE === array_key_exists($attrname, $attrarr))
   882 	if ($mode == 1 && false === array_key_exists($attrname, $attrarr))
   683 		# special case, for when the attribute list ends with a valueless
   883 		# special case, for when the attribute list ends with a valueless
   684 		# attribute like "selected"
   884 		# attribute like "selected"
   685 		$attrarr[$attrname] = array ('name' => $attrname, 'value' => '', 'whole' => $attrname, 'vless' => 'y');
   885 		$attrarr[$attrname] = array ('name' => $attrname, 'value' => '', 'whole' => $attrname, 'vless' => 'y');
   686 
   886 
   687 	return $attrarr;
   887 	return $attrarr;
   689 
   889 
   690 /**
   890 /**
   691  * Performs different checks for attribute values.
   891  * Performs different checks for attribute values.
   692  *
   892  *
   693  * The currently implemented checks are "maxlen", "minlen", "maxval", "minval"
   893  * The currently implemented checks are "maxlen", "minlen", "maxval", "minval"
   694  * and "valueless" with even more checks to come soon.
   894  * and "valueless".
   695  *
   895  *
   696  * @since 1.0.0
   896  * @since 1.0.0
   697  *
   897  *
   698  * @param string $value Attribute value
   898  * @param string $value Attribute value
   699  * @param string $vless Whether the value is valueless or not. Use 'y' or 'n'
   899  * @param string $vless Whether the value is valueless. Use 'y' or 'n'
   700  * @param string $checkname What $checkvalue is checking for.
   900  * @param string $checkname What $checkvalue is checking for.
   701  * @param mixed $checkvalue What constraint the value should pass
   901  * @param mixed $checkvalue What constraint the value should pass
   702  * @return bool Whether check passes (true) or not (false)
   902  * @return bool Whether check passes
   703  */
   903  */
   704 function wp_kses_check_attr_val($value, $vless, $checkname, $checkvalue) {
   904 function wp_kses_check_attr_val($value, $vless, $checkname, $checkvalue) {
   705 	$ok = true;
   905 	$ok = true;
   706 
   906 
   707 	switch (strtolower($checkname)) {
   907 	switch (strtolower($checkname)) {
   734 			if ($value > $checkvalue)
   934 			if ($value > $checkvalue)
   735 				$ok = false;
   935 				$ok = false;
   736 			break;
   936 			break;
   737 
   937 
   738 		case 'minval' :
   938 		case 'minval' :
   739 			# The minval check checks that the attribute value is a positive integer,
   939 			# The minval check makes sure that the attribute value is a positive integer,
   740 			# and that it is not smaller than the given value.
   940 			# and that it is not smaller than the given value.
   741 
   941 
   742 			if (!preg_match('/^\s{0,6}[0-9]{1,6}\s{0,6}$/', $value))
   942 			if (!preg_match('/^\s{0,6}[0-9]{1,6}\s{0,6}$/', $value))
   743 				$ok = false;
   943 				$ok = false;
   744 			if ($value < $checkvalue)
   944 			if ($value < $checkvalue)
   745 				$ok = false;
   945 				$ok = false;
   746 			break;
   946 			break;
   747 
   947 
   748 		case 'valueless' :
   948 		case 'valueless' :
   749 			# The valueless check checks if the attribute has a value
   949 			# The valueless check makes sure if the attribute has a value
   750 			# (like <a href="blah">) or not (<option selected>). If the given value
   950 			# (like <a href="blah">) or not (<option selected>). If the given value
   751 			# is a "y" or a "Y", the attribute must not have a value.
   951 			# is a "y" or a "Y", the attribute must not have a value.
   752 			# If the given value is an "n" or an "N", the attribute must have one.
   952 			# If the given value is an "n" or an "N", the attribute must have one.
   753 
   953 
   754 			if (strtolower($checkvalue) != $vless)
   954 			if (strtolower($checkvalue) != $vless)
   773  * @param array $allowed_protocols Allowed protocols to keep
   973  * @param array $allowed_protocols Allowed protocols to keep
   774  * @return string Filtered content
   974  * @return string Filtered content
   775  */
   975  */
   776 function wp_kses_bad_protocol($string, $allowed_protocols) {
   976 function wp_kses_bad_protocol($string, $allowed_protocols) {
   777 	$string = wp_kses_no_null($string);
   977 	$string = wp_kses_no_null($string);
   778 	$string2 = $string.'a';
   978 	$iterations = 0;
   779 
   979 
   780 	while ($string != $string2) {
   980 	do {
   781 		$string2 = $string;
   981 		$original_string = $string;
   782 		$string = wp_kses_bad_protocol_once($string, $allowed_protocols);
   982 		$string = wp_kses_bad_protocol_once($string, $allowed_protocols);
   783 	} # while
   983 	} while ( $original_string != $string && ++$iterations < 6 );
       
   984 
       
   985 	if ( $original_string != $string )
       
   986 		return '';
   784 
   987 
   785 	return $string;
   988 	return $string;
   786 }
   989 }
   787 
   990 
   788 /**
   991 /**
   789  * Removes any NULL characters in $string.
   992  * Removes any null characters in $string.
   790  *
   993  *
   791  * @since 1.0.0
   994  * @since 1.0.0
   792  *
   995  *
   793  * @param string $string
   996  * @param string $string
   794  * @return string
   997  * @return string
   801 }
  1004 }
   802 
  1005 
   803 /**
  1006 /**
   804  * Strips slashes from in front of quotes.
  1007  * Strips slashes from in front of quotes.
   805  *
  1008  *
   806  * This function changes the character sequence  \"  to just  ". It leaves all
  1009  * This function changes the character sequence \" to just ". It leaves all
   807  * other slashes alone. It's really weird, but the quoting from
  1010  * other slashes alone. It's really weird, but the quoting from
   808  * preg_replace(//e) seems to require this.
  1011  * preg_replace(//e) seems to require this.
   809  *
  1012  *
   810  * @since 1.0.0
  1013  * @since 1.0.0
   811  *
  1014  *
   812  * @param string $string String to strip slashes
  1015  * @param string $string String to strip slashes
   813  * @return string Fixed strings with quoted slashes
  1016  * @return string Fixed string with quoted slashes
   814  */
  1017  */
   815 function wp_kses_stripslashes($string) {
  1018 function wp_kses_stripslashes($string) {
   816 	return preg_replace('%\\\\"%', '"', $string);
  1019 	return preg_replace('%\\\\"%', '"', $string);
   817 }
  1020 }
   818 
  1021 
   877  *
  1080  *
   878  * @param string $string Content to check for bad protocols
  1081  * @param string $string Content to check for bad protocols
   879  * @param string $allowed_protocols Allowed protocols
  1082  * @param string $allowed_protocols Allowed protocols
   880  * @return string Sanitized content
  1083  * @return string Sanitized content
   881  */
  1084  */
   882 function wp_kses_bad_protocol_once($string, $allowed_protocols) {
  1085 function wp_kses_bad_protocol_once($string, $allowed_protocols, $count = 1 ) {
   883 	global $_kses_allowed_protocols;
  1086 	$string2 = preg_split( '/:|&#0*58;|&#x0*3a;/i', $string, 2 );
   884 	$_kses_allowed_protocols = $allowed_protocols;
  1087 	if ( isset($string2[1]) && ! preg_match('%/\?%', $string2[0]) ) {
   885 
  1088 		$string = trim( $string2[1] );
   886 	$string2 = preg_split('/:|&#58;|&#x3a;/i', $string, 2);
  1089 		$protocol = wp_kses_bad_protocol_once2( $string2[0], $allowed_protocols );
   887 	if ( isset($string2[1]) && !preg_match('%/\?%', $string2[0]) )
  1090 		if ( 'feed:' == $protocol ) {
   888 		$string = wp_kses_bad_protocol_once2($string2[0]) . trim($string2[1]);
  1091 			if ( $count > 2 )
   889 	else
  1092 				return '';
   890 		$string = preg_replace_callback('/^((&[^;]*;|[\sA-Za-z0-9])*)'.'(:|&#58;|&#[Xx]3[Aa];)\s*/', 'wp_kses_bad_protocol_once2', $string);
  1093 			$string = wp_kses_bad_protocol_once( $string, $allowed_protocols, ++$count );
       
  1094 			if ( empty( $string ) )
       
  1095 				return $string;
       
  1096 		}
       
  1097 		$string = $protocol . $string;
       
  1098 	}
   891 
  1099 
   892 	return $string;
  1100 	return $string;
   893 }
  1101 }
   894 
  1102 
   895 /**
  1103 /**
   896  * Callback for wp_kses_bad_protocol_once() regular expression.
  1104  * Callback for wp_kses_bad_protocol_once() regular expression.
   897  *
  1105  *
   898  * This function processes URL protocols, checks to see if they're in the
  1106  * This function processes URL protocols, checks to see if they're in the
   899  * white-list or not, and returns different data depending on the answer.
  1107  * whitelist or not, and returns different data depending on the answer.
   900  *
  1108  *
   901  * @access private
  1109  * @access private
   902  * @since 1.0.0
  1110  * @since 1.0.0
   903  *
  1111  *
   904  * @param mixed $matches string or preg_replace_callback() matches array to check for bad protocols
  1112  * @param string $string URI scheme to check against the whitelist
       
  1113  * @param string $allowed_protocols Allowed protocols
   905  * @return string Sanitized content
  1114  * @return string Sanitized content
   906  */
  1115  */
   907 function wp_kses_bad_protocol_once2($matches) {
  1116 function wp_kses_bad_protocol_once2( $string, $allowed_protocols ) {
   908 	global $_kses_allowed_protocols;
       
   909 
       
   910 	if ( is_array($matches) ) {
       
   911 		if ( ! isset($matches[1]) || empty($matches[1]) )
       
   912 			return '';
       
   913 
       
   914 		$string = $matches[1];
       
   915 	} else {
       
   916 		$string = $matches;
       
   917 	}
       
   918 
       
   919 	$string2 = wp_kses_decode_entities($string);
  1117 	$string2 = wp_kses_decode_entities($string);
   920 	$string2 = preg_replace('/\s/', '', $string2);
  1118 	$string2 = preg_replace('/\s/', '', $string2);
   921 	$string2 = wp_kses_no_null($string2);
  1119 	$string2 = wp_kses_no_null($string2);
   922 	$string2 = strtolower($string2);
  1120 	$string2 = strtolower($string2);
   923 
  1121 
   924 	$allowed = false;
  1122 	$allowed = false;
   925 	foreach ( (array) $_kses_allowed_protocols as $one_protocol)
  1123 	foreach ( (array) $allowed_protocols as $one_protocol )
   926 		if (strtolower($one_protocol) == $string2) {
  1124 		if ( strtolower($one_protocol) == $string2 ) {
   927 			$allowed = true;
  1125 			$allowed = true;
   928 			break;
  1126 			break;
   929 		}
  1127 		}
   930 
  1128 
   931 	if ($allowed)
  1129 	if ($allowed)
   950 
  1148 
   951 	$string = str_replace('&', '&amp;', $string);
  1149 	$string = str_replace('&', '&amp;', $string);
   952 
  1150 
   953 	# Change back the allowed entities in our entity whitelist
  1151 	# Change back the allowed entities in our entity whitelist
   954 
  1152 
   955 	$string = preg_replace('/&amp;([A-Za-z][A-Za-z0-9]{0,19});/', '&\\1;', $string);
  1153 	$string = preg_replace_callback('/&amp;([A-Za-z]{2,8});/', 'wp_kses_named_entities', $string);
   956 	$string = preg_replace_callback('/&amp;#0*([0-9]{1,5});/', 'wp_kses_normalize_entities2', $string);
  1154 	$string = preg_replace_callback('/&amp;#(0*[0-9]{1,7});/', 'wp_kses_normalize_entities2', $string);
   957 	$string = preg_replace_callback('/&amp;#([Xx])0*(([0-9A-Fa-f]{2}){1,2});/', 'wp_kses_normalize_entities3', $string);
  1155 	$string = preg_replace_callback('/&amp;#[Xx](0*[0-9A-Fa-f]{1,6});/', 'wp_kses_normalize_entities3', $string);
   958 
  1156 
   959 	return $string;
  1157 	return $string;
   960 }
  1158 }
   961 
  1159 
   962 /**
  1160 /**
   963  * Callback for wp_kses_normalize_entities() regular expression.
  1161  * Callback for wp_kses_normalize_entities() regular expression.
   964  *
  1162  *
   965  * This function helps wp_kses_normalize_entities() to only accept 16 bit values
  1163  * This function only accepts valid named entity references, which are finite,
   966  * and nothing more for &#number; entities.
  1164  * case-sensitive, and highly scrutinized by HTML and XML validators.
   967  *
  1165  *
   968  * @access private
  1166  * @since 3.0.0
   969  * @since 1.0.0
       
   970  *
  1167  *
   971  * @param array $matches preg_replace_callback() matches array
  1168  * @param array $matches preg_replace_callback() matches array
   972  * @return string Correctly encoded entity
  1169  * @return string Correctly encoded entity
   973  */
  1170  */
       
  1171 function wp_kses_named_entities($matches) {
       
  1172 	global $allowedentitynames;
       
  1173 
       
  1174 	if ( empty($matches[1]) )
       
  1175 		return '';
       
  1176 
       
  1177 	$i = $matches[1];
       
  1178 	return ( ( ! in_array($i, $allowedentitynames) ) ? "&amp;$i;" : "&$i;" );
       
  1179 }
       
  1180 
       
  1181 /**
       
  1182  * Callback for wp_kses_normalize_entities() regular expression.
       
  1183  *
       
  1184  * This function helps wp_kses_normalize_entities() to only accept 16-bit values
       
  1185  * and nothing more for &#number; entities.
       
  1186  *
       
  1187  * @access private
       
  1188  * @since 1.0.0
       
  1189  *
       
  1190  * @param array $matches preg_replace_callback() matches array
       
  1191  * @return string Correctly encoded entity
       
  1192  */
   974 function wp_kses_normalize_entities2($matches) {
  1193 function wp_kses_normalize_entities2($matches) {
   975 	if ( ! isset($matches[1]) || empty($matches[1]) )
  1194 	if ( empty($matches[1]) )
   976 		return '';
  1195 		return '';
   977 
  1196 
   978 	$i = $matches[1];
  1197 	$i = $matches[1];
   979 	return ( ( ! valid_unicode($i) ) || ($i > 65535) ? "&amp;#$i;" : "&#$i;" );
  1198 	if (valid_unicode($i)) {
       
  1199 		$i = str_pad(ltrim($i,'0'), 3, '0', STR_PAD_LEFT);
       
  1200 		$i = "&#$i;";
       
  1201 	} else {
       
  1202 		$i = "&amp;#$i;";
       
  1203 	}
       
  1204 
       
  1205 	return $i;
   980 }
  1206 }
   981 
  1207 
   982 /**
  1208 /**
   983  * Callback for wp_kses_normalize_entities() for regular expression.
  1209  * Callback for wp_kses_normalize_entities() for regular expression.
   984  *
  1210  *
   989  *
  1215  *
   990  * @param array $matches preg_replace_callback() matches array
  1216  * @param array $matches preg_replace_callback() matches array
   991  * @return string Correctly encoded entity
  1217  * @return string Correctly encoded entity
   992  */
  1218  */
   993 function wp_kses_normalize_entities3($matches) {
  1219 function wp_kses_normalize_entities3($matches) {
   994 	if ( ! isset($matches[2]) || empty($matches[2]) )
  1220 	if ( empty($matches[1]) )
   995 		return '';
  1221 		return '';
   996 
  1222 
   997 	$hexchars = $matches[2];
  1223 	$hexchars = $matches[1];
   998 	return ( ( ! valid_unicode(hexdec($hexchars)) ) ? "&amp;#x$hexchars;" : "&#x$hexchars;" );
  1224 	return ( ( ! valid_unicode(hexdec($hexchars)) ) ? "&amp;#x$hexchars;" : '&#x'.ltrim($hexchars,'0').';' );
   999 }
  1225 }
  1000 
  1226 
  1001 /**
  1227 /**
  1002  * Helper function to determine if a Unicode value is valid.
  1228  * Helper function to determine if a Unicode value is valid.
  1003  *
  1229  *
  1004  * @param int $i Unicode value
  1230  * @param int $i Unicode value
  1005  * @return bool true if the value was a valid Unicode number
  1231  * @return bool True if the value was a valid Unicode number
  1006  */
  1232  */
  1007 function valid_unicode($i) {
  1233 function valid_unicode($i) {
  1008 	return ( $i == 0x9 || $i == 0xa || $i == 0xd ||
  1234 	return ( $i == 0x9 || $i == 0xa || $i == 0xd ||
  1009 			($i >= 0x20 && $i <= 0xd7ff) ||
  1235 			($i >= 0x20 && $i <= 0xd7ff) ||
  1010 			($i >= 0xe000 && $i <= 0xfffd) ||
  1236 			($i >= 0xe000 && $i <= 0xfffd) ||
  1135  *
  1361  *
  1136  * @since 2.0.0
  1362  * @since 2.0.0
  1137  * @uses add_filter() See description for what functions are added to what hooks.
  1363  * @uses add_filter() See description for what functions are added to what hooks.
  1138  */
  1364  */
  1139 function kses_init_filters() {
  1365 function kses_init_filters() {
  1140 	// Normal filtering.
  1366 	// Normal filtering
  1141 	add_filter('pre_comment_content', 'wp_filter_kses');
       
  1142 	add_filter('title_save_pre', 'wp_filter_kses');
  1367 	add_filter('title_save_pre', 'wp_filter_kses');
       
  1368 
       
  1369 	// Comment filtering
       
  1370 	if ( current_user_can( 'unfiltered_html' ) )
       
  1371 		add_filter( 'pre_comment_content', 'wp_filter_post_kses' );
       
  1372 	else
       
  1373 		add_filter( 'pre_comment_content', 'wp_filter_kses' );
  1143 
  1374 
  1144 	// Post filtering
  1375 	// Post filtering
  1145 	add_filter('content_save_pre', 'wp_filter_post_kses');
  1376 	add_filter('content_save_pre', 'wp_filter_post_kses');
  1146 	add_filter('excerpt_save_pre', 'wp_filter_post_kses');
  1377 	add_filter('excerpt_save_pre', 'wp_filter_post_kses');
  1147 	add_filter('content_filtered_save_pre', 'wp_filter_post_kses');
  1378 	add_filter('content_filtered_save_pre', 'wp_filter_post_kses');
  1158  * hook (priority is also default).
  1389  * hook (priority is also default).
  1159  *
  1390  *
  1160  * @since 2.0.6
  1391  * @since 2.0.6
  1161  */
  1392  */
  1162 function kses_remove_filters() {
  1393 function kses_remove_filters() {
  1163 	// Normal filtering.
  1394 	// Normal filtering
  1164 	remove_filter('pre_comment_content', 'wp_filter_kses');
       
  1165 	remove_filter('title_save_pre', 'wp_filter_kses');
  1395 	remove_filter('title_save_pre', 'wp_filter_kses');
       
  1396 
       
  1397 	// Comment filtering
       
  1398 	remove_filter( 'pre_comment_content', 'wp_filter_post_kses' );
       
  1399 	remove_filter( 'pre_comment_content', 'wp_filter_kses' );
  1166 
  1400 
  1167 	// Post filtering
  1401 	// Post filtering
  1168 	remove_filter('content_save_pre', 'wp_filter_post_kses');
  1402 	remove_filter('content_save_pre', 'wp_filter_post_kses');
  1169 	remove_filter('excerpt_save_pre', 'wp_filter_post_kses');
  1403 	remove_filter('excerpt_save_pre', 'wp_filter_post_kses');
  1170 	remove_filter('content_filtered_save_pre', 'wp_filter_post_kses');
  1404 	remove_filter('content_filtered_save_pre', 'wp_filter_post_kses');
  1176  * If you remove the kses_init() function from 'init' hook and
  1410  * If you remove the kses_init() function from 'init' hook and
  1177  * 'set_current_user' (priority is default), then none of the Kses filter hooks
  1411  * 'set_current_user' (priority is default), then none of the Kses filter hooks
  1178  * will be added.
  1412  * will be added.
  1179  *
  1413  *
  1180  * First removes all of the Kses filters in case the current user does not need
  1414  * First removes all of the Kses filters in case the current user does not need
  1181  * to have Kses filter the content. If the user does not have unfiltered html
  1415  * to have Kses filter the content. If the user does not have unfiltered_html
  1182  * capability, then Kses filters are added.
  1416  * capability, then Kses filters are added.
  1183  *
  1417  *
  1184  * @uses kses_remove_filters() Removes the Kses filters
  1418  * @uses kses_remove_filters() Removes the Kses filters
  1185  * @uses kses_init_filters() Adds the Kses filters back if the user
  1419  * @uses kses_init_filters() Adds the Kses filters back if the user
  1186  *		does not have unfiltered HTML capability.
  1420  *		does not have unfiltered HTML capability.
  1194 }
  1428 }
  1195 
  1429 
  1196 add_action('init', 'kses_init');
  1430 add_action('init', 'kses_init');
  1197 add_action('set_current_user', 'kses_init');
  1431 add_action('set_current_user', 'kses_init');
  1198 
  1432 
       
  1433 /**
       
  1434  * Inline CSS filter
       
  1435  *
       
  1436  * @since 2.8.1
       
  1437  */
  1199 function safecss_filter_attr( $css, $deprecated = '' ) {
  1438 function safecss_filter_attr( $css, $deprecated = '' ) {
       
  1439 	if ( !empty( $deprecated ) )
       
  1440 		_deprecated_argument( __FUNCTION__, '2.8.1' ); // Never implemented
       
  1441 
  1200 	$css = wp_kses_no_null($css);
  1442 	$css = wp_kses_no_null($css);
  1201 	$css = str_replace(array("\n","\r","\t"), '', $css);
  1443 	$css = str_replace(array("\n","\r","\t"), '', $css);
  1202 
  1444 
  1203 	if ( preg_match( '%[\\(&]|/\*%', $css ) ) // remove any inline css containing \ ( & or comments
  1445 	if ( preg_match( '%[\\(&=}]|/\*%', $css ) ) // remove any inline css containing \ ( & } = or comments
  1204 		return '';
  1446 		return '';
  1205 
  1447 
  1206 	$css_array = split( ';', trim( $css ) );
  1448 	$css_array = explode( ';', trim( $css ) );
  1207 	$allowed_attr = apply_filters( 'safe_style_css', array( 'text-align', 'margin', 'color', 'float',
  1449 	$allowed_attr = apply_filters( 'safe_style_css', array( 'text-align', 'margin', 'color', 'float',
  1208 	'border', 'background', 'background-color', 'border-bottom', 'border-bottom-color',
  1450 	'border', 'background', 'background-color', 'border-bottom', 'border-bottom-color',
  1209 	'border-bottom-style', 'border-bottom-width', 'border-collapse', 'border-color', 'border-left',
  1451 	'border-bottom-style', 'border-bottom-width', 'border-collapse', 'border-color', 'border-left',
  1210 	'border-left-color', 'border-left-style', 'border-left-width', 'border-right', 'border-right-color',
  1452 	'border-left-color', 'border-left-style', 'border-left-width', 'border-right', 'border-right-color',
  1211 	'border-right-style', 'border-right-width', 'border-spacing', 'border-style', 'border-top',
  1453 	'border-right-style', 'border-right-width', 'border-spacing', 'border-style', 'border-top',
  1226 		$css_item = trim( $css_item );
  1468 		$css_item = trim( $css_item );
  1227 		$found = false;
  1469 		$found = false;
  1228 		if ( strpos( $css_item, ':' ) === false ) {
  1470 		if ( strpos( $css_item, ':' ) === false ) {
  1229 			$found = true;
  1471 			$found = true;
  1230 		} else {
  1472 		} else {
  1231 			$parts = split( ':', $css_item );
  1473 			$parts = explode( ':', $css_item );
  1232 			if ( in_array( trim( $parts[0] ), $allowed_attr ) )
  1474 			if ( in_array( trim( $parts[0] ), $allowed_attr ) )
  1233 				$found = true;
  1475 				$found = true;
  1234 		}
  1476 		}
  1235 		if ( $found ) {
  1477 		if ( $found ) {
  1236 			if( $css != '' )
  1478 			if( $css != '' )