Вывод шорткода искажается, когда в содержимом присутствует символ стрелки "<"


У меня есть очень простой шорткод для печати некоторого текста с использованием предварительных тегов

function term_shortcode( $atts, $content = null ) 
{
    return "<pre>" . htmlentities($content) . "</pre>";
}
add_shortcode( 'term', 'term_shortcode' );

Но при использовании шорткода, если в содержимом есть символ стрелки, вывод будет ужасно испорчен. Шорткод собирает содержимое за пределами конца шорткода.

Вот пример

[term]    
ABC < DEF
[/term]
MORE CONTENT. This is also taken up by the above shortcode.

Если символ стрелки влево "<" удален, он выводится нормально.

Как мне это исправить?

Визуальный редактор полностью отключен. Используя только текстовый редактор и ввод чистого html.

 2
Author: Silver Moon, 2015-10-15

3 answers

Эта проблема была введена в WP 4.2.3 с введением функции do_shortcodes_in_html_tags(), которая выполняет синтаксический анализ содержимого HTML для защиты от содержимого, содержащего короткие коды, созданные ненадежными участниками/авторами, которые, специально создавая атрибуты короткого кода, могут создавать эксплойты XSS.

Если эта ситуация с безопасностью не относится к вам, и вы хотите, чтобы это работало только на вашем сайте, то простым обходным путем является замена фильтра по умолчанию do_shortcode на вашу собственную версию с вызов do_shortcodes_in_html_tags() удален, например

add_action( 'init', function () {
    remove_filter( 'the_content', 'do_shortcode', 11 );
    add_filter( 'the_content', function ( $content ) {
        global $shortcode_tags;

        if ( false === strpos( $content, '[' ) ) {
            return $content;
        }

        if (empty($shortcode_tags) || !is_array($shortcode_tags))
            return $content;

        $tagnames = array_keys($shortcode_tags);
        $tagregexp = join( '|', array_map('preg_quote', $tagnames) );
        $pattern = "/\\[($tagregexp)/s";

        if ( 1 !== preg_match( $pattern, $content ) ) {
            // Avoids parsing HTML when there are no shortcodes or embeds anyway.
            return $content;
        }

        // Avoid check for users without unfiltered html: $content = do_shortcodes_in_html_tags( $content, $ignore_html );

        $pattern = get_shortcode_regex();
        $content = preg_replace_callback( "/$pattern/s", 'do_shortcode_tag', $content );

        // Always restore square braces so we don't break things like <!--[if IE ]>
        // Not needed if do_shortcodes_in_html_tags not called: $content = unescape_invalid_shortcodes( $content );

        return $content;
    }, 11 );
} );

Во время моего тестирования вам, возможно, также придется столкнуться с проблемами wpautop()...

 2
Author: bonger, 2015-10-15 19:09:41

Короткие коды не следует использовать в качестве замены html-тегов. В этом случае, если вы хотите использовать <pre>, просто используйте его, не придумывайте для него шорткод.

Использование "

В вашем случае, противоположность тому, что вы пытаетесь сделать, вероятно, является лучшим подходом. Вместо кодирования элементы html, вы должны предположить, что они уже закодированы, и вы декодируете их, чтобы поместить их в <pre>. Таким образом, вы также сможете использовать визуальный редактор для шорткода.

 1
Author: Mark Kaplun, 2015-10-15 09:26:50

Я бы попробовал использовать htmlspecialchars() вместо htmlentities() и посмотрите, решит ли это проблему.

 1
Author: Benjamin Love, 2015-10-15 19:30:51