В посте преобразуйте в сущности теги, которые не разрешены, и оставьте теги разрешенными - PullRequest
0 голосов
/ 03 июня 2011

У меня есть форма, в которой пользователь может опубликовать глобальное уведомление в системе (для просмотра другими пользователями).
Система выводит HTML напрямую из БД (когда пользователь хочет увидеть уведомление).
Я бы хотел, чтобы некоторые html-теги оставались нетронутыми, а остальные - с применением htmlspecialchars ().
Я уже пытался применить

 str_replace($search, $replace, htmlspecialchars($str))

стратегия, но она кажется очень медленной. Слишком медленно, на самом деле. И также это не безопасно, что всегда будет работать, есть ли альтернатива для этого?
Я хотел что-то, что сделало работу strip_tags () за исключением того, что вместо чередования тегов он будет применять htmlspecialchars к недопустимым тегам.

ДОБАВИТЬ (ed) информация (по запросу):

$ str может быть любого размера, о котором вы только можете подумать. Я подумал об использовании большой строки (1М символов (генерируется случайным образом с некоторыми разрешенными и некоторыми недопустимыми тегами внутри. Все теги имели атрибуты) по причине тестирования одного из худших сценариев С логикой: если это работает так, то это должно работать для более простых случаев.
Серверу потребовалось 5 секунд для полной обработки str_replace (с htmlspecialchars). Этот тест был сделан на моем компьютере с процессором 2 ГГц и оперативной памятью DDR3.
$ search и $ replace имеют в общей сложности 7 замен. Тем не менее они не всегда работают. В некоторых случаях $ search дает ложные срабатывания или ложные отрицания.
Чтобы уточнить, я применяю эти изменения при сохранении в БД, а не при извлечении из БД.

Ответы [ 2 ]

1 голос
/ 03 июня 2011

Вы можете попробовать этот код ( должен быть улучшен ):

function callback(array $matches) {
    return htmlspecialchars_decode($matches[0]);
}
$str = 'some <i>string</i> <b>with</b> tags '
     . '<a href="#">some link</a> '
     . '<img alt="" src="http://sstatic.net/stackoverflow/img/favicon.ico"/><hr/>';
$str = htmlspecialchars($str);
$str = preg_replace_callback('#(&lt;(i|a)(?: .+?)?&gt;.*?&lt;/(\1)&gt;|&lt;(?:img)(?: .*?)?/&gt;)#', 'callback', $str);
echo $str;

Регулярное выражение выглядит ( должно выглядеть ) для 2 типов строк:

  • <tag attributes>content</tag>, при этом часть tag является одинаковой для открытия закрывающего тега, а attributes и content являются необязательными
  • <tag attributes/>, при этом attributesопционально

Теги перечислены в (i|a) части для <tag></tag> типов тегов и (?:img) для <tag/> типов тегов.

Если он находит соответствующие теги, онпередает содержимое в функцию callback(), которая преобразует его обратно с помощью htmlspecialchars_decode().Это необходимо для декодирования кавычек и других закодированных символов в списке атрибутов.

Я не уверен, работает ли он во всех случаях, т. Е. Соответствует ли он всем необходимым тегам.Если это работает в общем, то шаблон и функция callback() должны быть улучшены, так что callback() декодирует только <, > символов и список атрибутов;содержимое тегов (т. е. some link часть в <a href='#'>some link</a>) не должно быть декодировано.

1 голос
/ 03 июня 2011

str_replace вместе с htmlspecialchars не замедляется.

Возможно, у вас есть какое-то узкое место где-то еще.

...