WordPress.org

Make WordPress Core

Changeset 28727


Ignore:
Timestamp:
06/10/14 14:33:16 (3 years ago)
Author:
wonderboymusic
Message:

In wptexturize(), ensure that texturization does not corrupt contents of HTML elements, HTML comments, and smartcode attributes.

Adds a variety of unit tests/assertions.

Props miqrogroove.
Fixes #12690, #8912, #27602.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/formatting.php

    r28726 r28727  
    159159    } 
    160160 
     161    // If there's nothing to do, just stop. 
     162    if ( empty( $text ) ) { 
     163        return $text; 
     164    } 
     165 
    161166    // Transform into regexp sub-expression used in _wptexturize_pushpop_element 
    162167    // Must do this every time in case plugins use these filters in a context sensitive manner 
     
    181186    $no_texturize_shortcodes_stack = array(); 
    182187 
    183     $textarr = preg_split('/(<.*>|\[.*\])/Us', $text, -1, PREG_SPLIT_DELIM_CAPTURE); 
     188    // Look for shortcodes and HTML elements. 
     189 
     190    $regex =  '/('          // Capture the entire match. 
     191        .   '<'     // Find start of element. 
     192        .   '(?(?=!--)' // Is this a comment? 
     193        .       '.+?--\s*>' // Find end of comment 
     194        .   '|' 
     195        .       '.+?>'      // Find end of element 
     196        .   ')' 
     197        . '|' 
     198        .   '\['        // Find start of shortcode. 
     199        .   '\[?'       // Shortcodes may begin with [[ 
     200        .   '[^\[\]<>]+'    // Shortcodes do not contain other shortcodes or HTML elements. 
     201        .   '\]'        // Find end of shortcode. 
     202        .   '\]?'       // Shortcodes may end with ]] 
     203        . ')/s'; 
     204 
     205    $textarr = preg_split( $regex, $text, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY ); 
    184206 
    185207    foreach ( $textarr as &$curl ) { 
    186         if ( empty( $curl ) ) { 
    187             continue; 
    188         } 
    189  
    190         // Only call _wptexturize_pushpop_element if first char is correct tag opening 
     208        // Only call _wptexturize_pushpop_element if $curl is a delimeter. 
    191209        $first = $curl[0]; 
    192         if ( '<' === $first ) { 
    193             _wptexturize_pushpop_element($curl, $no_texturize_tags_stack, $no_texturize_tags, '<', '>'); 
    194         } elseif ( '[' === $first ) { 
    195             _wptexturize_pushpop_element($curl, $no_texturize_shortcodes_stack, $no_texturize_shortcodes, '[', ']'); 
     210        if ( '<' === $first && '>' === substr( $curl, -1 ) ) { 
     211            // This is an HTML delimeter. 
     212 
     213            if ( '<!--' !== substr( $curl, 0, 4 ) ) { 
     214                _wptexturize_pushpop_element( $curl, $no_texturize_tags_stack, $no_texturize_tags, '<', '>' ); 
     215            } 
     216 
     217        } elseif ( '[' === $first && 1 === preg_match( '/^\[[^\[\]<>]+\]$/', $curl ) ) { 
     218            // This is a shortcode delimeter. 
     219 
     220            _wptexturize_pushpop_element( $curl, $no_texturize_shortcodes_stack, $no_texturize_shortcodes, '[', ']' ); 
     221 
     222        } elseif ( '[' === $first && 1 === preg_match( '/^\[\[?[^\[\]<>]+\]\]?$/', $curl ) ) { 
     223            // This is an escaped shortcode delimeter. 
     224 
     225            // Do not texturize. 
     226            // Do not push to the shortcodes stack. 
     227 
    196228        } elseif ( empty($no_texturize_shortcodes_stack) && empty($no_texturize_tags_stack) ) { 
    197  
    198             // This is not a tag, nor is the texturization disabled static strings 
     229            // This is neither a delimeter, nor is this content inside of no_texturize pairs.  Do texturize. 
     230 
    199231            $curl = str_replace($static_characters, $static_replacements, $curl); 
    200  
    201             // regular expressions 
    202232            $curl = preg_replace($dynamic_characters, $dynamic_replacements, $curl); 
    203233 
  • trunk/tests/phpunit/tests/formatting/WPTexturize.php

    r28726 r28727  
    11291129        ); 
    11301130    } 
     1131 
     1132    /** 
     1133     * Test HTML and shortcode avoidance. 
     1134     * 
     1135     * @ticket 12690 
     1136     * @dataProvider data_tag_avoidance 
     1137     */ 
     1138    function test_tag_avoidance( $input, $output ) { 
     1139        return $this->assertEquals( $output, wptexturize( $input ) ); 
     1140    } 
     1141 
     1142    function data_tag_avoidance() { 
     1143        return array( 
     1144            array( 
     1145                '[ photos by <a href="http://example.com/?a[]=1&a[]=2"> this guy </a> ]', 
     1146                '[ photos by <a href="http://example.com/?a[]=1&#038;a[]=2"> this guy </a> ]', 
     1147            ), 
     1148            array( 
     1149                '[gallery ...]', 
     1150                '[gallery ...]', 
     1151            ), 
     1152            array( 
     1153                '[[gallery ...]', // This tag is still valid. 
     1154                '[[gallery ...]', 
     1155            ), 
     1156            array( 
     1157                '[gallery ...]]', // This tag is also valid. 
     1158                '[gallery ...]]', 
     1159            ), 
     1160            array( 
     1161                '[/...]', // This would actually be ignored by the shortcode system.  The decision to not texturize it is intentional, if not correct. 
     1162                '[/...]', 
     1163            ), 
     1164            array( 
     1165                '[...]...[/...]', // These are potentially usable shortcodes. 
     1166                '[...]&#8230;[/...]', 
     1167            ), 
     1168            array( 
     1169                '[[...]]...[[/...]]', // Shortcode parsing will ignore the inner ]...[ part and treat this as a single escaped shortcode. 
     1170                '[[...]]&#8230;[[/...]]', 
     1171            ), 
     1172            array( 
     1173                '[[[...]]]...[[[/...]]]', // Again, shortcode parsing matches, but only the [[...] and [/...]] parts. 
     1174                '[[[...]]]&#8230;[[[/...]]]', 
     1175            ), 
     1176            array( 
     1177                '[[code]...[/code]...', // These are potentially usable shortcodes.  Unfortunately, the meaning of [[/code] is ambiguous unless we run the entire shortcode regexp. 
     1178                '[[code]&#8230;[/code]...', // Same behavior as 3.9 due to buggy logic in _wptexturize_pushpop_element().  See ticket #28483. 
     1179            ), 
     1180            array( 
     1181                '[code]...[/code]]...', // These are potentially usable shortcodes.  Unfortunately, the meaning of [/code]] is ambiguous unless we run the entire shortcode regexp. 
     1182                '[code]...[/code]]...', // This test would not pass in 3.9 because the extra brace was always ignored by texturize. 
     1183            ), 
     1184            array( 
     1185                '[gal>ery ...]', 
     1186                '[gal>ery &#8230;]', 
     1187            ), 
     1188            array( 
     1189                '[gallery ...', 
     1190                '[gallery &#8230;', 
     1191            ), 
     1192            array( 
     1193                '[gallery <br ... /> ...]', 
     1194                '[gallery <br ... /> &#8230;]', 
     1195            ), 
     1196            array( 
     1197                '<br [gallery ...] ... />', 
     1198                '<br [gallery ...] ... />', 
     1199            ), 
     1200            array( 
     1201                '<br [gallery ...] ... /', 
     1202                '<br [gallery ...] &#8230; /', 
     1203            ), 
     1204            array( 
     1205                '<br ... />', 
     1206                '<br ... />', 
     1207            ), 
     1208            array( 
     1209                '<br ... />...<br ... />', 
     1210                '<br ... />&#8230;<br ... />', 
     1211            ), 
     1212            array( 
     1213                '[gallery ...]...[gallery ...]', 
     1214                '[gallery ...]&#8230;[gallery ...]', 
     1215            ), 
     1216            array( 
     1217                '[[gallery ...]]', 
     1218                '[[gallery ...]]', 
     1219            ), 
     1220            array( 
     1221                '[[gallery ...]', 
     1222                '[[gallery ...]', 
     1223            ), 
     1224            array( 
     1225                '[gallery ...]]', 
     1226                '[gallery ...]]', 
     1227            ), 
     1228            array( 
     1229                '[/gallery ...]]', 
     1230                '[/gallery ...]]', 
     1231            ), 
     1232            array( 
     1233                '[[gallery <br ... /> ...]]', 
     1234                '[[gallery <br ... /> &#8230;]]', 
     1235            ), 
     1236            array( 
     1237                '<br [[gallery ...]] ... />', 
     1238                '<br [[gallery ...]] ... />', 
     1239            ), 
     1240            array( 
     1241                '<br [[gallery ...]] ... /', 
     1242                '<br [[gallery ...]] &#8230; /', 
     1243            ), 
     1244            array( 
     1245                '[[gallery ...]]...[[gallery ...]]', 
     1246                '[[gallery ...]]&#8230;[[gallery ...]]', 
     1247            ), 
     1248            array( 
     1249                '[[gallery ...]...[/gallery]]', 
     1250                '[[gallery ...]&#8230;[/gallery]]', 
     1251            ), 
     1252            array( 
     1253                '<!-- ... -->', 
     1254                '<!-- ... -->', 
     1255            ), 
     1256            array( 
     1257                '<!--...-->', 
     1258                '<!--...-->', 
     1259            ), 
     1260            array( 
     1261                '<!-- ... -- >', 
     1262                '<!-- ... -- >', 
     1263            ), 
     1264            array( 
     1265                '<!-- <br /> [gallery] ... -->', 
     1266                '<!-- <br /> [gallery] ... -->', 
     1267            ), 
     1268            array( 
     1269                '...<!-- ... -->...', 
     1270                '&#8230;<!-- ... -->&#8230;', 
     1271            ), 
     1272            array( 
     1273                '[gallery ...]...<!-- ... -->...<br ... />', 
     1274                '[gallery ...]&#8230;<!-- ... -->&#8230;<br ... />', 
     1275            ), 
     1276            array( 
     1277                '<ul><li>Hello.</li><!--<li>Goodbye.</li>--></ul>', 
     1278                '<ul><li>Hello.</li><!--<li>Goodbye.</li>--></ul>', 
     1279            ), 
     1280        ); 
     1281    } 
    11311282} 
Note: See TracChangeset for help on using the changeset viewer.