#php #post #htmlspecialchars
#php #Публикация #htmlspecialchars
Вопрос:
У меня есть форма, в которой пользователь может опубликовать глобальное уведомление в системе (для просмотра другими пользователями).
Система выводит HTML непосредственно из базы данных (когда пользователь хочет увидеть уведомление).
Я бы хотел, чтобы некоторые теги html оставались нетронутыми, а к остальным применялись htmlspecialchars().
Я уже пытался применить
str_replace($search, $replace, htmlspecialchars($str))
стратегия, но, похоже, она действительно медленная. На самом деле слишком медленно. А также это небезопасно, что всегда будет работать, есть ли альтернатива для этого?
Я хотел что-то, что выполняло бы работу strip_tags (), за исключением того, что вместо чередования тегов оно применяло бы htmlspecialchars к недопустимым тегам.
ДОБАВЬТЕ (отредактируйте) информацию (по запросу):
$ str может быть любого размера, который вы можете придумать. Я подумал об использовании большой строки (1 М символов (генерируется случайным образом с некоторыми разрешенными и некоторыми запрещенными тегами внутри. У всех тегов были атрибуты) по причине тестирования одного из наихудших сценариев с логикой: если это работает так, это должно работать для более простых случаев.
Серверу потребовалось 5 секунд, чтобы обработать полный str_replace (с htmlspecialchars). Этот тест был выполнен на моем компьютере с процессором 2 ГГц и оперативной памятью DDR3.
оба $ search и $ replace имеют в общей сложности 7 замен. Тем не менее, они не всегда работают. В некоторых случаях $search выдает ложные срабатывания или ложноотрицательные значения.
Чтобы уточнить, я применяю эти изменения при сохранении в БД, а не при извлечении из БД.
Комментарии:
1. Если скорость действительно является проблемой, то вы могли бы применить этот фильтр к вводу , чтобы это выполнялось только один раз, а не на выходе.
2. @El Yobo, я полагаю, что он уже это делает.
3. Вопрос, похоже, не указывает, делает ли он это при вводе или выводе; но если бы это было при вводе, где это делается только один раз, скорость, казалось бы, была бы меньшей проблемой, поэтому я предполагаю, что он делает это при выводе.
4. @El Yobo, есть две трудноуловимые фразы, где сказано: » В post преобразуйте в … » (в заголовке; я полагаю, что «в post» — это POST-запрос) и » Система выводит HTML непосредственно из базы данных «. В любом случае, действительно странно, что из-за этих двух функций возникают проблемы с производительностью. Возможно, стоит предоставить немного больше информации — содержимое
$search
и$replace
, размер$str
, частота вызова этих функций, некоторые тайминги.5. @binary, да, я вижу, что сейчас он имел в виду именно это
@brunoais, средняя длина английского слова составляет 5 символов; получается около 250 слов на страницу. Ваши 1 МЛН символов примерно эквивалентны книге на 800 страниц — вы действительно уверены, что стоит беспокоиться о вещах такого размера?
Ответ №1:
Вы могли бы попробовать этот код (должен быть улучшен):
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('#(amp;<(i|a)(?: . ?)?amp;>.*?amp;</(1)amp;>|amp;<(?:img)(?: .*?)?/amp;>)#', '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. Ок, готово и работает. Я использовал вашу идею. Исправлены ошибки, заменены некоторые материалы, адаптировано для поддержки тегов внутри тегов, теперь выполняется меньшая проверка. Это немного быстрее, чем str_replace() (с учетом времени, затраченного на создание массивов). Цель не в том, чтобы заботиться о том, хорошо ли написан HTML. Это сделано только для того, чтобы убедиться, что разрешенные теги отображаются как HTML-теги, а не как сущности. Спасибо за хорошую помощь.
2. Создание массивов? Если вы говорите о массивах, которые создаются для совпадений, вы можете использовать
?:
, чтобы избежать создания ненужных массивов.3. Я имею в виду создание массивов для str_replace()
Ответ №2:
str_replace
наряду с htmlspecialchars
НЕ является медленным.
Вероятно, у вас есть какое-то узкое место где-то еще.
Комментарии:
1. хорошо… основная проблема заключается в том, что этот метод также заключается в том, что он действительно ненадежен. Мне нужно что-то получше для решения этой проблемы. Особенно, если я работаю с тегами с атрибутами… Как я могу решить проблему с заменой конечных тегов?
2. конечный тег заменяет? что такое
3. @yes123 <a href=»something» > Как мне правильно заменить > в этом, используя str_replace?
4.
str_replace('>','what ever',$string);
?5. «конечные замены тегов» означает, что должны быть заменены оба,
<b>
и совпадающий</b>
, а не только открывающий тег<b>
.