WordPress.org

Make WordPress Core

Changeset 2896


Ignore:
Timestamp:
09/20/2005 10:18:47 PM (16 years ago)
Author:
ryan
Message:

Filter posts with kses for users who do not have the unfiltered_html cap. Props donncha. fixes #1674

Location:
trunk/wp-includes
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/wp-includes/default-filters.php

    r2517 r2896  
    2626
    2727add_filter('pre_comment_content', 'stripslashes', 1);
    28 add_filter('pre_comment_content', 'wp_filter_kses');
    2928add_filter('pre_comment_content', 'wp_rel_nofollow', 15);
    3029add_filter('pre_comment_content', 'balanceTags', 30);
  • trunk/wp-includes/kses.php

    r2151 r2896  
    11<?php
     2
    23// Added wp_ prefix to avoid conflicts with existing kses users
    34# kses 0.2.1 - HTML/XHTML filter that only allows some elements and attributes
     
    78# E-mail:      metaur at users dot sourceforge dot net
    89# Web page:    http://sourceforge.net/projects/kses
    9 # Paper mail:  (not at the moment)
     10# Paper mail:  Ulf Harnhammar
     11#              Ymergatan 17 C
     12#              753 25  Uppsala
     13#              SWEDEN
    1014#
    1115# [kses strips evil scripts!]
    1216if (!defined('CUSTOM_TAGS'))
    1317    define('CUSTOM_TAGS', false);
    14    
     18
    1519// You can override this in your my-hacks.php file
    1620if (!CUSTOM_TAGS) {
    17 $allowedtags = array(
    18     'a' => array(
    19         'href' => array(),
    20         'title' => array()
    21         ),
    22     'abbr' => array('title' => array()),
    23     'acronym' => array('title' => array()),
    24     'b' => array(),
    25     'blockquote' => array('cite' => array()),
    26 //  'br' => array(),
    27     'code' => array(),
    28 //  'del' => array('datetime' => array()),
    29 //  'dd' => array(),
    30 //  'dl' => array(),
    31 //  'dt' => array(),
    32     'em' => array(),
    33     'i' => array(),
    34 //  'ins' => array('datetime' => array(), 'cite' => array()),
    35 //  'li' => array(),
    36 //  'ol' => array(),
    37 //  'p' => array(),
    38 //  'q' => array(),
    39     'strike' => array(),
    40     'strong' => array(),
    41 //  'sub' => array(),
    42 //  'sup' => array(),
    43 //  'u' => array(),
    44 //  'ul' => array(),
     21    $allowedposttags = array ('address' => array (), 'applet' => array ('codebase' => array (), 'code' => array (), 'name' => array (), 'alt' => array ()), 'area' => array ('shape' => array (), 'coords' => array (), 'href' => array (), 'alt' => array ()), 'a' => array ('href' => array (), 'title' => array (), 'rel' => array (), 'rev' => array (), 'name' => array ()), 'abbr' => array ('title' => array ()), 'acronym' => array ('title' => array ()), 'b' => array (), 'base' => array ('href' => array ()), 'basefont' => array ('size' => array ()), 'bdo' => array ('dir' => array ()), 'big' => array (), 'blockquote' => array ('cite' => array ()), 'body' => array ('alink' => array (), 'background' => array (), 'bgcolor' => array (), 'link' => array (), 'text' => array (), 'vlink' => array ()), 'br' => array (), 'button' => array ('disabled' => array (), 'name' => array (), 'type' => array (), 'value' => array ()), 'caption' => array ('align' => array ()), 'code' => array (), 'col' => array ('align' => array (), 'char' => array (), 'charoff' => array (), 'span' => array (), 'valign' => array (), 'width' => array ()), 'del' => array ('datetime' => array ()), 'dd' => array (), 'div' => array ('align' => array ()), 'dl' => array (), 'dt' => array (), 'em' => array (), 'fieldset' => array (), 'font' => array ('color' => array (), 'face' => array (), 'size' => array ()), 'form' => array ('action' => array (), 'accept' => array (), 'accept-charset' => array (), 'enctype' => array (), 'method' => array (), 'name' => array (), 'target' => array ()), 'frame' => array ('frameborder' => array (), 'longsesc' => array (), 'marginheight' => array (), 'marginwidth' => array (), 'name' => array (), 'noresize' => array (), 'scrolling' => array (), 'src' => array ()), 'frameset' => array ('cols' => array (), 'rows' => array ()), 'head' => array ('profile' => array ()), 'h1' => array ('align' => array ()), 'h2' => array ('align' => array ()), 'h3' => array ('align' => array ()), 'h4' => array ('align' => array ()), 'h5' => array ('align' => array ()), 'h6' => array ('align' => array ()), 'hr' => array ('align' => array (), 'noshade' => array (), 'size' => array (), 'width' => array ()), 'html' => array ('xmlns' => array ()), 'i' => array (), 'iframe' => array ('align' => array (), 'frameborder' => array (), 'height' => array (), 'londesc' => array (), 'marginheight' => array (), 'marginwidth' => array (), 'name' => array (), 'scrolling' => array (), 'src' => array (), 'width' => array ()), 'img' => array ('alt' => array (), 'align' => array (), 'border' => array (), 'height' => array (), 'hspace' => array (), 'ismap' => array (), 'longdesc' => array (), 'usemap' => array (), 'vspace' => array (), 'src' => array (), 'width' => array ()), 'input' => array ('accept' => array (), 'align' => array (), 'alt' => array (), 'checked' => array (), 'disabled' => array (), 'maxlength' => array (), 'name' => array (), 'readonly' => array (), 'size' => array (), 'src' => array (), 'type' => array (), 'value' => array ()), 'ins' => array ('datetime' => array (), 'cite' => array ()), 'kbd' => array (), 'label' => array ('for' => array ()), 'legend' => array ('align' => array ()), 'li' => array (), 'link' => array ('charset' => array (), 'href' => array (), 'hreflang' => array (), 'media' => array (), 'rel' => array (), 'rev' => array (), 'target' => array (), 'type' => array ()), 'map' => array ('id' => array (), 'name' => array ()), 'menu' => array (), 'meta' => array ('content' => array (), 'http-equiv' => array (), 'name' => array (), 'scheme' => array ()), 'noframes' => array (), 'noscript' => array (), 'object' => array ('align' => array (), 'archive' => array (), 'border' => array (), 'classid' => array (), 'codebase' => array (), 'codetype' => array (), 'data' => array (), 'declare' => array (), 'height' => array (), 'hspace' => array (), 'name' => array (), 'standby' => array (), 'type' => array (), 'usemap' => array (), 'vspace' => array (), 'width' => array ()), 'ol' => array ('compact' => array (), 'start' => array (), 'type' => array ()), 'optgroup' => array ('label' => array (), 'disabled' => array ()), 'option' => array ('disabled' => array (), 'label' => array (), 'selected' => array (), 'value' => array ()), 'p' => array ('align' => array ()), 'param' => array ('name' => array (), 'type' => array (), 'value' => array (), 'valuetype' => array ()), 'pre' => array ('width' => array ()), 'q' => array ('cite' => array ()), 's' => array (), 'strike' => array (), 'strong' => array (), 'style' => array ('type' => array (), 'media' => array ()), 'sub' => array (), 'sup' => array (), 'table' => array ('align' => array (), 'bgcolor' => array (), 'border' => array (), 'cellpadding' => array (), 'cellspacing' => array (), 'frame' => array (), 'rules' => array (), 'summary' => array (), 'width' => array ()), 'tbody' => array ('align' => array (), 'char' => array (), 'charoff' => array (), 'valign' => array ()), 'td' => array ('abbr' => array (), 'align' => array (), 'axis' => array (), 'bgcolor' => array (), 'char' => array (), 'charoff' => array (), 'colspan' => array (), 'headers' => array (), 'height' => array (), 'nowrap' => array (), 'rowspan' => array (), 'scope' => array (), 'valign' => array (), 'width' => array ()), 'textarea' => array ('cols' => array (), 'rows' => array (), 'disabled' => array (), 'name' => array (), 'readonly' => array ()), 'tfoot' => array ('align' => array (), 'char' => array (), 'charoff' => array (), 'valign' => array ()), 'th' => array ('abbr' => array (), 'align' => array (), 'axis' => array (), 'bgcolor' => array (), 'char' => array (), 'charoff' => array (), 'colspan' => array (), 'headers' => array (), 'height' => array (), 'nowrap' => array (), 'rowspan' => array (), 'scope' => array (), 'valign' => array (), 'width' => array ()), 'thead' => array ('align' => array (), 'char' => array (), 'charoff' => array (), 'valign' => array ()), 'title' => array (), 'tr' => array ('align' => array (), 'bgcolor' => array (), 'char' => array (), 'charoff' => array (), 'valign' => array ()), 'tt' => array (), 'u' => array (), 'ul' => array (), 'var' => array ());
     22    $allowedtags = array ('a' => array ('href' => array (), 'title' => array ()), 'abbr' => array ('title' => array ()), 'acronym' => array ('title' => array ()), 'b' => array (), 'blockquote' => array ('cite' => array ()),
     23        //  'br' => array(),
     24    'code' => array (),
     25        //  'del' => array('datetime' => array()),
     26        //  'dd' => array(),
     27        //  'dl' => array(),
     28        //  'dt' => array(),
     29    'em' => array (), 'i' => array (),
     30        //  'ins' => array('datetime' => array(), 'cite' => array()),
     31        //  'li' => array(),
     32        //  'ol' => array(),
     33        //  'p' => array(),
     34        //  'q' => array(),
     35    'strike' => array (), 'strong' => array (),
     36        //  'sub' => array(),
     37        //  'sup' => array(),
     38        //  'u' => array(),
     39        //  'ul' => array(),
    4540    );
    4641}
    47 function wp_kses($string, $allowed_html, $allowed_protocols =
    48                array('http', 'https', 'ftp', 'news', 'nntp', 'feed', 'gopher', 'mailto'))
    49 ###############################################################################
    50 # This function makes sure that only the allowed HTML element names, attribute
    51 # names and attribute values plus only sane HTML entities will occur in
    52 # $string. You have to remove any slashes from PHP's magic quotes before you
    53 # call this function.
    54 ###############################################################################
    55 {
    56   $string = wp_kses_no_null($string);
    57   $string = wp_kses_js_entities($string);
    58   $string = wp_kses_normalize_entities($string);
    59   $string = wp_kses_hook($string);
    60   $allowed_html_fixed = wp_kses_array_lc($allowed_html);
    61   return wp_kses_split($string, $allowed_html_fixed, $allowed_protocols);
     42function wp_kses($string, $allowed_html, $allowed_protocols = array ('http', 'https', 'ftp', 'news', 'nntp', 'telnet', 'feed', 'gopher', 'mailto'))
     43    ###############################################################################
     44        # This function makes sure that only the allowed HTML element names, attribute
     45        # names and attribute values plus only sane HTML entities will occur in
     46        # $string. You have to remove any slashes from PHP's magic quotes before you
     47        # call this function.
     48        ###############################################################################
     49    {
     50    $string = wp_kses_no_null($string);
     51    $string = wp_kses_js_entities($string);
     52    $string = wp_kses_normalize_entities($string);
     53    $string = wp_kses_hook($string);
     54    $allowed_html_fixed = wp_kses_array_lc($allowed_html);
     55    return wp_kses_split($string, $allowed_html_fixed, $allowed_protocols);
    6256} # function wp_kses
    6357
    64 
    6558function wp_kses_hook($string)
    6659###############################################################################
     
    6861###############################################################################
    6962{
    70   return $string;
     63    return $string;
    7164} # function wp_kses_hook
    7265
    73 
    7466function wp_kses_version()
    7567###############################################################################
     
    7769###############################################################################
    7870{
    79   return '0.2.1';
     71    return '0.2.2';
    8072} # function wp_kses_version
    81 
    8273
    8374function wp_kses_split($string, $allowed_html, $allowed_protocols)
     
    8778###############################################################################
    8879{
    89   return preg_replace('%(<'.   # EITHER: <
    90                       '[^>]*'. # things that aren't >
    91                       '(>|$)'. # > or end of string
    92                       '|>)%e', # OR: just a >
    93                       "wp_kses_split2('\\1', \$allowed_html, ".
    94                       '$allowed_protocols)',
    95                       $string);
     80    return preg_replace('%(<'.# EITHER: <
     81    '[^>]*'.# things that aren't >
     82    '(>|$)'.# > or end of string
     83    '|>)%e', # OR: just a >
     84    "wp_kses_split2('\\1', \$allowed_html, ".'$allowed_protocols)', $string);
    9685} # function wp_kses_split
    97 
    9886
    9987function wp_kses_split2($string, $allowed_html, $allowed_protocols)
     
    10593###############################################################################
    10694{
    107   $string = wp_kses_stripslashes($string);
    108 
    109   if (substr($string, 0, 1) != '<')
    110     return '&gt;';
    111     # It matched a ">" character
    112 
    113   if (!preg_match('%^<\s*(/\s*)?([a-zA-Z0-9]+)([^>]*)>?$%', $string, $matches))
    114     return '';
    115     # It's seriously malformed
    116 
    117   $slash = trim($matches[1]);
    118   $elem = $matches[2];
    119   $attrlist = $matches[3];
    120 
    121   if (!is_array($allowed_html[strtolower($elem)]))
    122     return '';
    123     # They are using a not allowed HTML element
    124 
    125   return wp_kses_attr("$slash$elem", $attrlist, $allowed_html,
    126                    $allowed_protocols);
     95    $string = wp_kses_stripslashes($string);
     96
     97    if (substr($string, 0, 1) != '<')
     98        return '&gt;';
     99    # It matched a ">" character
     100
     101    if (!preg_match('%^<\s*(/\s*)?([a-zA-Z0-9]+)([^>]*)>?$%', $string, $matches))
     102        return '';
     103    # It's seriously malformed
     104
     105    $slash = trim($matches[1]);
     106    $elem = $matches[2];
     107    $attrlist = $matches[3];
     108
     109    if (!@ is_array($allowed_html[strtolower($elem)]))
     110        return '';
     111    # They are using a not allowed HTML element
     112
     113    if ($slash != '')
     114        return "<$slash$elem>";
     115    # No attributes are allowed for closing elements
     116
     117    return wp_kses_attr("$slash$elem", $attrlist, $allowed_html, $allowed_protocols);
    127118} # function wp_kses_split2
    128 
    129119
    130120function wp_kses_attr($element, $attr, $allowed_html, $allowed_protocols)
     
    138128###############################################################################
    139129{
    140 # Is there a closing XHTML slash at the end of the attributes?
    141 
    142   $xhtml_slash = '';
    143   if (preg_match('%\s/\s*$%', $attr))
    144     $xhtml_slash = ' /';
    145 
    146 # Are any attributes allowed at all for this element?
    147 
    148   if (count($allowed_html[strtolower($element)]) == 0)
    149     return "<$element$xhtml_slash>";
    150 
    151 # Split it
    152 
    153   $attrarr = wp_kses_hair($attr, $allowed_protocols);
    154 
    155 # Go through $attrarr, and save the allowed attributes for this element
    156 # in $attr2
    157 
    158   $attr2 = '';
    159 
    160   foreach ($attrarr as $arreach)
    161   {
    162     $current = $allowed_html[strtolower($element)]
    163                             [strtolower($arreach['name'])];
    164     if ($current == '')
    165       continue; # the attribute is not allowed
    166 
    167     if (!is_array($current))
    168       $attr2 .= ' '.$arreach['whole'];
    169     # there are no checks
    170 
    171     else
    172     {
    173     # there are some checks
    174       $ok = true;
    175       foreach ($current as $currkey => $currval)
    176         if (!wp_kses_check_attr_val($arreach['value'], $arreach['vless'],
    177                                  $currkey, $currval))
    178         { $ok = false; break; }
    179 
    180       if ($ok)
    181         $attr2 .= ' '.$arreach['whole']; # it passed them
    182     } # if !is_array($current)
    183   } # foreach
    184 
    185 # Remove any "<" or ">" characters
    186 
    187   $attr2 = preg_replace('/[<>]/', '', $attr2);
    188 
    189   return "<$element$attr2$xhtml_slash>";
     130    # Is there a closing XHTML slash at the end of the attributes?
     131
     132    $xhtml_slash = '';
     133    if (preg_match('%\s/\s*$%', $attr))
     134        $xhtml_slash = ' /';
     135
     136    # Are any attributes allowed at all for this element?
     137
     138    if (@ count($allowed_html[strtolower($element)]) == 0)
     139        return "<$element$xhtml_slash>";
     140
     141    # Split it
     142
     143    $attrarr = wp_kses_hair($attr, $allowed_protocols);
     144
     145    # Go through $attrarr, and save the allowed attributes for this element
     146    # in $attr2
     147
     148    $attr2 = '';
     149
     150    foreach ($attrarr as $arreach) {
     151        if (!@ isset ($allowed_html[strtolower($element)][strtolower($arreach['name'])]))
     152            continue; # the attribute is not allowed
     153
     154        $current = $allowed_html[strtolower($element)][strtolower($arreach['name'])];
     155        if ($current == '')
     156            continue; # the attribute is not allowed
     157
     158        if (!is_array($current))
     159            $attr2 .= ' '.$arreach['whole'];
     160        # there are no checks
     161
     162        else {
     163            # there are some checks
     164            $ok = true;
     165            foreach ($current as $currkey => $currval)
     166                if (!wp_kses_check_attr_val($arreach['value'], $arreach['vless'], $currkey, $currval)) {
     167                    $ok = false;
     168                    break;
     169                }
     170
     171            if ($ok)
     172                $attr2 .= ' '.$arreach['whole']; # it passed them
     173        } # if !is_array($current)
     174    } # foreach
     175
     176    # Remove any "<" or ">" characters
     177
     178    $attr2 = preg_replace('/[<>]/', '', $attr2);
     179
     180    return "<$element$attr2$xhtml_slash>";
    190181} # function wp_kses_attr
    191 
    192182
    193183function wp_kses_hair($attr, $allowed_protocols)
     
    201191###############################################################################
    202192{
    203   $attrarr = array();
    204   $mode = 0;
    205   $attrname = '';
    206 
    207 # Loop through the whole attribute list
    208 
    209   while (strlen($attr) != 0)
    210   {
    211     $working = 0; # Was the last operation successful?
    212 
    213     switch ($mode)
    214     {
    215       case 0: # attribute name, href for instance
    216 
    217         if (preg_match('/^([-a-zA-Z]+)/', $attr, $match))
    218         {
    219           $attrname = $match[1];
    220           $working = $mode = 1;
    221           $attr = preg_replace('/^[-a-zA-Z]+/', '', $attr);
    222         }
    223 
    224         break;
    225 
    226       case 1: # equals sign or valueless ("selected")
    227 
    228         if (preg_match('/^\s*=\s*/', $attr)) # equals sign
    229         {
    230           $working = 1; $mode = 2;
    231           $attr = preg_replace('/^\s*=\s*/', '', $attr);
    232           break;
    233         }
    234 
    235         if (preg_match('/^\s+/', $attr)) # valueless
    236         {
    237           $working = 1; $mode = 0;
    238           $attrarr[] = array
    239                         ('name'  => $attrname,
    240                          'value' => '',
    241                          'whole' => $attrname,
    242                          'vless' => 'y');
    243           $attr = preg_replace('/^\s+/', '', $attr);
    244         }
    245 
    246         break;
    247 
    248       case 2: # attribute value, a URL after href= for instance
    249 
    250         if (preg_match('/^"([^"]*)"(\s+|$)/', $attr, $match))
    251          # "value"
    252         {
    253           $thisval = wp_kses_bad_protocol($match[1], $allowed_protocols);
    254 
    255           $attrarr[] = array
    256                         ('name'  => $attrname,
    257                          'value' => $thisval,
    258                          'whole' => "$attrname=\"$thisval\"",
    259                          'vless' => 'n');
    260           $working = 1; $mode = 0;
    261           $attr = preg_replace('/^"[^"]*"(\s+|$)/', '', $attr);
    262           break;
    263         }
    264 
    265         if (preg_match("/^'([^']*)'(\s+|$)/", $attr, $match))
    266          # 'value'
    267         {
    268           $thisval = wp_kses_bad_protocol($match[1], $allowed_protocols);
    269 
    270           $attrarr[] = array
    271                         ('name'  => $attrname,
    272                          'value' => $thisval,
    273                          'whole' => "$attrname='$thisval'",
    274                          'vless' => 'n');
    275           $working = 1; $mode = 0;
    276           $attr = preg_replace("/^'[^']*'(\s+|$)/", '', $attr);
    277           break;
    278         }
    279 
    280         if (preg_match("%^([^\s\"']+)(\s+|$)%", $attr, $match))
    281          # value
    282         {
    283           $thisval = wp_kses_bad_protocol($match[1], $allowed_protocols);
    284 
    285           $attrarr[] = array
    286                         ('name'  => $attrname,
    287                          'value' => $thisval,
    288                          'whole' => "$attrname=\"$thisval\"",
    289                          'vless' => 'n');
    290                          # We add quotes to conform to W3C's HTML spec.
    291           $working = 1; $mode = 0;
    292           $attr = preg_replace("%^[^\s\"']+(\s+|$)%", '', $attr);
    293         }
    294 
    295         break;
    296     } # switch
    297 
    298     if ($working == 0) # not well formed, remove and try again
    299     {
    300       $attr = wp_kses_html_error($attr);
    301       $mode = 0;
    302     }
    303   } # while
    304 
    305   if ($mode == 1)
    306   # special case, for when the attribute list ends with a valueless
    307   # attribute like "selected"
    308     $attrarr[] = array
    309                   ('name'  => $attrname,
    310                    'value' => '',
    311                    'whole' => $attrname,
    312                    'vless' => 'y');
    313 
    314   return $attrarr;
     193    $attrarr = array ();
     194    $mode = 0;
     195    $attrname = '';
     196
     197    # Loop through the whole attribute list
     198
     199    while (strlen($attr) != 0) {
     200        $working = 0; # Was the last operation successful?
     201
     202        switch ($mode) {
     203            case 0 : # attribute name, href for instance
     204
     205                if (preg_match('/^([-a-zA-Z]+)/', $attr, $match)) {
     206                    $attrname = $match[1];
     207                    $working = $mode = 1;
     208                    $attr = preg_replace('/^[-a-zA-Z]+/', '', $attr);
     209                }
     210
     211                break;
     212
     213            case 1 : # equals sign or valueless ("selected")
     214
     215                if (preg_match('/^\s*=\s*/', $attr)) # equals sign
     216                    {
     217                    $working = 1;
     218                    $mode = 2;
     219                    $attr = preg_replace('/^\s*=\s*/', '', $attr);
     220                    break;
     221                }
     222
     223                if (preg_match('/^\s+/', $attr)) # valueless
     224                    {
     225                    $working = 1;
     226                    $mode = 0;
     227                    $attrarr[] = array ('name' => $attrname, 'value' => '', 'whole' => $attrname, 'vless' => 'y');
     228                    $attr = preg_replace('/^\s+/', '', $attr);
     229                }
     230
     231                break;
     232
     233            case 2 : # attribute value, a URL after href= for instance
     234
     235                if (preg_match('/^"([^"]*)"(\s+|$)/', $attr, $match))
     236                    # "value"
     237                    {
     238                    $thisval = wp_kses_bad_protocol($match[1], $allowed_protocols);
     239
     240                    $attrarr[] = array ('name' => $attrname, 'value' => $thisval, 'whole' => "$attrname=\"$thisval\"", 'vless' => 'n');
     241                    $working = 1;
     242                    $mode = 0;
     243                    $attr = preg_replace('/^"[^"]*"(\s+|$)/', '', $attr);
     244                    break;
     245                }
     246
     247                if (preg_match("/^'([^']*)'(\s+|$)/", $attr, $match))
     248                    # 'value'
     249                    {
     250                    $thisval = wp_kses_bad_protocol($match[1], $allowed_protocols);
     251
     252                    $attrarr[] = array ('name' => $attrname, 'value' => $thisval, 'whole' => "$attrname='$thisval'", 'vless' => 'n');
     253                    $working = 1;
     254                    $mode = 0;
     255                    $attr = preg_replace("/^'[^']*'(\s+|$)/", '', $attr);
     256                    break;
     257                }
     258
     259                if (preg_match("%^([^\s\"']+)(\s+|$)%", $attr, $match))
     260                    # value
     261                    {
     262                    $thisval = wp_kses_bad_protocol($match[1], $allowed_protocols);
     263
     264                    $attrarr[] = array ('name' => $attrname, 'value' => $thisval, 'whole' => "$attrname=\"$thisval\"", 'vless' => 'n');
     265                    # We add quotes to conform to W3C's HTML spec.
     266                    $working = 1;
     267                    $mode = 0;
     268                    $attr = preg_replace("%^[^\s\"']+(\s+|$)%", '', $attr);
     269                }
     270
     271                break;
     272        } # switch
     273
     274        if ($working == 0) # not well formed, remove and try again
     275            {
     276            $attr = wp_kses_html_error($attr);
     277            $mode = 0;
     278        }
     279    } # while
     280
     281    if ($mode == 1)
     282        # special case, for when the attribute list ends with a valueless
     283        # attribute like "selected"
     284        $attrarr[] = array ('name' => $attrname, 'value' => '', 'whole' => $attrname, 'vless' => 'y');
     285
     286    return $attrarr;
    315287} # function wp_kses_hair
    316 
    317288
    318289function wp_kses_check_attr_val($value, $vless, $checkname, $checkvalue)
     
    323294###############################################################################
    324295{
    325   $ok = true;
    326 
    327   switch (strtolower($checkname))
    328   {
    329     case 'maxlen':
    330     # The maxlen check makes sure that the attribute value has a length not
    331     # greater than the given value. This can be used to avoid Buffer Overflows
    332     # in WWW clients and various Internet servers.
    333 
    334       if (strlen($value) > $checkvalue)
    335         $ok = false;
    336       break;
    337 
    338     case 'minlen':
    339     # The minlen check makes sure that the attribute value has a length not
    340     # smaller than the given value.
    341 
    342       if (strlen($value) < $checkvalue)
    343         $ok = false;
    344       break;
    345 
    346     case 'maxval':
    347     # The maxval check does two things: it checks that the attribute value is
    348     # an integer from 0 and up, without an excessive amount of zeroes or
    349     # whitespace (to avoid Buffer Overflows). It also checks that the attribute
    350     # value is not greater than the given value.
    351     # This check can be used to avoid Denial of Service attacks.
    352 
    353       if (!preg_match('/^\s{0,6}[0-9]{1,6}\s{0,6}$/', $value))
    354         $ok = false;
    355       if ($value > $checkvalue)
    356         $ok = false;
    357       break;
    358 
    359     case 'minval':
    360     # The minval check checks that the attribute value is a positive integer,
    361     # and that it is not smaller than the given value.
    362 
    363       if (!preg_match('/^\s{0,6}[0-9]{1,6}\s{0,6}$/', $value))
    364         $ok = false;
    365       if ($value < $checkvalue)
    366         $ok = false;
    367       break;
    368 
    369     case 'valueless':
    370     # The valueless check checks if the attribute has a value
    371     # (like <a href="blah">) or not (<option selected>). If the given value
    372     # is a "y" or a "Y", the attribute must not have a value.
    373     # If the given value is an "n" or an "N", the attribute must have one.
    374 
    375       if (strtolower($checkvalue) != $vless)
    376         $ok = false;
    377       break;
    378   } # switch
    379 
    380   return $ok;
     296    $ok = true;
     297
     298    switch (strtolower($checkname)) {
     299        case 'maxlen' :
     300            # The maxlen check makes sure that the attribute value has a length not
     301            # greater than the given value. This can be used to avoid Buffer Overflows
     302            # in WWW clients and various Internet servers.
     303
     304            if (strlen($value) > $checkvalue)
     305                $ok = false;
     306            break;
     307
     308        case 'minlen' :
     309            # The minlen check makes sure that the attribute value has a length not
     310            # smaller than the given value.
     311
     312            if (strlen($value) < $checkvalue)
     313                $ok = false;
     314            break;
     315
     316        case 'maxval' :
     317            # The maxval check does two things: it checks that the attribute value is
     318            # an integer from 0 and up, without an excessive amount of zeroes or
     319            # whitespace (to avoid Buffer Overflows). It also checks that the attribute
     320            # value is not greater than the given value.
     321            # This check can be used to avoid Denial of Service attacks.
     322
     323            if (!preg_match('/^\s{0,6}[0-9]{1,6}\s{0,6}$/', $value))
     324                $ok = false;
     325            if ($value > $checkvalue)
     326                $ok = false;
     327            break;
     328
     329        case 'minval' :
     330            # The minval check checks that the attribute value is a positive integer,
     331            # and that it is not smaller than the given value.
     332
     333            if (!preg_match('/^\s{0,6}[0-9]{1,6}\s{0,6}$/', $value))
     334                $ok = false;
     335            if ($value < $checkvalue)
     336                $ok = false;
     337            break;
     338
     339        case 'valueless' :
     340            # The valueless check checks if the attribute has a value
     341            # (like <a href="blah">) or not (<option selected>). If the given value
     342            # is a "y" or a "Y", the attribute must not have a value.
     343            # If the given value is an "n" or an "N", the attribute must have one.
     344
     345            if (strtolower($checkvalue) != $vless)
     346                $ok = false;
     347            break;
     348    } # switch
     349
     350    return $ok;
    381351} # function wp_kses_check_attr_val
    382 
    383352
    384353function wp_kses_bad_protocol($string, $allowed_protocols)
     
    390359###############################################################################
    391360{
    392   $string = wp_kses_no_null($string);
    393   $string2 = $string.'a';
    394 
    395   while ($string != $string2)
    396   {
    397     $string2 = $string;
    398     $string = wp_kses_bad_protocol_once($string, $allowed_protocols);
    399   } # while
    400 
    401   return $string;
     361    $string = wp_kses_no_null($string);
     362    $string2 = $string.'a';
     363
     364    while ($string != $string2) {
     365        $string2 = $string;
     366        $string = wp_kses_bad_protocol_once($string, $allowed_protocols);
     367    } # while
     368
     369    return $string;
    402370} # function wp_kses_bad_protocol
    403371
    404 
    405372function wp_kses_no_null($string)
    406373###############################################################################
     
    408375###############################################################################
    409376{
    410   $string = preg_replace('/\0+/', '', $string);
    411   $string = preg_replace('/(\\\\0)+/', '', $string);
    412 
    413   return $string;
     377    $string = preg_replace('/\0+/', '', $string);
     378    $string = preg_replace('/(\\\\0)+/', '', $string);
     379
     380    $string = preg_replace('/\xad+/', '', $string); # deals with Opera "feature"
     381
     382    return $string;
    414383} # function wp_kses_no_null
    415 
    416384
    417385function wp_kses_stripslashes($string)
     
    422390###############################################################################
    423391{
    424   return preg_replace('%\\\\"%', '"', $string);
     392    return preg_replace('%\\\\"%', '"', $string);
    425393} # function wp_kses_stripslashes
    426394
    427 
    428395function wp_kses_array_lc($inarray)
    429396###############################################################################
     
    431398###############################################################################
    432399{
    433   $outarray = array();
    434 
    435   foreach ($inarray as $inkey => $inval)
    436   {
    437     $outkey = strtolower($inkey);
    438     $outarray[$outkey] = array();
    439 
    440     foreach ($inval as $inkey2 => $inval2)
    441     {
    442       $outkey2 = strtolower($inkey2);
    443       $outarray[$outkey][$outkey2] = $inval2;
    444     } # foreach $inval
    445   } # foreach $inarray
    446 
    447   return $outarray;
     400    $outarray = array ();
     401
     402    foreach ($inarray as $inkey => $inval) {
     403        $outkey = strtolower($inkey);
     404        $outarray[$outkey] = array ();
     405
     406        foreach ($inval as $inkey2 => $inval2) {
     407            $outkey2 = strtolower($inkey2);
     408            $outarray[$outkey][$outkey2] = $inval2;
     409        } # foreach $inval
     410    } # foreach $inarray
     411
     412    return $outarray;
    448413} # function wp_kses_array_lc
    449 
    450414
    451415function wp_kses_js_entities($string)
     
    455419###############################################################################
    456420{
    457   return preg_replace('%&\s*\{[^}]*(\}\s*;?|$)%', '', $string);
     421    return preg_replace('%&\s*\{[^}]*(\}\s*;?|$)%', '', $string);
    458422} # function wp_kses_js_entities
    459 
    460423
    461424function wp_kses_html_error($string)
     
    466429###############################################################################
    467430{
    468   return preg_replace('/^("[^"]*("|$)|\'[^\']*(\'|$)|\S)*\s*/', '', $string);
     431    return preg_replace('/^("[^"]*("|$)|\'[^\']*(\'|$)|\S)*\s*/', '', $string);
    469432} # function wp_kses_html_error
    470 
    471433
    472434function wp_kses_bad_protocol_once($string, $allowed_protocols)
     
    476438###############################################################################
    477439{
    478   return preg_replace('/^((&[^;]*;|[\sA-Za-z0-9])*)'.
    479                       '(:|&#58;|&#[Xx]3[Aa];)\s*/e',
    480                       'wp_kses_bad_protocol_once2("\\1", $allowed_protocols)',
    481                       $string);
     440    return preg_replace('/^((&[^;]*;|[\sA-Za-z0-9])*)'.'(:|&#58;|&#[Xx]3[Aa];)\s*/e', 'wp_kses_bad_protocol_once2("\\1", $allowed_protocols)', $string);
    482441} # function wp_kses_bad_protocol_once
    483 
    484442
    485443function wp_kses_bad_protocol_once2($string, $allowed_protocols)
     
    489447###############################################################################
    490448{
    491   $string2 = wp_kses_decode_entities($string);
    492   $string2 = preg_replace('/\s/', '', $string2);
    493   $string2 = wp_kses_no_null($string2);
    494   $string2 = strtolower($string2);
    495 
    496   $allowed = false;
    497   foreach ($allowed_protocols as $one_protocol)
    498     if (strtolower($one_protocol) == $string2)
    499     {
    500       $allowed = true;
    501       break;
    502     }
    503 
    504   if ($allowed)
    505     return "$string2:";
    506   else
    507     return '';
     449    $string2 = wp_kses_decode_entities($string);
     450    $string2 = preg_replace('/\s/', '', $string2);
     451    $string2 = wp_kses_no_null($string2);
     452    $string2 = strtolower($string2);
     453
     454    $allowed = false;
     455    foreach ($allowed_protocols as $one_protocol)
     456        if (strtolower($one_protocol) == $string2) {
     457            $allowed = true;
     458            break;
     459        }
     460
     461    if ($allowed)
     462        return "$string2:";
     463    else
     464        return '';
    508465} # function wp_kses_bad_protocol_once2
    509 
    510466
    511467function wp_kses_normalize_entities($string)
     
    515471###############################################################################
    516472{
    517 # Disarm all entities by converting & to &amp;
    518 
    519   $string = str_replace('&', '&amp;', $string);
    520 
    521 # Change back the allowed entities in our entity whitelist
    522 
    523   $string = preg_replace('/&amp;([A-Za-z][A-Za-z0-9]{0,19});/',
    524                          '&\\1;', $string);
    525   $string = preg_replace('/&amp;#0*([0-9]{1,5});/e',
    526                          'wp_kses_normalize_entities2("\\1")', $string);
    527   $string = preg_replace('/&amp;#([Xx])0*(([0-9A-Fa-f]{2}){1,2});/',
    528                          '&#\\1\\2;', $string);
    529 
    530   return $string;
     473    # Disarm all entities by converting & to &amp;
     474
     475    $string = str_replace('&', '&amp;', $string);
     476
     477    # Change back the allowed entities in our entity whitelist
     478
     479    $string = preg_replace('/&amp;([A-Za-z][A-Za-z0-9]{0,19});/', '&\\1;', $string);
     480    $string = preg_replace('/&amp;#0*([0-9]{1,5});/e', 'wp_kses_normalize_entities2("\\1")', $string);
     481    $string = preg_replace('/&amp;#([Xx])0*(([0-9A-Fa-f]{2}){1,2});/', '&#\\1\\2;', $string);
     482
     483    return $string;
    531484} # function wp_kses_normalize_entities
    532 
    533485
    534486function wp_kses_normalize_entities2($i)
     
    538490###############################################################################
    539491{
    540   return (($i > 65535) ? "&amp;#$i;" : "&#$i;");
     492    return (($i > 65535) ? "&amp;#$i;" : "&#$i;");
    541493} # function wp_kses_normalize_entities2
    542 
    543494
    544495function wp_kses_decode_entities($string)
     
    549500###############################################################################
    550501{
    551   $string = preg_replace('/&#([0-9]+);/e', 'chr("\\1")', $string);
    552   $string = preg_replace('/&#[Xx]([0-9A-Fa-f]+);/e', 'chr(hexdec("\\1"))',
    553                          $string);
    554 
    555   return $string;
     502    $string = preg_replace('/&#([0-9]+);/e', 'chr("\\1")', $string);
     503    $string = preg_replace('/&#[Xx]([0-9A-Fa-f]+);/e', 'chr(hexdec("\\1"))', $string);
     504
     505    return $string;
    556506} # function wp_kses_decode_entities
    557507
    558 function wp_filter_kses( $string ) {
     508function wp_filter_kses($data) {
    559509    global $allowedtags;
    560     return wp_kses($string, $allowedtags);
     510    return wp_kses($data, $allowedtags);
    561511}
    562512
     513function wp_filter_post_kses($data) {
     514    global $allowedposttags;
     515    return wp_kses($data, $allowedposttags);
     516}
     517
     518function kses_init() {
     519    global $current_user;
     520
     521    get_currentuserinfo(); // set $current_user
     522    if (current_user_can('unfiltered_html') == false) {
     523        add_filter('pre_comment_author', 'wp_filter_kses');
     524        add_filter('pre_comment_content', 'wp_filter_kses');
     525        add_filter('content_save_pre', 'wp_filter_post_kses');
     526    }
     527}
     528add_action('init', 'kses_init');
    563529?>
     530
Note: See TracChangeset for help on using the changeset viewer.