По умолчанию WordPress удаляет любой контент, который может быть неэкранированным HTML, в комментариях от незарегистрированных пользователей, что хорошо для защиты от XSS, но излишне расширяет эту фильтрацию и на элементы <pre>
. В моем блоге, где почти каждое сообщение содержит комментарии, основанные на фрагментах HTML-кода, эта фильтрация доставила моим пользователям (и мне) массу неприятных проблем.
Есть ли способ "исправить" эту чрезмерно агрессивную фильтрацию внутри элементов <pre>
в незарегистрированных комментариях, не отключая ее для остальной части комментария? Желательно, чтобы таким образом выживали обновления.
небольшое решение; выделение было в моем блоге с помощью JavaScript
function pre_esc_html($content) {
return preg_replace_callback(
'#(<pre.*?>)(.*?)(</pre>)#imsu',
create_function(
'$i',
'return $i[1].esc_html($i[2]).$i[3];'
),
$content
);
}
add_filter(
'the_content',
'pre_esc_html',
9
);
Хотя это может быть немного больше, чем вы ищете, WP-синтаксис отключает фильтрацию HTML внутри тегов <pre>
внутри постов и комментариев (AFAIK). Это также работает для Wordpress 3.0, хотя веб-сайт говорит, что работает только с 2.8.
Если вы хотите сделать это проще, я предлагаю заглянуть в wp-syntax.php
внутри плагина (особенно в самом низу, где они используют add_filters()
), чтобы увидеть, как они отключают автоматическую HTML-фильтрацию Wordpress в тегах <pre>
. Затем вы можете применить это к комментариям.
Правка: я посмотрел на файл, и они используют регулярные выражения и PHP preg_replace_callback()
, чтобы сохранить оригинальный HTML в тегах <pre>
. Возможно, вам придется изменить его в соответствии с вашими потребностями.
Вы бы, например, (примечание: непроверенный код):
<?php
// Unique string for placeholder
$custom_token = md5(uniqid(Rand()));
// Store all the matches in an array
$custom_matches = array();
function custom_substitute(&$match) {
global $custom_token, $custom_matches;
$i = count($custom_matches);
// Store the match for later use
$custom_matches[$i] = $match;
// Unique placeholder so that we know where to put the code that was ripped out
return '<p>' . $custom_token . '</p>';
}
function custom_replace($match) {
global $custom_matches;
$i = intval($match[1]);
$match = $custom_matches[$i];
// The index might be off - you might want to double-check it
return htmlentities($match[1]);
}
function custom_before_content_filter($content) {
return preg_replace_callback("/\s*<pre+>(.*)<\/pre>\s*/siU", 'custom_substitute', $content);
}
function custom_after_content_filter($content) {
global $custom_token;
return preg_replace_callback("/<p>\s*" . $custom_token . "\s*<\/p>/si", 'custom_replace', $content);
}
// Run the "before" filter first, with priority of 0
add_filter('comment_text', 'custom_before_content_filter', 0);
// Now run the "after" filter
add_filter('comment_text', 'custom_after_content_filter', 99);