|
|
|
| Вот есть список допустимых тегов и допустимых атрибутов.
Как отбросить все остальные теги и атрибуты?
$AllowedTags = array("a", "b", "blink", "blockquote", "br", "caption", "center", "col", "colgroup", "comment",
"em", "font", "h1", "h2", "h3", "h4", "h5", "h6", "hr", "img", "li", "marquee", "ol", "p", "pre", "s",
"small", "span", "strike", "strong", "sub", "sup", "table", "tbody", "td", "tfoot", "th",
"thead", "tr", "tt", "u", "ul");
$AllowedAttr = array("abbr", "align", "alt", "axis", "background", "behavior", "bgcolor", "border", "bordercolor",
"bordercolordark", "bordercolorlight", "bottompadding", "cellpadding", "cellspacing", "char",
"charoff", "cite", "clear", "color", "cols", "direction", "face", "font-weight", "headers",
"height", "href", "hspace", "leftpadding", "loop", "noshade", "nowrap", "point-size", "rel",
"rev", "rightpadding", "rowspan", "rules", "scope", "scrollamount", "scrolldelay", "size",
"span", "src", "start", "summary", "target", "title", "toppadding", "type", "valign",
"value", "vspace", "width", "wrap"); | |
|
|
|
|
|
|
|
для: Eugene77
(17.01.2008 в 15:15)
| | Как вариант, воспользоваться каким-нибудь xml парсером, а потом собрать документ обратно использую только разрешенные теги и аттрибуты.
Ну или просто брать все что внутри <>, выбирать оттуда все что имеет структуру attr="var" и выкидывать все что не проходит проверку. | |
|
|
|
|
|
|
|
для: Loki
(17.01.2008 в 16:12)
| | C xml парсером - это пока мне не понятно.
Может быть ссылочку подкинете?
А вот регулярные выражения что-то туго подбираются.
Для простоты я разбил на унарные теги и двойные:
<?
$AllowedTags1 = array("br", "col", "hr", "img");
$AllowedTags2 = array("a", "b", "blink", "blockquote", "caption", "center", "col", "colgroup",
"em", "font", "h1", "h2", "h3", "h4", "h5", "h6", "hr", "li", "marquee", "ol", "p", "pre", "s",
"small", "span", "strike", "strong", "sub", "sup", "table", "tbody", "td", "tfoot", "th",
"thead", "tr", "tt", "u", "ul");
$AllowedAttr = array("abbr", "align", "alt", "axis", "background", "behavior", "bgcolor", "border", "bordercolor",
"bordercolordark", "bordercolorlight", "bottompadding", "cellpadding", "cellspacing", "char",
"charoff", "cite", "clear", "color", "cols", "direction", "face", "font-weight", "headers",
"height", "href", "hspace", "leftpadding", "loop", "noshade", "nowrap", "point-size", "rel",
"rev", "rightpadding", "rowspan", "rules", "scope", "scrollamount", "scrolldelay", "size",
"span", "src", "start", "summary", "target", "title", "toppadding", "type", "valign",
"value", "vspace", "width", "wrap");
$t1='/<['.implode('|',$AllowedTags1).'].*>/i';
$t2='/<('.implode('|',$AllowedTags2).')([\s\t\n]*)(.*)([\s\t\n]*)>(.*)<\/('.implode('|',$AllowedTags2).')([\s\t\n]*)>/is';
$a='['.implode ('|',$AllowedAttr).']';
function ins($match){
echo '<br>';
echo htmlspecialchars($match[0]);
preg_replace_callback($t2, 'ins', $html);
|
В принципе, такая функция вычленяет теги и если её вызывать рекурсивно, то наверно и с вложенностью можно разобраться, но кажется мне, что я не на верном пути. Слишком уж замысловато... | |
|
|
|
|
|
|
|
для: Eugene77
(17.01.2008 в 20:57)
| | $t1='/<['.implode('|',$AllowedTags1).'].*>/i'; - это выражение у Вас получилось "жадным". Вследствие чего, под .* попадет как можно больше символов. Т.е. из "text <br> text <br> text" под .* попадет "> text <br". Добавте модификатор U или "?" (квантификатор) после .*
$t2='/<('.implode('|',$AllowedTags2).')([\s\t\n]*)(.*)([\s\t\n]*)>(.*)<\/('.implode('|',$AllowedTags2).')([\s\t\n]*)>/is';
Здесь аналогичные проблемы с жадностью... И некоторые поправки:
([\s\t\n]*)(.*)([\s\t\n]*) во-первых, \s содержит в себе и \t, и \n. Т.е. достаточно \s*. Ну и во-вторых, под вторую ([\s\t\n]*) ничего не попадет из-за жадной .*
Вот так правильнее будет, наверное: $t2='/<('.implode('|',$AllowedTags2).')(.*?)>(.*?)<\/\\1\s*>/is';
$a='['.implode ('|',$AllowedAttr).']'; - только с круглыми скобками по краям... Правда толку от этого выражения не будет, наверное... | |
|
|
|
|
|
|
|
для: kasmanaft
(17.01.2008 в 21:28)
| | Спасибо за совет!
Только он всех проблем не решает.
Ведь вложенность тегов никто не отменял.
Значит определённыя жадность мне на пользу : )
С другой стороны, со своей жадностью я вылетаю за пределы отдельных тегов.
То есть если пойти таким путём, то придётся чередовать жадные и не жадные запросы, сравнивать результаты и рекурсивно вызывать функцию.
Пар из ушей гарантирован.
Тут видно не тот подход я выбрал. Надо смотреть куда-то в сторону XML & XSLT.
Пока ничего не нашёл подходящего, хотя книги в поиске встречаются, читать целые книги мне сейчас некогда.
А статьи приводят примеры слишком далёкие от моей задачки. | |
|
|
|
|
|
|
|
для: Eugene77
(18.01.2008 в 17:56)
| | >> Ведь вложенность тегов никто не отменял.
А вообще-то.... закрывающие теги Вам и не нужны, наверное. Обработать сначала открывающие, а там, если надо, и с закрывающими можно что-нибудь наделать....
PS С помощью рег. выражений можно и вложенные теги обойти с помощью рекурсии (именно рекурсивных рег. выражений (?R) ). Но это не лучшее решение судя по всему... | |
|
|
|
|
|
|
|
для: kasmanaft
(18.01.2008 в 18:54)
| | >А вообще-то.... закрывающие теги Вам и не нужны, наверное. Обработать сначала открывающие, а там, если надо, и с закрывающими можно что-нибудь наделать....
>
Так будет проще, конечно.
Вообще реальный выриант...
Но что-то я боюсь его использовать. Мнится мне в нём какая-то опасность, уязвимость.
Разные браузеры будут по-разному реагировать но нарушения в порядке тегов. Через это можно запустить какой угодно код вредоносный в некоторые из браузеров.
Впрочем, можно решить проблему, проверив в начале нет ли нарушения в порядке следования тегов. Тогда уже смело можно всё распарсить.
Как бы такую проверочку изобрести?
То есть как проверить что внутри каждого тега только пары парных тегов?
Может быть, как раз ваша рекурсия и подойдёт:
>PS С помощью рег. выражений можно и вложенные теги обойти с помощью рекурсии (именно рекурсивных рег. выражений (?R) ). Но это не лучшее решение судя по всему...
У вас нет на примете статьи по рекурсивным рег. выраж.? | |
|
|
|
|
|
|
|
для: Eugene77
(19.01.2008 в 18:44)
| | >> Разные браузеры будут по-разному реагировать но нарушения в порядке тегов.
Ну это другой вопрос.. Порядок тегов можно и без этого всего нарушить. Главное его не нарушить, удаляя лишние теги :)
Но это не проблема, вроде как: удаляя атрибуты порядок тегов не нарушите, удаляя запрещенные теги, удалите и закрывающие..
> Через это можно запустить какой угодно код вредоносный в некоторые из браузеров.
Это врядли.. Вы код для чего чистите? Ничего опасного туда проникнуть не должно, вроде.
> У вас нет на примете статьи по рекурсивным рег. выраж.?
Нет, рекурсию вообще-то не часто используют (тут на форуме так вообще ни одного примера не встречал).. Наверное, поэтому и статей нет... Хотя, я не интересовался. (сам по мануалу разобрался на php.net)
> Как бы такую проверочку изобрести?
>То есть как проверить что внутри каждого тега только пары парных тегов?
>Может быть, как раз ваша рекурсия и подойдёт:
Нет, тут рекурсию вряд ли возможно прикрутить.. С помощью нее удобно выдрать парный тег, а проверить все ли они парные, думаю, не получится.
Вот так, наверное, можно сделать: удалять постепенно самые вложенные теги, внутри которых нет других тегов.. удалять, удалять.. пока есть чего. Потом: остался какой из тегов (открывающий/закрывающий) - значит теги были расставлены неверно. Единственное: придется удалить перед этим непарные теги.
Если проводить эту процедуру только при обновлении записи, нагрузки будут не очень большие, наверное....
Приблизительно так можно выдрать самый вложенный тег:
#<([a-z]+)[^>]*>((?!</?[a-z]+[^>]*>).)*?</\\1[^>]*>#is (не проверял) | |
|
|
|
|
|
|
|
для: kasmanaft
(22.01.2008 в 18:41)
| | Да, такое выражение решало бы мою проблему.
(Остальное я, кажется, сам всилах дописать)
Только вот не понимаю я вашей регулярки #<([a-z]+)[^>]*>((?!</?[a-z]+[^>]*>).)*?</\\1[^>]*>#is
Объясните, пожалуйста, как работает: ((?!</?[a-z]+[^>]*>).)*? | |
|
|
|
|
|
|
|
для: Eugene77
(23.01.2008 в 19:41)
| | <([a-z]+)[^>]*> - с этим, наверное, нет вопросов?..
(?!str) - три символа после текущего должны быть не "str".
(?!</?[a-z]+[^>]*>) - аналогично: некоторое количество символов после текущего не должны подходить под этот шаблон. То есть не: "<", после которой, возможно, "/", обязательно несколько букв, возможно, несколько "не >" и, наконец, закрывающая ">". Иначе говоря, строка после текущего символа не должна быть тегом.
. - и после всего этого любой символ (который "не тег").
*? - произвольное, минимально возможное, количество символов (которые "не тег" :) ).
</\\1[^>]*> - закрывающий тег (\\1). | |
|
|
|
|
|
|
|
для: kasmanaft
(24.01.2008 в 13:35)
| | Нет, не работает
<?
$html = '<td> <td></td>';
$expr = '#<([a-z]+)[^>]*>((?!</?[a-z]+[^>]*>).)*?</\\1[^>]*>#is';
$r = preg_replace($expr, '', $html);
echo $r;
|
Даёт пустую строку. | |
|
|
|
|
|
|
|
для: Eugene77
(24.01.2008 в 20:53)
| | Хм.. у меня "<td> " | |
|
|
|
|
|
|
|
для: kasmanaft
(24.01.2008 в 20:59)
| | Прошу прощения, что-то не то ляпнул!
Вот что даёт пустую строку:
$html = '<td> </tr>'; | |
|
|
|
|
|
|
|
для: Eugene77
(25.01.2008 в 19:34)
| | А что оно должно давать? :)
Если хотите "самый вложенный тег" выбрать, используйте preg_match().. | |
|
|
|
|
|
|
|
для: kasmanaft
(25.01.2008 в 20:14)
| | >А что оно должно давать? :)
>
>Если хотите "самый вложенный тег" выбрать, используйте preg_match()..
Вероятно я что-то не понял, но строка вроде как не соответствует шаблону.
Закрыающий и открывающий теги различны. Поэтому оно не должно было бы быть затронуто функцией. Вот я и сделал вывод, что выражение работает не так как ожидалось.
То есть я ожидал, что при каждом применении preg_replace к строке, из строки будут исчезать самые вложенные теги, но лишь те, которые действительно парные, а не разные. | |
|
|
|
|
|
|
|
для: Eugene77
(26.01.2008 в 20:34)
| | Упс, прошу прощения, не доглядел... Всё верно, это глюк.
Получилось что в этом выражении: <([a-z]+)[^>]*>; под [a-z]+ попали не все буквы, а часть попала под [^>]*. То есть "t" у тегов совпали, оно решило, что теги одинаковые...
Можно вот так испраить выражение: #<([a-z]+)\b[^>]*>((?!</?[a-z]+[^>]*>).)*?</\\1\b[^>]*>#is
\b означает границу "слова", что гарантирует, что теги больше рваться не будут. | |
|
|
|
|
|
|
|
для: kasmanaft
(27.01.2008 в 14:53)
| | Ура!
Торжество КА[смических технологий теперь не вызывает сомнений!
Только я не понял зачем b во втором случае?! | |
|
|
|
|
|
|
|
для: Eugene77
(27.01.2008 в 20:33)
| | :)
Да всё ради того же... Будет, например, открывающий тег "a" и закрывающий "applet". Опять та же бяка будет ("pplet" попадеть под [^>]*). | |
|
|
|
|
|
|
|
для: kasmanaft
(27.01.2008 в 21:05)
| | Ещё маленькая поправка: забыл про теги h1, h2 и др... в общем, к [a-z]+ еще надо бы цифры добавить ([a-z0-9]+).
PS спецификация еще "_" разрешает.. может быть, и его туда же. | |
|
|
|
|
|
|
|
для: kasmanaft
(28.01.2008 в 09:40)
| | >Ещё маленькая поправка: забыл про теги h1, h2 и др... в общем, к [a-z]+ еще надо бы цифры добавить ([a-z0-9]+).
Здорово! И я проглядел.
>
>PS спецификация еще "_" разрешает.. может быть, и его туда же.
Мне не надо все теги. Хотя в каких тегах есть "_"? =О
Вот так пишу:
function check_pair_tegs($html){
$singlets = array("br", "hr", "img");
$html = preg_replace('#</?('.implode('|', $singlets).')(\s+.*|\s*)>#isU', '', $html);
$expr = '#<([a-z][a-z1-9]+)\b[^>]*>((?!</?[a-z]+[^>]*>).)*?</\\1\b[^>]*>#is';
while($html != $html1 = preg_replace($expr, '', $html)) $html = $html1;
if($html=='') return true; else return false;
}
|
Но почему-то пропускает < br> и даже <_br> | |
|
|
|
|
|
|
|
для: Eugene77
(28.01.2008 в 17:30)
| | В каком смысле пропускает?
var_dump(check_pair_tegs("<td>s</td>")); - true
var_dump(check_pair_tegs("<td> <br> </td>")); - true
var_dump(check_pair_tegs("<td> <brrr> </td>")); - false
var_dump(check_pair_tegs("<br> <br>")); - false, потому что после замены остается " " (а не пустая строка)
var_dump(check_pair_tegs("<a></a>")); - false, потому что после буквы "a" нет обязательных букв/цифр ([a-z][a-z1-9]+)
А "< br>", "<_br>" не являются HTML тегами.. заменять их ни на что не надо.
PS всё же tag, а не teg. | |
|
|
|
|
|
|
|
для: kasmanaft
(28.01.2008 в 19:00)
| | var_dump(check_pair_tags("<td><_img></td>")); -true
var_dump(check_pair_tags("<td>< img></td>")); -true
Вот это меня и смущает
Тоесть пробел или символ подчёркивания перед именем непарного тега не выдаёт мне ошибки, хотя это должно быть ошибкой. Загадка!
Насчёт teg -извините, я думал в касмосе, как раз-таки tag не актуален : ) | |
|
|
|
|
|
|
|
для: Eugene77
(28.01.2008 в 20:19)
| | Почему это должно быть ошибкой?
Тег это: открывающая <, идентификатор (вроде они так зовутся), начинающийся с буквы, может содержить буквы,цифры,знак подчеркивания. Через пробел идут атрибуты, потом ">".
< img> - это не тег! и ваше выражение его попросту не трогает (а не заменяет).
что "<td>< img></td>", что "<td>blablabla</td>"...
PS я не касмонафт ;-) | |
|
|
|
|
|
|
|
для: kasmanaft
(28.01.2008 в 20:28)
| | >
>< img> - это не тег! и ваше выражение его попросту не трогает (а не заменяет).
>что "<td>< img></td>", что "<td>blablabla</td>"...
>
Если бы..
В том-то и дело, что трогает и удаляет, Иначе функция возвратила бы false!
True она возвращает только если удалось удалить всё начисто. | |
|
|
|
|
|
|
|
для: Eugene77
(29.01.2008 в 17:47)
| | Она удаляет <td>..</td> и всё, что попало между ними. Попал не_тег ( =] ) "< img>" - удалила и его.
var_dump(check_pair_tags("< img>")) вернет false.. Всё верно.
var_dump(check_pair_tags("<img>")) - true.... | |
|
|
|
|
|
|
|
для: kasmanaft
(29.01.2008 в 18:50)
| | Логично.
Спасибо!
Здорово помогли!
Ещё бы статью про "!?" порекомендовали... | |
|
|
|
|
|
|
|
для: Eugene77
(31.01.2008 в 17:10)
| | Да, было бы совсем неплохо :))
Да только я сам не читал ни одной.... Мануал да Фридла чуть-чуть...
(Добавил: и форум! понимание приходит с практикой..)
Может быть, стоит вот это прочитать:
http://www.phpclub.ru/detail/article/regexp_1
http://www.phpclub.ru/detail/article/regexp_2 | |
|
|
|
|
|
|
|
для: kasmanaft
(01.02.2008 в 19:09)
| | Начитавшись статей(спасибо за замечательные ссылки) я стал пробовать размышлять.
Но никак не пойму почему бы не упростить вашу регулярку, например до такого состояния:
'#(.*)<([a-z][a-z1-6]*)\b[^>]*>([^<>]*)</\\2\b[^>]*>(.*)#is'
|
? | |
|
|
|
|
|
|
|
для: Eugene77
(10.02.2008 в 10:04)
| | В таком случае пользователи не смогут использовать "<>".
Ну, можете "попросить" их использовать < > .. А может вообще перебьются :)
Может быть, вручную заменить все "<>" (не являющиеся частью тегов) перед проверкой. Всё равно заменять ведь придется.. Так что можно и упростить выражение.
PS "(.*)" по краям - лишнее.. | |
|
|
|
|
|
|
|
для: kasmanaft
(10.02.2008 в 11:41)
| | Да,пожалуй, я мог бы и сам догадаться.
Просто ещё не совсем привычные материи - поэтому мысли туго в голове шевелятся. Спасибо!
Лучше вашего варианта мне ничего не придумать! | |
|
|
|
|
|
|
|
для: Eugene77
(17.01.2008 в 15:15)
| | Во так работает:
$h = fopen("http://marketing.rbc.ru/","r");
while (!feof ($h)) {
$content = fgetss($h,1024,'<br><col><hr><img><h1></h1><h2></h2><h3></h3><h4></h4><h5>
</h5><h6></h6><a></a><b></b><blink></blink><blockquote></blockquote><caption>
</caption><center></center><col></col><colgroup></colgroup><em></em><font></font><hr>
</hr><li></li><marquee></marquee><ol></ol><p></p><pre></pre><s></s><small></small><span>
</span><strike></strike><strong></strong><sub></sub><sup></sup><table></table><tbody></tbody><td></td><tfoot></tfoot><th></th><thead></thead><tr></tr><tt></tt><u></u><ul></ul>');
echo $content;
}
|
| |
|
|
|
|
|
|
|
для: rombikr
(07.02.2008 в 17:02)
| | Да, дальше уж не сложно...
Если парность тегов проверена, то лишние можно откинуть или так или strip_tags()
Ну а атрибуты регуляркой, но она совсем простая | |
|
|
|
|