Server IP : 180.180.241.3 / Your IP : 216.73.216.252 Web Server : Microsoft-IIS/7.5 System : Windows NT NETWORK-NHRC 6.1 build 7601 (Windows Server 2008 R2 Standard Edition Service Pack 1) i586 User : IUSR ( 0) PHP Version : 5.3.28 Disable Function : NONE MySQL : ON | cURL : ON | WGET : OFF | Perl : OFF | Python : OFF | Sudo : OFF | Pkexec : OFF Directory : C:/AppServ/www/app/webroot/news/administrator/components/com_jfusion/models/parsers/ |
Upload File : |
<?php /** * nbbc parser * * PHP version 5 * * @category JFusion * @package Models * @author Phantom Inker <webmaster@jfusion.org> * @copyright 2008 Phantom Inker. All rights reserved. * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL * @link http://www.jfusion.org */ /* This is a compressed copy of NBBC. Do not edit! Copyright (c) 2008-9, the Phantom Inker. All rights reserved. Portions Copyright (c) 2004-2008 AddedBytes.com Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE PHANTOM INKER "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ define("BBCODE_VERSION", "1.4.5"); define("BBCODE_RELEASE", "2010-09-17"); define("BBCODE_VERBATIM", 2); define("BBCODE_REQUIRED", 1); define("BBCODE_OPTIONAL", 0); define("BBCODE_PROHIBIT", -1); define("BBCODE_CHECK", 1); define("BBCODE_OUTPUT", 2); define("BBCODE_ENDTAG", 5); define("BBCODE_TAG", 4); define("BBCODE_TEXT", 3); define("BBCODE_NL", 2); define("BBCODE_WS", 1); define("BBCODE_EOI", 0); define("BBCODE_LEXSTATE_TEXT", 0); define("BBCODE_LEXSTATE_TAG", 1); define("BBCODE_MODE_SIMPLE", 0); define("BBCODE_MODE_CALLBACK", 1); define("BBCODE_MODE_INTERNAL", 2); define("BBCODE_MODE_LIBRARY", 3); define("BBCODE_MODE_ENHANCED", 4); define("BBCODE_STACK_TOKEN", 0); define("BBCODE_STACK_TEXT", 1); define("BBCODE_STACK_TAG", 2); define("BBCODE_STACK_CLASS", 3); if (!function_exists('str_split')) { /** * @param $string * @param int $split_length * @return array */ function str_split($string, $split_length = 1) { $array = explode("\r\n", chunk_split($string, $split_length)); array_pop($array); return $array; } } $BBCode_SourceDir = dirname(__FILE__); /** * */ class BBCodeLexer { var $token; var $text; var $tag; var $state; var $input; var $ptr; var $unget; var $verbatim; var $debug; var $tagmarker; var $end_tagmarker; var $pat_main; var $pat_comment; var $pat_comment2; var $pat_wiki; /** * @param $string * @param string $tagmarker */ function BBCodeLexer($string, $tagmarker = '[') { $regex_beginmarkers = Array('[' => '\[', '<' => '<', '{' => '\{', '(' => '\('); $regex_endmarkers = Array('[' => '\]', '<' => '>', '{' => '\}', '(' => '\)'); $endmarkers = Array('[' => ']', '<' => '>', '{' => '}', '(' => ')'); if (!isset($regex_endmarkers[$tagmarker])) $tagmarker = '['; $e = $regex_endmarkers[$tagmarker]; $b = $regex_beginmarkers[$tagmarker]; $this->tagmarker = $tagmarker; $this->end_tagmarker = $endmarkers[$tagmarker]; $this->pat_main = "/( " . "{$b}" . "(?! -- | ' | !-- | {$b}{$b} )" . "(?: [^\\n\\r{$b}{$e}] | \\\" [^\\\"\\n\\r]* \\\" | \\' [^\\'\\n\\r]* \\' )*" . "{$e}" . "| {$b}{$b} (?: [^{$e}\\r\\n] | {$e}[^{$e}\\r\\n] )* {$e}{$e}" . "| {$b} (?: -- | ' ) (?: [^{$e}\\n\\r]* ) {$e}" . "| {$b}!-- (?: [^-] | -[^-] | --[^{$e}] )* --{$e}" . "| -----+" . "| \\x0D\\x0A | \\x0A\\x0D | \\x0D | \\x0A" . "| [\\x00-\\x09\\x0B-\\x0C\\x0E-\\x20]+(?=[\\x0D\\x0A{$b}]|-----|$)" . "| (?<=[\\x0D\\x0A{$e}]|-----|^)[\\x00-\\x09\\x0B-\\x0C\\x0E-\\x20]+" . " )/Dx"; $this->input = preg_split($this->pat_main, $string, -1, PREG_SPLIT_DELIM_CAPTURE); $this->pat_comment = "/^ {$b} (?: -- | ' ) /Dx"; $this->pat_comment2 = "/^ {$b}!-- (?: [^-] | -[^-] | --[^{$e}] )* --{$e} $/Dx"; $this->pat_wiki = "/^ {$b}{$b} ([^\\|]*) (?:\\|(.*))? {$e}{$e} $/Dx"; $this->ptr = 0; $this->unget = false; $this->state = BBCODE_LEXSTATE_TEXT; $this->verbatim = false; $this->token = BBCODE_EOI; $this->tag = false; $this->text = ''; } /** * @return int */ function GuessTextLength() { $length = 0; $ptr = 0; $state = BBCODE_LEXSTATE_TEXT; while ($ptr < count($this->input)) { $text = $this->input[$ptr++]; if ($state == BBCODE_LEXSTATE_TEXT) { $state = BBCODE_LEXSTATE_TAG; $length+= strlen($text); } else { switch (ord(substr($this->text, 0, 1))) { case 10: case 13: $state = BBCODE_LEXSTATE_TEXT; $length++; break; default: $state = BBCODE_LEXSTATE_TEXT; $length+= strlen($text); break; case 40: case 60: case 91: case 123: $state = BBCODE_LEXSTATE_TEXT; break; } } } return $length; } /** * @return bool|int */ function NextToken() { if ($this->unget) { $this->unget = false; return $this->token; } while (true) { if ($this->ptr >= count($this->input)) { $this->text = ''; $this->tag = false; return $this->token = BBCODE_EOI; } $this->text = preg_replace("/[\\x00-\\x08\\x0B-\\x0C\\x0E-\\x1F]/", "", $this->input[$this->ptr++]); if ($this->verbatim) { $this->tag = false; if ($this->state == BBCODE_LEXSTATE_TEXT) { $this->state = BBCODE_LEXSTATE_TAG; $token_type = BBCODE_TEXT; } else { $this->state = BBCODE_LEXSTATE_TEXT; switch (ord(substr($this->text, 0, 1))) { case 10: case 13: $token_type = BBCODE_NL; break; default: $token_type = BBCODE_WS; break; case 45: case 40: case 60: case 91: case 123: $token_type = BBCODE_TEXT; break; } } if (strlen($this->text) > 0) return $this->token = $token_type; } else if ($this->state == BBCODE_LEXSTATE_TEXT) { $this->state = BBCODE_LEXSTATE_TAG; $this->tag = false; if (strlen($this->text) > 0) return $this->token = BBCODE_TEXT; } else { switch (ord(substr($this->text, 0, 1))) { case 10: case 13: $this->tag = false; $this->state = BBCODE_LEXSTATE_TEXT; return $this->token = BBCODE_NL; case 45: if (preg_match("/^-----/", $this->text)) { $this->tag = Array('_name' => 'rule', '_endtag' => false, '_default' => ''); $this->state = BBCODE_LEXSTATE_TEXT; return $this->token = BBCODE_TAG; } else { $this->tag = false; $this->state = BBCODE_LEXSTATE_TEXT; if (strlen($this->text) > 0) return $this->token = BBCODE_TEXT; continue; } default: $this->tag = false; $this->state = BBCODE_LEXSTATE_TEXT; return $this->token = BBCODE_WS; case 40: case 60: case 91: case 123: if (preg_match($this->pat_comment, $this->text)) { $this->state = BBCODE_LEXSTATE_TEXT; continue; } if (preg_match($this->pat_comment2, $this->text)) { $this->state = BBCODE_LEXSTATE_TEXT; continue; } if (preg_match($this->pat_wiki, $this->text, $matches)) { $this->tag = Array('_name' => 'wiki', '_endtag' => false, '_default' => @$matches[1], 'title' => @$matches[2]); $this->state = BBCODE_LEXSTATE_TEXT; return $this->token = BBCODE_TAG; } $this->tag = $this->Internal_DecodeTag($this->text); $this->state = BBCODE_LEXSTATE_TEXT; return $this->token = ($this->tag['_end'] ? BBCODE_ENDTAG : BBCODE_TAG); } } } return false; } function UngetToken() { if ($this->token !== BBCODE_EOI) $this->unget = true; } /** * @return bool|int */ function PeekToken() { $result = $this->NextToken(); if ($this->token !== BBCODE_EOI) $this->unget = true; return $result; } /** * @return array */ function SaveState() { return Array('token' => $this->token, 'text' => $this->text, 'tag' => $this->tag, 'state' => $this->state, 'input' => $this->input, 'ptr' => $this->ptr, 'unget' => $this->unget, 'verbatim' => $this->verbatim); } /** * @param $state * @return mixed */ function RestoreState($state) { if (!is_array($state)) return; $this->token = @$state['token']; $this->text = @$state['text']; $this->tag = @$state['tag']; $this->state = @$state['state']; $this->input = @$state['input']; $this->ptr = @$state['ptr']; $this->unget = @$state['unget']; $this->verbatim = @$state['verbatim']; } /** * @param $string * @return mixed */ function Internal_StripQuotes($string) { if (preg_match("/^\\\"(.*)\\\"$/", $string, $matches)) return $matches[1]; else if (preg_match("/^\\'(.*)\\'$/", $string, $matches)) return $matches[1]; else return $string; } /** * @param $ptr * @param $pieces * @return int|string */ function Internal_ClassifyPiece($ptr, $pieces) { if ($ptr >= count($pieces)) return -1; $piece = $pieces[$ptr]; if ($piece == '=') return '='; else if (preg_match("/^[\\'\\\"]/", $piece)) return '"'; else if (preg_match("/^[\\x00-\\x20]+$/", $piece)) return ' '; else return 'A'; } /** * @param $tag * @return array */ function Internal_DecodeTag($tag) { $result = Array('_tag' => $tag, '_endtag' => '', '_name' => '', '_hasend' => false, '_end' => false, '_default' => false); $tag = substr($tag, 1, strlen($tag) - 2); $ch = ord(substr($tag, 0, 1)); if ($ch >= 0 && $ch <= 32) return $result; $pieces = preg_split("/(\\\"[^\\\"]+\\\"|\\'[^\\']+\\'|=|[\\x00-\\x20]+)/", $tag, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); $ptr = 0; if (count($pieces) < 1) return $result; if (@substr($pieces[$ptr], 0, 1) == '/') { $result['_name'] = strtolower(substr($pieces[$ptr++], 1)); $result['_end'] = true; } else { $result['_name'] = strtolower($pieces[$ptr++]); $result['_end'] = false; } while (($type = $this->Internal_ClassifyPiece($ptr, $pieces)) == ' ') $ptr++; $params = Array(); if ($type != '=') { $result['_default'] = false; $params[] = Array('key' => '', 'value' => ''); } else { $ptr++; while (($type = $this->Internal_ClassifyPiece($ptr, $pieces)) == ' ') $ptr++; if ($type == "\"") $value = $this->Internal_StripQuotes($pieces[$ptr++]); else { $after_space = false; $start = $ptr; while (($type = $this->Internal_ClassifyPiece($ptr, $pieces)) != - 1) { if ($type == ' ') $after_space = true; if ($type == '=' && $after_space) break; $ptr++; } if ($type == - 1) $ptr--; if ($type == '=') { $ptr--; while ($ptr > $start && $this->Internal_ClassifyPiece($ptr, $pieces) == ' ') $ptr--; while ($ptr > $start && $this->Internal_ClassifyPiece($ptr, $pieces) != ' ') $ptr--; } $value = ''; for (;$start <= $ptr;$start++) { if ($this->Internal_ClassifyPiece($start, $pieces) == ' ') $value.= " "; else $value.= $this->Internal_StripQuotes($pieces[$start]); } $value = trim($value); $ptr++; } $result['_default'] = $value; $params[] = Array('key' => '', 'value' => $value); } /** * @ignore * @var $key string */ while (($type = $this->Internal_ClassifyPiece($ptr, $pieces)) != - 1) { while ($type == ' ') { $ptr++; $type = $this->Internal_ClassifyPiece($ptr, $pieces); } if ($type == 'A' || $type == '"') $key = strtolower($this->Internal_StripQuotes(@$pieces[$ptr++])); else if ($type == '=') { $ptr++; continue; } else if ($type == - 1) break; while (($type = $this->Internal_ClassifyPiece($ptr, $pieces)) == ' ') $ptr++; if ($type != '=') $value = $this->Internal_StripQuotes($key); else { $ptr++; while (($type = $this->Internal_ClassifyPiece($ptr, $pieces)) == ' ') $ptr++; if ($type == '"') { $value = $this->Internal_StripQuotes($pieces[$ptr++]); } else if ($type != - 1) { $value = $pieces[$ptr++]; while (($type = $this->Internal_ClassifyPiece($ptr, $pieces)) != - 1 && $type != ' ') $value.= $pieces[$ptr++]; } else $value = ''; } if (substr($key, 0, 1) != '_') $result[$key] = $value; $params[] = Array('key' => $key, 'value' => $value); } $result['_params'] = $params; return $result; } } /** * */ class BBCodeLibrary { var $default_smileys = Array(':)' => 'smile.gif', ':-)' => 'smile.gif', '=-)' => 'smile.gif', ':(' => 'frown.gif', ':-(' => 'frown.gif', '=(' => 'frown.gif', '=-(' => 'frown.gif', ':D' => 'bigsmile.gif', ':-D' => 'bigsmile.gif', '=D' => 'bigsmile.gif', '=-D' => 'bigsmile.gif', '>:(' => 'angry.gif', '>:-(' => 'angry.gif', '>=(' => 'angry.gif', '>=-(' => 'angry.gif', 'D:' => 'angry.gif', 'D-:' => 'angry.gif', 'D=' => 'angry.gif', 'D-=' => 'angry.gif', '>:)' => 'evil.gif', '>:-)' => 'evil.gif', '>=)' => 'evil.gif', '>=-)' => 'evil.gif', '>:D' => 'evil.gif', '>:-D' => 'evil.gif', '>=D' => 'evil.gif', '>=-D' => 'evil.gif', '>;)' => 'sneaky.gif', '>;-)' => 'sneaky.gif', '>;D' => 'sneaky.gif', '>;-D' => 'sneaky.gif', 'O:)' => 'saint.gif', 'O:-)' => 'saint.gif', 'O=)' => 'saint.gif', 'O=-)' => 'saint.gif', ':O' => 'surprise.gif', ':-O' => 'surprise.gif', '=O' => 'surprise.gif', '=-O' => 'surprise.gif', ':?' => 'confuse.gif', ':-?' => 'confuse.gif', '=?' => 'confuse.gif', '=-?' => 'confuse.gif', ':s' => 'worry.gif', ':-S' => 'worry.gif', '=s' => 'worry.gif', '=-S' => 'worry.gif', ':|' => 'neutral.gif', ':-|' => 'neutral.gif', '=|' => 'neutral.gif', '=-|' => 'neutral.gif', ':I' => 'neutral.gif', ':-I' => 'neutral.gif', '=I' => 'neutral.gif', '=-I' => 'neutral.gif', ':/' => 'irritated.gif', ':-/' => 'irritated.gif', '=/' => 'irritated.gif', '=-/' => 'irritated.gif', ':\\' => 'irritated.gif', ':-\\' => 'irritated.gif', '=\\' => 'irritated.gif', '=-\\' => 'irritated.gif', ':P' => 'tongue.gif', ':-P' => 'tongue.gif', '=P' => 'tongue.gif', '=-P' => 'tongue.gif', 'X-P' => 'tongue.gif', '8)' => 'bigeyes.gif', '8-)' => 'bigeyes.gif', 'B)' => 'cool.gif', 'B-)' => 'cool.gif', ';)' => 'wink.gif', ';-)' => 'wink.gif', ';D' => 'bigwink.gif', ';-D' => 'bigwink.gif', '^_^' => 'anime.gif', '^^;' => 'sweatdrop.gif', '>_>' => 'lookright.gif', '>.>' => 'lookright.gif', '<_<' => 'lookleft.gif', '<.<' => 'lookleft.gif', 'XD' => 'laugh.gif', 'X-D' => 'laugh.gif', ':3' => 'smile3.gif', ':-3' => 'smile3.gif', '=3' => 'smile3.gif', '=-3' => 'smile3.gif', ';3' => 'wink3.gif', ';-3' => 'wink3.gif', '<g>' => 'teeth.gif', '<G>' => 'teeth.gif', 'o.O' => 'boggle.gif', 'O.o' => 'boggle.gif', ':blue:' => 'blue.gif', ':zzz:' => 'sleepy.gif', '<3' => 'heart.gif', ':star:' => 'star.gif',); var $default_tag_rules = Array('b' => Array('simple_start' => "<b>", 'simple_end' => "</b>", 'class' => 'inline', 'allow_in' => Array('listitem', 'block', 'columns', 'inline', 'link'), 'plain_start' => "<b>", 'plain_end' => "</b>",), 'i' => Array('simple_start' => "<i>", 'simple_end' => "</i>", 'class' => 'inline', 'allow_in' => Array('listitem', 'block', 'columns', 'inline', 'link'), 'plain_start' => "<i>", 'plain_end' => "</i>",), 'u' => Array('simple_start' => "<u>", 'simple_end' => "</u>", 'class' => 'inline', 'allow_in' => Array('listitem', 'block', 'columns', 'inline', 'link'), 'plain_start' => "<u>", 'plain_end' => "</u>",), 's' => Array('simple_start' => "<strike>", 'simple_end' => "</strike>", 'class' => 'inline', 'allow_in' => Array('listitem', 'block', 'columns', 'inline', 'link'), 'plain_start' => "<i>", 'plain_end' => "</i>",), 'font' => Array('mode' => BBCODE_MODE_LIBRARY, 'allow' => Array('_default' => '/^[a-zA-Z0-9._ -]+$/'), 'method' => 'DoFont', 'class' => 'inline', 'allow_in' => Array('listitem', 'block', 'columns', 'inline', 'link'),), 'color' => Array('mode' => BBCODE_MODE_ENHANCED, 'allow' => Array('_default' => '/^#?[a-zA-Z0-9._ -]+$/'), 'template' => '<span style="color:{$_default/tw}">{$_content/v}</span>', 'class' => 'inline', 'allow_in' => Array('listitem', 'block', 'columns', 'inline', 'link'),), 'size' => Array('mode' => BBCODE_MODE_LIBRARY, 'allow' => Array('_default' => '/^[0-9.]+$/D'), 'method' => 'DoSize', 'class' => 'inline', 'allow_in' => Array('listitem', 'block', 'columns', 'inline', 'link'),), 'sup' => Array('simple_start' => "<sup>", 'simple_end' => "</sup>", 'class' => 'inline', 'allow_in' => Array('listitem', 'block', 'columns', 'inline', 'link'),), 'sub' => Array('simple_start' => "<sub>", 'simple_end' => "</sub>", 'class' => 'inline', 'allow_in' => Array('listitem', 'block', 'columns', 'inline', 'link'),), 'spoiler' => Array('simple_start' => "<span class=\"bbcode_spoiler\">", 'simple_end' => "</span>", 'class' => 'inline', 'allow_in' => Array('listitem', 'block', 'columns', 'inline', 'link'),), 'acronym' => Array('mode' => BBCODE_MODE_ENHANCED, 'template' => '<span class="bbcode_acronym" title="{$_default/e}">{$_content/v}</span>', 'class' => 'inline', 'allow_in' => Array('listitem', 'block', 'columns', 'inline', 'link'),), 'url' => Array('mode' => BBCODE_MODE_LIBRARY, 'method' => 'DoURL', 'class' => 'link', 'allow_in' => Array('listitem', 'block', 'columns', 'inline'), 'content' => BBCODE_REQUIRED, 'plain_start' => "<a href=\"{\$link}\">", 'plain_end' => "</a>", 'plain_content' => Array('_content', '_default'), 'plain_link' => Array('_default', '_content'),), 'email' => Array('mode' => BBCODE_MODE_LIBRARY, 'method' => 'DoEmail', 'class' => 'link', 'allow_in' => Array('listitem', 'block', 'columns', 'inline'), 'content' => BBCODE_REQUIRED, 'plain_start' => "<a href=\"mailto:{\$link}\">", 'plain_end' => "</a>", 'plain_content' => Array('_content', '_default'), 'plain_link' => Array('_default', '_content'),), 'wiki' => Array('mode' => BBCODE_MODE_LIBRARY, 'method' => "DoWiki", 'class' => 'link', 'allow_in' => Array('listitem', 'block', 'columns', 'inline'), 'end_tag' => BBCODE_PROHIBIT, 'content' => BBCODE_PROHIBIT, 'plain_start' => "<b>[", 'plain_end' => "]</b>", 'plain_content' => Array('title', '_default'), 'plain_link' => Array('_default', '_content'),), 'img' => Array('mode' => BBCODE_MODE_LIBRARY, 'method' => "DoImage", 'class' => 'image', 'allow_in' => Array('listitem', 'block', 'columns', 'inline', 'link'), 'end_tag' => BBCODE_REQUIRED, 'content' => BBCODE_REQUIRED, 'plain_start' => "[image]", 'plain_content' => Array(),), 'rule' => Array('mode' => BBCODE_MODE_LIBRARY, 'method' => "DoRule", 'class' => 'block', 'allow_in' => Array('listitem', 'block', 'columns'), 'end_tag' => BBCODE_PROHIBIT, 'content' => BBCODE_PROHIBIT, 'before_tag' => "sns", 'after_tag' => "sns", 'plain_start' => "\n-----\n", 'plain_end' => "", 'plain_content' => Array(),), 'br' => Array('mode' => BBCODE_MODE_SIMPLE, 'simple_start' => "<br />\n", 'simple_end' => "", 'class' => 'inline', 'allow_in' => Array('listitem', 'block', 'columns', 'inline', 'link'), 'end_tag' => BBCODE_PROHIBIT, 'content' => BBCODE_PROHIBIT, 'before_tag' => "s", 'after_tag' => "s", 'plain_start' => "\n", 'plain_end' => "", 'plain_content' => Array(),), 'left' => Array('simple_start' => "\n<div class=\"bbcode_left\" style=\"text-align:left\">\n", 'simple_end' => "\n</div>\n", 'allow_in' => Array('listitem', 'block', 'columns'), 'before_tag' => "sns", 'after_tag' => "sns", 'before_endtag' => "sns", 'after_endtag' => "sns", 'plain_start' => "\n", 'plain_end' => "\n",), 'right' => Array('simple_start' => "\n<div class=\"bbcode_right\" style=\"text-align:right\">\n", 'simple_end' => "\n</div>\n", 'allow_in' => Array('listitem', 'block', 'columns'), 'before_tag' => "sns", 'after_tag' => "sns", 'before_endtag' => "sns", 'after_endtag' => "sns", 'plain_start' => "\n", 'plain_end' => "\n",), 'center' => Array('simple_start' => "\n<div class=\"bbcode_center\" style=\"text-align:center\">\n", 'simple_end' => "\n</div>\n", 'allow_in' => Array('listitem', 'block', 'columns'), 'before_tag' => "sns", 'after_tag' => "sns", 'before_endtag' => "sns", 'after_endtag' => "sns", 'plain_start' => "\n", 'plain_end' => "\n",), 'indent' => Array('simple_start' => "\n<div class=\"bbcode_indent\" style=\"margin-left:4em\">\n", 'simple_end' => "\n</div>\n", 'allow_in' => Array('listitem', 'block', 'columns'), 'before_tag' => "sns", 'after_tag' => "sns", 'before_endtag' => "sns", 'after_endtag' => "sns", 'plain_start' => "\n", 'plain_end' => "\n",), 'columns' => Array('simple_start' => "\n<table class=\"bbcode_columns\"><tbody><tr><td class=\"bbcode_column bbcode_firstcolumn\">\n", 'simple_end' => "\n</td></tr></tbody></table>\n", 'class' => 'columns', 'allow_in' => Array('listitem', 'block', 'columns'), 'end_tag' => BBCODE_REQUIRED, 'content' => BBCODE_REQUIRED, 'before_tag' => "sns", 'after_tag' => "sns", 'before_endtag' => "sns", 'after_endtag' => "sns", 'plain_start' => "\n", 'plain_end' => "\n",), 'nextcol' => Array('simple_start' => "\n</td><td class=\"bbcode_column\">\n", 'class' => 'nextcol', 'allow_in' => Array('columns'), 'end_tag' => BBCODE_PROHIBIT, 'content' => BBCODE_PROHIBIT, 'before_tag' => "sns", 'after_tag' => "sns", 'before_endtag' => "sns", 'after_endtag' => "sns", 'plain_start' => "\n", 'plain_end' => "",), 'code' => Array('mode' => BBCODE_MODE_ENHANCED, 'template' => "\n<div class=\"bbcode_code\">\n<div class=\"bbcode_code_head\">Code:</div>\n<div class=\"bbcode_code_body\">{\$_content/v}</div>\n</div>\n", 'class' => 'code', 'allow_in' => Array('listitem', 'block', 'columns'), 'content' => BBCODE_VERBATIM, 'before_tag' => "sns", 'after_tag' => "sn", 'before_endtag' => "sn", 'after_endtag' => "sns", 'plain_start' => "\n<b>Code:</b>\n", 'plain_end' => "\n",), 'quote' => Array('mode' => BBCODE_MODE_LIBRARY, 'method' => "DoQuote", 'allow_in' => Array('listitem', 'block', 'columns'), 'before_tag' => "sns", 'after_tag' => "sns", 'before_endtag' => "sns", 'after_endtag' => "sns", 'plain_start' => "\n<b>Quote:</b>\n", 'plain_end' => "\n",), 'list' => Array('mode' => BBCODE_MODE_LIBRARY, 'method' => 'DoList', 'class' => 'list', 'allow_in' => Array('listitem', 'block', 'columns'), 'before_tag' => "sns", 'after_tag' => "sns", 'before_endtag' => "sns", 'after_endtag' => "sns", 'plain_start' => "\n", 'plain_end' => "\n",), '*' => Array('simple_start' => "<li>", 'simple_end' => "</li>\n", 'class' => 'listitem', 'allow_in' => Array('list'), 'end_tag' => BBCODE_OPTIONAL, 'before_tag' => "s", 'after_tag' => "s", 'before_endtag' => "sns", 'after_endtag' => "sns", 'plain_start' => "\n * ", 'plain_end' => "\n",),); /** * @param BBCode_Parser $bbcode * @param $action * @param $name * @param $default * @param $params * @param $content * @return bool|string */ function DoURL($bbcode, $action, $name, $default, $params, $content) { if ($action == BBCODE_CHECK) return true; $url = is_string($default) ? $default : $bbcode->UnHTMLEncode(strip_tags($content)); if ($bbcode->IsValidURL($url)) { if ($bbcode->debug) print "ISVALIDURL<br />"; if ($bbcode->url_targetable !== false && isset($params['target'])) $target = " target=\"" . $bbcode->nbbchtmlspecialchars($params['target']) . "\""; else $target = ''; if ($bbcode->url_target !== false) if (!($bbcode->url_targetable == 'override' && isset($params['target']))) $target = " target=\"" . $bbcode->nbbchtmlspecialchars($bbcode->url_target) . "\""; return '<a href="' . $bbcode->nbbchtmlspecialchars($url) . '" class="bbcode_url"' . $target . '>' . $content . '</a>'; } else return $bbcode->nbbchtmlspecialchars($params['_tag']) . $content . $bbcode->nbbchtmlspecialchars($params['_endtag']); } /** * @param BBCode_Parser $bbcode * @param $action * @param $name * @param $default * @param $params * @param $content * @return bool|string */ function DoEmail($bbcode, $action, $name, $default, $params, $content) { if ($action == BBCODE_CHECK) return true; $email = is_string($default) ? $default : $bbcode->UnHTMLEncode(strip_tags($content)); if ($bbcode->IsValidEmail($email)) return '<a href="mailto:' . $bbcode->nbbchtmlspecialchars($email) . '" class="bbcode_email">' . $content . '</a>'; else return $bbcode->nbbchtmlspecialchars($params['_tag']) . $content . $bbcode->nbbchtmlspecialchars($params['_endtag']); } /** * @param $bbcode * @param $action * @param $name * @param $default * @param $params * @param $content * @return string */ function DoSize($bbcode, $action, $name, $default, $params, $content) { switch ($default) { case '0': $size = '.5em'; break; case '1': $size = '.67em'; break; case '2': $size = '.83em'; break; default: case '3': $size = '1.0em'; break; case '4': $size = '1.17em'; break; case '5': $size = '1.5em'; break; case '6': $size = '2.0em'; break; case '7': $size = '2.5em'; break; } return "<span style=\"font-size:$size\">$content</span>"; } /** * @param $bbcode * @param $action * @param $name * @param $default * @param $params * @param $content * @return string */ function DoFont($bbcode, $action, $name, $default, $params, $content) { $fonts = explode(",", $default); $result = ''; $special_fonts = Array('serif' => 'serif', 'sans-serif' => 'sans-serif', 'sans serif' => 'sans-serif', 'sansserif' => 'sans-serif', 'sans' => 'sans-serif', 'cursive' => 'cursive', 'fantasy' => 'fantasy', 'monospace' => 'monospace', 'mono' => 'monospace',); foreach($fonts as $font) { $font = trim($font); if (isset($special_fonts[$font])) { if (strlen($result) > 0) $result.= ","; $result.= $special_fonts[$font]; } else if (strlen($font) > 0) { if (strlen($result) > 0) $result.= ","; $result.= "'$font'"; } } return "<span style=\"font-family:$result\">$content</span>"; } /** * @param BBCode_Parser $bbcode * @param $action * @param $name * @param $default * @param $params * @param $content * @return bool|string */ function DoWiki($bbcode, $action, $name, $default, $params, $content) { $name = $bbcode->Wikify($default); if ($action == BBCODE_CHECK) return strlen($name) > 0; $title = trim(@$params['title']); if (strlen($title) <= 0) $title = trim($default); return "<a href=\"{$bbcode->wiki_url}$name\" class=\"bbcode_wiki\">" . $bbcode->nbbchtmlspecialchars($title) . "</a>"; } /** * @param BBCode_Parser $bbcode * @param $action * @param $name * @param $default * @param $params * @param $content * @return bool|string */ function DoImage($bbcode, $action, $name, $default, $params, $content) { if ($action == BBCODE_CHECK) return true; $content = trim($bbcode->UnHTMLEncode(strip_tags($content))); if (preg_match("/\\.(?:gif|jpeg|jpg|jpe|png)$/", $content)) { if (preg_match("/^[a-zA-Z0-9_][^:]+$/", $content)) { if (!preg_match("/(?:\\/\\.\\.\\/)|(?:^\\.\\.\\/)|(?:^\\/)/", $content)) { $info = @getimagesize("{$bbcode->local_img_dir}/{$content}"); if ($info[2] == IMAGETYPE_GIF || $info[2] == IMAGETYPE_JPEG || $info[2] == IMAGETYPE_PNG) { return "<img src=\"" . $bbcode->nbbchtmlspecialchars("{$bbcode->local_img_url}/{$content}") . "\" alt=\"" . $bbcode->nbbchtmlspecialchars(basename($content)) . "\" width=\"" . $bbcode->nbbchtmlspecialchars($info[0]) . "\" height=\"" . $bbcode->nbbchtmlspecialchars($info[1]) . "\" class=\"bbcode_img\" />"; } } } else if ($bbcode->IsValidURL($content, false)) { return "<img src=\"" . $bbcode->nbbchtmlspecialchars($content) . "\" alt=\"" . $bbcode->nbbchtmlspecialchars(basename($content)) . "\" class=\"bbcode_img\" />"; } } return $bbcode->nbbchtmlspecialchars($params['_tag']) . $bbcode->nbbchtmlspecialchars($content) . $bbcode->nbbchtmlspecialchars($params['_endtag']); } /** * @param $bbcode * @param $action * @param $name * @param $default * @param $params * @param $content * @return bool|string */ function DoRule($bbcode, $action, $name, $default, $params, $content) { if ($action == BBCODE_CHECK) return true; else return $bbcode->rule_html; } /** * @param BBCode_Parser $bbcode * @param $action * @param $name * @param $default * @param $params * @param $content * @return bool|string */ function DoQuote($bbcode, $action, $name, $default, $params, $content) { if ($action == BBCODE_CHECK) return true; if (isset($params['name'])) { $title = $bbcode->nbbchtmlspecialchars(trim($params['name'])) . " wrote"; if (isset($params['date'])) $title.= " on " . $bbcode->nbbchtmlspecialchars(trim($params['date'])); $title.= ":"; if (isset($params['url'])) { $url = trim($params['url']); if ($bbcode->IsValidURL($url)) $title = "<a href=\"" . $bbcode->nbbchtmlspecialchars($params['url']) . "\">" . $title . "</a>"; } } else if (!is_string($default)) $title = "Quote:"; else $title = $bbcode->nbbchtmlspecialchars(trim($default)) . " wrote:"; return "\n<div class=\"bbcode_quote\">\n<div class=\"bbcode_quote_head\">" . $title . "</div>\n<div class=\"bbcode_quote_body\">" . $content . "</div>\n</div>\n"; } /** * @param $bbcode * @param $action * @param $name * @param $default * @param $params * @param $content * @return bool|string */ function DoList($bbcode, $action, $name, $default, $params, $content) { $list_styles = Array('1' => 'decimal', '01' => 'decimal-leading-zero', 'i' => 'lower-roman', 'I' => 'upper-roman', 'a' => 'lower-alpha', 'A' => 'upper-alpha',); $ci_list_styles = Array('circle' => 'circle', 'disc' => 'disc', 'square' => 'square', 'greek' => 'lower-greek', 'armenian' => 'armenian', 'georgian' => 'georgian',); $ul_types = Array('circle' => 'circle', 'disc' => 'disc', 'square' => 'square',); $default = trim($default); if ($action == BBCODE_CHECK) { if (!is_string($default) || strlen($default) == "") return true; else if (isset($list_styles[$default])) return true; else if (isset($ci_list_styles[strtolower($default) ])) return true; else return false; } $type = ''; /** * @ignore * @var $elem string */ if (!is_string($default) || strlen($default) == "") { $elem = 'ul'; $type = ''; } else if ($default == '1') { $elem = 'ol'; $type = ''; } else if (isset($list_styles[$default])) { $elem = 'ol'; $type = $list_styles[$default]; } else { $default = strtolower($default); if (isset($ul_types[$default])) { $elem = 'ul'; $type = $ul_types[$default]; } else if (isset($ci_list_styles[$default])) { $elem = 'ol'; $type = $ci_list_styles[$default]; } } if (strlen($type)) return "\n<$elem class=\"bbcode_list\" style=\"list-style-type:$type\">\n$content</$elem>\n"; else return "\n<$elem class=\"bbcode_list\">\n$content</$elem>\n"; } } /** * */ class BBCodeEmailAddressValidator { /** * @param $strEmailAddress * @return bool */ function check_email_address($strEmailAddress) { if (preg_match('/[\x00-\x1F\x7F-\xFF]/', $strEmailAddress)) { return false; } $intAtSymbol = strrpos($strEmailAddress, '@'); if ($intAtSymbol === false) { return false; } $arrEmailAddress[0] = substr($strEmailAddress, 0, $intAtSymbol); $arrEmailAddress[1] = substr($strEmailAddress, $intAtSymbol + 1); $arrTempAddress[0] = preg_replace('/"[^"]+"/', '', $arrEmailAddress[0]); $arrTempAddress[1] = $arrEmailAddress[1]; $strTempAddress = $arrTempAddress[0] . $arrTempAddress[1]; if (strrpos($strTempAddress, '@') !== false) { return false; } if (!$this->check_local_portion($arrEmailAddress[0])) { return false; } if (!$this->check_domain_portion($arrEmailAddress[1])) { return false; } return true; } /** * @param $strLocalPortion * @return bool */ function check_local_portion($strLocalPortion) { if (!$this->check_text_length($strLocalPortion, 1, 64)) { return false; } $arrLocalPortion = explode('.', $strLocalPortion); for ($i = 0, $max = sizeof($arrLocalPortion);$i < $max;$i++) { if (!preg_match('.^(' . '([A-Za-z0-9!#$%&\'*+/=?^_`{|}~-]' . '[A-Za-z0-9!#$%&\'*+/=?^_`{|}~-]{0,63})' . '|' . '("[^\\\"]{0,62}")' . ')$.', $arrLocalPortion[$i])) { return false; } } return true; } /** * @param $strDomainPortion * @return bool */ function check_domain_portion($strDomainPortion) { if (!$this->check_text_length($strDomainPortion, 1, 255)) { return false; } if (preg_match('/^(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])' . '(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}$/', $strDomainPortion) || preg_match('/^\[(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])' . '(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}\]$/', $strDomainPortion)) { return true; } else { $arrDomainPortion = explode('.', $strDomainPortion); if (sizeof($arrDomainPortion) < 2) { return false; } for ($i = 0, $max = sizeof($arrDomainPortion);$i < $max;$i++) { if (!$this->check_text_length($arrDomainPortion[$i], 1, 63)) { return false; } if (!preg_match('/^(([A-Za-z0-9][A-Za-z0-9-]{0,61}[A-Za-z0-9])|' . '([A-Za-z0-9]+))$/', $arrDomainPortion[$i])) { return false; } } } return true; } /** * @param $strText * @param $intMinimum * @param $intMaximum * @return bool */ function check_text_length($strText, $intMinimum, $intMaximum) { $intTextLength = strlen($strText); if (($intTextLength < $intMinimum) || ($intTextLength > $intMaximum)) { return false; } else { return true; } } } /** * */ class BBCode_Parser { var $tag_rules; var $defaults; var $current_class; var $root_class; var $lost_start_tags; var $start_tags; var $allow_ampersand; var $tag_marker; var $ignore_newlines; var $plain_mode; var $detect_urls; var $url_pattern; var $output_limit; var $text_length; var $was_limited; var $limit_tail; var $limit_precision; var $smiley_dir; var $smiley_url; var $smileys; var $smiley_regex; var $enable_smileys; var $wiki_url; var $local_img_dir; var $local_img_url; var $url_targetable; var $url_target; var $rule_html; var $pre_trim; var $post_trim; var $debug; var $quote_style; var $charset; var $stack; /** * @var $lexer BBCodeLexer */ var $lexer; var $smiley_info; function BBCode_Parser() { $this->defaults = new BBCodeLibrary; $this->tag_rules = $this->defaults->default_tag_rules; $this->smileys = $this->defaults->default_smileys; $this->enable_smileys = true; $this->smiley_regex = false; $this->smiley_dir = $this->GetDefaultSmileyDir(); $this->smiley_url = $this->GetDefaultSmileyURL(); $this->wiki_url = $this->GetDefaultWikiURL(); $this->local_img_dir = $this->GetDefaultLocalImgDir(); $this->local_img_url = $this->GetDefaultLocalImgURL(); $this->rule_html = $this->GetDefaultRuleHTML(); $this->pre_trim = ''; $this->post_trim = ''; $this->root_class = 'block'; $this->lost_start_tags = Array(); $this->start_tags = Array(); $this->tag_marker = '['; $this->allow_ampsersand = false; $this->current_class = $this->root_class; $this->debug = false; $this->ignore_newlines = false; $this->output_limit = 0; $this->plain_mode = false; $this->was_limited = false; $this->limit_tail = "..."; $this->limit_precision = 0.15; $this->detect_urls = false; $this->url_pattern = '<a href="{$url/h}">{$text/h}</a>'; $this->url_targetable = false; $this->url_target = false; $this->quote_style = ENT_COMPAT; $this->charset = 'UTF-8'; } /** * @param int $style */ function SetQuoteStyle($style = ENT_COMPAT) { $this->quote_style = $style; } /** * @param string $charset */ function SetCharset($charset = 'UTF-8') { $this->charset = $charset; } /** * @param string $trim */ function SetPreTrim($trim = "a") { $this->pre_trim = $trim; } /** * @return string */ function GetPreTrim() { return $this->pre_trim; } /** * @param string $trim */ function SetPostTrim($trim = "a") { $this->post_trim = $trim; } /** * @return string */ function GetPostTrim() { return $this->post_trim; } /** * @param string $class */ function SetRoot($class = 'block') { $this->root_class = $class; } function SetRootInline() { $this->root_class = 'inline'; } function SetRootBlock() { $this->root_class = 'block'; } /** * @return string */ function GetRoot() { return $this->root_class; } /** * @param bool $enable */ function SetDebug($enable = true) { $this->debug = $enable; } /** * @return bool */ function GetDebug() { return $this->debug; } /** * @param bool $enable */ function SetAllowAmpersand($enable = true) { $this->allow_ampersand = $enable; } function GetAllowAmpersand() { return $this->allow_ampersand; } /** * @param string $marker */ function SetTagMarker($marker = '[') { $this->tag_marker = $marker; } /** * @return string */ function GetTagMarker() { return $this->tag_marker; } /** * @param bool $ignore */ function SetIgnoreNewlines($ignore = true) { $this->ignore_newlines = $ignore; } /** * @return bool */ function GetIgnoreNewlines() { return $this->ignore_newlines; } /** * @param int $limit */ function SetLimit($limit = 0) { $this->output_limit = $limit; } /** * @return int */ function GetLimit() { return $this->output_limit; } /** * @param string $tail */ function SetLimitTail($tail = "...") { $this->limit_tail = $tail; } /** * @return string */ function GetLimitTail() { return $this->limit_tail; } /** * @param float $prec */ function SetLimitPrecision($prec = 0.15) { $this->limit_precision = $prec; } /** * @return float */ function GetLimitPrecision() { return $this->limit_precision; } /** * @return bool */ function WasLimited() { return $this->was_limited; } /** * @param bool $enable */ function SetPlainMode($enable = true) { $this->plain_mode = $enable; } /** * @return bool */ function GetPlainMode() { return $this->plain_mode; } /** * @param bool $enable */ function SetDetectURLs($enable = true) { $this->detect_urls = $enable; } /** * @return bool */ function GetDetectURLs() { return $this->detect_urls; } /** * @param $pattern */ function SetURLPattern($pattern) { $this->url_pattern = $pattern; } /** * @return string */ function GetURLPattern() { return $this->url_pattern; } /** * @param $enable */ function SetURLTargetable($enable) { $this->url_targetable = $enable; } /** * @return bool */ function GetURLTargetable() { return $this->url_targetable; } /** * @param $target */ function SetURLTarget($target) { $this->url_target = $target; } /** * @return bool */ function GetURLTarget() { return $this->url_target; } /** * @param $name * @param $rule */ function AddRule($name, $rule) { $this->tag_rules[$name] = $rule; } /** * @param $name */ function RemoveRule($name) { unset($this->tag_rules[$name]); } /** * @param $name * @return bool */ function GetRule($name) { return isset($this->tag_rules[$name]) ? $this->tag_rules[$name] : false; } function ClearRules() { $this->tag_rules = Array(); } /** * @param $name * @return bool */ function GetDefaultRule($name) { return isset($this->defaults->default_tag_rules[$name]) ? $this->defaults->default_tag_rules[$name] : false; } /** * @param $name */ function SetDefaultRule($name) { if (isset($this->defaults->default_tag_rules[$name])) $this->AddRule($name, $this->defaults->default_tag_rules[$name]); else $this->RemoveRule($name); } /** * @return array */ function GetDefaultRules() { return $this->defaults->default_tag_rules; } function SetDefaultRules() { $this->tag_rules = $this->defaults->default_tag_rules; } /** * @param $url */ function SetWikiURL($url) { $this->wiki_url = $url; } /** * @param $url * @return string */ function GetWikiURL($url) { return $this->wiki_url; } /** * @return string */ function GetDefaultWikiURL() { return '/?page='; } /** * @param $path */ function SetLocalImgDir($path) { $this->local_img_dir = $path; } /** * @return string */ function GetLocalImgDir() { return $this->local_img_dir; } /** * @return string */ function GetDefaultLocalImgDir() { return "img"; } /** * @param $path */ function SetLocalImgURL($path) { $this->local_img_url = $path; } /** * @return string */ function GetLocalImgURL() { return $this->local_img_url; } /** * @return string */ function GetDefaultLocalImgURL() { return "img"; } /** * @param $html */ function SetRuleHTML($html) { $this->rule_html = $html; } /** * @return string */ function GetRuleHTML() { return $this->rule_html; } /** * @return string */ function GetDefaultRuleHTML() { return "\n<hr class=\"bbcode_rule\" />\n"; } /** * @param $code * @param $image */ function AddSmiley($code, $image) { $this->smileys[$code] = $image; $this->smiley_regex = false; } /** * @param $code */ function RemoveSmiley($code) { unset($this->smileys[$code]); $this->smiley_regex = false; } /** * @param $code * @return bool */ function GetSmiley($code) { return isset($this->smileys[$code]) ? $this->smileys[$code] : false; } function ClearSmileys() { $this->smileys = Array(); $this->smiley_regex = false; } /** * @param $code * @return bool */ function GetDefaultSmiley($code) { return isset($this->defaults->default_smileys[$code]) ? $this->defaults->default_smileys[$code] : false; } /** * @param $code */ function SetDefaultSmiley($code) { $this->smileys[$code] = @$this->defaults->default_smileys[$code]; $this->smiley_regex = false; } /** * @return array */ function GetDefaultSmileys() { return $this->defaults->default_smileys; } function SetDefaultSmileys() { $this->smileys = $this->defaults->default_smileys; $this->smiley_regex = false; } /** * @param $path */ function SetSmileyDir($path) { $this->smiley_dir = $path; } /** * @return string */ function GetSmileyDir() { return $this->smiley_dir; } /** * @return string */ function GetDefaultSmileyDir() { return "smileys"; } /** * @param $path */ function SetSmileyURL($path) { $this->smiley_url = $path; } /** * @return string */ function GetSmileyURL() { return $this->smiley_url; } /** * @return string */ function GetDefaultSmileyURL() { return "smileys"; } /** * @param bool $enable */ function SetEnableSmileys($enable = true) { $this->enable_smileys = $enable; } /** * @return bool */ function GetEnableSmileys() { return $this->enable_smileys; } /** * @param $string * @return mixed */ function nl2br($string) { return preg_replace("/\\x0A|\\x0D|\\x0A\\x0D|\\x0D\\x0A/", "<br />\n", $string); } /** * @param $string * @return string */ function UnHTMLEncode($string) { if (function_exists("html_entity_decode")) return html_entity_decode($string, $this->quote_style, $this->charset); $string = preg_replace('~&#x([0-9a-f]+);~ei', 'chr(hexdec("\\1"))', $string); $string = preg_replace('~&#([0-9]+);~e', 'chr("\\1")', $string); $trans_tbl = get_html_translation_table(HTML_ENTITIES, $this->quote_style); $trans_tbl = array_flip($trans_tbl); return strtr($string, $trans_tbl); } /** * @param $string * @return string */ function Wikify($string) { return rawurlencode(str_replace(" ", "_", trim(preg_replace("/[!?;@#\$%\\^&*<>=+`~\\x00-\\x20_-]+/", " ", $string)))); } /** * @param $string * @param bool $email_too * @return bool */ function IsValidURL($string, $email_too = true) { if (preg_match("/^ (?:https?|ftp):\\/\\/ (?: (?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\\.)+ [a-zA-Z0-9] (?:[a-zA-Z0-9-]*[a-zA-Z0-9])? | \\[ (?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3} (?: 25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-zA-Z0-9-]*[a-zA-Z0-9]: (?:[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x21-\\x5A\\x53-\\x7F] |\\\\[\\x01-\\x09\\x0B\\x0C\\x0E-\\x7F])+ ) \\] ) (?::[0-9]{1,5})? (?:[\\/\\?\\#][^\\n\\r]*)? $/Dx", $string)) return true; if (preg_match("/^[^:]+([\\/\\\\?#][^\\r\\n]*)?$/D", $string)) return true; if ($email_too) if (substr($string, 0, 7) == "mailto:") return $this->IsValidEmail(substr($string, 7)); return false; } /** * @param $string * @return bool */ function IsValidEmail($string) { $validator = new BBCodeEmailAddressValidator; return $validator->check_email_address($string); /* return preg_match("/^ (?: [a-z0-9\\!\\#\\\$\\%\\&\\'\\*\\+\\/=\\?\\^_`\\{\\|\\}~-]+ (?:\.[a-z0-9\\!\\#\\\$\\%\\&\\'\\*\\+\\/=\\?\\^_`\\{\\|\\}~-]+)* | \"(?:[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x21\\x23-\\x5B\\x5D-\\x7F] |\\\\[\\x01-\\x09\\x0B\\x0C\\x0E-\\x7F])*\" ) @ (?: (?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+ [a-z0-9] (?:[a-z0-9-]*[a-z0-9])? | \\[ (?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3} (?: 25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]: (?:[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x21-\\x5A\\x53-\\x7F] |\\\\[\\x01-\\x09\\x0B\\x0C\\x0E-\\x7F])+ ) \\] ) $/Dx", $string); */ } /** * @param $string * @return mixed|string */ function HTMLEncode($string) { if (!$this->allow_ampersand) return $this->nbbchtmlspecialchars($string); else return str_replace(Array('<', '>', '"'), Array('<', '>', '"'), $string); } /** * @param $string * @return array|mixed|string */ function FixupOutput($string) { if (!$this->detect_urls) { $output = $this->Internal_ProcessSmileys($string); } else { $chunks = $this->Internal_AutoDetectURLs($string); $output = Array(); if (count($chunks)) { $is_a_url = false; foreach($chunks as $index => $chunk) { if (!$is_a_url) { $chunk = $this->Internal_ProcessSmileys($chunk); } $output[] = $chunk; $is_a_url = !$is_a_url; } } $output = implode("", $output); } return $output; } /** * @param $string * @return mixed|string */ function Internal_ProcessSmileys($string) { if (!$this->enable_smileys || $this->plain_mode) { $output = $this->HTMLEncode($string); } else { if ($this->smiley_regex === false) { $this->Internal_RebuildSmileys(); } $tokens = preg_split($this->smiley_regex, $string, -1, PREG_SPLIT_DELIM_CAPTURE); if (count($tokens) <= 1) { $output = $this->HTMLEncode($string); } else { $output = ''; $is_a_smiley = false; foreach($tokens as $token) { if (!$is_a_smiley) { $output.= $this->HTMLEncode($token); } else { if (isset($this->smiley_info[$token])) { $info = $this->smiley_info[$token]; } else { $info = @getimagesize($this->smiley_dir . '/' . $this->smileys[$token]); $this->smiley_info[$token] = $info; } $alt = $this->nbbchtmlspecialchars($token); $output.= "<img src=\"" . $this->nbbchtmlspecialchars($this->smiley_url . '/' . $this->smileys[$token]) . "\" width=\"{$info[0]}\" height=\"{$info[1]}\"" . " alt=\"$alt\" title=\"$alt\" class=\"bbcode_smiley\" />"; } $is_a_smiley = !$is_a_smiley; } } } return $output; } function Internal_RebuildSmileys() { $regex = Array("/(?<![\\w])("); $first = true; foreach($this->smileys as $code => $filename) { if (!$first) $regex[] = "|"; $regex[] = preg_quote("$code", '/'); $first = false; } $regex[] = ")(?![\\w])/"; $this->smiley_regex = implode("", $regex); } /** * @param $string * @return array */ function Internal_AutoDetectURLs($string) { $output = preg_split("/( (?: (?:https?|ftp) : \\/* (?: (?: (?: [a-zA-Z0-9-]{2,} \\. )+ (?: arpa | com | org | net | edu | gov | mil | int | [a-z]{2} | aero | biz | coop | info | museum | name | pro | example | invalid | localhost | test | local | onion | swift ) ) | (?: [0-9]{1,3} \\. [0-9]{1,3} \\. [0-9]{1,3} \\. [0-9]{1,3} ) | (?: [0-9A-Fa-f:]+ : [0-9A-Fa-f]{1,4} ) ) (?: : [0-9]+ )? (?! [a-zA-Z0-9.:-] ) (?: \\/ [^&?#\\(\\)\\[\\]\\{\\}<>\\'\\\"\\x00-\\x20\\x7F-\\xFF]* )? (?: [?#] [^\\(\\)\\[\\]\\{\\}<>\\'\\\"\\x00-\\x20\\x7F-\\xFF]+ )? ) | (?: (?: (?: (?: [a-zA-Z0-9-]{2,} \\. )+ (?: arpa | com | org | net | edu | gov | mil | int | [a-z]{2} | aero | biz | coop | info | museum | name | pro | example | invalid | localhost | test | local | onion | swift ) ) | (?: [0-9]{1,3} \\. [0-9]{1,3} \\. [0-9]{1,3} \\. [0-9]{1,3} ) ) (?: : [0-9]+ )? (?! [a-zA-Z0-9.:-] ) (?: \\/ [^&?#\\(\\)\\[\\]\\{\\}<>\\'\\\"\\x00-\\x20\\x7F-\\xFF]* )? (?: [?#] [^\\(\\)\\[\\]\\{\\}<>\\'\\\"\\x00-\\x20\\x7F-\\xFF]+ )? ) | (?: [a-zA-Z0-9._-]{2,} @ (?: (?: (?: [a-zA-Z0-9-]{2,} \\. )+ (?: arpa | com | org | net | edu | gov | mil | int | [a-z]{2} | aero | biz | coop | info | museum | name | pro | example | invalid | localhost | test | local | onion | swift ) ) | (?: [0-9]{1,3} \\. [0-9]{1,3} \\. [0-9]{1,3} \\. [0-9]{1,3} ) ) ) )/Dx", $string, -1, PREG_SPLIT_DELIM_CAPTURE); if (count($output) > 1) { $is_a_url = false; foreach($output as $index => $token) { if ($is_a_url) { if (preg_match("/^[a-zA-Z0-9._-]{2,}@/", $token)) { $url = "mailto:" . $token; } else if (preg_match("/^(https?:|ftp:)\\/*([^\\/&?#]+)\\/*(.*)\$/", $token, $matches)) { $url = $matches[1] . '/' . '/' . $matches[2] . "/" . $matches[3]; } else { preg_match("/^([^\\/&?#]+)\\/*(.*)\$/", $token, $matches); $url = "http:/" . "/" . $matches[1] . "/" . $matches[2]; } $params = @parse_url($url); if (!is_array($params)) $params = Array(); $params['url'] = $url; $params['link'] = $url; $params['text'] = $token; $output[$index] = $this->FillTemplate($this->url_pattern, $params); } $is_a_url = !$is_a_url; } } return $output; } /** * @param $template * @param $insert_array * @param array $default_array * @return string */ function FillTemplate($template, $insert_array, $default_array = Array()) { $pieces = preg_split('/(\{\$[a-zA-Z0-9_.:\/-]+\})/', $template, -1, PREG_SPLIT_DELIM_CAPTURE); if (count($pieces) <= 1) return $template; $result = Array(); $is_an_insert = false; foreach($pieces as $piece) { if (!$is_an_insert) { $result[] = $piece; } else if (!preg_match('/\{\$([a-zA-Z0-9_:-]+)((?:\\.[a-zA-Z0-9_:-]+)*)(?:\/([a-zA-Z0-9_:-]+))?\}/', $piece, $matches)) { $result[] = $piece; } else { if (isset($insert_array[$matches[1]])) $value = @$insert_array[$matches[1]]; else $value = @$default_array[$matches[1]]; if (strlen(@$matches[2])) { foreach(explode(".", substr($matches[2], 1)) as $index) { if (is_array($value)) $value = @$value[$index]; else if (is_object($value)) { $value = (array)$value; $value = @$value[$index]; } else $value = ''; } } switch (gettype($value)) { case 'boolean': $value = $value ? "true" : "false"; break; case 'integer': $value = (string)$value; break; case 'double': $value = (string)$value; break; case 'string': break; default: $value = ''; break; } if (strlen(@$matches[3])) $flags = array_flip(str_split($matches[3])); else $flags = Array(); if (!isset($flags['v'])) { if (isset($flags['w'])) $value = preg_replace("/[\\x00-\\x09\\x0B-\x0C\x0E-\\x20]+/", " ", $value); if (isset($flags['t'])) $value = trim($value); if (isset($flags['b'])) $value = basename($value); if (isset($flags['e'])) $value = $this->HTMLEncode($value); else if (isset($flags['k'])) $value = $this->Wikify($value); else if (isset($flags['h'])) $value = $this->nbbchtmlspecialchars($value); else if (isset($flags['u'])) $value = urlencode($value); if (isset($flags['n'])) $value = $this->nl2br($value); } $result[] = $value; } $is_an_insert = !$is_an_insert; } return implode("", $result); } /** * @param $array * @param int $start * @return string */ function Internal_CollectText($array, $start = 0) { ob_start(); for ($start = intval($start), $end = count($array);$start < $end;$start++) print $array[$start][BBCODE_STACK_TEXT]; $output = ob_get_contents(); ob_end_clean(); return $output; } /** * @param $array * @param int $start * @param int $end * @return string */ function Internal_CollectTextReverse($array, $start = 0, $end = 0) { ob_start(); for ($start = intval($start);$start >= $end;$start--) print $array[$start][BBCODE_STACK_TEXT]; $output = ob_get_contents(); ob_end_clean(); return $output; } /** * @param $pos * @return array */ function Internal_GenerateOutput($pos) { $output = Array(); while (count($this->stack) > $pos) { $token = array_pop($this->stack); if ($token[BBCODE_STACK_TOKEN] != BBCODE_TAG) { $output[] = $token; } else { $name = @$token[BBCODE_STACK_TAG]['_name']; $rule = @$this->tag_rules[$name]; $end_tag = @$rule['end_tag']; if (!isset($rule['end_tag'])) $end_tag = BBCODE_REQUIRED; else $end_tag = $rule['end_tag']; array_pop($this->start_tags[$name]); if ($end_tag == BBCODE_PROHIBIT) { $output[] = Array(BBCODE_STACK_TOKEN => BBCODE_TEXT, BBCODE_STACK_TAG => false, BBCODE_STACK_TEXT => $token[BBCODE_STACK_TEXT], BBCODE_STACK_CLASS => $this->current_class,); } else { if ($end_tag == BBCODE_REQUIRED) @$this->lost_start_tags[$name]+= 1; $end = $this->Internal_CleanupWSByIteratingPointer(@$rule['before_endtag'], 0, $output); $this->Internal_CleanupWSByPoppingStack(@$rule['after_tag'], $output); $tag_body = $this->Internal_CollectTextReverse($output, count($output) - 1, $end); $this->Internal_CleanupWSByPoppingStack(@$rule['before_tag'], $this->stack); $this->Internal_UpdateParamsForMissingEndTag(@$token[BBCODE_STACK_TAG]); $tag_output = $this->DoTag(BBCODE_OUTPUT, $name, @$token[BBCODE_STACK_TAG]['_default'], @$token[BBCODE_STACK_TAG], $tag_body); $output = Array(Array(BBCODE_STACK_TOKEN => BBCODE_TEXT, BBCODE_STACK_TAG => false, BBCODE_STACK_TEXT => $tag_output, BBCODE_STACK_CLASS => $this->current_class)); } } } $this->Internal_ComputeCurrentClass(); return $output; } /** * @param $class_list * @return bool */ function Internal_RewindToClass($class_list) { $pos = count($this->stack) - 1; while ($pos >= 0 && !in_array($this->stack[$pos][BBCODE_STACK_CLASS], $class_list)) $pos--; if ($pos < 0) { if (!in_array($this->root_class, $class_list)) return false; } $output = $this->Internal_GenerateOutput($pos + 1); while (count($output)) { $token = array_pop($output); $token[BBCODE_STACK_CLASS] = $this->current_class; $this->stack[] = $token; } return true; } /** * @param $tag_name * @return array|bool|string */ function Internal_FinishTag($tag_name) { if (strlen($tag_name) <= 0) return false; if (isset($this->start_tags[$tag_name]) && count($this->start_tags[$tag_name])) $pos = array_pop($this->start_tags[$tag_name]); else $pos = - 1; if ($pos < 0) return false; $newpos = $this->Internal_CleanupWSByIteratingPointer(@$this->tag_rules[$tag_name]['after_tag'], $pos + 1, $this->stack); $delta = $newpos - ($pos + 1); $output = $this->Internal_GenerateOutput($newpos); $newend = $this->Internal_CleanupWSByIteratingPointer(@$this->tag_rules[$tag_name]['before_endtag'], 0, $output); $output = $this->Internal_CollectTextReverse($output, count($output) - 1, $newend); while ($delta-- > 0) array_pop($this->stack); $this->Internal_ComputeCurrentClass(); return $output; } function Internal_ComputeCurrentClass() { if (count($this->stack) > 0) $this->current_class = $this->stack[count($this->stack) - 1][BBCODE_STACK_CLASS]; else $this->current_class = $this->root_class; } /** * @param array|bool $array * @param bool $raw * @return string */ function Internal_DumpStack($array = false, $raw = false) { if (!$raw) $string = '<span style="color: #0000CC;">'; else $string = ''; if ($array === false) $array = $this->stack; foreach($array as $item) { switch (@$item[BBCODE_STACK_TOKEN]) { case BBCODE_TEXT: $string.= "\"" . $this->nbbchtmlspecialchars(@$item[BBCODE_STACK_TEXT]) . "\" "; break; case BBCODE_WS: $string.= "WS "; break; case BBCODE_NL: $string.= "NL "; break; case BBCODE_TAG: $string.= "[" . $this->nbbchtmlspecialchars(@$item[BBCODE_STACK_TAG]['_name']) . "] "; break; default: $string.= "unknown "; break; } } if (!$raw) $string.= "</span>"; return $string; } /** * @param $pattern * @param $array * @return mixed */ function Internal_CleanupWSByPoppingStack($pattern, &$array) { if (strlen($pattern) <= 0) return; $oldlen = count($array); foreach(str_split($pattern) as $char) { switch ($char) { case 's': while (count($array) > 0 && $array[count($array) - 1][BBCODE_STACK_TOKEN] == BBCODE_WS) array_pop($array); break; case 'n': if (count($array) > 0 && $array[count($array) - 1][BBCODE_STACK_TOKEN] == BBCODE_NL) array_pop($array); break; case 'a': while (count($array) > 0 && (($token = $array[count($array) - 1][BBCODE_STACK_TOKEN]) == BBCODE_WS || $token == BBCODE_NL)) array_pop($array); break; } } if (count($array) != $oldlen) { $this->Internal_ComputeCurrentClass(); } } /** * @param $pattern * @return mixed */ function Internal_CleanupWSByEatingInput($pattern) { if (strlen($pattern) <= 0) return; foreach(str_split($pattern) as $char) { switch ($char) { case 's': $token_type = $this->lexer->NextToken(); while ($token_type == BBCODE_WS) { $token_type = $this->lexer->NextToken(); } $this->lexer->UngetToken(); break; case 'n': $token_type = $this->lexer->NextToken(); if ($token_type != BBCODE_NL) $this->lexer->UngetToken(); break; case 'a': $token_type = $this->lexer->NextToken(); while ($token_type == BBCODE_WS || $token_type == BBCODE_NL) { $token_type = $this->lexer->NextToken(); } $this->lexer->UngetToken(); break; } } } /** * @param $pattern * @param $pos * @param $array * @return mixed */ function Internal_CleanupWSByIteratingPointer($pattern, $pos, $array) { if (strlen($pattern) <= 0) return $pos; foreach(str_split($pattern) as $char) { switch ($char) { case 's': while ($pos < count($array) && $array[$pos][BBCODE_STACK_TOKEN] == BBCODE_WS) $pos++; break; case 'n': if ($pos < count($array) && $array[$pos][BBCODE_STACK_TOKEN] == BBCODE_NL) $pos++; break; case 'a': while ($pos < count($array) && (($token = $array[$pos][BBCODE_STACK_TOKEN]) == BBCODE_WS || $token == BBCODE_NL)) $pos++; break; } } return $pos; } /** * @param $string * @param $limit * @return string */ function Internal_LimitText($string, $limit) { $chunks = preg_split("/([\\x00-\\x20]+)/", $string, -1, PREG_SPLIT_DELIM_CAPTURE); $output = ''; foreach($chunks as $chunk) { if (strlen($output) + strlen($chunk) > $limit) break; $output.= $chunk; } $output = rtrim($output); return $output; } function Internal_DoLimit() { $this->Internal_CleanupWSByPoppingStack("a", $this->stack); if (strlen($this->limit_tail) > 0) { $this->stack[] = Array(BBCODE_STACK_TOKEN => BBCODE_TEXT, BBCODE_STACK_TEXT => $this->limit_tail, BBCODE_STACK_TAG => false, BBCODE_STACK_CLASS => $this->current_class,); } $this->was_limited = true; } /** * @param $action * @param $tag_name * @param $default_value * @param $params * @param $contents * @return bool|mixed|string */ function DoTag($action, $tag_name, $default_value, $params, $contents) { $tag_rule = @$this->tag_rules[$tag_name]; switch ($action) { case BBCODE_CHECK: if (isset($tag_rule['allow'])) { foreach($tag_rule['allow'] as $param => $pattern) { if ($param == '_content') $value = $contents; else if ($param == '_defaultcontent') { if (strlen($default_value)) $value = $default_value; else $value = $contents; } else { if (isset($params[$param])) $value = $params[$param]; else $value = @$tag_rule['default'][$param]; } if (!preg_match($pattern, $value)) { return false; } } return true; } switch (@$tag_rule['mode']) { default: case BBCODE_MODE_SIMPLE: $result = true; break; case BBCODE_MODE_ENHANCED: $result = true; break; case BBCODE_MODE_INTERNAL: $result = @call_user_func(Array($this, @$tag_rule['method']), BBCODE_CHECK, $tag_name, $default_value, $params, $contents); break; case BBCODE_MODE_LIBRARY: $result = @call_user_func(Array($this->defaults, @$tag_rule['method']), $this, BBCODE_CHECK, $tag_name, $default_value, $params, $contents); break; case BBCODE_MODE_CALLBACK: $result = @call_user_func(@$tag_rule['method'], $this, BBCODE_CHECK, $tag_name, $default_value, $params, $contents); break; } return $result; case BBCODE_OUTPUT: if ($this->plain_mode) { if (!isset($tag_rule['plain_content'])) $plain_content = Array('_content'); else $plain_content = $tag_rule['plain_content']; $result = $possible_content = ''; foreach($plain_content as $possible_content) { if ($possible_content == '_content' && strlen($contents) > 0) { $result = $contents; break; } if (isset($params[$possible_content]) && strlen($params[$possible_content]) > 0) { $result = $this->nbbchtmlspecialchars($params[$possible_content]); break; } } $start = @$tag_rule['plain_start']; $end = @$tag_rule['plain_end']; if (isset($tag_rule['plain_link'])) { $link = $possible_content = ''; foreach($tag_rule['plain_link'] as $possible_content) { if ($possible_content == '_content' && strlen($contents) > 0) { $link = $this->UnHTMLEncode(strip_tags($contents)); break; } if (isset($params[$possible_content]) && strlen($params[$possible_content]) > 0) { $link = $params[$possible_content]; break; } } $params = @parse_url($link); if (!is_array($params)) $params = Array(); $params['link'] = $link; $params['url'] = $link; $start = $this->FillTemplate($start, $params); $end = $this->FillTemplate($end, $params); } return $start . $result . $end; } switch (@$tag_rule['mode']) { default: case BBCODE_MODE_SIMPLE: $result = @$tag_rule['simple_start'] . $contents . @$tag_rule['simple_end']; break; case BBCODE_MODE_ENHANCED: $result = $this->Internal_DoEnhancedTag($tag_rule, $params, $contents); break; case BBCODE_MODE_INTERNAL: $result = @call_user_func(Array($this, @$tag_rule['method']), BBCODE_OUTPUT, $tag_name, $default_value, $params, $contents); break; case BBCODE_MODE_LIBRARY: $result = @call_user_func(Array($this->defaults, @$tag_rule['method']), $this, BBCODE_OUTPUT, $tag_name, $default_value, $params, $contents); break; case BBCODE_MODE_CALLBACK: $result = @call_user_func(@$tag_rule['method'], $this, BBCODE_OUTPUT, $tag_name, $default_value, $params, $contents); break; } return $result; default: return false; } } /** * @param $tag_rule * @param $params * @param $contents * @return string */ function Internal_DoEnhancedTag($tag_rule, $params, $contents) { $params['_content'] = $contents; $params['_defaultcontent'] = strlen(@$params['_default']) ? $params['_default'] : $contents; return $this->FillTemplate(@$tag_rule['template'], $params, @$tag_rule['default']); } /** * @param $params */ function Internal_UpdateParamsForMissingEndTag(&$params) { switch ($this->tag_marker) { case '[': $tail_marker = ']'; break; case '<': $tail_marker = '>'; break; case '{': $tail_marker = '}'; break; case '(': $tail_marker = ')'; break; default: $tail_marker = $this->tag_marker; break; } $params['_endtag'] = $this->tag_marker . '/' . $params['_name'] . $tail_marker; } /** * @param $tag_name * @param $tag_params * @param $tag_rule * @return mixed */ function Internal_ProcessIsolatedTag($tag_name, $tag_params, $tag_rule) { if (!$this->DoTag(BBCODE_CHECK, $tag_name, @$tag_params['_default'], $tag_params, "")) { $this->stack[] = Array(BBCODE_STACK_TOKEN => BBCODE_TEXT, BBCODE_STACK_TEXT => $this->FixupOutput($this->lexer->text), BBCODE_STACK_TAG => false, BBCODE_STACK_CLASS => $this->current_class,); return; } $this->Internal_CleanupWSByPoppingStack(@$tag_rule['before_tag'], $this->stack); $output = $this->DoTag(BBCODE_OUTPUT, $tag_name, @$tag_params['_default'], $tag_params, ""); $this->Internal_CleanupWSByEatingInput(@$tag_rule['after_tag']); $this->stack[] = Array(BBCODE_STACK_TOKEN => BBCODE_TEXT, BBCODE_STACK_TEXT => $output, BBCODE_STACK_TAG => false, BBCODE_STACK_CLASS => $this->current_class,); } /** * @param $tag_name * @param $tag_params * @param $tag_rule * @return mixed */ function Internal_ProcessVerbatimTag($tag_name, $tag_params, $tag_rule) { $state = $this->lexer->SaveState(); $end_tag = $this->lexer->tagmarker . "/" . $tag_name . $this->lexer->end_tagmarker; $start = count($this->stack); $this->lexer->verbatim = true; /** * @ignore * @var $end_tag_params array */ while (($token_type = $this->lexer->NextToken()) != BBCODE_EOI) { if ($this->lexer->text == $end_tag) { $end_tag_params = $this->lexer->tag; break; } if ($this->output_limit > 0 && $this->text_length + strlen($this->lexer->text) >= $this->output_limit) { $text = $this->Internal_LimitText($this->lexer->text, $this->output_limit - $this->text_length); if (strlen($text) > 0) { $this->text_length+= strlen($text); $this->stack[] = Array(BBCODE_STACK_TOKEN => BBCODE_TEXT, BBCODE_STACK_TEXT => $this->FixupOutput($text), BBCODE_STACK_TAG => false, BBCODE_STACK_CLASS => $this->current_class,); } $this->Internal_DoLimit(); break; } $this->text_length+= strlen($this->lexer->text); $this->stack[] = Array(BBCODE_STACK_TOKEN => $token_type, BBCODE_STACK_TEXT => $this->nbbchtmlspecialchars($this->lexer->text), BBCODE_STACK_TAG => $this->lexer->tag, BBCODE_STACK_CLASS => $this->current_class,); } $this->lexer->verbatim = false; if ($token_type == BBCODE_EOI) { $this->lexer->RestoreState($state); $this->stack[] = Array(BBCODE_STACK_TOKEN => BBCODE_TEXT, BBCODE_STACK_TEXT => $this->FixupOutput($this->lexer->text), BBCODE_STACK_TAG => false, BBCODE_STACK_CLASS => $this->current_class,); return; } $newstart = $this->Internal_CleanupWSByIteratingPointer(@$tag_rule['after_tag'], $start, $this->stack); $this->Internal_CleanupWSByPoppingStack(@$tag_rule['before_endtag'], $this->stack); $this->Internal_CleanupWSByEatingInput(@$tag_rule['after_endtag']); $content = $this->Internal_CollectText($this->stack, $newstart); array_splice($this->stack, $start); $this->Internal_ComputeCurrentClass(); $this->Internal_CleanupWSByPoppingStack(@$tag_rule['before_tag'], $this->stack); $tag_params['_endtag'] = $end_tag_params['_tag']; $tag_params['_hasend'] = true; $output = $this->DoTag(BBCODE_OUTPUT, $tag_name, @$tag_params['_default'], $tag_params, $content); $this->stack[] = Array(BBCODE_STACK_TOKEN => BBCODE_TEXT, BBCODE_STACK_TEXT => $output, BBCODE_STACK_TAG => false, BBCODE_STACK_CLASS => $this->current_class,); } function Internal_ParseStartTagToken() { $tag_params = $this->lexer->tag; $tag_name = @$tag_params['_name']; if (!isset($this->tag_rules[$tag_name])) { $this->stack[] = Array(BBCODE_STACK_TOKEN => BBCODE_TEXT, BBCODE_STACK_TEXT => $this->FixupOutput($this->lexer->text), BBCODE_STACK_TAG => false, BBCODE_STACK_CLASS => $this->current_class,); return; } $tag_rule = $this->tag_rules[$tag_name]; $allow_in = is_array($tag_rule['allow_in']) ? $tag_rule['allow_in'] : Array($this->root_class); if (!in_array($this->current_class, $allow_in)) { if (!$this->Internal_RewindToClass($allow_in)) { $this->stack[] = Array(BBCODE_STACK_TOKEN => BBCODE_TEXT, BBCODE_STACK_TEXT => $this->FixupOutput($this->lexer->text), BBCODE_STACK_TAG => false, BBCODE_STACK_CLASS => $this->current_class,); return; } } $end_tag = isset($tag_rule['end_tag']) ? $tag_rule['end_tag'] : BBCODE_REQUIRED; if ($end_tag == BBCODE_PROHIBIT) { $this->Internal_ProcessIsolatedTag($tag_name, $tag_params, $tag_rule); return; } if (!$this->DoTag(BBCODE_CHECK, $tag_name, @$tag_params['_default'], $tag_params, "")) { $this->stack[] = Array(BBCODE_STACK_TOKEN => BBCODE_TEXT, BBCODE_STACK_TEXT => $this->FixupOutput($this->lexer->text), BBCODE_STACK_TAG => false, BBCODE_STACK_CLASS => $this->current_class,); return; } if (@$tag_rule['content'] == BBCODE_VERBATIM) { $this->Internal_ProcessVerbatimTag($tag_name, $tag_params, $tag_rule); return; } if (isset($tag_rule['class'])) $newclass = $tag_rule['class']; else $newclass = $this->root_class; $this->stack[] = Array(BBCODE_STACK_TOKEN => $this->lexer->token, BBCODE_STACK_TEXT => $this->FixupOutput($this->lexer->text), BBCODE_STACK_TAG => $this->lexer->tag, BBCODE_STACK_CLASS => ($this->current_class = $newclass),); if (!isset($this->start_tags[$tag_name])) $this->start_tags[$tag_name] = Array(count($this->stack) - 1); else $this->start_tags[$tag_name][] = count($this->stack) - 1; } function Internal_ParseEndTagToken() { $tag_params = $this->lexer->tag; $tag_name = @$tag_params['_name']; $contents = $this->Internal_FinishTag($tag_name); if ($contents === false) { if (@$this->lost_start_tags[$tag_name] > 0) { $this->lost_start_tags[$tag_name]--; } else { $this->stack[] = Array(BBCODE_STACK_TOKEN => BBCODE_TEXT, BBCODE_STACK_TEXT => $this->FixupOutput($this->lexer->text), BBCODE_STACK_TAG => false, BBCODE_STACK_CLASS => $this->current_class,); } return; } $start_tag_node = array_pop($this->stack); $start_tag_params = $start_tag_node[BBCODE_STACK_TAG]; $this->Internal_ComputeCurrentClass(); $this->Internal_CleanupWSByPoppingStack(@$this->tag_rules[$tag_name]['before_tag'], $this->stack); $start_tag_params['_endtag'] = $tag_params['_tag']; $start_tag_params['_hasend'] = true; $output = $this->DoTag(BBCODE_OUTPUT, $tag_name, @$start_tag_params['_default'], $start_tag_params, $contents); $this->Internal_CleanupWSByEatingInput(@$this->tag_rules[$tag_name]['after_endtag']); $this->stack[] = Array(BBCODE_STACK_TOKEN => BBCODE_TEXT, BBCODE_STACK_TEXT => $output, BBCODE_STACK_TAG => false, BBCODE_STACK_CLASS => $this->current_class,); } /** * @param $string * @return array|mixed|string */ function Parse($string) { $this->lexer = new BBCodeLexer($string, $this->tag_marker); $this->lexer->debug = $this->debug; $old_output_limit = $this->output_limit; if ($this->output_limit > 0) { if (strlen($string) < $this->output_limit) { $this->output_limit = 0; } else if ($this->limit_precision > 0) { $guess_length = $this->lexer->GuessTextLength(); if ($guess_length < $this->output_limit * ($this->limit_precision + 1.0)) { $this->output_limit = 0; } else { } } } $this->stack = Array(); $this->start_tags = Array(); $this->lost_start_tags = Array(); $this->text_length = 0; $this->was_limited = false; if (strlen($this->pre_trim) > 0) $this->Internal_CleanupWSByEatingInput($this->pre_trim); $newline = $this->plain_mode ? "\n" : "<br />\n"; while (true) { if (($token_type = $this->lexer->NextToken()) == BBCODE_EOI) { break; } switch ($token_type) { case BBCODE_TEXT: if ((!isset($this->lexer->input[$this->lexer->ptr]) || (isset($this->lexer->input[$this->lexer->ptr]) && $this->lexer->input[$this->lexer->ptr] != '[/img]')) && $this->output_limit > 0 && $this->text_length + strlen($this->lexer->text) >= $this->output_limit) { $text = $this->Internal_LimitText($this->lexer->text, $this->output_limit - $this->text_length); if (strlen($text) > 0) { $this->text_length+= strlen($text); $this->stack[] = Array(BBCODE_STACK_TOKEN => BBCODE_TEXT, BBCODE_STACK_TEXT => $this->FixupOutput($text), BBCODE_STACK_TAG => false, BBCODE_STACK_CLASS => $this->current_class,); } $this->Internal_DoLimit(); break 2; } if (isset($this->lexer->input[$this->lexer->ptr]) && $this->lexer->input[$this->lexer->ptr] != '[/img]') { $this->text_length+=1; } else { $this->text_length+= strlen($this->lexer->text); } $this->stack[] = Array(BBCODE_STACK_TOKEN => BBCODE_TEXT, BBCODE_STACK_TEXT => $this->FixupOutput($this->lexer->text), BBCODE_STACK_TAG => false, BBCODE_STACK_CLASS => $this->current_class,); break; case BBCODE_WS: if ($this->output_limit > 0 && $this->text_length + strlen($this->lexer->text) >= $this->output_limit) { $this->Internal_DoLimit(); break 2; } $this->text_length+= strlen($this->lexer->text); $this->stack[] = Array(BBCODE_STACK_TOKEN => BBCODE_WS, BBCODE_STACK_TEXT => $this->lexer->text, BBCODE_STACK_TAG => false, BBCODE_STACK_CLASS => $this->current_class,); break; case BBCODE_NL: if ($this->ignore_newlines) { if ($this->output_limit > 0 && $this->text_length + 1 >= $this->output_limit) { $this->Internal_DoLimit(); break 2; } $this->text_length+= 1; $this->stack[] = Array(BBCODE_STACK_TOKEN => BBCODE_WS, BBCODE_STACK_TEXT => "\n", BBCODE_STACK_TAG => false, BBCODE_STACK_CLASS => $this->current_class,); } else { $this->Internal_CleanupWSByPoppingStack("s", $this->stack); if ($this->output_limit > 0 && $this->text_length + 1 >= $this->output_limit) { $this->Internal_DoLimit(); break 2; } $this->text_length+= 1; $this->stack[] = Array(BBCODE_STACK_TOKEN => BBCODE_NL, BBCODE_STACK_TEXT => $newline, BBCODE_STACK_TAG => false, BBCODE_STACK_CLASS => $this->current_class,); $this->Internal_CleanupWSByEatingInput("s"); } break; case BBCODE_TAG: $this->Internal_ParseStartTagToken(); break; case BBCODE_ENDTAG: $this->Internal_ParseEndTagToken(); break; default: break; } } if (strlen($this->post_trim) > 0) $this->Internal_CleanupWSByPoppingStack($this->post_trim, $this->stack); $result = $this->Internal_GenerateOutput(0); $result = $this->Internal_CollectTextReverse($result, count($result) - 1); $this->output_limit = $old_output_limit; if ($this->plain_mode) { $result = preg_replace("/[\\x00-\\x09\\x0B-\\x20]+/", " ", $result); $result = preg_replace("/(?:[\\x20]*\\n){2,}[\\x20]*/", "\n\n", $result); $result = trim($result); } return $result; } /** * @param $text * @return string */ function nbbchtmlspecialchars($text) { if (version_compare(PHP_VERSION, '5.2.3') >= 0) { $text = htmlspecialchars($text, $this->quote_style, $this->charset, false); } else { $text = htmlspecialchars($text, $this->quote_style, $this->charset); } return $text; } }