Make WordPress Core

Ticket #29557: poc_pos_29557.diff

File poc_pos_29557.diff, 9.7 KB (added by kitchin, 11 years ago)

POC, insufficient, do not use. Less regex, more strpos.

  • src/wp-includes/formatting.php

     
    203203        $no_texturize_tags_stack = array();
    204204        $no_texturize_shortcodes_stack = array();
    205205
    206         // Look for shortcodes and HTML elements.
     206        $textarr = $typearr = array(); // these are co-ordinated arrays, numerically indexed
     207        _wptexturize_split_extract_all( $text, $textarr, $typearr );
    207208
    208         $comment_regex =
    209                         '!'                             // Start of comment, after the <.
    210                 .       '(?:'                   // Unroll the loop: Consume everything until --> is found.
    211                 .               '-(?!->)'       // Dash not followed by end of comment.
    212                 .               '[^\-]*+'       // Consume non-dashes.
    213                 .       ')*+'                   // Loop possessively.
    214                 .       '(?:-->)?';             // End of comment. If not found, match all input.
    215        
    216         $shortcode_regex =
    217                         '\['                    // Find start of shortcode.
    218                 .       '[\/\[]?'               // Shortcodes may begin with [/ or [[
    219                 .       '[^\s\/\[\]]'   // No whitespace before name.
    220                 .       '[^\[\]]*+'             // Shortcodes do not contain other shortcodes. Possessive critical.
    221                 .       '\]'                    // Find end of shortcode.
    222                 .       '\]?';                  // Shortcodes may end with ]]
    223        
    224         $regex =
    225                         '/('                                    // Capture the entire match.
    226                 .               '<'                                     // Find start of element.
    227                 .               '(?(?=!--)'                     // Is this a comment?
    228                 .                       $comment_regex  // Find end of comment.
    229                 .               '|'
    230                 .                       '[^>]+>'                // Find end of element.
    231                 .               ')'
    232                 .       '|'
    233                 .               $shortcode_regex        // Find shortcodes.
    234                 .       ')/s';
     209        foreach ( $textarr as $i => &$curl ) {
     210                $type = $typearr[ $i ];
    235211
    236         $textarr = preg_split( $regex, $text, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY );
     212                // Only call _wptexturize_pushpop_element if $curl is a delimiter.
    237213
    238         foreach ( $textarr as &$curl ) {
    239                 // Only call _wptexturize_pushpop_element if $curl is a delimiter.
    240                 $first = $curl[0];
    241                 if ( '<' === $first && '<!--' === substr( $curl, 0, 4 ) ) {
     214                if ( $type == 'comment' ) {
     215
    242216                        // This is an HTML comment delimeter.
    243217
    244218                        continue;
    245219
    246                 } elseif ( '<' === $first && '>' === substr( $curl, -1 ) ) {
     220                } elseif ( $type == 'tag' ) {
    247221                        // This is an HTML element delimiter.
    248222
    249223                        _wptexturize_pushpop_element( $curl, $no_texturize_tags_stack, $no_texturize_tags );
     
    253227
    254228                        continue;
    255229
    256                 } elseif ( '[' === $first && 1 === preg_match( '/^' . $shortcode_regex . '$/', $curl ) ) {
     230                } elseif ( $type == 'shortcode' ) {
    257231                        // This is a shortcode delimiter.
    258232
    259233                        if ( '[[' !== substr( $curl, 0, 2 ) && ']]' !== substr( $curl, -2 ) ) {
     
    297271}
    298272
    299273/**
     274 * Look for 1. HTML comments, 2. then possible shortcodes, 3. then HTML tags (not comments).
     275 *
     276 * @access private
     277 *
     278 * @param string $text.
     279 * @param array $textarr.
     280 * @param array $typearr.
     281 */
     282function _wptexturize_split_extract_all( &$text, &$textarr, &$typearr ) {
     283
     284        // Look for comment.
     285        while ( is_int( $p = strpos( $text, '<!--' ) ) ) {
     286                // Note text must advance in every case to prevent runaway loop.
     287
     288                if ( $p ) {
     289                        // Process text before comment.
     290                        $html = substr( $text, 0, $p );
     291                        _wptexturize_split_extract_shortcodes_and_tags( $html, $textarr, $typearr );
     292                        // Advance to the comment.
     293                        $text = substr( $text, $p );
     294                }
     295
     296                // Find the comment, minimally '<!-->'.
     297                if ( is_int( $p = strpos( $text, '-->' ) ) ) {
     298                        $p += 3;
     299                        // Push the comment.
     300                        $textarr[] = substr( $text, 0, $p );
     301                        $typearr[]= 'comment';
     302                        // Advance past the comment.
     303                        $text = substr( $text, $p);
     304                } else {
     305                        // Unclosed comment, treat as comment.
     306                        // Note in other function, unclosed tags treated as text, not tags.
     307                        // Push and stop.
     308                        $textarr[] = $text;
     309                        $typearr[]= 'comment';
     310                        $text = '';
     311                }
     312
     313        }
     314        // Process text after last comment.
     315        if ( $text != '' ) {
     316                _wptexturize_split_extract_shortcodes_and_tags( $text, $textarr, $typearr );
     317        }
     318}
     319
     320/**
     321 * Look for 1. possible shortcodes, 2. then HTML tags (not comments).
     322 *
     323 * Text must have comments already stripped.
     324 *
     325 * @access private
     326 *
     327 * @param string $text.
     328 * @param array $textarr.
     329 * @param array $typearr.
     330 */
     331function _wptexturize_split_extract_shortcodes_and_tags( &$text, &$textarr, &$typearr ) {
     332
     333        // xx would static be the same as php parser work?
     334        $shortcode_regex =
     335                        '/'
     336                .       '\['                    // Find start of shortcode.
     337                .       '[\/\[]?'               // Shortcodes may begin with [/ or [[
     338                .       '[^\s\/\[\]]'   // No whitespace before name.
     339                .       '[^\[\]]*+'             // Shortcodes do not contain other shortcodes. Possessive critical.
     340                .       '\]'                    // Find end of shortcode.
     341                .       '\]?'                   // Shortcodes may end with ]]
     342                .       '/';
     343
     344        // Look for possible shortcodes.
     345        if ( is_int( strpos( $text, '[' ) ) ) {
     346
     347                while ( preg_match( $shortcode_regex, $text, $matches, PREG_OFFSET_CAPTURE ) ) {
     348                        // Note text must advance in every case to prevent runaway loop.
     349                       
     350                        if ( $start = $matches[0][1] ) {                // integer position
     351                                // Process text before match.
     352                                $html = substr( $text, 0, $start );
     353                                _wptexturize_split_extract_tags( $html, $textarr, $typearr );
     354                        }
     355                       
     356                        // Push match.
     357                        $textarr[] = $matches[0][0];                    // string match
     358                        $typearr[]= 'shortcode';
     359                        // Advance past match.
     360                        // Match guaranteed not empty.
     361                        $text = substr( $text, $start + strlen( $matches[0][0] ) );
     362                }
     363
     364        }
     365
     366        // Process text after last shortcode.
     367        if ( $text != '' ) {
     368                _wptexturize_split_extract_tags( $text, $textarr, $typearr );
     369        }
     370}
     371
     372/**
     373 * Look for HTML tags (not comments).
     374 *
     375 * Text must have comments already stripped.
     376 *
     377 * @access private
     378 *
     379 * @param string $text.
     380 * @param array $textarr.
     381 * @param array $typearr.
     382 */
     383function _wptexturize_split_extract_tags( &$text, &$textarr, &$typearr ) {
     384
     385        // Look for tag.
     386        while ( is_int( $p = strpos( $text, '<' ) ) ) {
     387                // Note text must advance in every case to prevent runaway loop.
     388
     389                if ( $p ) {
     390                        // Push the text before the match.
     391                        $textarr[] = substr( $text, 0, $p );
     392                        $typearr[] = 'text';
     393                        // Advance to the match.
     394                        $text = substr( $text, $p );
     395                }
     396
     397                // Find the tag, minimally '<>'.
     398                if ( is_int( $p = strpos( $text, '>' ) ) ) {
     399                        $p++;
     400                        // Push the match.
     401                        $textarr[] = substr( $text, 0, $p );
     402                        $typearr[] = 'tag';
     403                        // Advance past the match.
     404                        $text = substr( $text, $p );
     405                } else {
     406                        // Unclosed tag. Treat as text, not tag.
     407                        // Note in other function, unclosed comments treated as comments.
     408                        // Push and stop.
     409                        $textarr[] = $text;
     410                        $typearr[] = 'text';
     411                        $text = '';
     412                }
     413
     414        }
     415       
     416        // Push text after last tag.
     417        if ( $text != '' ) {
     418                $textarr[] = $text;
     419                $typearr[] = 'text';
     420        }
     421}
     422
     423/**
    300424 * Search for disabled element tags. Push element to stack on tag open and pop
    301425 * on tag close.
    302426 *
  • tests/phpunit/tests/formatting/WPTexturize.php

     
    12451245                        ),
    12461246                        array(
    12471247                                '<br [gallery ...] ... />',
    1248                                 '<br [gallery ...] ... />',
     1248                                // Changed for POC patch see #29557.
     1249                                // '<br [gallery ...] ... />',
     1250                                '<br [gallery ...] &#8230; />',
    12491251                        ),
    12501252                        array(
    12511253                                '<br [gallery ...] ... /',
     
    12851287                        ),
    12861288                        array(
    12871289                                '<br [[gallery ...]] ... />',
    1288                                 '<br [[gallery ...]] ... />',
     1290                                // Changed for POC patch see #29557.
     1291                                // '<br [[gallery ...]] ... />',
     1292                                '<br [[gallery ...]] &#8230; />',
    12891293                        ),
    12901294                        array(
    12911295                                '<br [[gallery ...]] ... /',
     
    13691373                        ),
    13701374                        array(
    13711375                                '[ regex catches this <a href="[quote]">here</a> ]',
    1372                                 '[ regex catches this <a href="[quote]">here</a> ]',
     1376                                // Changed for POC patch see #29557.
     1377                                // '[ regex catches this <a href="[quote]">here</a> ]',
     1378                                '[ regex catches this <a href=&#8221;[quote]&#8220;>here</a> ]',
    13731379                        ),
    13741380                        array(
    13751381                                '[ but also catches the <b>styled "[quote]" here</b> ]',
     
    13791385                                '[Let\'s get crazy<input>[caption code="<a href=\'?a[]=100\'>hello</a>"]</input>world]', // caption shortcode is invalid here because it contains [] chars.
    13801386                                '[Let&#8217;s get crazy<input>[caption code=&#8221;<a href=\'?a[]=100\'>hello</a>&#8220;]</input>world]',
    13811387                        ),
     1388                        // Added for POC patch see #29557.
     1389                        array(
     1390                                '<a href="test.php?foo[bar]=1">here</a>',
     1391                                // Trunk behavior:
     1392                                // '<a href="test.php?foo[bar]=1">here</a>',
     1393                                // Undesirable POC behavior:
     1394                                '<a href=&#8221;test.php?foo[bar]=1&#8243;>here</a>',
     1395                        ),
     1396                        // Added for POC patch see #29557. Trunk also passes this test.
     1397                        array(
     1398                                '<b unclosed tag ... treated as text',
     1399                                '<b unclosed tag &#8230; treated as text',
     1400                        ),
     1401                        // Tentative #24990 test:
     1402                        array(
     1403                                '[caption]<a href=""><img alt="[shortcode]" title="[shortcode]"></a> Caption Text [shortcode][/caption]',
     1404                                // Trunk passes this test:
     1405                                // '[caption]<a href=""><img alt="[shortcode]" title="[shortcode]"></a> Caption Text [shortcode][/caption]',
     1406                                // Changed for POC patch see #29557
     1407                                '[caption]<a href=""><img alt=&#8221;[shortcode]&#8221; title=&#8221;[shortcode]&#8220;></a> Caption Text [shortcode][/caption]',
     1408                        ),
     1409                        // Tentative #24990 test:
     1410                        array(
     1411                                '[caption][shortcode]<a href=""><img></a>[/shortcode] Caption Text[/caption]',
     1412                                // Trunk and POC patch both pass, see #29557:
     1413                                '[caption][shortcode]<a href=""><img></a>[/shortcode] Caption Text[/caption]',
     1414                        ),                     
    13821415                );
    13831416        }
    13841417
     
    17471780         */
    17481781        function test_unregistered_shortcodes( $input, $output ) {
    17491782                add_filter( 'no_texturize_shortcodes', array( $this, 'filter_shortcodes' ), 10, 1 );
    1750        
     1783
    17511784                $output = $this->assertEquals( $output, wptexturize( $input ) );
    1752        
     1785
    17531786                remove_filter( 'no_texturize_shortcodes', array( $this, 'filter_shortcodes' ), 10, 1 );
    17541787                return $output;
    17551788        }
    1756        
     1789
    17571790        function filter_shortcodes( $disabled ) {
    17581791                $disabled[] = 'audio';
    17591792                return $disabled;