В посте преобразуйте в сущности теги, которые не разрешены, и оставьте теги разрешенными

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

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

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

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

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

2 ответа

Решение

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

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/stackru/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>) не должен быть расшифрован.

str_replace вместе с htmlspecialchars Не медленный

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

Другие вопросы по тегам