getSmiliesEmos(); $self = dirname($_SERVER['PHP_SELF']); $this->_root_url = $self == '/' ? '' : $self; $this->_smilies = array( ':D' => '', ';)' => '', ':p' => '', ':P' => '', ':)' => '', ':(' => '', ':o' => '', ':O' => '', '^^' => '', '>:(' => '', '8)' => '', ); $this->_emos = array( ':lol:' => '', ':huh:' => '', ':angry:' => '', ':cool:' => '', ':moon:' => '', ); } function &getInstance() { static $instance = NULL; if ($instance === NULL) $instance = array(new BBEmoticons); return $instance[0]; } function parse($text) { foreach($this->_smilies as $smily => $image) { // => $img $regex = '~('.preg_quote($smily).')(\W|$)~e'; $text = preg_replace($regex, '$this->_smilies["$1"]."$2"', $text); } $text = str_replace(array_keys($this->_emos), array_values($this->_emos), $text); return $text; } function revert($text) { $text = strtr($text, array_flip($this->_smilies)); $text = strtr($text, array_flip($this->_emos)); return $text; } } // includes carriage returns function nltobr($str) { return preg_replace("~(\r\n|\n\r|\r|\n)+~", '
', $str); } class BBCodeStack { var $_items = array(); var $_size = 0; function _update() { $this->_size = sizeof($this->_items); } function getSize() { return $this->_size; } function pop() { $ret = FALSE; if ($this->_size > 0) $ret = TRUE; array_pop($this->_items); $this->_update(); return $ret; } function push(&$value) { $this->_items[] = &$value; $this->_update(); } function &top() { $ret = NULL; if ($this->_size > 0) $ret = &$this->_items[$this->_size - 1]; return $ret; } } class BBNode { var $_children = array(); function addChild(&$child) { $this->_children[] = &$child; } function getChildren() { return $this->_children; } function getTagNames() { return array(); } function getRevertPatterns() { return array(); } function flatten($noparse = FALSE) { $buffer = ''; for ($i = 0; $i < sizeof($this->_children); $i++) { $buffer .= $this->_children[$i]->flatten($noparse); } return $buffer; } function revert() { $buffer = ''; for ($i = 0; $i < sizeof($this->_children); $i++) { $buffer .= $this->_children[$i]->revert(); } return $buffer; } } class BBRootNode extends BBNode { function getTag() { return 'ROOT_TAG'; } } class BBTextNode extends BBNode { var $_text; function BBTextNode($text) { $this->_text = $text; } function handleUrl($matches) { $url = ($matches[2]) ? $matches[0] : 'http://' . $matches[0]; return "". $matches[0] .""; } function flatten($noparse = FALSE) { if ($noparse) return $this->_text; $buffer = preg_replace_callback(K4_REGEX_URL, array(&$this, 'handleUrl'), $this->_text); $paras = preg_split('~(?:(\r\n|\n\r|\r|\n)){2}~', $buffer); if (count($paras) > 1) { $buffer = ''; foreach ($paras as $para) if ($para = trim($para)) $buffer .= "\n\n

". nltobr($para) ."

"; $buffer .= "\n\n"; } $emos = &BBEmoticons::getInstance(); $buffer = $emos->parse($buffer); return $buffer; } function revert() { return $this->_text; } } class BBTagNode extends BBNode { var $_tag; var $_attrib; function BBTagNode($tag, $attrib) { $this->_tag = $tag; $this->_attrib = $attrib; } function getClass() { return 'class="bb_'.$this->getTag().'"'; } function getTag() { return $this->_tag; } function getUnparsed($noparse = FALSE) { $attrib = ($this->_attrib) ? '=' . $this->_attrib : ''; return "[{$this->_tag}$attrib]" . parent::flatten($noparse) . "[/{$this->_tag}]"; } } class BBDefaultNode extends BBTagNode { function flatten($noparse = FALSE) { return $this->getUnparsed($noparse); } } class BBTagRegistry { var $_parse = array(); var $_revert = array(); var $_default; function BBTagRegistry($default) { $this->_default = $default; } function getParserClass($tag) { $class = $this->_default; $tag = strtolower($tag); if (isset($this->_parse[$tag])) $class = $this->_parse[$tag]; return $class; } function getReverterClass($tag) { $ret = $this->_default; foreach ($this->_revert as $class => $pattern) { if (preg_match($pattern, $tag)) { $ret = $class; } } return $ret; } function register($class) { if (class_exists($class)) { $tags = call_user_func(array($class, 'getTagNames')); foreach ($tags as $tag) $this->_parse[$tag] = $class; $patterns = call_user_func(array($class, 'getRevertPatterns')); foreach ($patterns as $pattern) $this->_revert[$pattern] = $class; } } } class BBParser { var $_reg; function BBParser() { $this->_reg = &new BBTagRegistry('BBDefaultNode'); } function register($class) { $this->_reg->register($class); return TRUE; } function &createRegistry() { $this->register('BBFormatNode'); $this->register('BBCenterNode'); $this->register('BBLeftNode'); $this->register('BBRightNode'); $this->register('BBJustifyNode'); $this->register('BBCodeNode'); $this->register('BBLinkNode'); $this->register('BBListNode'); $this->register('BBListItemNode'); $this->register('BBPhpNode'); $this->register('BBQuoteNode'); $this->register('BBImgNode'); $this->register('BBLinkNode'); return $this->_reg; } function revert($buffer) { $stack = &new BBCodeStack; $root = &new BBRootNode; $registry = &$this->createRegistry(); $emos = &BBEmoticons::getInstance(); $buffer = preg_replace('~\n?~', "\n", $buffer); $buffer = $emos->revert($buffer); $buffer = str_replace("©", "(c)", $buffer); $buffer = str_replace("™", "(tm)", $buffer); $buffer = str_replace("®", "(r)", $buffer); $buffer = str_replace("—", "--", $buffer); $buffer = str_replace("–", " - ", $buffer); $buffer = str_replace("…", "...", $buffer); $buffer = preg_replace("~([0-9]+)×([0-9]+)~i", "$1x$2", $buffer); $stack->push($root); $matches = preg_split('~< ( (?>[^<>]+) | (?R) )* >~x', $buffer, -1, PREG_SPLIT_DELIM_CAPTURE); foreach ($matches as $i => $match) { $parent = &$stack->top(); if ((int)$i & 1) { if (preg_match('~^(/?)([a-z]+)(?: class="bb_([a-z]+)"(.*?)(/?))?$~i', $match, $tag)) { if ($tag[5] == '/') { $class = $registry->getParserClass($tag[3]); $node = &new $class($tag[3], $tag[4]); $parent->addChild($node); } elseif ($tag[1] == '/') { if ($stack->getSize() > 1) $stack->pop(); } else { $class = $registry->getParserClass($tag[3]); $node = &new $class($tag[3], $tag[4]); $stack->push($node); $parent->addChild($node); } } else { $class = $registry->getParserClass(''); $node = &new $class('', ''); $stack->push($node); $parent->addChild($node); } } else { $node = &new BBTextNode($match); $parent->addChild($node); } } return $root->revert(); } function parse($buffer) { $stack = &new BBCodeStack; $root = &new BBRootNode; $registry = &$this->createRegistry(); $stack->push($root); // htmlspecialchars ? $buffer = htmlentities($buffer, ENT_QUOTES, K4_CHARSET); $buffer = preg_replace("~\(c\)~i", "©", $buffer); $buffer = preg_replace("~\(tm\)~i", "™", $buffer); $buffer = preg_replace("~\(r\)~i", "®", $buffer); $buffer = preg_replace("~--([a-zA-Z\s])?~", "—", $buffer); $buffer = preg_replace("~\s-\s~", "–", $buffer); $buffer = preg_replace("~\.\.\.~", "…", $buffer); $buffer = preg_replace("~([0-9]+)x([0-9]+)~i", "$1×$2", $buffer); $matches = preg_split('~\[ ( (?>[^\[\]]+) | (?R) )* \]~x', $buffer, -1, PREG_SPLIT_DELIM_CAPTURE); foreach ($matches as $i => $match) { $parent = &$stack->top(); if ((int)$i & 1) { if (preg_match('~^(/?)([a-z]+)(?:=([^\]]*))?$~i', $match, $tag)) { $class = $registry->getParserClass($tag[2]); if ($tag[1] == '/') { if ($tag[2] == $parent->getTag()) { $stack->pop(); } else { $node = &new BBTextNode("[$match]"); $parent->addChild($node); } } else { $node = &new $class($tag[2], $tag[3]); $stack->push($node); $parent->addChild($node); } } else { $node = &new BBTextNode("[$match]"); $parent->addChild($node); } } else { $node = &new BBTextNode($match); $parent->addChild($node); } } return $root->flatten(); } } /** * * TAG COMPILERS * */ class BBCenterNode extends BBTagNode { function flatten($noparse = FALSE) { if ($noparse) return $this->getUnparsed($noparse); $body = parent::flatten($noparse); $class = $this->getClass(); return "
$body
"; } function getTagNames() { return array('center'); } function revert() { $body = parent::revert(); return "[center]{$body}[/center]"; } } class BBLeftNode extends BBTagNode { function flatten($noparse = FALSE) { if ($noparse) return $this->getUnparsed($noparse); $body = parent::flatten($noparse); $class = $this->getClass(); return "
$body
"; } function getTagNames() { return array('left'); } function revert() { $body = parent::revert(); return "[left]{$body}[/left]"; } } class BBRightNode extends BBTagNode { function flatten($noparse = FALSE) { if ($noparse) return $this->getUnparsed($noparse); $body = parent::flatten($noparse); $class = $this->getClass(); return "
$body
"; } function getTagNames() { return array('right'); } function revert() { $body = parent::revert(); return "[right]{$body}[/right]"; } } class BBJustifyNode extends BBTagNode { function flatten($noparse = FALSE) { if ($noparse) return $this->getUnparsed($noparse); $body = parent::flatten($noparse); $class = $this->getClass(); return "
$body
"; } function getTagNames() { return array('justify'); } function revert() { $body = parent::revert(); return "[justify]{$body}[/justify]"; } } class BBCodeNode extends BBTagNode { function flatten($noparse = FALSE) { if ($noparse) return $this->getUnparsed($noparse); return "
". parent::flatten(TRUE) ."
"; } function getTagNames() { return array('code'); } function revert() { $body = parent::revert(); return "[code]{$body}[/code]"; } } class BBFormatNode extends BBTagNode { function getSize() { $size = $this->_attrib; if (intval($size) == $size) return $size; if (in_array($size, array(1,2,3,4,5))) { $sizes = array(1=>'12px',2=>'16px',3=>'20px',4=>'24px',5=>'28px',6=>'32px'); return $sizes[$size]; } } function getColor() { $color = $this->_attrib; if (ctype_alpha($color)) return $color; if (preg_match('~^#[0-9a-f]{3,6}$~i', $color)) return $color; } function getFont() { $font = $this->_attrib; if (ctype_alpha($font)) { $fonts = array('comic'=>'\'Comic Sans MS\'','arial'=>'Arial, Helvetica, sans-serif','times'=>'\'Times New Roman\', Times, serif','verdana'=>'Verdana, Arial, Helvetica, sans-serif'); if(isset($fonts[$font])) { $font = $fonts[$font]; } return $font; } } function flatten($noparse = FALSE) { if ($noparse) return $this->getUnparsed($noparse); $body = parent::flatten($noparse); $styles = array( 'b' => 'font-weight: bold;', 'i' => 'font-style: italic;', 'u' => 'text-decoration: underline;', 'color' => 'color: '.$this->getColor().';', 'size' => 'font-size: '.$this->getSize().';', 'font' => 'font-family: '.$this->getFont().';', 'indent' => 'margin-left: 40px;', 'outdent' => 'margin-left: 0px;', ); $tag = $this->getTag(); $style = $styles[$tag]; $class = $this->getClass(); return "$body"; } function getTagNames() { return array('b', 'color', 'i', 'size', 'u', 'font', 'indent', 'outdent'); } function revert() { switch ($this->getTag()) { case 'b': { return "[b]".parent::revert()."[/b]"; } case 'i': { return "[i]".parent::revert()."[/i]"; } case 'u': { return "[u]".parent::revert()."[/u]"; } case 'size': { $size = preg_replace('~^.*font-size: (\S+);.*$~', '$1', $this->_attrib); return "[size=$size]".parent::revert()."[/size]"; } case 'color': { $color = preg_replace('~^.*color: (\S+);.*$~', '$1', $this->_attrib); return "[color=$color]".parent::revert()."[/color]"; } case 'font': { $font = preg_replace('~^.*font-family: (\S+);.*$~', '$1', $this->_attrib); return "[font=$font]".parent::revert()."[/font]"; } case 'indent': { return "[indent]".parent::revert()."[/indent]"; } case 'outdent': { return "[outdent]".parent::revert()."[/outdent]"; } } } } class BBLinkNode extends BBTagNode { function flatten($noparse = FALSE) { if ($noparse) return $this->getUnparsed($noparse); $body = parent::flatten(TRUE); $url = ($this->_attrib) ? $this->_attrib : $this->_body; return "$body"; } function getTagNames() { return array('link', 'url'); } function revert() { $body = parent::revert(); $tag = $this->getTag(); $url = preg_replace('~^.*href="([^"]*)".*$~', '$1', $this->_attrib); return "[$tag=$url]{$body}[/$tag]"; } } class BBImgNode extends BBTagNode { function flatten($noparse = FALSE) { if ($noparse) return $this->getUnparsed($noparse); $url = parent::flatten(TRUE); //$url = ($this->_attrib) ? $this->_attrib : $this->_body; $class = $this->getClass(); return "\"\""; } function getTagNames() { return array('img'); } function revert() { $body = parent::revert(); $src = preg_replace('~^.*src="([^"]*)".*$~', '$1', $this->_attrib); return "[img]".$src."[/img]"; } } class BBListNode extends BBTagNode { function flatten($noparse = FALSE) { if ($noparse) return $this->getUnparsed($noparse); $body = parent::flatten($noparse); $class = $this->getClass(); $items = explode('[*]', $body); $param = $this->_attrib; if (ctype_digit($param)) { $list = 'ol'; $attribs = " type=\"1\" start=\"$param\""; } elseif ($param == 'a' || $param == 'A' || $param == 'i' || $param == 'I') { $list = 'ol'; $attribs = " type=\"$param\""; } else { $list = 'ul'; $attribs = ''; } $buffer = ''; foreach ($items as $item) { if (trim($item)) $buffer .= "
  • $item
  • "; } return "<$list class=\"bbcode_list\" $attribs>\n$buffer"; } function getTagNames() { return array('list'); } function revert() { $body = parent::revert(); $type = preg_replace('~^.*type(=)"([^"]*)".*$~', '$1$2', $this->_attrib); return "[list$type]{$body}[/list]"; } } class BBListItemNode extends BBTagNode { function getTagNames() { return array('li'); } function revert() { $body = parent::revert(); return "[*]{$body}"; } } class BBPhpNode extends BBTagNode { function flatten($noparse = FALSE) { if ($noparse) return $this->getUnparsed($noparse); $body = parent::flatten(TRUE); $geshi = &new GeSHi($body, 'PHP'); return "
    ". $geshi->parse_code() ."
    "; } function getTagNames() { return array('php'); } function revert() { $body = parent::revert(); return "[php]{$body}[/php]"; } } class BBQuoteNode extends BBTagNode { function flatten($noparse = FALSE) { if ($noparse) return $this->getUnparsed($noparse); return "
    ". parent::flatten() ."
    "; } function getTagNames() { return array('quote'); } } ?>