Вход Регистрация
Файл: outs/jevix/jevix.class.php
Строк: 487
<?php

class Jevix
{
    const 
PRINTABLE = 0x1;
    const 
ALPHA = 0x2;
    const 
LAT = 0x4;
    const 
RUS = 0x8;
    const 
NUMERIC = 0x10;
    const 
SPACE = 0x20;
    const 
NAME = 0x40;
    const 
URL = 0x100;
    const 
NOPRINT = 0x200;
    const 
PUNCTUATUON = 0x400;
    const 
HTML_QUOTE = 0x2000;
    const 
TAG_QUOTE = 0x4000;
    const 
QUOTE_CLOSE = 0x8000;
    const 
NL = 0x10000;
    const 
QUOTE_OPEN = 0;
    const 
STATE_TEXT = 0;
    const 
STATE_TAG_PARAMS = 1;
    const 
STATE_TAG_PARAM_VALUE = 2;
    const 
STATE_INSIDE_TAG = 3;
    const 
STATE_INSIDE_NOTEXT_TAG = 4;
    const 
STATE_INSIDE_PREFORMATTED_TAG = 5;

    public 
$blackListMode = false;
    public 
$commonTagParamRules = array();
    public 
$tagsRules = array();
    public 
$entities1 = array();
    public 
$entities2 = array();
    public 
$dash = " — ";
    public 
$apostrof = "’";
    public 
$dotes = "…";
    public 
$nl = "rn";
    public 
$mediaSrcValidate = false;
    public 
$mediaValidSrc = array();
    public 
$forceShortTags = array('br', 'img', 'input', 'hr', 'link');
    protected 
$text;
    protected 
$textBuf;
    protected 
$textLen = 0;
    protected 
$curPos;
    protected 
$curCh;
    protected 
$curChOrd;
    protected 
$curChClass;
    protected 
$curParentTag;
    protected 
$states;
    protected 
$quotesOpened = 0;
    protected 
$brAdded = 0;
    protected 
$state;
    protected 
$tagsStack;
    protected 
$openedTag;
    protected 
$isXHTMLMode = false;
    protected 
$noTypoMode = true;
    public 
$isAutoLinkMode = false;
    public 
$outBuffer = '';
    public 
$errors;

    const 
TR_TAG_LIST = 1;
    const 
TR_PARAM_ALLOWED = 2;
    const 
TR_PARAM_REQUIRED = 3;
    const 
TR_TAG_SHORT = 4;
    const 
TR_TAG_CUT = 5;
    const 
TR_TAG_CHILD = 6;
    const 
TR_TAG_CONTAINER = 7;
    const 
TR_TAG_CHILD_TAGS = 8;
    const 
TR_TAG_PARENT = 9;
    const 
TR_TAG_PREFORMATTED = 10;
    const 
TR_PARAM_AUTO_ADD = 11;
    const 
TR_TAG_NO_TYPOGRAPHY = 12;
    const 
TR_TAG_IS_EMPTY = 13;
    const 
TR_TAG_NO_AUTO_BR = 14;

    protected 
$chClasses = array(0 => 512, 1 => 512, 2 => 512, 3 => 512, 4 => 512, 5 => 512, 6 => 512, 7 => 512, 8 => 512, 9 => 32, 10 => 66048, 11 => 512, 12 => 512, 13 => 66048, 14 => 512, 15 => 512, 16 => 512, 17 => 512, 18 => 512, 19 => 512, 20 => 512, 21 => 512, 22 => 512, 23 => 512, 24 => 512, 25 => 512, 26 => 512, 27 => 512, 28 => 512, 29 => 512, 30 => 512, 31 => 512, 32 => 32, 97 => 71, 98 => 71, 99 => 71, 100 => 71, 101 => 71, 102 => 71, 103 => 71, 104 => 71, 105 => 71, 106 => 71, 107 => 71, 108 => 71, 109 => 71, 110 => 71, 111 => 71, 112 => 71, 113 => 71, 114 => 71, 115 => 71, 116 => 71, 117 => 71, 118 => 71, 119 => 71, 120 => 71, 121 => 71, 122 => 71, 65 => 71, 66 => 71, 67 => 71, 68 => 71, 69 => 71, 70 => 71, 71 => 71, 72 => 71, 73 => 71, 74 => 71, 75 => 71, 76 => 71, 77 => 71, 78 => 71, 79 => 71, 80 => 71, 81 => 71, 82 => 71, 83 => 71, 84 => 71, 85 => 71, 86 => 71, 87 => 71, 88 => 71, 89 => 71, 90 => 71, 1072 => 11, 1073 => 11, 1074 => 11, 1075 => 11, 1076 => 11, 1077 => 11, 1078 => 11, 1079 => 11, 1080 => 11, 1081 => 11, 1082 => 11, 1083 => 11, 1084 => 11, 1085 => 11, 1086 => 11, 1087 => 11, 1088 => 11, 1089 => 11, 1090 => 11, 1091 => 11, 1092 => 11, 1093 => 11, 1094 => 11, 1095 => 11, 1096 => 11, 1097 => 11, 1098 => 11, 1099 => 11, 1100 => 11, 1101 => 11, 1102 => 11, 1103 => 11, 1040 => 11, 1041 => 11, 1042 => 11, 1043 => 11, 1044 => 11, 1045 => 11, 1046 => 11, 1047 => 11, 1048 => 11, 1049 => 11, 1050 => 11, 1051 => 11, 1052 => 11, 1053 => 11, 1054 => 11, 1055 => 11, 1056 => 11, 1057 => 11, 1058 => 11, 1059 => 11, 1060 => 11, 1061 => 11, 1062 => 11, 1063 => 11, 1064 => 11, 1065 => 11, 1066 => 11, 1067 => 11, 1068 => 11, 1069 => 11, 1070 => 11, 1071 => 11, 48 => 337, 49 => 337, 50 => 337, 51 => 337, 52 => 337, 53 => 337, 54 => 337, 55 => 337, 56 => 337, 57 => 337, 34 => 57345, 39 => 16385, 46 => 1281, 44 => 1025, 33 => 1025, 63 => 1281, 58 => 1025, 59 => 1281, 1105 => 11, 1025 => 11, 47 => 257, 38 => 257, 37 => 257, 45 => 257, 95 => 257, 61 => 257, 43 => 257, 35 => 257, 124 => 257,);

    protected function &
strToArray( $str )
    {
        
$chars = null;
        
preg_match_all('/./su', $str, $chars);
        return 
$chars[0];
    }

    function 
parse( $text )
    {
        
$this->curPos = -1;
        
$this->curCh = null;
        
$this->curChOrd = 0;
        
$this->state = self::STATE_TEXT;
        
$this->states = array();
        
$this->quotesOpened = 0;
        
$this->noTypoMode = false;
        
$this->text = $text;
        
$this->textBuf = $this->strToArray($this->text);
        
$this->textLen = count($this->textBuf);
        
$this->getCh();
        
$content = '';
        
$this->outBuffer = '';
        
$this->brAdded = 0;
        
$this->tagsStack = array();
        
$this->openedTag = null;
        
$this->errors = array();

        
$this->skipSpaces();

        
$this->anyThing($content);

        if ( 
mb_strstr($content, '<!--') && (mb_substr_count($content, '<!--') > mb_substr_count($content, '-->')) )
        {
            
$content .= '-->';
        }

        return 
$content;
    }

    protected function 
getCh()
    {
        return 
$this->goToPosition($this->curPos + 1);
    }

    protected function 
goToPosition( $position )
    {
        
$this->curPos = $position;
        if ( 
$this->curPos < $this->textLen )
        {
            
$this->curCh = $this->textBuf[$this->curPos];
            
$this->curChOrd = uniord($this->curCh);
            
$this->curChClass = $this->getCharClass($this->curChOrd);
        }
        else
        {
            
$this->curCh = null;
            
$this->curChOrd = 0;
            
$this->curChClass = 0;
        }
        return 
$this->curCh;
    }

    protected function 
saveState()
    {
        
$state = array(
            
'pos' => $this->curPos,
            
'ch' => $this->curCh,
            
'ord' => $this->curChOrd,
            
'class' => $this->curChClass,
        );

        
$this->states[] = $state;
        return 
count($this->states) - 1;
    }

    protected function 
restoreState( $index = null )
    {
        if ( !
count($this->states) )
        {
            throw new 
Exception('The end of stack');
        }

        if ( 
$index == null )
        {
            
$state = array_pop($this->states);
        }
        else
        {
            if ( !isset(
$this->states[$index]) )
            {
                throw new 
Exception('Invalid stack index');
            }
            
$state = $this->states[$index];
            
$this->states = array_slice($this->states, 0, $index);
        }

        
$this->curPos = $state['pos'];
        
$this->curCh = $state['ch'];
        
$this->curChOrd = $state['ord'];
        
$this->curChClass = $state['class'];
    }

    protected function 
matchCh( $ch, $skipSpaces = false )
    {
        if ( 
$this->curCh == $ch )
        {
            
$this->getCh();
            if ( 
$skipSpaces )
            {
                
$this->skipSpaces();
            }
            return 
true;
        }

        return 
false;
    }

    protected function 
matchChClass( $chClass, $skipSpaces = false )
    {
        if ( (
$this->curChClass & $chClass) == $chClass )
        {
            
$ch = $this->curCh;
            
$this->getCh();
            if ( 
$skipSpaces )
            {
                
$this->skipSpaces();
            }
            return 
$ch;
        }

        return 
false;
    }

    protected function 
matchStr( $str, $skipSpaces = false )
    {
        
$this->saveState();
        
$len = mb_strlen($str, 'UTF-8');
        
$test = '';
        while ( 
$len-- && $this->curChClass )
        {
            
$test.=$this->curCh;
            
$this->getCh();
        }

        if ( 
$test == $str )
        {
            if ( 
$skipSpaces )
            {
                
$this->skipSpaces();
            }
            return 
true;
        }
        else
        {
            
$this->restoreState();
            return 
false;
        }
    }

    protected function 
skipUntilCh( $ch )
    {
        
$chPos = mb_strpos($this->text, $ch, $this->curPos, 'UTF-8');
        if ( 
$chPos )
        {
            return 
$this->goToPosition($chPos);
        }
        else
        {
            return 
false;
        }
    }

    protected function 
skipUntilStr( $str )
    {
        
$str = $this->strToArray($str);
        
$firstCh = $str[0];
        
$len = count($str);
        while ( 
$this->curChClass )
        {
            if ( 
$this->curCh == $firstCh )
            {
                
$this->saveState();
                
$this->getCh();
                
$strOK = true;
                for ( 
$i = 1; $i < $len; $i++ )
                {
                    if ( !
$this->curChClass )
                    {
                        return 
false;
                    }

                    if ( 
$this->curCh != $str[$i] )
                    {
                        
$strOK = false;
                        break;
                    }

                    
$this->getCh();
                }

                if ( !
$strOK )
                {
                    
$this->restoreState();
                }
                else
                {
                    return 
true;
                }
            }

            
$this->getCh();
        }
        return 
false;
    }

    protected function 
getCharClass( $ord )
    {
        return isset(
$this->chClasses[$ord]) ? $this->chClasses[$ord] : self::PRINTABLE;
    }

    protected function 
skipSpaces( &$count = 0 )
    {
        while ( 
$this->curChClass == self::SPACE )
        {
            
$this->getCh();
            
$count++;
        }
        return 
$count > 0;
    }

    protected function 
name( &$name = '', $minus = false )
    {
        
$this->skipNL();

        if ( (
$this->curChClass & self::LAT) == self::LAT )
        {
            
$name.=$this->curCh;
            
$this->getCh();
        }
        else
        {
            return 
false;
        }

        while ( ((
$this->curChClass & self::NAME) == self::NAME || ($minus && !in_array($this->curCh, array(' ', '=', '>')) ) ) )
        {
            
$name.=$this->curCh;
            
$this->getCh();
        }

        
$this->skipSpaces();
        return 
true;
    }

    protected function 
tag( &$tag, &$params, &$content, &$short )
    {
        
$this->saveState();
        
$params = array();
        
$tag = '';
        
$closeTag = '';
        
$params = array();
        
$short = false;

        if ( !
$this->tagOpen($tag, $params, $short) )
        {
            return 
false;
        }

        if ( 
$short )
        {
            return 
true;
        }

        
$oldState = $this->state;
        
$oldNoTypoMode = $this->noTypoMode;

        if ( !empty(
$this->tagsRules[$tag][self::TR_TAG_PREFORMATTED]) )
        {
            
$this->state = self::STATE_INSIDE_PREFORMATTED_TAG;
        }
        elseif ( !empty(
$this->tagsRules[$tag][self::TR_TAG_CONTAINER]) )
        {
            
$this->state = self::STATE_INSIDE_NOTEXT_TAG;
        }
        elseif ( !empty(
$this->tagsRules[$tag][self::TR_TAG_NO_TYPOGRAPHY]) )
        {
            
$this->noTypoMode = true;
            
$this->state = self::STATE_INSIDE_TAG;
        }
        else
        {
            
$this->state = self::STATE_INSIDE_TAG;
        }

        
array_push($this->tagsStack, $tag);
        
$this->openedTag = $tag;
        
$content = '';
        if ( 
$this->state == self::STATE_INSIDE_PREFORMATTED_TAG )
        {
            
$this->preformatted($content, $tag);
        }
        else
        {
            
$this->anyThing($content, $tag);
        }

        
array_pop($this->tagsStack);
        
$this->openedTag = !empty($this->tagsStack) ? array_pop($this->tagsStack) : null;

        
$isTagClose = $this->tagClose($closeTag);
        if ( 
$isTagClose && ($tag != $closeTag) )
        {
            
$this->error("Invalid tag close $closeTag. > expected $tag");
        }

        
$this->state = $oldState;
        
$this->noTypoMode = $oldNoTypoMode;

        return 
true;
    }

    protected function 
preformatted( &$content = '', $insideTag = null )
    {
        while ( 
$this->curChClass )
        {
            if ( 
$this->curCh == '<' )
            {
                
$tag = '';
                
$this->saveState();

                
$isClosedTag = $this->tagClose($tag);

                if ( 
$isClosedTag )
                {
                    
$this->restoreState();
                }

                if ( 
$isClosedTag && $tag == $insideTag )
                {
                    return;
                }
            }
            
$content.= isset($this->entities2[$this->curCh]) ? $this->entities2[$this->curCh] : $this->curCh;
            
$this->getCh();
        }
    }

    protected function 
tagOpen( &$name, &$params, &$short = false )
    {
        
$restore = $this->saveState();

        if ( !
$this->matchCh('<') )
        {
            return 
false;
        }
        
$this->skipSpaces();
        if ( !
$this->name($name) )
        {
            
$this->restoreState();
            return 
false;
        }
        
$name = mb_strtolower($name, 'UTF-8');

        if ( 
$this->curCh != '>' && $this->curCh != '/' )
        {
            
$this->tagParams($params);
        }

        
$short = ( /* $this->curCh == '/' && */ in_array($name, $this->forceShortTags) && !empty($this->tagsRules[$name][self::TR_TAG_SHORT]) );

        
$slash = $this->matchCh('/');

        if ( !
$short && $slash && empty($this->tagsRules[$name][self::TR_TAG_SHORT]) )
        {
            
$this->restoreState();
            return 
false;
        }

        if ( 
$slash )
        {
            
$short = true;
        }

        
$this->skipSpaces();

        if ( !
$this->matchCh('>') )
        {
            
$this->restoreState($restore);
            return 
false;
        }

        
$this->skipSpaces();
        return 
true;
    }

    protected function 
tagParams( &$params = array() )
    {
        
$name = null;
        
$value = null;
        while ( 
$this->tagParam($name, $value) )
        {
            
$params[$name] = $value;
            
$name = '';
            
$value = '';
        }
        return 
count($params) > 0;
    }

    protected function 
tagParam( &$name, &$value )
    {
        
$this->saveState();
        if ( !
$this->name($name, true) )
        {
            return 
false;
        }

        if ( !
$this->matchCh('=', true) )
        {
            if ( (
$this->curCh == '>' || ($this->curChClass & self::LAT) == self::LAT ) )
            {
                
$value = $name;
                return 
true;
            }
            else
            {
                
$this->restoreState();
                return 
false;
            }
        }

        
$quote = $this->matchChClass(self::TAG_QUOTE, true);

        if ( !
$this->tagParamValue($value, $quote) )
        {
            
$this->restoreState();
            return 
false;
        }

        if ( 
$quote && !$this->matchCh($quote, true) )
        {
            
$this->restoreState();
            return 
false;
        }

        
$this->skipSpaces();
        return 
true;
    }

    protected function 
tagParamValue( &$value, $quote )
    {
        if ( 
$quote !== false )
        {
            
$escape = false;
            while ( 
$this->curChClass && ($this->curCh != $quote || $escape) )
            {
                
$escape = false;

                
$value.=isset($this->entities1[$this->curCh]) ? $this->entities1[$this->curCh] : $this->curCh;

                if ( 
$this->curCh == '\' )
                {
                    $escape = true;
                }
                $this->getCh();
            }
        }
        else
        {
            while ( $this->curChClass && !($this->curChClass & self::SPACE) && $this->curCh != '
>' )
            {
                $value.=isset($this->entities1[$this->curCh]) ? $this->entities1[$this->curCh] : $this->curCh;
                $this->getCh();
            }
        }

        return true;
    }

    protected function tagClose( &$name )
    {
        $this->saveState();
        if ( !$this->matchCh('
<') )
        {
            return false;
        }
        $this->skipSpaces();
        if ( !$this->matchCh('
/') )
        {
            $this->restoreState();
            return false;
        }
        $this->skipSpaces();
        if ( !$this->name($name) )
        {
            $this->restoreState();
            return false;
        }
        $name = mb_strtolower($name, '
UTF-8');
        $this->skipSpaces();
        if ( !$this->matchCh('
>') )
        {
            $this->restoreState();
            return false;
        }
        return true;
    }

    protected function makeTag( $tag, $params, $content, $short, $parentTag = null )
    {
        $this->curParentTag = $parentTag;

        $tag = mb_strtolower($tag, '
UTF-8');

        $tagRules = isset($this->tagsRules[$tag]) ? $this->tagsRules[$tag] : null;

        $parentTagIsContainer = $parentTag && isset($this->tagsRules[$parentTag][self::TR_TAG_CONTAINER]);

        if ( ( $this->blackListMode && !empty($tagRules[self::TR_TAG_LIST]) ) || (!$this->blackListMode && empty($tagRules[self::TR_TAG_LIST]) ) )
        {
            return !empty($this->tagsRules[$tag][self::TR_TAG_CUT]) ? '' : $content;
        }

        if ( (!$this->blackListMode && !$tagRules ) || (!$this->blackListMode && empty($tagRules[self::TR_TAG_LIST])) || ( $this->blackListMode && !empty($tagRules[self::TR_TAG_LIST]) ) )
        {
            return $parentTagIsContainer ? '' : $content;
        }

// hardcoded black list
        if ( in_array($tag, array('
meta', 'title', 'html', 'body', 'head')) )
        {
            return '';
        }
// params processing
        $resParams = array();

        foreach ( $params as $param => $value )
        {
            $param = mb_strtolower($param, '
UTF-8');
            $value = trim($value);

// custom iframe processing
            if ( $this->mediaSrcValidate && in_array($tag, array('
iframe', 'object', 'embed', 'param')) && in_array($param, array('src')) )
            {
                $val = $value;

                if ( mb_substr($val, 0, 2) == '
//' )
                
{
                    
$val = 'http:' . $val;
                }

                
$urlArr = parse_url($val);

                
$parts = explode('.', $urlArr['host']);

                if ( 
count($parts) < 2 )
                {
                    return 
'';
                }

                
$d1 = array_pop($parts);
                
$d2 = array_pop($parts);

                
$host = $d2 . '.' . $d1;

                if ( !
in_array($host, $this->mediaValidSrc) && !in_array($urlArr['host'], $this->mediaValidSrc) )
                {
                    return 
'';
                }
            }

// if value is empty ignore param
//            if ( empty($value) )
//            {
//                continue;
//            }

            
if ( $this->blackListMode )
            {
                if ( 
in_array('*', $this->commonTagParamRules) || !empty($tagRules[self::TR_PARAM_ALLOWED]['*']) || isset($tagRules[self::TR_PARAM_ALLOWED][$param]) || in_array($param, $this->commonTagParamRules) )
                {
                    continue;
                }
            }
            else
            {
                if ( !
in_array('*', $this->commonTagParamRules) && empty($tagRules[self::TR_PARAM_ALLOWED]['*']) && !isset($tagRules[self::TR_PARAM_ALLOWED][$param]) && !in_array($param, $this->commonTagParamRules) )
                {
                    continue;
                }
            }

            
$resParams[$param] = $value;
        }

        
$text = '<' . $tag;

        foreach ( 
$resParams as $param => $value )
        {
            
$text.=' ' . $param . '="' . $value . '"';
        }

        
$text.= $short ? ' />' : '>';

        if ( isset(
$tagRules[self::TR_TAG_CONTAINER]) )
        {
            
$text .= "rn";
        }
        if ( !
$short )
        {
            
$text.= $content . '</' . $tag . '>';
        }
        if ( 
$parentTagIsContainer )
        {
            
$text .= "rn";
        }
        if ( 
$tag == 'br' )
        {
            
$text.="rn";
        }

        return 
$text;
    }

    protected function 
comment()
    {
        return 
false;
        if ( !
$this->matchStr('<!--') )
        {
            return 
false;
        }
        return 
$this->skipUntilStr('-->');
    }

    protected function 
anyThing( &$content = '', $parentTag = null )
    {
        
$this->skipNL();

        while ( 
$this->curChClass )
        {
            
$tag = '';
            
$params = null;
            
$text = null;
            
$shortTag = false;
            
$name = null;

            if ( 
$this->state == self::STATE_INSIDE_NOTEXT_TAG && $this->curCh != '<' )
            {
                
$this->skipUntilCh('<');
            }

            if ( 
$this->curCh == '<' && $this->tag($tag, $params, $text, $shortTag) )
            {
                
$tagText = $this->makeTag($tag, $params, $text, $shortTag, $parentTag);

                
$content.=$tagText;

                if ( 
$tag == 'br' )
                {
                    
$this->skipNL();
                }
                elseif ( empty(
$tagText) )
                {
                    
$this->skipSpaces();
                }
            }
            elseif ( 
$this->curCh == '<' && $this->comment() )
            {
                continue;
            }
            elseif ( 
$this->curCh == '<' )
            {
                
$this->saveState();
                if ( 
$this->tagClose($name) )
                {
                    if ( 
$this->state == self::STATE_INSIDE_TAG || $this->state == self::STATE_INSIDE_NOTEXT_TAG )
                    {
                        
$this->restoreState();
                        return 
false;
                    }
                    else
                    {
                        
$this->error('Unexpectedly closed tag `>` ' . $name);
                    }
                }
                else
                {
                    if ( 
$this->state != self::STATE_INSIDE_NOTEXT_TAG )
                    {
                        
$content.= '<'; //$this->entities2['<'];
                    
}
                    
$this->getCh();
                }
            }
            elseif ( 
$this->text($text) )
            {
                
$content.=$text;
            }
        }

//        $content = str_replace(array('<!--', '-->'), array('##lc##', '##lc##'), $content);
//        $content = str_replace(array('<', '>'), array('&lt;', '&gt;'), $content);
//        $content = str_replace(array('##lc##', '##lc##'), array('<!--', '-->'), $content);

        
return true;
    }

    protected function 
skipNL( &$count = 0 )
    {
        if ( !(
$this->curChClass & self::NL) )
        {
            return 
false;
        }

        
$count++;
        
$firstNL = $this->curCh;
        
$nl = $this->getCh();

        while ( 
$this->curChClass & self::NL )
        {

            if ( 
$nl == $firstNL )
            {
                
$count++;
            }
            
$nl = $this->getCh();

            
$this->skipSpaces();
        }
        return 
true;
    }

    protected function 
text( &$text )
    {
        
$text = '';
        
$dash = '';
        
$newLine = true;
        
$newWord = true;
        
$url = null;
        
$href = null;

        while ( (
$this->curCh != '<') && $this->curChClass )
        {
            
$brCount = 0;
            
$spCount = 0;
            
$quote = null;
            
$closed = false;
            
$punctuation = null;
            
$entity = null;

            
$this->skipSpaces($spCount);

            if ( 
$spCount > 0 )
            {
                
$text.=' ';
                
$newWord = true;
            }
            elseif ( 
$this->skipNL($brCount) )
            {
                if ( 
$this->curParentTag && isset($this->tagsRules[$this->curParentTag]) && isset($this->tagsRules[$this->curParentTag][self::TR_TAG_NO_AUTO_BR]) && (is_null($this->openedTag) or isset($this->tagsRules[$this->openedTag][self::TR_TAG_NO_AUTO_BR]))
                )
                {
                    
                }
                else
                {
                    
$text.= str_repeat("rn", $brCount);
                }

                
$newLine = true;
                
$newWord = true;
            }
            elseif ( 
$this->isAutoLinkMode && ($this->curChClass & self::LAT) && $this->openedTag != 'a' && $this->url($url, $href) )
            {
                
$linkLabel = $url;

                if ( 
strlen($linkLabel) > 60 )
                {
                    
$arr = parse_url($linkLabel);

                    
$domain = (!empty($arr['scheme']) ? $arr['scheme'] . '://' : '' ) . (!empty($arr['host']) ? $arr['host'] : '' ) . (!empty($arr['port']) ? ':' . $arr['port'] : '' ) . '/';
                    
$qs = (!empty($arr['path']) ? $arr['path'] : '' ) . (!empty($arr['query']) ? '?' . $arr['query'] : '' );

                    if ( 
strlen($qs) > 23 )
                    {
                        
$qs = '...' . substr($qs, -20);
                    }

                    
$linkLabel = $domain . $qs;
                }


                
$text.= $this->makeTag('a', array('href' => $href, 'class' => 'peep_autolink', 'target' => '_blank', 'rel' => 'nofollow'), $linkLabel, false);
                
$newWord = true;
            }
            elseif ( 
$this->curChClass & self::PRINTABLE )
            {
                
$text.=isset($this->entities2[$this->curCh]) ? $this->entities2[$this->curCh] : $this->curCh;
                
$this->getCh();
                
$newWord = false;
                
$newLine = false;
            }
            else
            {
                
$this->getCh();
            }
        }

        
$this->skipSpaces();
        return 
$text != '';
    }

    
// fake function to optimize url function
    
private function simpleMatchString( $string )
    {
        
$count = mb_strlen($string);
        for ( 
$i = 0; $i < $count; $i++ )
        {
            if ( !isset(
$this->textBuf[$this->curPos + $i]) || $this->textBuf[$this->curPos + $i] !== mb_substr($string, $i, 1) )
            {
                return 
false;
            }
        }
        return 
true;
    }

    protected function 
url( &$url, &$href )
    {
        
$hrefPrefix = null;

        if ( !empty(
$this->curPos) && $this->getCharClass(uniord($this->textBuf[$this->curPos - 1])) === self::PRINTABLE )
        {
            return 
false;
        }

        if ( 
$this->curCh === 'h' )
        {
            if ( 
$this->simpleMatchString('http://') )
            {
                
$hrefPrefix = 'http://';
                
$this->goToPosition($this->curPos + 7);
            }
            else if ( 
$this->simpleMatchString('https://') )
            {
                
$hrefPrefix = 'https://';
                
$this->goToPosition($this->curPos + 8);
            }
        }
        else if ( 
$this->curCh === 'w' )
        {
            if ( 
$this->simpleMatchString('www.') )
            {
                
$hrefPrefix = 'http://www.';
                
$urlPrefix = 'www.';
                
$this->goToPosition($this->curPos + 4);
            }
        }

        if ( 
$hrefPrefix === null )
        {
            return 
false;
        }

        
$this->saveState();
        
$url = '';
        
$urlChMask = self::URL | self::ALPHA;
        
$urlPunctValidChars = array(":", ",", "!", "'", "~", ".", ";");
        
        while ( 
$this->curChClass & $urlChMask || in_array($this->curCh, $urlPunctValidChars) )
        {            
            
$url.= $this->curCh;
            
$this->getCh();
        }
        
        
$chCount = 0;        
        
        for( 
$i = (mb_strlen($url) - 1); $i >= 0; $i-- )
        {
            if( 
in_array(mb_substr($url, $i, 1), $urlPunctValidChars) )
            {
                
$chCount++;
            }
            else
            {
                break;
            }
        }
        
        if( 
$chCount > 0 )
        {
            
$url = mb_substr($url, 0, mb_strlen($url) - $chCount);
            
$this->goToPosition($this->curPos-$chCount);
        }       
        
        if( 
mb_strlen($url) == 0 )
        {
            return 
false;
        }
        
        if ( !
mb_strlen($url) )
        {
            
$this->restoreState();
            return 
false;
        }

        
$href = $hrefPrefix . $url;
        
$url = !empty($urlPrefix) ? $urlPrefix . $url : $href;
        return 
true;
    }

    protected function 
error( $message )
    {
        
$str = '';
        
$strEnd = min($this->curPos + 8, $this->textLen);
        for ( 
$i = $this->curPos; $i < $strEnd; $i++ )
        {
            
$str.=$this->textBuf[$i];
        }

        
$this->errors[] = array(
            
'message' => $message,
            
'pos' => $this->curPos,
            
'ch' => $this->curCh,
            
'line' => 0,
            
'str' => $str,
        );
    }
}

function 
uniord( $c )
{
    
$h = ord($c{0});
    if ( 
$h <= 0x7F )
    {
        return 
$h;
    }
    else if ( 
$h < 0xC2 )
    {
        return 
false;
    }
    else if ( 
$h <= 0xDF )
    {
        return (
$h & 0x1F) << 6 | (ord($c{1}) & 0x3F);
    }
    else if ( 
$h <= 0xEF )
    {
        return (
$h & 0x0F) << 12 | (ord($c{1}) & 0x3F) << 6 | (ord($c{2}) & 0x3F);
    }
    else if ( 
$h <= 0xF4 )
    {
        return (
$h & 0x0F) << 18 | (ord($c{1}) & 0x3F) << 12 | (ord($c{2}) & 0x3F) << 6 | (ord($c{3}) & 0x3F);
    }
    else
    {
        return 
false;
    }
}
Онлайн: 0
Реклама