Привет всем. Я пишу сайт, и столкнулся с задачей создать форму для отправки комментария или поста.
<div id="textDiv" style="width:100%;height:200px;position:relative;"> <textarea id="textBox" name="content" class="textarea"></textarea> <div id="handleBottom" style="width:100%; height:5px; background-color:#C0C0C0; position:absolute; top:195px; cursor:s-resize;"> </div> </div>
Пользователь набирает текст в textarea -> submit и инфа попадает в базу. Сейчас нет никаких проверок контена или обработки bb-кодов и прочего. Т.е. никто не мешает пользователю вписать javascript-код и к примеру украсть кукисы, оно по идее должно выполниться.. В связи с этим назрел вопрос, как лучше/удобнее реализовать форматирование текста.. (поддержка тегов подразумивается) + как лучше всего фильтровать содержимое поста ? Желательно примеры из личной практики, если таковые имеются. В общем все мысли, готов выслушать.. =)
PS: При создании поста в Input Format есть режим Full HTML, т.е. туда при желании можно впихать рабочий js ?

Простого
Простого однозначного решения, для гибкого разграничения, пожалуй нет.
Но на CPAN ЕМНИП есть модули парсящие javascript, и выковыривать его не очень сложно, так что можно попробовать.
javascript вставляется несколькими методами (<script inline, <script include, просто добавка обработчиков в теги), так что если не удалять совсем все теги, остается только их полностью парсить..
Ну или средний по сложности вариант, создать собственное подмножество тегов типа тех-же bb-кодов, и тоже их парсить и жестко ограничивать функциональность.
fu7ur3
PS: При создании поста в Input Format есть режим Full HTML, т.е. туда при желании можно впихать рабочий js ?
Тут следует обратить внимание, что запрос не обязательно придет из вашими руками написанных форм.
Злоумышленник может сам создать строку запроса и послать ее используя, например, wget.
[ниже - IMHO]
Сам я давненько подобным не занимался,
но если бы занимался, то использовал бы либо конструкцию
$content =~ s/<script.*?>|<\/script>//sg;
Либо обрабатывал бы все теги, удаляя все, что не соответствует списку разрешенных.
Так, по моему, делает ЖЖ.
Т.е. где-то так:
В первом случае — нет начального тега - значит нет скрипта.
Второй случай позволяет более тонко контролировать ввод, но имеет ряд недостатков, в том числе и громоздкость.
К тому же этот код не проходил релаьных тестов :))
Оба случая оставляют как есть содержимое парных тегов.
И, конечно же, соглашусь с предидущим оратором: наверняка на CPAN есть нечто подобное.
Я уже исправил
Я уже исправил свой пост - как всегда забыл что хатеэмельные скобки тут не показываются ;) вобщем проблема в том что можно javascript и без явного тега <script> вставлять.
Да, я еще
Да, я еще обратил внимание на то что пост неполный :)
Насколько я понимаю, имеется в виду
1. <script>alert('Hello world')</script>
2. <script type='text/javascript' src='helloworld.js'></script>
3. <body onload='alert("Hello world")'> </body>
Тогда остается только второй вариант из приведенных мною.
Я забыл снабдить его необходимыми комментариями:
он находит все html теги в содержимом и, если тег не определенн как разрешенный - просто удаляет вместе с параметрами тега.
Т.е. после обработки вариант 2 будет содержать просто alert('Hello world'), что будет интерпритировано браузером как обычный текст, варианты 2 и 3 будут пустыми, при условии, что теги script и body запрещены.
Если рассмотреть четвертый вариант - обработчики в разрешенном теге:
<div onload='alert("gigi")'>
То придется дописать в вышеобозначенный код еще и обработку параметров для разрешенных тегов (кста, по моему жж это тоже делает)
btw, исходный код livejournal открыт. И для желающих не изобретать велосипед есть возможность взять оттуда. Но мне больше нравится велосипед.
Всем спасибо,
Всем спасибо, за мысли! =) Выкладываю не суд общественности то что у меня получилось:
Это весь функционал для добавления комментов, все что мне надо. Ругайте.
Вот например
Вот например строка вызовет не совсем правильное выполнение, мне кажется.
[link=http://test.com]lalala[/link][/link]Может быть стоит в коде
$text =~ s/\[link.*=(.*http\:\/\/.*)\](.*)\[\/link\]/<a href="$1">$2</a>/g;заменить '.*' на '.*?' ?
В первых двух строках < и > съелись. Я прав? :)
Тогда
$text =~ s/<script.*?>|<\/script>//sg;нужно поместить в самое начало либо просто выбросить.А, да... еще
$text =~ s!\[(/{0,1}[biu])\]!<$1>!g;должна с успехом заменить
Но это на любителя.
В итоге:
Минус всего этого в том что не проверяется парность тегов. А так выглядит достаточно работоспособным.
Хотя, наверняка куча дырок.
Ну и на последок, я бы предпочел принимать ссылку на переменную, модифицировать ее, а возвращать 0 или 1:
korshak, спасибо за
korshak, спасибо за ценные советы..
В первых двух строках < и > съелись. Я прав? :)
Да, именно так :)
Вот еще столкнулся с проблемой. Хочу сделать чтобы просто ссылки без тегов (http://kiev.pm.org) превращались в
kiev.pm.org
$$text =~ s/(http\:\/\/.*)/\<a href="$1"\>$1\<\/a\>/g;но как быть с тегами [link=http://kiev.pm.org/node/260]Perl Community[/link], оно цепляет его URL тоже, как бытЬ ?
$$text =~ s/\[link=(http\:\/\/.*?)\](.*?)\[\/link\]/\<a href="$1"\>$2\<\/a\>/g;т.е. надо сдела чтобы эти 2 правила одновременно работали.
Есть одна мысль построчно обрабатывать $text, а если в строке 2 разных ссылки.. В общем хелп..
Вот что сейчас есть.
------------------Есть способ, но
Есть способ, но вобще-то это извращение и потеря производительности.
Но имхо, всяко лучше чем писать полный разбор.
Да, кста. в этомслучае уже стоило бы заменить http на http|https|ftp|telnet, это как минимум =)
Это мракобесие будет одновременно выгребать и просто ссылки, и ссылки обрамленные тегом link. В первом случае вместо текста описания будет поставлена сама ссылка, во втором - текст описания из link
Если проследить логическое развитие кода, то скоро он все-таки перейдет к полному разбору текста.
По секрету скажу, что это, по моему, единственный способ избежать костылей и граблей,
но использовать его стоит только тогда, когда в этом есть реальная необходимость.
Да и производительность на нам можно получить достаточно приемлемую.
Вообщем, если настанет такой момент, рекомендую пересмотреть мой первый ответ.
Он может показаться интересным =) (но не раньше)