Php BB коды

Иногда нам хочется добавить изюминку к нашим скриптам, сохранять в базе сообщения от пользователей не только в простом текстовом формате, но и давать им возможность форматировать свои сообщения как текст html. Здесь и нужны так называемые BB коды. То есть, это придуманные нами парные теги, которые при использовании нами будут преобразовываться в html теги.

BB код Преобразование Описание
&#91;b&#93; что-то здесь &#91;/b&#93; <b>что-то здесь</b> жирный текст
&#91;i&#93; что-то здесь &#91;/i&#93; <i>что-то здесь</i> наклонный текст
&#91;u&#93; что-то здесь &#91;/u&#93; <u>что-то здесь</u> подчеркнутый текст
&#91;q&#93;что-то здесь &#91;/q&#93; <table><tr><td>
что-то здесь
</td></tr></table> выделенная цитата
&#91; list &#93; что-то здесь&#91;/list&#93; <ul><li>что-то здесь</li></ul> не нумерованный список
&#91;listn&#93;что-то здесь &#91;/listn&#93; <ol><li>что-то здесь</li></ol> нумерованный список
(url)что-то здесь (/url) <a href="">что-то здесь</a> Url ссылка
Ранее в разделе Php база, мы научились с Вами сохранять данные в таком формате, чтобы он не причинил вреда при выводе его из базы в html текст, теперь будем добавлять BB коды, а потом их преобразовывать в html. Пользователю, которого мы лишили html форматирования, теперь становится интереснее. Но, как обычно, в любом начинании есть проблемы.
Одна из проблем в том, что пользователь может забыть закрыть тег, или, ещё хуже, какой-нибудь нехороший пользователь специально захочет Вам навредить. Так вот, как найти парные теги в сообщении полученном из формы, которое пользователь послал в Гостевую книгу или в Форум? Дело в том, что если у Вас простая Гостевая, это не требуется, но если есть BB коды, это становится актуально, ведь потом эти парные теги мы будем заменять на их html эквиваленты:

К примеру:
&#91;b&#93; что-то здесь &#91;/b&#93;, посланное пользователем, преобразуется в
<b>что-то здесь</b>, в этих BB кодах

Теперь представьте, что пользователь по ошибке или специально открыл только один тег
&#91;b&#93; что-то здесь, а закрыть тег не захотел, то получится:
<b>что-то здесь, а закрыть тег не захотел, то получится

То есть, надо проверять парность тегов:
- убирать в начале текста закрывающийся тег &#91;/b&#93;;
- убирать в конце текста открывающийся тег &#91;b&#93;;
- убирать пустые парные теги &#91;b&#93; &#91;/b&#93;;
- убирать повторяющиеся теги &#91;b&#93;&#91;b&#93; или &#91;/b&#93;&#91;/b&#93;;

Создадим такую функцию и посмотрим как она работает:

<?php
    # функция, которая убирает мусор в парных тегах
function Teg ($one,$teg,$too,$path){
$on = preg_quote ($one,"~");
$to = preg_quote ($too,"~");
$saerch1 = preg_quote ($one,"~") . $teg . preg_quote ($too,"~");
$saerch2 = preg_quote ($one,"~") . "/" . $teg . preg_quote ($too,"~");
$path = preg_replace ("~[ ]+~"," ",$path); 
$path = trim ($path);
$path = preg_replace ("~(".$saerch1."[ ]?".$saerch1.")+~", $one.$teg.$too, $path); 
$path = preg_replace ("~(".$saerch2."[ ]?".$saerch2.")+~", $one."/".$teg.$too, $path); 
$path = preg_replace ("~ˆ([ ]*".$saerch2.")*~","",$path); 
$path = preg_replace ("~(".$saerch1."[ ]*)*$~","",$path); 
$_search = "~".$saerch1."(.+)".$saerch2."~U";
$search = array ();
if ( preg_match_all ($_search, $path, $array, PREG_PATTERN_ORDER)){
while ( list (, $val) = each ($array[0])){
$content = "~" . preg_quote ($val,"~") . "~U";
if ( !empty ($search[0])){ if ($content==$search[0]){continue;} }
if ( @array_search ($content,$search)){ continue; }
$search[] = $content;
$pp = preg_replace ("~".$on."[/]?".$teg.$to."~","",$val);
if ( !preg_match ("~[a-zA-Z0-9а-яА-Я_]~",$pp)){ $pp = " "; }
else { $pp = $one.$teg.$too.$pp.$one."/".$teg.$too; }
$replace[] = $pp;
}
$search[] = "~0~e";
$replace[] = "0";
$path = preg_replace ($search, $replace, $path); 
$path = preg_replace ("~[ ]+~"," ",$path); 
$path = preg_replace ("~".$on."([/]?)".$teg.$to."[ ]?".$on."\\1".$teg.$to."~s", $one."\\1".$teg.$too, $path);
}
if ( !preg_match ($_search, $path)){ $path = preg_replace ("~".$on."[/]?".$teg.$to."~", '', $path); }
return $path;
} 

    # строка с плохими парными тегами
$string = " &#91;/b&#93; &#91;/b&#93; &#91;/b&#93;&#91;b&#93; Проб&#91;b&#93;у&#91;b&#93;&#91;b&#93;ем &#91;/b&#93;Обм&#91;b&#93;ан&#91;b&#93;уть &#91;b&#93;Програ &#91;/b&#93; &#91;/b&#93; &#91;/b&#93;мму &#91;b&#93; &#91;b&#93; &#91;b&#93; ";
echo $string."\n<br><br>";

    # применим функцию по сбору мусора
    # в ней четыре аргумента: первые три показывают
    # какой тег проверяем, а последний где проверяем
$string = Teg ("&#91;","b","&#93;",$string);
echo $string;

?>


В итоге работы программы получим:

&#91;/b&#93; &#91;/b&#93; &#91;/b&#93;&#91;b&#93; Проб&#91;b&#93;у&#91;b&#93;&#91;b&#93;ем &#91;/b&#93;Обм&#91;b&#93;ан&#91;b&#93;уть &#91;b&#93;Програ &#91;/b&#93; &#91;/b&#93; &#91;/b&#93;мму &#91;b&#93; &#91;b&#93; &#91;b&#93;

&#91;b&#93; Пробуем &#91;/b&#93;Обм&#91;b&#93;ануть Програ &#91;/b&#93;мму

То есть, в базу, при таком подходе мы запишем только парные теги. Вы скажете зачем всё это надо, но одно дело когда, например не закрылся тег &#91;b&#93;, ещё пол беды (весь тест далее будет выделен жирным шрифтом), и совсем другое когда не закрылся &#91;q&#93;, который мы будем преобразовывать в начало таблицы <table><tr><td> (представляете, что будет на странице при выводе такого не закрытого тега).

То есть, теперь подведем итог:
Пользователь послал сообщение $message, которое мы будем записывать в базу, как убрать html дескрипторы из сообщения мы знаем (раздел Php база), теперь оставим парные и уберем пустые теги BB кодов:

<?php 
    // оставим парные и уберем пустые теги 
$message = Teg ("&#91;","b","&#93;",$message); 
$message = Teg ("&#91;","i","&#93;",$message); 
$message = Teg ("&#91;","u","&#93;",$message); 
$message = Teg ("&#91;","q","&#93;",$message); 
$message = Teg ("&#91;","list","&#93;",$message); 
$message = Teg ("&#91;","listn","&#93;",$message); 
$message = Teg ("(","url",")",$message); 
    // записываем сообщение в базу 
$fp = fopen ("Base.dat","a"); 
fputs ($fp,"$message\n"); 
fclose ($fp); 
?>

При таком подходе, мы оставляем мало шансов злоумышленнику навредить нам, и даем дополнительные возможности добросовестному пользователю по использованию html разметки в своих сообщениях.
Теги:
BB коды
Добавлено: 02 Апреля 2018 19:11:40 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...