Вход Регистрация
Файл: public_html/core/antimat.class.php
Строк: 117
<?php

require ('UTF8.php');
require (
'ReflectionTypeHint.php');

class 
Text_Censure
{
    private function 
__construct() {}
    
/**
     *
     * @param    string       $s         строка для проверки
     * @param    string       $delta     ширина найденного фрагмента в словах
     *                                   (кол-во слов от матного слова слева и справа, максимально 10)
     * @param    string       $continue  строка, которая будет вставлена в начале и в конце фрагмента
     * @param    bool         $is_html   расценивать строку как HTML код?
     *                                   в режиме $is_html === TRUE html код игнорируется, а html сущности заменяются в "чистый" UTF-8
     * @param    string|null  $replace   строка, на которую заменять матный фрагмент, например: '[ой]' ($replace д.б. в кодировке $charset)
     *                                   опция работает в PHP >= 5.2.0
     * @param    string       $charset   кодировка символов (родная кодировка -- UTF-8, для других будет прозрачное перекодирование)
     * @return   bool|string|int|null    Если $replace === NULL, то возвращает FALSE, если мат не обнаружен, иначе фрагмент текста с матерным словом.
     *                                   Если $replace !== NULL, то возвращает исходную строку, где фрагменты мата заменены на $replace.
     *                                   В случае возникновения ошибки возвращает код ошибки > 0 (integer):
     *                                     * PREG_INTERNAL_ERROR
     *                                     * PREG_BACKTRACK_LIMIT_ERROR (see also pcre.backtrack_limit)
     *                                     * PREG_RECURSION_LIMIT_ERROR (see also pcre.recursion_limit)
     *                                     * PREG_BAD_UTF8_ERROR
     *                                     * PREG_BAD_UTF8_OFFSET_ERROR (since PHP 5.3.0)
     *                                   Или -1, если ReflectionTypeHint вернул ошибку
     */
    
public static function parse(
        
$s,
        
$delta 3,
        
$continue "xe2x80xa6",
        
$is_html true,
        
$replace null,
        
$charset 'UTF-8')
    {
        if (
$s === null) return null;
        static 
$re_badwords null;
        if (
$re_badwords === null)
        {
            
#предлоги русского языка:
            #[всуо]|
            #по|за|на|об|до|от|вы|вс|вз|из|ис|
            #под|про|при|над|низ|раз|рас|воз|вос|
            #пооб|повы|пона|поза|недо|пере|одно|
            #полуза|произ|пораз|много|
            
$pretext = array(
                
#1
                
'[уyоoаa]_?      (?=[еёeхx])',        #у, о   (уебать, охуеть, ахуеть)
                
'[вvbсc]_?       (?=[хпбмгжxpmgj])',  #в, с   (впиздячить, схуярить)
                
'[вvbсc]_?[ъь]_? (?=[еёe])',          #въ, съ (съебаться, въебать)
                
'ё_?             (?=[бb6])',          #ё      (ёбля)
                #2
                
'[вvb]_?[ыi]_?',      #вы
                
'[зz3]_?[аa]_?',      #за
                
'[нnh]_?[аaеeиi]_?',  #на, не, ни
                
'[вvb]_?[сc]_?          (?=[хпбмгжxpmgj])',  #вс (вспизднуть)
                
'[оo]_?[тtбb6]_?        (?=[хпбмгжxpmgj])',  #от, об
                
'[оo]_?[тtбb6]_?[ъь]_?  (?=[еёe])',          #отъ, объ
                
'[иiвvb]_?[зz3]_?       (?=[хпбмгжxpmgj])',  #[ив]з
                
'[иiвvb]_?[зz3]_?[ъь]_? (?=[еёe])',          #[ив]зъ
                
'[иi]_?[сc]_?           (?=[хпбмгжxpmgj])',  #ис
                
'[пpдdg]_?[оo]_? (?> [бb6]_?         (?=[хпбмгжxpmgj])
                               | [бb6]_?  [ъь]_? (?=[еёe])
                               | [зz3]_? [аa] _?
                             )?'
,  #по, до, пообъ, дообъ, поза, доза (двойные символы вырезаются!)
                #3
                
'[пp]_?[рr]_?[оoиi]_?',  #пр[ои]
                
'[зz3]_?[лl]_?[оo]_?',   #зло (злоебучая)
                
'[нnh]_?[аa]_?[дdg]_?         (?=[хпбмгжxpmgj])',  #над
                
'[нnh]_?[аa]_?[дdg]_?[ъь]_?   (?=[еёe])',          #надъ
                
'[пp]_?[оoаa]_?[дdg]_?        (?=[хпбмгжxpmgj])',  #под
                
'[пp]_?[оoаa]_?[дdg]_?[ъь]_?  (?=[еёe])',          #подъ
                
'[рr]_?[аa]_?[зz3сc]_?        (?=[хпбмгжxpmgj])',  #ра[зс]
                
'[рr]_?[аa]_?[зz3сc]_?[ъь]_?  (?=[еёe])',          #ра[зс]ъ
                
'[вvb]_?[оo]_?[зz3сc]_?       (?=[хпбмгжxpmgj])',  #во[зс]
                
'[вvb]_?[оo]_?[зz3сc]_?[ъь]_? (?=[еёe])',          #во[зс]ъ
                #4
                
'[нnh]_?[еe]_?[дdg]_?[оo]_?',    #недо
                
'[пp]_?[еe]_?[рr]_?[еe]_?',      #пере
                
'[oо]_?[дdg]_?[нnh]_?[оo]_?',    #одно
                
'[кk]_?[oо]_?[нnh]_?[оo]_?',     #коно    (коноебиться)
                
'[мm]_?[уy]_?[дdg]_?[oоaа]_?',   #муд[оа] (мудаёб)
                
'[oо]_?[сc]_?[тt]_?[оo]_?',      #осто    (остопиздело)
                
'[дdg]_?[уy]_?[рpr]_?[оoаa]_?',  #дур[оа]
                
'[хx]_?[уy]_?[дdg]_?[оoаa]_?',   #худ[оа] (худоебина)
                #5
                
'[мm]_?[нnh]_?[оo]_?[гg]_?[оo]_?',    #много
                
'[мm]_?[оo]_?[рpr]_?[дdg]_?[оoаa]_?'#морд[оа]
                
'[мm]_?[оo]_?[зz3]_?[гg]_?[оoаa]_?',  #мозг[оа]
                
'[дdg]_?[оo]_?[лl]_?[бb6]_?[оoаa]_?'#долб[оа]
                
'[оo]_?[сc]_?[тt]_?[рpr]_?[оo]_?',    #остро
            
);
            
$badwords = array(
                
#Слово на букву Х
                
'(?<=PL) %RE_PRETEXT%?
                      [hхx]_?[уyu]_?[ийiеeёяюju]     #хуй, хуя, хую, хуем, хуёвый, охуительный
                      #исключения:
                      (?<! _hue(?=_)     #HUE     -- цветовая палитра
                         | _hue(?=so_)   #hueso   -- испанское слово
                         | _хуе(?=дин)   #Хуедин  -- город в Румынии
                         | _hyu(?=ndai_) #Hyundai -- марка корейского автомобиля
                      )'
,
                
#Слово на букву П
                
'(?<=PL) %RE_PRETEXT%?
                      [пp]_?[иieеё]_?[зz3]_?[дd](?=_?[:vowel:])'
,  #п[ие]зда, пизде, пиздёж, пизду, пиздюлина, пиздобол, опиздинеть, пиздых, подпёздывать
                #Слово на букву Е
                
'(?<=PL) %RE_PRETEXT%?
                      [eеё]_?
                            #исключения
                            (?<!н[eе][её]_|т_е_)    #неё, т.е. большие
                      [бb6]_? (?= [уyиi]_                       #ебу, еби
                                | [ыиiоoaаеeёуy]_?[:consonant:] #ебут, ебать, ебись, ебёт, поеботина, выебываться, ёбарь
                                   #исключения
                                  (?<!_ebo[kt](?=_)|буд)        #ebook, eboot, ее будут
                                | [лl](?:[оoаaыиiя]|ya)         #ебло, ебла, ебливая, еблись, еблысь, ёбля
                                | [нn]_?[уy]                    #ёбнул, ёбнутый
                                | [кk]_?[аa]                    #взъёбка
                                | [сc]_?[тt]                    #ебсти
                               )'
,
                
#Слово на букву Е (c обязательной приставкой от 2-х и более букв!)
                
'(?<=PL) %RE_PRETEXT%
                      (?<= pLpL|pL_pL_)
                      [eеё]_?[бb6]    #долбоёб, дураёб, изъёб, заёб, заебай, разъебай, мудоёбы
            '
,
                
#Слово на букву Е
                
'(?<=PL) ёб (?=PL)',  #ёб твою мать
                #Слово на букву Б
                
'(?<=PL) %RE_PRETEXT%?
                      [бb6]_?[лl]_?(?:я|ya)(?: _         #бля
                                             | _?[тдtd]  #блять, бляди
                                           )'
,
                
#ПИДОР
                
'(?<=PL) [пp]_?[иieе]_?[дdg]_?[eеaаoо]_?[rpр]',  #п[ие]д[оеа]р
                #МУДАК
                
'(?<=PL) [мm]_?[уy]_?[дdg]_?[аa]  #мудак, мудачок
                      #исключения:
                      (?<!_myda(?=s_))  #Chelonia mydas -- морская зеленая (суповая) черепаха
            '
,
                
#ЖОПА
                
'(?<=PL) [zж]_?h?_?[оo]_?[pп]_?[aаyуыiеeoо]',  #жоп[ауыео]
                #МАНДА
                #исключения: город Мандалай, округ Мандаль, индейский народ Мандан, фамилия Мандель, мандарин
                
'(?<=PL) [мm]_?[аa]_?[нnh]_?[дdg]_?[aаyуыiеeoо]  #манд[ауыео]
                      #исключения:
                      (?<! манда(?=[лн]|рин)
                         | manda(?=[ln]|rin)
                         | манде(?=ль)
                      )'
,
                
#ГОВНО
                
'(?<=PL) [гg]_?[оo]_?[вvb]_?[нnh]_?[оoаaяеeyу]',  #говн[оаяеу]
                #FUCK
                
'(?<=PL) f_?u_?[cс]_?k',  #fuck, fucking
                /*
                #ЛОХ
                ' л_?[оo]_?[хx]',
                #СУКА
                '[^р]_?[scс]_?[yуu]_?[kк]_?[aаiи]', #сука (кроме слова "барсука" - это животное-грызун)
                '[^р]_?[scс]_?[yуu]_?[4ч]_?[кk]',   #сучк(и) (кроме слова "барсучка")
                #ХЕР
                ' %RE_PRETEXT%?[хxh]_?[еe]_?[рpr](_?[нnh]_?(я|ya)| )', #%RE_PRETEXT%хер(ня)
                #ЗАЛУПА
                ' [зz3]_?[аa]_?[лl]_?[уy]_?[пp]_?[аa]',
                */
            
);
            
$trans = array(
                
'_'             => 'x20',                       #пробел
                
'pL'           => '[^x20d]',                  #буква
                
'PL'           => '[x20d]',                   #не буква
                
'[:vowel:]'     => '[аеиоуыэюяёaeioyu]',         #гласные буквы
                
'[:consonant:]' => '[^аеиоуыэюяёaeioyux20d]',  #согласные буквы
            
);
            
$re_badwords str_replace(
                
'%RE_PRETEXT%',
                
'(?:' implode('|'$pretext) . ')',  #однократный шаблон с альтернативами использовать нельзя!
                
'~' implode('|'$badwords) . '~sxuSX'
            
);
            
$re_badwords strtr($re_badwords$trans);
        }
        
$s       UTF8::convert_from($s,       $charset);
        
$replace UTF8::convert_from($replace$charset);
        
$ss $s;  #saves original string
        
if ($is_html)
        {
            
#скрипты не вырезаем, т.к. м.б. обходной маневр на с кодом на javascript:
            #<script>document.write('сло'+'во')</script>
            #хотя давать пользователю возможность использовать код на javascript нехорошо
            
$s is_callable(array('HTML''strip_tags')) ? HTML::strip_tags($snulltrue, array('comment''style''map''frameset''object''applet'))
                                                          : 
strip_tags($s);
            
#заменяем html-сущности в "чистый" UTF-8
            
$s UTF8::html_entity_decode($s$is_htmlspecialchars true);
        }
        if (
strtoupper(substr($charset03)) === 'UTF')  #UTF-8, UTF-16, UTF-32
        
{
            
#remove combining diactrical marks
            
$additional_chars = array(
                
"xc2xad",  #"мягкие" переносы строк (&shy;)
            
);
            
$s UTF8::diactrical_remove($s$additional_chars);
        }
        
#ВотБ/яПидорыОхуелиБлятьНахуйПохуйПи3децПолный
        
if (version_compare(PHP_VERSION'5.2.0''>='))
        {
            
$s preg_replace('~     [p{Lu}3] (?>p{Ll}+|/\\|[@36]+)++   #Вот
                                 (?= [p{Lu}3] (?:p{Ll} |/\\|[@36] ) )   #Бля
                               ~sxuSX'
'$0 '$s);
        }
        
$s UTF8::lowercase($s);
        
#получаем в массив только буквы и цифры
        #"с_л@о#во,сxc2xa7лово.Слово" -> "с л о во с лово слово слово слово слово"
        
preg_match_all('~(?> xd0[xb0-xbf]|xd1[x80-x8fx91]  #[а-я]
                          |  /\\     #л
                          |  @         #а
                          |  [a-zd]+
                          )+
                        ~sxSX'
$s$m);
        
$s ' ' implode(' '$m[0]) . ' ';
        
$trans = array(
            
'/\' => 'л',  #Б/ЯТЬ --> БЛЯТЬ
            '
@'   => 'а',  #пизд@  --> пизда
        );
        $s = strtr($s, $trans);
        #цифровые подделки под буквы
        $trans = array(
            '
~ []++ [3зx20]*+ ~sxuSX' => 'з',
            '
~ []++ [6бx20]*+ ~sxuSX' => 'б',
        );
        $s = preg_replace(array_keys($trans), array_values($trans), $s);
        #убираем все повторяющиеся символы, ловим обман типа "х-у-у-й"
        #"сллоооовоо   слово  х у у й" --> "слово слово х у й"
        $s = preg_replace('
/(  [xd0xd1][x80-xbfx20?  #optimized [а-я]
                             
| [a-zdx20?
                             ) \
1+
                           /
sxSX', '$1', $s);
        if ($replace === null || version_compare(PHP_VERSION, '
5.2.0', '<'))
        {
            $result = preg_match($re_badwords, $s, $m, PREG_OFFSET_CAPTURE);
            if (function_exists('
preg_last_error') && preg_last_error() !== PREG_NO_ERROR) return preg_last_error();
            if ($result === false) return 1;  #PREG_INTERNAL_ERROR = 1
            if ($result && $replace === null)
            {
                list($word, $offset) = $m[0];
                $s1 = substr($s, 0, $offset);
                $s2 = substr($s, $offset + strlen($word));
                $delta = intval($delta);
                if ($delta === 0) $fragment = '
[' . trim($word) . ']';
                else
                {
                    if ($delta < 1 || $delta > 10) $delta = 3;
                    preg_match('
/  (?> x20 (?>[xd0xd1][x80-xbf]|[a-zd]+)++ ){1,' . $delta . '}+
                                   x20?+
                                $/sxSX', $s1, $m1);
                    preg_match('/^ (?>[xd0xd1][x80-xbf]|[a-zd]+)*+  #ending
                                   x20?+
                                   (?> (?>[xd0xd1][x80-xbf]|[a-zd]+)++ x20 ){0,' . $delta . '}+
                                /sxSX', $s2, $m2);
                    $fragment = (ltrim(@$m1[0]) !== ltrim($s1) ? $continue : '') .
                        trim((isset($m1[0]) ? $m1[0] : '') . '[' . trim($word) . ']' . (isset($m2[0]) ? $m2[0] : '')) .
                        (rtrim(@$m2[0]) !== rtrim($s2) ? $continue : '');
                }
                return UTF8::convert_to($fragment, $charset);
            }
            return false;
        }
        $result = preg_match_all($re_badwords, $s, $m);
        if (function_exists('preg_last_error') && preg_last_error() !== PREG_NO_ERROR) return preg_last_error();
        if ($result === false) return 1;  #PREG_INTERNAL_ERROR = 1
        if ($result > 0)
        {
            #d($s, $m[0]);
            $s = $ss;
            #замена матного фрагмента на $replace
            foreach ($m[0] as $w)
            {
                $re_w = '~' . preg_replace_callback('~(?:/\\|[^x20])~suSX', array('self', '_make_regexp_callback'), $w) . '~sxuiSX';
                $ss = preg_replace($re_w, $replace, $ss);
                #d($re_w);
            }
            while ($ss !== $s) $ss = self::parse($s = $ss, $delta, $continue, $is_html, $replace, 'UTF-8');
        }
        return UTF8::convert_to($ss, $charset);
    }
    private static function _make_regexp_callback(array $m)
    {
        #$re_holes = '[x00-x20-_*~.'"^=`:]';
        #$re_holes = '[x00-x2fx3a-x40x5b-x60x7b-x7f]';
        $re_holes = '(?!/\\)[^p{L}d]';  #non letter, non digit, non '/'
        if ($m[0] === 'а')     $re = '[@аА]++           (?>[:holes:]|[@аА]+)*+';
        elseif ($m[0] === 'з') $re = '[3зЗ]++           (?>[:holes:]|[3зЗ]+)*+';
        elseif ($m[0] === 'б') $re = '[6бБ]++           (?>[:holes:]|[6бБ]+)*+';
        elseif ($m[0] === 'л') $re = '(?>[лЛ]+|/\\)++ (?>[:holes:]|[лЛ]+|/\\)*+';
        else
        {
            #в PCRE-7.2 флаг /i в комбинации с /u в регулярном выражении почему-то не работает (BUG?)
            #поэтому делаем класс символов с буквами в обоих регистрах
            $char = '[' . preg_quote($m[0] . UTF8::uppercase($m[0]), '~') . ']';
            $re = str_replace('$0', $char, '$0++ (?>[:holes:]|$0+)*+');
        }
        return str_replace('[:holes:]', $re_holes, $re . "rn");
    }
}
Онлайн: 0
Реклама