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

#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> .