Вход Регистрация
Файл: social12/strip_tags_smart.php
Строк: 55
<?php

/**
 * Более продвинутый аналог strip_tags() для корректного вырезания тагов из html кода.
 * Функция strip_tags(), в зависимости от контекста, может работать не корректно.
 * Воможности:
 *   - корректно обрабатываются вхождения типа "a < b > c"
 *   - корректно обрабатывается "грязный" html, когда в значениях атрибутов тагов могут встречаться символы < >
 *   - корректно обрабатывается разбитый html
 *   - вырезаются комментарии, скрипты, стили, PHP, Perl, ASP код, MS Word таги
 *   - автоматически форматируется текст, если он содержит html код
 *   - защита от подделок типа: "<<fake>script>alert('hi')</</fake>script>"
 *
 * @param   string  $s
 * @param   array   $allowable_tags     Массив тагов, которые не будут вырезаны
 * @param   bool    $is_format_spaces   Форматировать пробелы и переносы строк?
 *                                      Текст форматируется автоматически, если он содержит html код:
 *                                      вид текста на выходе (plain) максимально приближеется виду текста в браузере на входе
 *                                      Другими словами, грамотно преобразует text/html в text/plain
 *                                      Если текст содержит html таги, $is_format_spaces = TRUE
 * @param   array   $pair_tags   массив имён парных тагов, которые будут удалены вместе с содержимым
 *                               см. значения по умолчанию
 * @param   array   $para_tags   массив имён парных тагов, которые будут восприниматься как параграфы (если $is_format_spaces = true)
 *                               см. значения по умолчанию
 * @return  string
 *
 * @author   Nasibullin Rinat <n a s i b u l l i n  at starlink ru>
 * @charset  ANSI
 * @version  4.0.4-dev2  :TODO: <pre>textrntext</pre>
 */
function strip_tags_smart(
    
/*string*/ $s,
    array 
$allowable_tags null,
    
/*boolean*/ $is_format_spaces false,
    array 
$pair_tags = array('script''style''map''iframe''frameset''object''applet''comment''button'),
    array 
$para_tags = array('p''td''th''li''h1''h2''h3''h4''h5''h6''div''form''title')
)
{
    static 
$_callback_type  false;
    static 
$_allowable_tags = array();
    static 
$_para_tags      = array();
    
#регулярное выражение для атрибутов тагов
    #корректно обрабатывает грязный и битый HTML в однобайтовой или UTF-8 кодировке!
    
static $re_attrs_fast_safe =  '(?> (?>[x20rnt]+|xc2xa0)+  #пробельные символы (д.б. обязательно)
                                       (?>
                                         #правильные атрибуты
                                                                        [^>"'
]+
                                         | (?<=[=
x20rnt]|xc2xa0"[^"]*"
                                         | (?<=[=x20rnt]|xc2xa0) '[^']*'
                                         #разбитые атрибуты
                                         |                              [^>]+
                                       )*
                                   )?';

    if (is_array(
$s) && $_callback_type === 'strip_tags')
    {
        
$tag = strtolower($s[1]);
        if (
$_allowable_tags &&
            (array_key_exists(
$tag$_allowable_tags) || array_key_exists('<' . trim(strtolower($s[0]), '< />') . '>', $_allowable_tags))
            ) return 
$s[0];
        if (
$tag == 'br') return "rn";
        if (
$_para_tags && array_key_exists($tag$_para_tags)) return "rnrn";
        return '';
    }

    if ((
$pos = strpos($s, '<') === false) || strpos($s, '>', $pos) === false)  #оптимизация скорости
    {
        #таги не найдены
        return 
$s;
    }

    #непарные таги (открывающие, закрывающие, !DOCTYPE, MS Word namespace)
    
$re_tags = '/<[/!]? ([a-zA-Z][a-zA-Zd]* (?>:[a-zA-Z][a-zA-Zd]*)?)' . $re_attrs_fast_safe . '/?>/sx';

    
$patterns = array(
        '/<([?%]) .*? \1>/sx',     #встроенный PHP, Perl, ASP код
        '/<![CDATA[ .*? ]]>/sx', #блоки CDATA
        #'/<![  [x20rnt]* [a-zA-Z] .*?  ]>/sx',  #:DEPRECATED: MS Word таги типа <![if! vml]>...<![endif]>

        '/<!--.*?-->/s', #комментарии

        #MS Word таги типа "
<![if! vml]>...<![endif]>",
        #условное выполнение кода для IE типа "
<!--[if expression]> HTML <![endif]-->"
        #условное выполнение кода для IE типа "
<![if expression]> HTML <![endif]>"
        #см. http://www.tigir.com/comments.htm
        '/<! (?>--)?
              [
              (?> [^]"']+ | "[^"]*" | '
[^']*' )*
              ]
              (
?>--)?
         >/sx',
    );
    if ($pair_tags)
    {
        #парные таги вместе с содержимым:
        foreach ($pair_tags as $k => $v) $pair_tags[$k] = preg_quote($v, '/');
        $patterns[] = '/<((?i:' . implode('|', $pair_tags) . '))' . $re_attrs_fast_safe . '> .*? </(?i:\1)' . $re_attrs_fast_safe . '>/sx';
    }
    #d($patterns);

    $i = 0; #защита от зацикливания
    $max = 99;
    while ($i < $max)
    {
        $s2 = preg_replace($patterns, '', $s);
        if ($i == 0)
        {
            $is_html = ($s2 != $s || preg_match($re_tags, $s2));
            if ($is_html)
            {
                #В библиотеке PCRE для PHP s - это любой пробельный символ, а именно класс символов [x09x0ax0cx0dx20xa0] или, по другому, [tnfr xa0]
                #Если s используется с модификатором /u, то s трактуется как [x09x0ax0cx0dx20]
                #Браузер не делает различия между пробельными символами,
                #друг за другом подряд идущие символы воспринимаются как один
                #$s = str_replace(array("r", "n", "t"), ' ', $s);
                $s2 = strtr($s2, "x09x0ax0cx0d", '    ');

                #массив тагов, которые не будут вырезаны
                if ($allowable_tags) $_allowable_tags = array_flip($allowable_tags);

                #парные таги, которые будут восприниматься как параграфы
                if ($para_tags) $_para_tags = array_flip($para_tags);
            }
        }#if

        #обработка тагов
        if ($is_html)
        {
            $_callback_type = 'strip_tags';
            $s2 = preg_replace_callback($re_tags, __FUNCTION__, $s2);
            $_callback_type = false;
        }

        if ($s === $s2) break;
        $s = $s2; $i++;
    }#while
    if ($i >= $max) $s = strip_tags($s); #too many cycles for replace...

    if ($is_format_spaces || $is_html)
    {
        #вырезаем дублирующие пробелы
        $s = preg_replace('/x20x20+/s', ' ', trim($s));
        #вырезаем пробелы в начале и в конце строк
        $s = str_replace(array("rnx20", "x20rn"), "rn", $s);
        #заменяем 2 и более переносов строк на 2 переноса строк
        $s = preg_replace('/rn[rn]+/s', "rnrn", $s);
    }
    return $s;
}

?>
Онлайн: 1
Реклама