Advertisement
Guest User

Untitled

a guest
Mar 3rd, 2011
175
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 47.78 KB | None | 0 0
  1. <?php
  2. /**
  3.  * Text Parsing functions
  4.  * This class parses bbcode in a given text to html,
  5.  * but not in the way you'd expect. It creates an array
  6.  * in which all possible tags and text is stored, and
  7.  * it loops through, searching for correct tags, and
  8.  * attaches them to a new-built string. This way is
  9.  * much faster and more reliable than usual preg/ereg
  10.  * based parsers, and has taken quite a while;)
  11.  * It also includes the highlighthing class for the
  12.  * <b>Quality Bulletin Board</b>. It is very flexible,
  13.  * and works with language files, which are on
  14.  * their turn based on regular expressions.
  15.  * This makes it all very flexible, and easy to edit.
  16.  *
  17.  
  18. **/
  19. // full error reporting
  20. error_reporting (E_ALL);
  21.  
  22. /**
  23.  * This constant means that a regular expression
  24.  * does not need any modifiers.
  25.  *
  26.  * @name   QBB_NONE
  27. **/
  28. define ('QBB_NONE', 0);
  29. /**
  30.  * This constant means that a regular expression
  31.  * needs the '.' to match newlines too.
  32.  *
  33.  * @name   QBB_DOTALL
  34. **/
  35. define ('QBB_DOTALL', 1);
  36. /**
  37.  * This constant means that a regular expression
  38.  * has to match without case-sensitivity.
  39.  *
  40.  * @name   QBB_CASELESS
  41. **/
  42. define ('QBB_CASELESS', 2);
  43.  
  44.  
  45.  
  46.  
  47. class bbcode
  48. {
  49.     /**#@+
  50.      * @access   protected
  51.      */
  52.  
  53.     /**
  54.      * Contains parsed text
  55.      *
  56.      * @var      array     _parsed
  57.     **/
  58.     var $_parsed = array ();
  59.     /**
  60.      * Contains aliases
  61.      *
  62.      * @var      array     _alias
  63.     **/
  64.     var $_alias = array (
  65.         '*' => 'li_short',
  66.         'hr' => 'line'
  67.     );
  68.     /**
  69.      * Parse tags?
  70.      *
  71.      * @var      boolean   _bb_mode
  72.     **/
  73.     var $_bb_mode = true;
  74.     /**
  75.      * Holds bbcode templates
  76.      *
  77.      * @var      array     _tpls
  78.     **/
  79.     var $_tpls = array ();
  80.     /**
  81.      * Regexes that'll be used
  82.      *
  83.      * @var      array     _regexes
  84.     **/
  85.     var $_regexes = array ();
  86.     /**
  87.      * All other simple replacement
  88.      *
  89.      * @var      array     _replaces
  90.     **/
  91.     var $_replaces = array ();
  92.     /**
  93.      * Check if we're inside tags
  94.      *
  95.      * Are we parsing inside a tag that's special?
  96.      * extra care taken, because tags
  97.      * may be nested
  98.      *
  99.      * @var      array     _in_tag
  100.     **/
  101.     var $_in_tag = array (
  102.         'list' => 0,
  103.         'table' => 0,
  104.         'tr' => 0
  105.     );
  106.     /**
  107.      * ID for div's
  108.      *
  109.      * @var      integer   _curr_id
  110.     **/
  111.     var $_curr_id = 1;
  112.  
  113.     /**#@-*/
  114.  
  115.     /**#@+
  116.      * @access   public
  117.      **/
  118.  
  119.     /**
  120.      * BBcode parsing constructor
  121.      *
  122.      * Sets up templates, autolinking etc.
  123.      *
  124.      * @param    string   [$tpl_file]
  125.      * @return   boolean
  126.     **/
  127.    
  128.     function bbcode ($tpl_file = './bbcode.htm')
  129.     {
  130.         // get the data from the tpl file
  131.         $data = file_get_contents ($tpl_file);
  132.         $data = str_replace ('\\', '\\\\', $data);
  133.         $data = str_replace ("'", "\'", $data);
  134.  
  135.         // replace all bb parts with a PHP piece which will insert it
  136.         // into the tpl array
  137.         $data = preg_replace (
  138.             '/<!-- BEGIN BB ([^\s]+) -->(.*?)<!-- END BB \1 -->/si',
  139.             "\$this->_tpls['\\1'] = trim ('\\2');",
  140.             $data
  141.         );
  142.         // evaluate
  143.         eval ($data);
  144.  
  145.         // some action for the replacement of email links etc.
  146.         $this->_regexes = array (
  147.             'find' => array (
  148.                 // emails
  149.                 '~(\s|^)([-a-z_][-a-z0-9._]*@[-a-z0-9_]+(?:\.[-a-z0-9_]+)+)\b~si',
  150.                 // links with http, https, ftp or even irc
  151.                 '#(^|[\n ])([\w]+?://[\w\#$%&~/.\-;:=,?@\[\]+]*)#is',
  152.                 // links with www.
  153.                 '#(^|[ \n\r\t])((www\.){1}([a-z0-9\-]{1,}(\.?)){1,}[a-z]{2,5}(:[0-9]{2,5}){0,1}((\/|~|\#|\?|=|&amp;|&|\+){1}[a-z0-9\-._%]{0,}){0,})#si'
  154.  
  155.  
  156.             ),
  157.             'replace' => array (
  158.                 '\1<a style="text-decoration:underline" href="mailto:\2">\2</a>',
  159.                 '\1<a style="text-decoration:underline" href="\2" target="_blank">\2</a>',
  160.                 '\1<a style="text-decoration:underline" href="http://\2" target="_blank">\2</a>',
  161.             )
  162.         );
  163.  
  164.        
  165.         /** Smileys *************/
  166.        
  167.         $this->_Smileys = array (
  168.             'find' => array (
  169.                '/:p/',
  170.                 '/:d/',
  171.                 '/;d/',
  172.                 '/;\)/',
  173.                 '/:\(/',
  174.                 '/:\|/',
  175.                 '/-\.\-/',
  176.                 '/x.x/',
  177.                 '/:s/',
  178.                 '/:\)/',
  179.                 '/:\$/',
  180.                 '/:\'\(/',
  181.                 '/\^\^/',
  182.                 '/xd/'
  183.             ),
  184.             'replace' => array (
  185.                 '<img src="/images/smileys/tonque.gif" alt=":P"/>',
  186.                 '<img src="/images/smileys/grin.gif" alt=":D"/>',
  187.                 '<img src="/images/smileys/decayed.gif" alt=";d"/>',
  188.                 '<img src="/images/smileys/wink.gif" alt=";)"/>',
  189.                 '<img src="/images/smileys/sad.png" alt=":("/>',
  190.                 '<img src="/images/smileys/hmm.png" alt=":|"/>',
  191.                 '<img src="/images/smileys/doubt.gif" alt="-.-"/>',
  192.                 '<img src="/images/smileys/wry.gif" alt="x.x"/>',
  193.                 '<img src="/images/smileys/pout.png" alt=":S"/>',
  194.                 '<img src="/images/smileys/happy.gif" alt=":)"/>',
  195.                 '<img src="/images/smileys/blush.gif" alt=":$"/>',
  196.                 '<img src="/images/smileys/cry.png" alt=":\'("/>',
  197.                 '<img src="/images/smileys/veryhappy.png" alt="^^"/>',
  198.                '<img src="/images/smileys/haha.png" alt="xD"/>'
  199.               ,
  200.             )
  201.         );
  202.        
  203.      
  204.  
  205.         // and return
  206.         return true;
  207.     }
  208.  
  209.     /**
  210.      * Call this to return a parsed text
  211.      *
  212.      * @param    string   $text
  213.      * @return   string
  214.     **/
  215.     function parse ($text)
  216.     {
  217.         // remove beginning and ending whitespaces
  218.         $text = trim ($text);
  219.         // replace all newlines with a linebreak tag (for later use)
  220.         $text = str_replace (array ("\r\n", "\r", "\n"), "[linebreak\0]", $text);
  221.        
  222.         // Add Slashes
  223.         $text = stripslashes($text);
  224.        
  225.         $text = htmlspecialchars($text);
  226.        // $text = htmlspecialchars($text);
  227.         // cut the text in pieces so we can easily loop
  228.         $this->_create_array($text);
  229.  
  230.         // parse the stack
  231.         $text = $this->_parse ();
  232.  
  233.         // replace the linebreak tags with normal newlines
  234.         $return = str_replace ("[linebreak\0]", "<br />\n", $text);
  235.         // and return
  236.         return $return;
  237.     }
  238.  
  239.     /**#@-*/
  240.  
  241.     /**#@+
  242.      * @access   protected
  243.      **/
  244.  
  245.     /**
  246.      * Parse a template with given variables
  247.      *
  248.      * @param    string   $part
  249.      * @param    array    $args
  250.      * @return   string
  251.     **/
  252.     function parse_bb_tpl ($part, $args)
  253.     {
  254.         // just a replace, with evaluation...
  255.         return preg_replace (
  256.             '/{([^}\s]+)}/e',
  257.             "isset (\$args['\\1']) ? \$args['\\1'] : '';",
  258.             $this->_tpls[$part]
  259.         );
  260.     }
  261.  
  262.     /**
  263.      * Cut the text in pieces
  264.      *
  265.      * @param    string   $text
  266.      * @return   boolean
  267.     **/
  268.     function _create_array ($text)
  269.     {
  270.         // empty the _parsed array
  271.         $this->_parsed = array ();
  272.  
  273.         // loop as long as the text has content
  274.         while (strlen ($text) > 0)
  275.         {
  276.            
  277.            
  278.             // the first found bracket
  279.             $bracket        = strpos ($text, '[');
  280.             // the second bracket
  281.             $second_bracket = strpos ($text, '[', $bracket + 1);
  282.             // and the first closer
  283.             $close          = strpos ($text, ']');
  284.            
  285.  
  286.            
  287.            
  288.  
  289.             // if there isnt a bracket or closer
  290.             if ($bracket === false || $close === false)
  291.             {
  292.                 // the rest is just normal text
  293.                 $this->_parsed[] = $text;
  294.                 // return
  295.                 return true;
  296.             }
  297.  
  298.             // loop as long as the [ and ] aren't right
  299.             while ($close < $bracket || $second_bracket < $close)
  300.             {
  301.                 // look if the second bracket comes before the closer
  302.                 if ($second_bracket < $close)
  303.                 {
  304.                     // if so, $bracket gets the value of $second_bracket
  305.                     $bracket = $second_bracket;
  306.                     // the second bracket gets a new position
  307.                     $second_bracket = strpos (strtolower($text), '[', $bracket + 1);
  308.                     // if that wasn't matched right
  309.                     if (!$second_bracket)
  310.                     {
  311.                         // the second bracket will be matched after the closer
  312.                         $second_bracket = $close + 1;
  313.                     }
  314.                 }
  315.                 // if the closer comes before the [
  316.                 if ($close < $bracket)
  317.                 {
  318.                     // update the closer
  319.                     $close = strpos ($text, ']', $close + 1);
  320.                 }
  321.             }
  322.  
  323.             // if the [ and ] seem to be correct
  324.             if ($bracket < $close && $close < $second_bracket)
  325.             {
  326.                 // the text before the tag
  327.                 $pre = substr ($text, 0, $bracket);
  328.                 // if this is empty
  329.                 if (strlen ($pre) > 0)
  330.                 {
  331.                     // add this to the _parsed
  332.                     $this->_parsed[] = $pre;
  333.                     // memory saving
  334.                     $pre = '';
  335.                 }
  336.                 // put the text in _parsed
  337.                 $this->_parsed[] = substr ($text, $bracket, $close - $bracket + 1);
  338.                 // $text has to be updated
  339.                                
  340.                 $text            = substr ($text, $close + 1);
  341.  
  342.             }
  343.         }
  344.         // return
  345.         return true;
  346.     }
  347.  
  348.     /**
  349.      * Parse the text (already cut in pieces)
  350.      *
  351.      * @param    array   [$stoppers]
  352.      * @param    array   [$allow]
  353.      * @return   string
  354.     **/
  355.     function _parse ($stoppers = array (), $allow = array ())
  356.     {
  357.        
  358.         // if the stack is empty
  359.         if (!$this->_parsed)
  360.         {
  361.             // return nothing
  362.             return '';
  363.         }
  364.  
  365.         // nested level and return text ''
  366.         $level = 0;
  367.         $text = '';
  368.  
  369.         // simple check so we can easily check
  370.         if (!is_array ($stoppers))
  371.         {
  372.             $stoppers = array ($stoppers);
  373.         }
  374.  
  375.         // for even levels with bb_mode off
  376.         $stoppers_leveled = array ();
  377.         // check for active bb_mode
  378.         if (!$this->_bb_mode)
  379.         {
  380.             // if it isn't active, we put all the stoppers in an array
  381.             // so we can check for the correct level
  382.             for ($i = 0, $size = count ($stoppers); $i < $size; $i++)
  383.             {
  384.                 // use the tagname function
  385.                 $stoppers_leveled[$this->_find_tagname ($stoppers[$i], false, true)] = true;
  386.             }
  387.         }
  388.         // flip the stoppers so we can use isset
  389.         $stoppers = array_flip ($stoppers);
  390.         $allow    = array_flip ($allow);
  391.  
  392.         // loop the pieces
  393.         while ($piece = array_shift ($this->_parsed))
  394.         {
  395.             // if it is a stopper
  396.             if (isset ($stoppers[$piece]))
  397.             {
  398.                 // check for zero-level or bb_mode active
  399.                 if (($level == 0 && !$this->_bb_mode) || $this->_bb_mode)
  400.                 {
  401.                     // if correct, return
  402.                     return $text;
  403.                 }
  404.                 // otherwise...
  405.                 else
  406.                 {
  407.                     // attach this piece
  408.                     $text .= $piece;
  409.                     // and lower the level
  410.                     $level--;
  411.                 }
  412.             }
  413.             // if it isn't a stopper
  414.             else
  415.             {
  416.                 // check if we can find a tagname first
  417.                 $name = $this->_find_tagname ($piece);
  418.                 $name = ($name !== false && isset ($this->_alias[$name]))
  419.                     ? $this->_alias[$name]
  420.                     : $name;
  421.                    
  422.                    
  423.  
  424.                 $allowed = (isset ($allow[$name]) || !$allow) ? true : false;
  425.  
  426.                 // if it was a valid tag, and the correct method exists
  427.                 if ($name !== false
  428.                     && method_exists (&$this, '_parse_bb_' .strtolower($name))
  429.                     && $allowed === true)
  430.                 {
  431.                     // check if bb_mode is active
  432.                     if ($this->_bb_mode)
  433.                     {
  434.                         // if so, find the complete tag without []
  435.                         $args     = $this->_find_tagname ($piece, true);
  436.                         // parse the arguments
  437.                         $args     = $this->_parse_bb_arguments ($args);
  438.                         // the correct method
  439.                         $function = '_parse_bb_' . $name;
  440.                         // append the parsed text to the text
  441.                         $text    .= $this->$function ($args);
  442.                     }
  443.                     // if bb_mode is unactive
  444.                     else
  445.                     {
  446.                         // check if this is a stopper
  447.                         if (isset ($stoppers_leveled[$name]))
  448.                         {
  449.                             // if so, update the level
  450.                             $level++;
  451.                         }
  452.                         // and append
  453.                         $text .= $piece;
  454.                     }
  455.                 }
  456.                 // if it wasn't a tag
  457.                 else
  458.                 {
  459.                     // check if we're in a disallowed zone
  460.                     if (!$allow)
  461.                     {
  462.                         // if bb_mode is active
  463.                         if ($this->_bb_mode)
  464.                         {
  465.                             // use the regexes to form a nicer text
  466.                             $piece = preg_replace (
  467.                                 $this->_regexes['find'],
  468.                                 $this->_regexes['replace'],
  469.                                 $piece
  470.                             );
  471.  
  472.                            
  473.                             // use the regexes to form a nicer text
  474.                             $piece = preg_replace (
  475.                                 $this->_Smileys['find'],
  476.                                 $this->_Smileys['replace'],
  477.                                 $piece
  478.                             );
  479.                            
  480.                             // use the regexes to form a nicer text
  481.                             $piece = preg_replace (
  482.                                 $this->_WordFilter,
  483.                                 '**Gefilterd**',
  484.                                 $piece
  485.                             );                            
  486.                        
  487.                         }
  488.                         // just a normal append
  489.                         $text .= $piece;
  490.                     }
  491.                 }
  492.             }
  493.         }
  494.         // after the loop just return
  495.         return $text;
  496.     }
  497.  
  498.     /**
  499.      * find the name of a tag in a piece of the content
  500.      *
  501.      * @param    string    $name
  502.      * @param    boolean   [$complete]
  503.      * @param    boolean   [$closer]
  504.      * @return   string
  505.     **/
  506.     function _find_tagname ($name, $complete = false, $closer = false)
  507.     {
  508.  
  509.        
  510.      
  511.        
  512.        
  513.         // check if it could be valid
  514.         if (substr ($name, 0, 1) == '[' && substr ($name, -1) == ']')
  515.         {
  516.            
  517.             // take off the [ and ]
  518.             $name = substr ($name, 1, -1);
  519.             // if it matches a /
  520.             if (substr ($name, 0, 1) == '/' && $closer !== false)
  521.             {
  522.                 // take the / off too
  523.                 $name = substr ($name, 1);
  524.             }
  525.  
  526.             // if it should be the complete tag
  527.             if ($complete !== false)
  528.             {
  529.                 // then return it now
  530.                 return $name;
  531.             }
  532.             // otherwise use strtok to match untill ' ' or '='
  533.             return strtok ($name, ' =');
  534.         }
  535.         // if it wasn't valid, return boolean false
  536.         return false;
  537.     }
  538.  
  539.     /**
  540.      * parse argument strings
  541.      *
  542.      * @param    string   $total
  543.      * @return   array
  544.     **/
  545.     function _parse_bb_arguments ($total)
  546.     {
  547.         // instantiate for errors
  548.         $matches = array ();
  549.         // match everything like argument='blablabla bla' or argument=blabla or even arg='bla\'bla\\'bla\\'
  550.         preg_match_all (
  551.             '/([A-Za-z_]+?)=(?:(\'|&quot;)(.*?(?<!\\\\)(?:\\\\\\\\)*)\2|([^\s]+))' .
  552.                 '(?:\s|$)/s',
  553.             $total,
  554.             $matches,
  555.             PREG_SET_ORDER
  556.         );
  557.  
  558.         // put up the arguments array
  559.         $args = array ();
  560.         // loop through all matches
  561.         for ($i = 0, $size = count ($matches); $i < $size; $i++)
  562.         {
  563.             // check if the quoted value was empty
  564.             if (trim ($matches[$i][3]) == '')
  565.             {
  566.                 // if the unquoted value was empty
  567.                 if (trim ($matches[$i][4]) == '')
  568.                 {
  569.                     // the value is ''
  570.                     $value = '';
  571.                 }
  572.                 // if not
  573.                 else
  574.                 {
  575.                     // assign the unquoted value
  576.                     $value = $matches[$i][4];
  577.                 }
  578.             }
  579.             // otherwise
  580.             else
  581.             {
  582.                 // assign the quoted value
  583.                 $value = $matches[$i][3];
  584.             }
  585.  
  586.             // erase whitespaces
  587.             $value = trim ($value);
  588.             // if the value wasn't empty
  589.             if ($value != '')
  590.             {
  591.                 // assign this argument to our array
  592.                 $args[strtolower ($matches[$i][1])] = $value;
  593.             }
  594.         }
  595.  
  596.         // return the arguments
  597.         return $args;
  598.     }
  599.  
  600.     /*
  601.      * THE PARSING FUNCTIONS BEGIN HERE
  602.      * a function should be built like this:
  603.      * name: _parse_bb_*tagname*
  604.      * 1 argument, $args for the given arguments
  605.      * pickup the content with $this->_parse (array ('stoppers1', 'stoppers2'));
  606.      * or with $this->_parse ('stopper');
  607.      * return.
  608.     **/
  609.  
  610.     /**
  611.      * show bold text
  612.      *
  613.      * @param    array   $args
  614.      * @return   string
  615.     **/
  616.     function _parse_bb_b ($args)
  617.     {
  618.         return '<strong>' . $this->_parse ('[/b]') . '</strong>';
  619.     }
  620.  
  621.     /**
  622.      * show italic text
  623.      *
  624.      * @param    array   $args
  625.      * @return   string
  626.     **/
  627.     function _parse_bb_i ($args)
  628.     {
  629.         return '<i>' . $this->_parse ('[/i]') . '</i>';
  630.     }
  631.  
  632.     /**
  633.      * show underlined text
  634.      *
  635.      * @param    array   $args
  636.      * @return   string
  637.     **/
  638.     function _parse_bb_u ($args)
  639.     {
  640.         return '<u>' . $this->_parse ('[/u]') . '</u>';
  641.     }
  642.  
  643.     /**
  644.      * show striken text
  645.      *
  646.      * @param    array   $args
  647.      * @return   string
  648.     **/
  649.     function _parse_bb_s ($args)
  650.     {
  651.         return '<s>' . $this->_parse ('[/s]') . '</s>';
  652.     }
  653.  
  654.     /**
  655.      * show subscript text
  656.      *
  657.      * @param    array   $args
  658.      * @return   string
  659.     **/
  660.     function _parse_bb_sub ($args)
  661.     {
  662.         return '<sub>' . $this->_parse ('[/sub]') . '</sub>';
  663.     }
  664.  
  665.     /**
  666.      * show superscript text
  667.      *
  668.      * @param    array   $args
  669.      * @return   string
  670.     **/
  671.     function _parse_bb_sup ($args)
  672.     {
  673.         return '<sup>' . $this->_parse ('[/sup]') . '</sup>';
  674.     }
  675.  
  676.     /**
  677.      * show colored text
  678.      *
  679.      * @param    array   $args
  680.      * @return   string
  681.     **/
  682.     function _parse_bb_color ($args)
  683.     {
  684.         // parse the text
  685.         $text = $this->_parse ('[/color]');
  686.  
  687.         // check the color
  688.         $color = (isset ($args['color'])) ? $args['color'] : false;
  689.         // match it to a simple regex
  690.         $color = (preg_match ('/^(?:#(?:[a-f0-9]{3}){1,2}|[a-z]{3,})$/i', $color))
  691.             ? $color
  692.             : false;
  693.         // return a span with the correct style if the color was correct
  694.         return ($color !== false) ? '<span style="color: ' . $color . ';">' .
  695.             $text . '</span>' : $text;
  696.     }
  697.  
  698.     /**
  699.      * show text with other size
  700.      *
  701.      * @param    array   $args
  702.      * @return   string
  703.     **/
  704.     function _parse_bb_size ($args)
  705.     {
  706.         // parse the text
  707.         $text = $this->_parse ('[/size]');
  708.         // get the size from the argument
  709.         $size = (isset ($args['size'])) ? $args['size'] : '';
  710.  
  711.         // look if the size is correct
  712.         switch ( $size )
  713.         {
  714.             // xsmall
  715.             case 'xklein':
  716.                 $size = '7px';
  717.             break;
  718.             // small
  719.             case 'klein':
  720.                 $size = '9px';
  721.             break;
  722.             // medium
  723.             case 'medium':
  724.                 $size = '12px';
  725.             break;
  726.             // large
  727.             case 'groot':
  728.                 $size = '18px';
  729.             break;
  730.             // xlarge
  731.             case 'xgroot':
  732.                 $size = '22px';
  733.             break;
  734.             default:
  735.                 return $text;
  736.         }
  737.         // return the span-ed text
  738.         return '<span style="font-size: ' . $size . ';">' . $text . '</span>';
  739.     }
  740.    
  741.    // een bbcode methode begint altijd met parse_bb_ en dan de tagnaam
  742.     function _parse_bb_login ($args)
  743.     {
  744.         global $is_user;
  745.        
  746.         // parse the text
  747.         $text = $this->_parse ('[/login]');
  748.         // get the size from the argument
  749.        
  750.         // return the span-ed text
  751.         return ($is_user) ? $text : '<div class="quote"><span style="font-weight:bold; color:red;">Je moet ingelogt zijn om dit deel te kunnen zien</span></div>';
  752.     }    
  753.    
  754.     /**
  755.      * show text with other size
  756.      *
  757.      * @param    array   $args
  758.      * @return   string
  759.     **/
  760.     function _parse_bb_align ($args)
  761.     {
  762.         // parse the text
  763.         $text = $this->_parse ('[/align]');
  764.         // get the size from the argument
  765.         $align = (isset ($args['align'])) ? $args['align'] : '';
  766.  
  767.         // look if the size is correct
  768.         switch ( $align )
  769.         {
  770.             // xsmall
  771.             case 'left':
  772.                 $align = 'left';
  773.             break;
  774.             // small
  775.             case 'center':
  776.                 $align = 'center';
  777.             break;
  778.             // medium
  779.             case 'right':
  780.                 $align = 'right';
  781.             break;
  782.  
  783.             default:
  784.                 return $text;
  785.         }
  786.         // return the span-ed text
  787.         return '<div style="text-align: ' . $align . ';">' . $text . '</div>';
  788.     }    
  789.  
  790.  
  791.     /**
  792.      * show a line
  793.      *
  794.      * @param    array   $args
  795.      * @return   string
  796.     **/
  797.     function _parse_bb_line ($args)
  798.     {
  799.         // a normal tag, simple line
  800.         return '<hr />';
  801.     }
  802.  
  803.     /**
  804.      * show a url
  805.      *
  806.      * @param    array   $args
  807.      * @return   string
  808.     **/
  809.     function _parse_bb_url ($args)
  810.     {
  811.         // 2 regexes to validate
  812.         $regex = array (
  813.              // links with: ftp http or https
  814.             '~^(?:https?|ftp|irc)://[-a-z0-9+&@#/%?=\~_|!:,.;]*[-a-z0-9+&@#/%=\~_|]$~i',
  815.             // url's that begin with www. or something like that
  816.             '~^[-a-z0-9+&@#/%?=\~_|!:,.;]+[-a-z0-9+&@#/%=\~_|]$~i'
  817.         );
  818.  
  819.         // check if it was set there
  820.         if (!isset ($args['url']))
  821.         {
  822.             // if so, disable ubb_mode
  823.             $this->_bb_mode = false;
  824.         }
  825.         // parse until /url
  826.         $text = $this->_parse ('[/url]');
  827.         // activate bb_mode no matter what
  828.         $this->_bb_mode = true;
  829.  
  830.         // check the url with the argument and the given text
  831.         $url = (isset ($args['url']))
  832.             ? $args['url']
  833.             : (
  834.                 (!empty ($text))
  835.                 ? $text
  836.                 : false
  837.             );
  838.  
  839.         // if no input was given
  840.         if ($url === false)
  841.         {
  842.             // return '' (text is also empty;))
  843.             return '';
  844.         }
  845.  
  846.         // check the url with 2 regex, first with www, second without
  847.         $url = (preg_match ($regex[0], $url))
  848.             ? $url
  849.             : (
  850.                 (preg_match ($regex[1], $url))
  851.                 ? 'http://' . $url
  852.                 : false
  853.             );
  854.         $text = (empty ($text)) ? $url : $text;
  855.  
  856.         return ($url !== false)
  857.             ? sprintf ('<a href="%s" target="_blank">%s</a> <img src="/images/icons/link.png" alt="een uitgaande link"/>', $url, $text)
  858.             : $text;
  859.     }
  860.    
  861.  
  862.     function _parse_bb_youtube ($args)
  863.     {
  864.         // set up arguments
  865.         $args = array (
  866.             'YOUTUBE_URL' => (isset ($args['youtube']) && !empty ($args['youtube']))
  867.                 ? $args['youtube']
  868.                 : 'Youtube',
  869.             'YOUTUBE_VIDEO' => trim (preg_replace (
  870.                 '/(^\[linebreak\0]|\[linebreak\0]$)/',
  871.                 '',
  872.                 $this->_parse ('[/youtube]')
  873.             ), "\r\n")
  874.         );
  875.         // return
  876.         return $this->parse_bb_tpl ('youtube', $args);
  877.     }
  878.  
  879.  
  880.     /**
  881.      * show bold text
  882.      *
  883.      * @param    array   $args
  884.      * @return   string
  885.     **/
  886.     function _parse_bb_email ($args)
  887.     {
  888.         $regex = '/^(?:[-a-z_][-a-z0-9._]*@[-a-z0-9_]+(?:\.[-a-z0-9_]+)+)$/si';
  889.  
  890.         // check if it was set there
  891.         if (!isset ($args['email']))
  892.         {
  893.             // if so, disable ubb_mode
  894.             $this->_bb_mode = false;
  895.         }
  896.         // parse until /url
  897.         $text = $this->_parse ('[/email]');
  898.         // activate bb_mode no matter what
  899.         $this->_bb_mode = true;
  900.  
  901.         // check the url with the argument and the given text
  902.         $email = (isset ($args['email']))
  903.             ? $args['email']
  904.             : (
  905.                 (!empty ($text))
  906.                     ? $text
  907.                     : false
  908.             );
  909.  
  910.         // if no input was given
  911.         if ($email === false)
  912.         {
  913.             // return '' (text is also empty;))
  914.             return '';
  915.         }
  916.  
  917.         // check the email with the regex
  918.         $email = (preg_match ($regex, $email)) ? $email : false;
  919.         $text = (empty ($text)) ? $email : $text;
  920.  
  921.         return ($email !== false)
  922.             ? sprintf ('<a href="mailto:%s" target="_blank">%s</a>', $email, $text)
  923.             : $text;
  924.     }
  925.  
  926.     /**
  927.      * show an image
  928.      *
  929.      * @param    array   $args
  930.      * @return   string
  931.     **/
  932.     function _parse_bb_img ($args)
  933.     {
  934.         // drop out of bb_mode
  935.         $this->_bb_mode = false;
  936.        
  937.         // get the url
  938.         $img            = (isset ($args['img']))
  939.             ? $args['img']
  940.             : $this->_parse ('[/img]');
  941.        
  942.         // go back into bb_mode
  943.         $this->_bb_mode = true;
  944.         // get some basic arguments
  945.         $width          = (isset ($args['width'])) ? $args['width'] : 0;
  946.         $height         = (isset ($args['height'])) ? $args['height'] : 0;
  947.         $alt            = (isset ($args['alt'])) ? $args['alt'] : '';
  948.  
  949.         // create the return statement
  950.         $return  = '<a class="fancybox" href="'.$img.'"><img style="max-width:95%; height:auto;" src="' . $img . '"';
  951.         $return .= ($width) ? ' width="' . $width . '"' : '';
  952.         $return .= ($height) ? ' height="' . $height . '"' : '';
  953.         $return .= ($alt) ? ' alt="' . $alt . '"' : ' alt="Afbeelding"';
  954.         $return .= ' /></a>';
  955.         // and return
  956.         return $return;
  957.     }
  958.    
  959.  
  960.     /**
  961.      * show a quote
  962.      *
  963.      * @param    array   $args
  964.      * @return   string
  965.     **/
  966.     function _parse_bb_quote ($args)
  967.     {
  968.        
  969.        
  970.        
  971.         // set up arguments
  972.         $args = array (
  973.             'QUOTE_BY' => (isset ($args['quote']) && !empty ($args['quote']))
  974.                 ? 'Quote '.sUsername($args['quote'])
  975.                 : 'Quote',
  976.             'QUOTE_TEXT' => trim (preg_replace (
  977.                 '/(^\[linebreak\0]|\[linebreak\0]$)/',
  978.                 '',
  979.                 $this->_parse ('[/quote]')
  980.             ), "\r\n")
  981.         );
  982.         // return
  983.         return $this->parse_bb_tpl ('quote', $args);
  984.     }
  985.  
  986.     /**
  987.      * show a code block
  988.       * code may be highlighted with languages like
  989.       * PHP, JAVA(script), CSS etc.
  990.      *
  991.      * @param    array    args
  992.      * @return   string
  993.      * @see      highlighter
  994.     **/
  995.     function _parse_bb_code ($args)
  996.     {
  997.         // drop out of bb_mode
  998.         $this->_bb_mode = false;
  999.         // this will parse from [code] till the closer
  1000.         $code = $this->_parse ('[/code]');
  1001.         // go back in bb_mode
  1002.         $this->_bb_mode = true;
  1003.  
  1004.         // take further action to have correct code
  1005.         $code = trim (str_replace ("[linebreak\0]", "\n", $code), "\r\n");
  1006.         // check for a starting position
  1007.         $start = (isset ($args['s']) && $args['s'] > 0) ? $args['s'] : 1;
  1008.         // count the newlines
  1009.         $size = substr_count ($code, "\n");
  1010.         // update the size
  1011.         $size += $start;
  1012.  
  1013.         // should we highlight?
  1014.         if (!(isset ($args['highlight']) && $args['highlight'] == 'no'))
  1015.         {
  1016.             // default language is php, but can be different
  1017.             $language = (isset ($args['lang'])) ? $args['lang'] : 'php';
  1018.  
  1019.             // decode html entities
  1020.             $code = html_entity_decode ($code);
  1021.             // start the highlight object.. this does all the work
  1022.             $h = &new highlighter ($language, $code);
  1023.             // get the highlighted code
  1024.             $code = $h->get_code ();
  1025.         }
  1026.         // if we should't highlight
  1027.         else
  1028.         {
  1029.             $language = 'Geen highlighting';
  1030.             // do some basic stuff
  1031.             $code = str_replace ("\t", '    ', $code);
  1032.             $code = str_replace (' ', '&nbsp;', $code);
  1033.             $code = nl2br ($code);
  1034.         }
  1035.  
  1036.         // create lines
  1037.         $lines = '';
  1038.         // loop
  1039.         for ($i = $start; $i <= $size; $i++)
  1040.         {
  1041.             $lines .= $i . '<br />';
  1042.         }
  1043.         // take away last <br />
  1044.         $lines = substr ($lines, 0, -6);
  1045.  
  1046.         // argument assignment
  1047.         $args = array (
  1048.             'CODE_NAME' => (isset ($args['file']))
  1049.                 ? ' (<i>' . $args['file'] . '</i>)'
  1050.                 : '',
  1051.             'CODE_LANGUAGE' => $language,
  1052.             'CODE_ID' => 'field_' . $this->_curr_id++,
  1053.             'CODE_LEFT_WIDTH' => 14 + ((strlen ($size) - 1) * 8),
  1054.             'CODE_LINES' => $lines,
  1055.             'CODE_CONTENT' => $code,
  1056.         );
  1057.  
  1058.         // return parsed text
  1059.         return $this->parse_bb_tpl ('code', $args);
  1060.     }
  1061.  
  1062.     /**
  1063.      * show a block without parsing
  1064.      *
  1065.      * @param    array   $args
  1066.      * @return   string
  1067.     **/
  1068.     function _parse_bb_ignore ($args)
  1069.     {
  1070.         // drop out of bb_mode
  1071.         $this->_bb_mode = false;
  1072.         // parse until /ignore
  1073.         $text = $this->_parse ('[/ignore]');
  1074.         // go back into bb_mode
  1075.         $this->_bb_mode = true;
  1076.         // and simply return
  1077.         return $text;
  1078.     }
  1079.  
  1080.     /**#@-*/
  1081. }
  1082.  
  1083.  
  1084. /**
  1085.  * Highlighting class, supporting multiple
  1086.  * languages in the form of language files,
  1087.  * using regexes to match keywords etc.
  1088.  *
  1089.  * @author    JeXuS
  1090.  * @package   TP
  1091. **/
  1092. class highlighter
  1093. {
  1094.     /**#@+
  1095.      * @access   private
  1096.     **/
  1097.  
  1098.     /**
  1099.      * holds the language data
  1100.      *
  1101.      * @var      array     _data
  1102.     **/
  1103.     var $_data = array ();
  1104.     /**
  1105.      * holds the highlighted text
  1106.      *
  1107.      * @var      string    _highlighted
  1108.     **/
  1109.     var $_highlighted = '';
  1110.     /**
  1111.      * holds the inserted code
  1112.      *
  1113.      * @var      string    _code
  1114.     **/
  1115.     var $_code = '';
  1116.     /**
  1117.      * holds the style used for highlighting
  1118.      *
  1119.      * @var      string    _span
  1120.     **/
  1121.     var $_span = '<span style="%s">%s</span>';
  1122.  
  1123.     /**#@-*/
  1124.  
  1125.     /**#@+
  1126.      * @access   public
  1127.     **/
  1128.  
  1129.     /**
  1130.      * The constructor, this makes sure the language
  1131.      * file is included, and then begins the highlighting
  1132.      * process.
  1133.      *
  1134.      * @param    string   $language
  1135.      * @param    string   $code
  1136.      * @return   boolean
  1137.     **/
  1138.  function highlighter ($language, $code)
  1139.     {
  1140.         // the current directory
  1141.         $this_dir = str_replace ('\\', '/', dirname (__FILE__));
  1142.  
  1143.         // we prefer unix newlines
  1144.         $code = str_replace (array ("\r\n", "\r"), "\n", $code);
  1145.         // erase beginning and ending newlines
  1146.         $code = trim ($code, "\n");
  1147.  
  1148.         // check if the given language is an existing
  1149.         // language file
  1150.         if (!is_file ($language))
  1151.         {
  1152.             // if not, remove all non-alpanumeric character
  1153.             $language = preg_replace ('~[^A-Za-z0-9]+~', '', $language);
  1154.             // and convert it to lowercase
  1155.             $language = strtolower ($language);
  1156.  
  1157.             // take the directory we're in from the __FILE__ constant, and
  1158.             // append the filename we want
  1159.             $filename = "{$this_dir}/languages/{$language}.lang.php";
  1160.  
  1161.             // if the file doesn't exist...
  1162.             if (!is_file ($filename))
  1163.             {
  1164.                 $this->_highlighted = nl2br (htmlspecialchars ($code));
  1165.                 return true;
  1166.             }
  1167.             // if the file does exist
  1168.             else
  1169.             {
  1170.                 // include it
  1171.                 include $filename;
  1172.             }
  1173.         }
  1174.         // if the language is an existing file
  1175.         else
  1176.         {
  1177.             // include it
  1178.             include $language;
  1179.         }
  1180.  
  1181.         // if the language data isn't set
  1182.         if (!isset ($language_data))
  1183.         {
  1184.             $this->_highlighted = nl2br (htmlspecialchars ($code));
  1185.             return true;
  1186.         }
  1187.  
  1188.         // set the language data to our member
  1189.         $this->_data = $language_data;
  1190.         // prepare all language regexes
  1191.         $this->_prepare_language ();
  1192.         // put the code in our member
  1193.         $this->_code = $code;
  1194.         // memory saving
  1195.         $code = '';
  1196.         // walk through the code
  1197.         $this->_walk_through ();
  1198.         // cleanup and finish the code
  1199.         $this->_finish_code ();
  1200.  
  1201.         // and return true
  1202.         return true;
  1203.     }
  1204.  
  1205.     /**
  1206.      * return parsed code
  1207.      *
  1208.      * @return   string
  1209.     **/
  1210.     function get_code ()
  1211.     {
  1212.         return $this->_highlighted;
  1213.     }
  1214.  
  1215.     /**#@-*/
  1216.  
  1217.     /**#@+
  1218.      * @access   private
  1219.     **/
  1220.  
  1221.     /**
  1222.      * prepare language regexes
  1223.      *
  1224.      * @return   boolean
  1225.     **/
  1226.     function _prepare_language ()
  1227.     {
  1228.         // the things we need to go through
  1229.         $correct = array (
  1230.             'script_delim', 'comments', 'strings',
  1231.             'regexes', 'symbols', 'keywords'
  1232.         );
  1233.  
  1234.         // check if oo_splitters should be done
  1235.         if (isset ($this->_data['oo_splitters']) && count ($this->_data['oo_splitters']) > 0)
  1236.         {
  1237.             $this->_data['is_oo_lang'] = true;
  1238.             $correct[] = 'oo_splitters';
  1239.         }
  1240.  
  1241.         // loop through the parts
  1242.         foreach ($correct as $part)
  1243.         {
  1244.             // check if we've an array to loop, or just one thing
  1245.             if (isset ($this->_data[$part][0]) && !is_array ($this->_data[$part][0]))
  1246.             {
  1247.                 // make it a regular regex, always starting at the beginning
  1248.                 $this->_data[$part][0]  = '~^' . str_replace ('~', '\~', $this->_data[$part][0]) . '~';
  1249.                 // try the dotall bit
  1250.                 $this->_data[$part][0] .= ($this->_data[$part][1] & QBB_DOTALL) ? 's' : '';
  1251.                 // and the caseless bit
  1252.                 $this->_data[$part][0] .= ($this->_data[$part][1] & QBB_CASELESS) ? 'i' : '';
  1253.                 // still make it an array
  1254.                 $this->_data[$part] = array ($this->_data[$part][0]);
  1255.             }
  1256.             // if it's an array
  1257.             else
  1258.             {
  1259.                 // loop through
  1260.                 foreach ($this->_data[$part] as $i => $piece)
  1261.                 {
  1262.                     // make it a regular regex, always starting at the beginning
  1263.                     $this->_data[$part][$i][0]  = '~^' . str_replace ('~', '\~', $this->_data[$part][$i][0]) . '~';
  1264.                     // try the dotall bit
  1265.                     $this->_data[$part][$i][0] .= ($this->_data[$part][$i][1] & QBB_DOTALL) ? 's' : '';
  1266.                     // and the caseless bit
  1267.                     $this->_data[$part][$i][0] .= ($this->_data[$part][$i][1] & QBB_CASELESS) ? 'i' : '';
  1268.                     // change it
  1269.                     $this->_data[$part][$i] = $this->_data[$part][$i][0];
  1270.                 }
  1271.             }
  1272.         }
  1273.         return true;
  1274.     }
  1275.  
  1276.     /**
  1277.      * cleanup and finish code
  1278.      *
  1279.      * @return boolean
  1280.     **/
  1281.     function _finish_code ()
  1282.     {
  1283.         // if it's empty
  1284.         if (empty ($this->_highlighted))
  1285.         {
  1286.             // return false
  1287.             return false;
  1288.         }
  1289.         // loop as long as the regex is valid
  1290.         while (preg_match ('~(<span[^>]+>)([^<]+)</span>(\s*)\1~', $this->_highlighted, $match))
  1291.         {
  1292.             // concat all span's with thesame color next to it
  1293.             $this->_highlighted = str_replace ($match[0], $match[1] . $match[2] . $match[3],
  1294.                 $this->_highlighted
  1295.             );
  1296.         }
  1297.         // replace tabs with four &nbsp;'s, and double spaces with 2 &nbsp;'s
  1298.         $this->_highlighted = str_replace (array ("\t", '  '), array ('&nbsp;&nbsp;&nbsp;&nbsp;', '&nbsp;&nbsp;'), $this->_highlighted);
  1299.         // graphical fix
  1300.         $this->_highlighted = str_replace ("\n ", "\n&nbsp;", $this->_highlighted);
  1301.         // nl2br, losing the \n
  1302.         $this->_highlighted = str_replace ("\n", '<br />', $this->_highlighted);
  1303.         // and return
  1304.         return true;
  1305.     }
  1306.  
  1307.     /**
  1308.      * checking if there's a valid match
  1309.      *
  1310.      * @param    integer   &$i
  1311.      * @param    array     $parts
  1312.      * @return   boolean
  1313.     **/
  1314.     function _check_for_match (&$i, $parts)
  1315.     {
  1316.         // the text to check
  1317.         $check_text = substr ($this->_code, $i);
  1318.  
  1319.         // loop through the parts given
  1320.         foreach ($parts as $part)
  1321.         {
  1322.             // go through the regexes
  1323.             foreach ($this->_data[$part] as $j => $regex)
  1324.             {
  1325.                 // try to match
  1326.                 if (preg_match ($regex, $check_text, $match))
  1327.                 {
  1328.                     // if it's a match with a keyword, and there's a links availabe...
  1329.                     if ($part == 'keywords' && !empty ($this->_data['links'][$j]))
  1330.                     {
  1331.                         // create a valid link
  1332.                         $link = sprintf ($this->_data['links'][$j], urlencode ($match[0]));
  1333.                         // attach an underline style
  1334.                         $style = $this->_data['styles'][$part][$j] . ' text-decoration: underline;';
  1335.                         // the piece will be only a link, no span
  1336.                         $piece = '<a href="' . $link . '" style="' . $style . '">' . htmlspecialchars ($match[0]) . '</a>';
  1337.                     }
  1338.                     // if it's a regular piece
  1339.                     else
  1340.                     {
  1341.                         // just a normal sprintf
  1342.                         $piece = sprintf (
  1343.                             $this->_span,
  1344.                             $this->_data['styles'][$part][$j],
  1345.                             htmlspecialchars ($match[0])
  1346.                         );
  1347.                     }
  1348.  
  1349.                     // append the piece
  1350.                     $this->_highlighted .= $piece;
  1351.                     // update &$i
  1352.                     $i += strlen ($match[0]) - 1;
  1353.                     // return true
  1354.                     return true;
  1355.                 }
  1356.             }
  1357.         }
  1358.  
  1359.         // return false
  1360.         return false;
  1361.     }
  1362.  
  1363.     /**
  1364.      * walk through the code, searching
  1365.      * for all kinds of things, comments,
  1366.      * strings, keywords etc.
  1367.      *
  1368.      * @return   boolean
  1369.     **/
  1370.     function _walk_through ()
  1371.     {
  1372.         // fixed length
  1373.         $length = strlen ($this->_code);
  1374.  
  1375.         // we're not in highlighting
  1376.         $in_highlighting = false;
  1377.         // should we check for delimiters
  1378.         $check_delim = true;
  1379.         // if the delimiters array is empty
  1380.         if (count ($this->_data['script_delim']) == 0)
  1381.         {
  1382.             // we always highlight
  1383.             $in_highlighting = true;
  1384.             // we don't check on delimiters
  1385.             $check_delim = false;
  1386.             // prepend the default color now
  1387.             $this->_highlighted .= '<span style="' . $this->_data['styles']['overall'] . '">';
  1388.         }
  1389.  
  1390.         // loop through
  1391.         for ($i = 0; $i < $length; $i++)
  1392.         {
  1393.             // take a big chunk of remaining code
  1394.             $text = substr ($this->_code, $i);
  1395.             // take the first character
  1396.             $first = substr ($text, 0, 1);
  1397.             // previous character
  1398.             $prev = substr ($this->_code, $i - 1, 1);
  1399.  
  1400.             // check if the first character is a space
  1401.             if (ctype_space ($first))
  1402.             {
  1403.                 // if so, append it
  1404.                 $this->_highlighted .= $first;
  1405.                 // and continue
  1406.                 continue;
  1407.             }
  1408.             /** note: the above increases speed a LOT **/
  1409.  
  1410.             // should we check for delimiters...
  1411.             if ($check_delim === true && $in_highlighting === false)
  1412.             {
  1413.                 // if we match a delimiter
  1414.                 if (preg_match ($this->_data['script_delim']['start'], $text, $match))
  1415.                 {
  1416.                     // append it to the source
  1417.                     $this->_highlighted .= '<span style="' . $this->_data['styles']['overall'] . '">';
  1418.                     // we're in highlighting
  1419.                     $in_highlighting = true;
  1420.                     // we need to start here again with highlighting
  1421.                     $i--;
  1422.                     // free ourselves from the loop
  1423.                     continue;
  1424.                 }
  1425.                 // append the first character
  1426.                 $this->_highlighted .= htmlspecialchars ($first);
  1427.                 // and continue
  1428.                 continue;
  1429.             }
  1430.  
  1431.             // check if in highlighting
  1432.             if ($in_highlighting === true)
  1433.             {
  1434.                 // check this last
  1435.                 if ($check_delim === true)
  1436.                 {
  1437.                     // try to match an ending delimiter
  1438.                     if (preg_match ($this->_data['script_delim']['end'], $text, $match))
  1439.                     {
  1440.                         // if matched, append it to the current code
  1441.                         $this->_highlighted .= htmlspecialchars ($match[0]) . '</span>';
  1442.                         // we've skipped out of highlighting
  1443.                         $in_highlighting = false;
  1444.                         // update counter
  1445.                         $i += strlen ($match[0]) - 1;
  1446.                         // go to the beginning of the loop
  1447.                         continue;
  1448.                     }
  1449.                 }
  1450.  
  1451.                 // in which parts should we look?
  1452.                 $find = array ('comments', 'strings', 'regexes');
  1453.                 // simple check if we MAY match keywords
  1454.                 if (!ctype_alpha ($prev) && $prev != '_')
  1455.                 {
  1456.                     // if correct, add it
  1457.                     $find[] = 'keywords';
  1458.                 }
  1459.  
  1460.                 // check for a match, give $i by reference
  1461.                 if ($this->_check_for_match ($i, $find))
  1462.                 {
  1463.                     // if matched, continue
  1464.                     continue;
  1465.                 }
  1466.  
  1467.                 // if we've got a `punct` character
  1468.                 if (ctype_punct ($first))
  1469.                 {
  1470.                     // check if this is an OO lang
  1471.                     if (isset ($this->_data['is_oo_lang']))
  1472.                     {
  1473.                         // if so, try to match a object splitter
  1474.                         if (preg_match ($this->_data['oo_splitters'][0], $text, $match))
  1475.                         {
  1476.                             // if matched, append this piece
  1477.                             $this->_highlighted .= sprintf (
  1478.                                 $this->_span,
  1479.                                 $this->_data['styles']['oo_splitters'][0],
  1480.                                 htmlspecialchars ($match[0])
  1481.                             );
  1482.                             // update $i
  1483.                             $i += strlen ($match[0]) - 1;
  1484.  
  1485.                             // new piece, not very long
  1486.                             $text = substr ($this->_code, $i, 100);
  1487.                             // try to match a method/child
  1488.                             if (preg_match ('~^[a-z*(_][a-z0-9_*]*~i', $text, $match))
  1489.                             {
  1490.                                 // if matched, append it
  1491.                                 $this->_highlighted .= sprintf (
  1492.                                     $this->_span,
  1493.                                     $this->_data['styles']['oo_methods'][0],
  1494.                                     htmlspecialchars ($match[0])
  1495.                                 );
  1496.                                 // update $i
  1497.                                 $i += strlen ($match[0]) - 1;
  1498.                             }
  1499.                             // continue in both cases
  1500.                             continue;
  1501.                         }
  1502.                     }
  1503.  
  1504.                     // loop through all symbols
  1505.                     foreach ($this->_data['symbols'] as $j => $regex)
  1506.                     {
  1507.                         // if we find a valid match
  1508.                         if (preg_match ($regex, $text, $match))
  1509.                         {
  1510.                             // if match, append |* starts to get boring
  1511.                             $this->_highlighted .= sprintf (
  1512.                                 $this->_span,
  1513.                                 $this->_data['styles']['symbols'][$j],
  1514.                                 htmlspecialchars ($match[0])
  1515.                             );
  1516.                             // update $i
  1517.                             $i += strlen ($match[0]) - 1;
  1518.                             // jump out of this loop, and continue the outer
  1519.                             continue 2;
  1520.                         }
  1521.                     }
  1522.                 }
  1523.  
  1524.                 // simple check
  1525.                 if (!ctype_alnum ($prev))
  1526.                 {
  1527.                     // try to match an integer/float
  1528.                     if (preg_match ('~^(?:0x[0-9A-Fa-f]+|[0-9]+(?:\.[0-9]+)?)~', $text, $match))
  1529.                     {
  1530.                         // if matched, append
  1531.                         $this->_highlighted .= sprintf (
  1532.                             $this->_span,
  1533.                             $this->_data['styles']['numbers'],
  1534.                             htmlspecialchars ($match[0])
  1535.                         );
  1536.                         // update $i
  1537.                         $i += strlen ($match[0]) - 1;
  1538.                         // continue
  1539.                         continue;
  1540.                     }
  1541.                 }
  1542.             }
  1543.             // append this character
  1544.             $this->_highlighted .= htmlspecialchars (substr ($this->_code, $i, 1));
  1545.         }
  1546.         // if we're still in highlighting
  1547.         if ($in_highlighting === true)
  1548.         {
  1549.             // append a closing span
  1550.             $this->_highlighted .= '</span>';
  1551.         }
  1552.  
  1553.         // return
  1554.         return true;
  1555.     }
  1556.  
  1557.     /**#@-*/
  1558. }
  1559. // ** EOF **
  1560. ?>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement