<?php

	/*
		Script Highlight for phpBB
		Version 1.5.1
		PHP4 compatible Version
		
		**************************************************************************
		
		Copyright (c) 2004 by Phillip 'Firebird' Berndt
		www.pberndt.com
		
		This program is free software; you can redistribute it and/or modify
		it under the terms of the GNU General Public License as published by
		the Free Software Foundation; either version 2 of the License, or
		(at your option) any later version.
	
		This program is distributed in the hope that it will be useful,
		but WITHOUT ANY WARRANTY; without even the implied warranty of
		MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
		GNU General Public License for more details.
	
	   	 For a full copy of the GPL visit
	    	http://www.gnu.org/licenses/gpl.txt
		
		**************************************************************************
		
		Install instructions:
		
		1) Copy this file to './includes/highlight_code.php'
		2) Open bbcode.php
		3) Search for a function called "bbencode_second_pass"
		4) Search for the line
		    $text = bbencode_second_pass_code($text, $uid, $bbcode_tpl);
		5) Replace it by
			require_once('./includes/highlight_code.php');
			$text = bbencode_do_highlight($text, $uid, $bbcode_tpl);
		6) Open overall_header.tpl and simple_header.tpl
		7) Add to _the top_ of the <style> .. </style> area:
		   @import url("includes/highlight_code.php");
		   
	*/
	
	class highlighter
	{
		var $text;
		var $parsed;
			
		var $keywords;
		var $inPhpBB;
		
		function highlighter()
		{
			// Generic keywords
			$this->keywords = array(
				// Data Types / Java / PHP
				'byte', 'short', 'int', 'long', 'boolean', 'char', 'float', 'double',
				'break', 'continue', 'do', 'while', 'for', 'if', 'else', 'switch', 
				'case', 'default', 'throw', 'try', 'catch', 'finally', 'class', 'extends',
				'implements', 'instanceof', 'interface', 'new', 'super', 'this', 'return',
				'void', 'abstract', 'private', 'public', 'protected', 'final', 'static',
				'throws', 'throw', 'import', 'package', 'native', 'synchronized', 
				'transient', 'volatile', 'and', 'or', 'xor', 'not', 'array', '__function__',
				'__class__', '__file__', '__line__', 'const', 'default', 'die', 'echo',
				'elseif', 'endif', 'endwhile', 'enddeclare', 'endforeach', 'endswitch', 'endfor',
				'foreach', 'eval', 'unset', 'require', 'include', 'require_once', 'include_once', 
				'list', 'global', 'as', 'function', 'var', 'isset',
				// HTML elements
				'a', 'abbr', 'acronym', 'address', 'applet', 'area', 'b', 
				'base', 'basefont', 'bdo', 'big', 'blockquote', 'body', 
				'br', 'button', 'caption', 'center', 'cite', 'code', 
				'col', 'colgroup', 'dd', 'del', 'dfn', 'dir', 
				'div', 'dl', 'dt', 'em', 'fieldset', 'font', 
				'form', 'frame', 'frameset', 'h1', 'h2', 'h3', 
				'h4', 'h5', 'h6', 'head', 'hr', 'html', 
				'i', 'iframe', 'img', 'input', 'ins', 'isindex', 
				'kbd', 'label', 'legend', 'li', 'link', 'map', 
				'menu', 'meta', 'noframes', 'noscript', 'object', 'ol', 
				'optgroup', 'option', 'p', 'param', 'pre', 'q', 
				's', 'samp', 'script', 'select', 'small', 'span', 
				'strike', 'strong', 'style', 'sub', 'sup', 'table', 
				'tbody', 'td', 'textarea', 'tfoot', 'th', 'thead', 
				'title', 'tr', 'tt', 'u', 'ul', 'var', 'end', 'dim',
				// HTML attributes
				'abbr', 'accept-charset', 'accept', 'accesskey', 'action', 'align', 'alink', 
				'alt', 'archive', 'axis', 'background', 'bgcolor', 'border', 
				'cellpadding', 'cellspacing', 'char', 'charoff', 'charset', 'checked', 
				'cite', 'class', 'classid', 'clear', 'code', 'codebase', 
				'codetype', 'color', 'cols', 'colspan', 'compact', 'content', 
				'coords', 'data', 'datetime', 'declare', 'defer', 'dir', 
				'disabled', 'enctype', 'face', 'for', 'frame', 'frameborder', 
				'headers', 'height', 'href', 'hreflang', 'hspace', 'http-equiv', 
				'id', 'ismap', 'label', 'lang', 'language', 'link', 
				'longdesc', 'marginheight', 'marginwidth', 'maxlength', 'media', 'method', 
				'multiple', 'name', 'nohref', 'noresize', 'noshade', 'nowrap', 
				'object', 'onblur', 'onchange', 'onclick', 'ondblclick', 'onfocus', 
				'onkeydown', 'onkeypress', 'onkeyup', 'onload', 'onmousedown', 'onmousemove', 
				'onmouseout', 'onmouseover', 'onmouseup', 'onreset', 'onselect', 'onsubmit', 
				'onunload', 'profile', 'prompt', 'readonly', 'rel', 'rev', 
				'rows', 'rowspan', 'rules', 'scheme', 'scope', 'scrolling', 
				'selected', 'shape', 'size', 'span', 'src', 'standby', 
				'start', 'style', 'summary', 'tabindex', 'target', 'text', 
				'title', 'type', 'usemap', 'valign', 'value', 'valuetype', 
				'version', 'vlink', 'vspace', 'width', 'onclick', 'onmouseover', 'onmouseout',
				'onfocus', 'onblur', 'onchange', 'onkeypress', 'onkeydown', 'onkeyup',
				// SQL
				'select', 'insert', 'update', 'delete', 'grant', 'where', 'union', 'join',
				'left', 'inner', 'right', 'group', 'order', 'by', 'from', 'limit'
			);
		}
		
		function add_default_keywords($whichKeywords)
		{
			switch($whichKeywords)
			{
				// CSS
				case 3:
					$addKeywords = array('color', 
					'font-weight', 'font-family', 'font-size', 'font-size-adjust', 'font-variant', 
					'font-style', 'font-stretch', 'text-decoration', 'text-transform', 'text-shadow', 
					'letter-spacing', 'word-spacing', 'line-height', 'vertical-align', 'text-indent', 
					'text-align', 'direction', 'unicode-bidi', 'background-color', 'background-image', 
					'background-attachment', 'background-repeat', 'background-position', 'background', 'border-width', 
					'border-top-width', 'border-left-width', 'border-bottom-width', 'border-right-width', 'border-color', 
					'border-style', 'border', 'border-top', 'border-left', 'border-bottom', 
					'border-right', 'margin', 'margin-top', 'margin-left', 'margin-bottom', 
					'margin-right', 'padding', 'padding-top', 'padding-left', 'padding-bottom', 
					'padding-right', 'top', 'left', 'bottom', 'right', 
					'width', 'min-width', 'max-width', 'height', 'z-index', 
					'visibility', 'overflow', 'float', 'clear', 'clip', 
					'display', 'white-space', 'list-style-type', 'list-style-image', 'list-style-position', 
					'list-style', 'table-layout', 'border-collapse', 'border-spacing', 'position');
					break;
					
				// SQL
				case 2:
					$addKeywords = array(
					'abort', 'abs', 'absolute', 'access', 'action', 'ada', 'add', 
					'admin', 'after', 'aggregate', 'alias', 'all', 'allocate', 
					'alter', 'analyse', 'analyze', 'and', 'any', 'are', 
					'array', 'as', 'asc', 'asensitive', 'assertion', 'assignment', 
					'asymmetric', 'at', 'atomic', 'authorization', 'avg', 'backward', 
					'before', 'begin', 'between', 'binary', 'bit', 'bitvar', 
					'bit_length', 'blob', 'boolean', 'both', 'breadth', 'by', 
					'c', 'cache', 'call', 'called', 'cardinality', 'cascade', 
					'cascaded', 'case', 'cast', 'catalog', 'catalog_name', 'chain', 
					'char', 'character', 'characteristics', 'character_length', 'character_set_catalog', 'character_set_name', 
					'character_set_schema', 'char_length', 'check', 'checked', 'checkpoint', 'class', 
					'class_origin', 'clob', 'close', 'cluster', 'coalesce', 'cobol', 
					'collate', 'collation', 'collation_catalog', 'collation_name', 'collation_schema', 'column', 
					'column_name', 'command_function', 'command_function_code', 'comment', 'commit', 'committed', 
					'completion', 'condition_number', 'connect', 'connection', 'connection_name', 'constraint', 
					'constraints', 'constraint_catalog', 'constraint_name', 'constraint_schema', 'constructor', 'contains', 
					'continue', 'convert', 'copy', 'corresponding', 'count', 'create', 
					'createdb', 'createuser', 'cross', 'cube', 'current', 'current_date', 
					'current_path', 'current_role', 'current_time', 'current_timestamp', 'current_user', 'cursor', 
					'cursor_name', 'cycle', 'data', 'database', 'date', 'datetime_interval_code', 
					'datetime_interval_precision', 'day', 'deallocate', 'dec', 'decimal', 'declare', 
					'default', 'deferrable', 'deferred', 'defined', 'definer', 'delete', 
					'delimiters', 'depth', 'deref', 'desc', 'describe', 'descriptor', 
					'destroy', 'destructor', 'deterministic', 'diagnostics', 'dictionary', 'disconnect', 
					'dispatch', 'distinct', 'do', 'domain', 'double', 'drop', 
					'dynamic', 'dynamic_function', 'dynamic_function_code', 'each', 'else', 'encoding', 
					'end', 'end-exec', 'equals', 'escape', 'every', 'except', 
					'exception', 'exclusive', 'exec', 'execute', 'existing', 'exists', 
					'explain', 'extend', 'external', 'extract', 'false', 'fetch', 
					'final', 'first', 'float', 'for', 'force', 'foreign', 
					'fortran', 'forward', 'found', 'free', 'from', 'full', 
					'function', 'g', 'general', 'generated', 'get', 'global', 
					'go', 'goto', 'grant', 'granted', 'group', 'grouping', 
					'handler', 'having', 'hierarchy', 'hold', 'host', 'hour', 
					'identity', 'ignore', 'ilike', 'immediate', 'implementation', 'in', 
					'increment', 'index', 'indicator', 'infix', 'inherits', 'initialize', 
					'initially', 'inner', 'inout', 'input', 'insensitive', 'insert', 
					'instance', 'instantiable', 'instead', 'int', 'integer', 'intersect', 
					'interval', 'into', 'invoker', 'is', 'isnull', 'isolation', 
					'iterate', 'join', 'k', 'key', 'key_member', 'key_type', 
					'lancompiler', 'language', 'large', 'last', 'lateral', 'leading', 
					'left', 'length', 'less', 'level', 'like', 'limit', 
					'listen', 'load', 'local', 'localtime', 'localtimestamp', 'location', 
					'locator', 'lock', 'lower', 'm', 'map', 'match', 
					'max', 'maxvalue', 'message_length', 'message_octet_length', 'message_text', 'method', 
					'min', 'minute', 'minvalue', 'mod', 'mode', 'modifies', 
					'modify', 'module', 'month', 'more', 'move', 'mumps', 
					'name', 'names', 'national', 'natural', 'nchar', 'nclob', 
					'new', 'next', 'no', 'nocreatedb', 'nocreateuser', 'none', 
					'not', 'nothing', 'notify', 'notnull', 'null', 'nullable', 
					'nullif', 'number', 'numeric', 'object', 'octet_length', 'of', 
					'off', 'offset', 'oids', 'old', 'on', 'only', 
					'open', 'operation', 'operator', 'option', 'options', 'or', 
					'order', 'ordinality', 'out', 'outer', 'output', 'overlaps', 
					'overlay', 'overriding', 'owner', 'pad', 'parameter', 'parameters', 
					'parameter_mode', 'parameter_name', 'parameter_ordinal_position', 'parameter_specific_catalog', 'parameter_specific_name', 'parameter_specific_schema', 
					'partial', 'pascal', 'password', 'path', 'pendant', 'pli', 
					'position', 'postfix', 'precision', 'prefix', 'preorder', 'prepare', 
					'preserve', 'primary', 'prior', 'privileges', 'procedural', 'procedure', 
					'public', 'read', 'reads', 'real', 'recursive', 'ref', 
					'references', 'referencing', 'reindex', 'relative', 'rename', 'repeatable', 
					'reset', 'restrict', 'result', 'return', 'returned_length', 'returned_octet_length', 
					'returned_sqlstate', 'returns', 'revoke', 'right', 'role', 'rollback', 
					'rollup', 'routine', 'routine_catalog', 'routine_name', 'routine_schema', 'row', 
					'rows', 'row_count', 'rule', 'savepoint', 'scale', 'schema', 
					'schema_name', 'scope', 'scroll', 'search', 'second', 'section', 
					'security', 'select', 'self', 'sensitive', 'sequence', 'serial', 
					'serializable', 'server_name', 'session', 'session_user', 'set', 'setof', 
					'sets', 'share', 'show', 'similar', 'simple', 'size', 
					'smallint', 'some', 'source', 'space', 'specific', 'specifictype', 
					'specific_name', 'sql', 'sqlcode', 'sqlerror', 'sqlexception', 'sqlstate', 
					'sqlwarning', 'start', 'state', 'statement', 'static', 'stdin', 
					'stdout', 'structure', 'style', 'subclass_origin', 'sublist', 'substring', 
					'sum', 'symmetric', 'sysid', 'system', 'system_user', 'table', 
					'table_name', 'temp', 'template', 'temporary', 'terminate', 'than', 
					'then', 'time', 'timestamp', 'timezone_hour', 'timezone_minute', 'to', 
					'toast', 'trailing', 'transaction', 'transactions_committed', 'transactions_rolled_back', 'transaction_active', 
					'transform', 'transforms', 'translate', 'translation', 'treat', 'trigger', 
					'trigger_catalog', 'trigger_name', 'trigger_schema', 'trim', 'true', 'truncate', 
					'trusted', 'type', 'uncommitted', 'under', 'union', 'unique', 
					'unknown', 'unlisten', 'unnamed', 'unnest', 'until', 'update', 
					'upper', 'usage', 'user', 'user_defined_type_catalog', 'user_defined_type_name', 'user_defined_type_schema', 
					'using', 'vacuum', 'valid', 'value', 'values', 'varchar', 
					'variable', 'varying', 'verbose', 'version', 'view', 'when', 
					'whenever', 'where', 'with', 'without', 'work', 'write', 
					'year', 'zone');
					break;
					
				// PHP Functions
				case 1:
					$addKeywords = get_defined_functions();
					$addKeywords = $addKeywords['internal'];
					return;
					// BUG!
					break;
			}
			
			$this->addKeywords($addKeywords);
		}
		
		// Add user defined keywords
		function addKeywords($keywords)
		{
			if(is_array($keywords))
				$this->keywords = array_merge($this->keywords, $keywords);
			elseif(is_string($keywords))
				$this->keywords[] = $keywords;
			else trigger_error('This is neither an array nor a string', E_USER_WARNING);
		}
		
		// Set whether this script runs from inside phpBB or not
		function inPhpBB($set)
		{
			$this->inPhpBB = is_bool($set) ? $set : false;
		}
		
		function &hl_tags()
		{
			// For correct handling of "\\", we need to convert \\ to html entities
			$this->parsed = str_replace('\\\\', '&#92;&#92;', $this->parsed);
			
			// All kinds of texts		
			$pcre 		  = '/(^|\s|\.|\(|\+|\=|\[|,|;)(&quot;&quot;|&quot;|\'|`)(.*)(?<!\\\\)\\2/siU';
			#$pcre_replace = '$1$2<span class="text">$3</span><!--text-->$2';
			if(!function_exists('hl_tags_textReplace'))
			{
				function hl_tags_textReplace($a)
				{
					return $a[1].$a[2].'<span class="text">'.str_replace('/*', '&#47;*', $a[3]).'</span>'.$a[2];
				}
			}
			$this->parsed = preg_replace_callback($pcre, 'hl_tags_textReplace', $this->parsed);
			
			// Heredoc notation of texts
			$pcre 		  = '/(^|\s|\.|\(|\+|\=|\[|,|;)&lt;&lt;&lt;(\S+)(.+)'."(\n\\2;?(?:\n|\$))/sU";
			$pcre_replace = '$1<span class="text">&lt;&lt;&lt;$2$3$4</span>';
			$this->parsed = preg_replace($pcre, $pcre_replace, $this->parsed);
			
			// Script tags
			$this->parsed = preg_replace('/&lt;script.*&gt;/siU', '<span class="tag">$0</span>', $this->parsed);
			
			// Code Tags
			$this->parsed = preg_replace('/(&lt;\?(php)?=?|\?&gt;|&lt;%=?|%&gt;)/si', '<span class="codetag">$0</span>', $this->parsed);			
			
			// Code Tags
			$this->parsed = preg_replace('/(&lt;\?(php)?=?|\?&gt;|&lt;%=?|%&gt;)/si', '<span class="codetag">$0</span>', $this->parsed);			
			
			// Unknown XML Tags
			$this->parsed = preg_replace('/(?!<>)(&lt;\/?)([a-z]+?(?:\s.+?)?)(&gt;)/si', '$1<span class="unknowntag">$2</span>$3', $this->parsed);
			
			
			return $this->parsed;
		}
		
		function hl_keywords()
		{
			// Highlight Keywords
			$keyword_pcre = implode('|', $this->keywords);
			$pcre		  = '/(\s|^|,|\)|\(|{|;|}|\[|&lt;\/?|=)('.$keyword_pcre.')(?=\s|$|,|=|\(|\)|;|:|\.|{|}|&gt;|\]|\/)/siU';
			$pcre_replace = '$1<span class="keyword">$2</span>';
			
			$this->parsed = preg_replace($pcre, $pcre_replace, $this->parsed);
			
			// Highlight numbers
			$this->parsed = preg_replace('/(\s|^|,|\)|\(|{|;|}|&lt;\/?|=)(\-?(?:[0-9]+e[0-9]+\.[0-9]+|[0-9]+\.[0-9]+|[0-9]+e[0-9]+|[0-9]+)(?:px|em|cm|%|in|mm|pt|pc|ex)?)(?=\s|$|,|=|\(|\)|;|:|{|}|&gt;|\/)/siU', '$1<span class="number">$2</span>$3', $this->parsed);
			$this->parsed = preg_replace('/(\s|^|,|\)|\(|{|;|}|&lt;\/?|=)(\-?0x(?:[0-9a-f]+e[0-9a-f]+\.[0-9a-f]+|[0-9a-f]+\.[0-9a-f]+|[0-9a-f]+e[0-9a-f]+|[0-9a-f]+))(?=\s|$|,|=|\(|\)|;|:|{|}|&gt;|\/)/siU', '$1<span class="number">$2</span>$3', $this->parsed);
			
			return $this->parsed;
		}
		
		function hl_comments()
		{
			// HTML comments are deactivated since some scripts use them - highlighting
			// would get auto-deactivated
			// $pcre 		  = '/(&lt;!--.+--&gt;|\/\*.+\*\/|\/\/.+\n|\n#.+\n)/siU';
			
			$pcre 		  = '/(\/\*.*\*\/|(?<=\s|^|;)(\/\/|REM ).*(?=\n|$)|(?<=\n|^)(#|\'|;).*(?=\n|$))/siU';
			$pcre_replace = '<span class="comment">$0</span>';
			$this->parsed = preg_replace($pcre, $pcre_replace, $this->parsed);
		}
		
		function hl_entities()
		{
			// HTML entities and PHP Variables
			$pcre 		  = '/(&amp;\S+(?<!&amp);|\$[A-Z0-9_\->]+?)/iU';
			$pcre_replace = '<span class="entity">$0</span>';
			$this->parsed = preg_replace($pcre, $pcre_replace, $this->parsed);
					
			// Any other HTML related stuff here
			// Colors
			$pcre 		  = '/#([0-9A-F]{6})(?![0-9A-F])/i';
			$pcre_replace = '<span class="htmlColor" onmouseover="this.firstChild.style.color=\'$0\'" onclick="this.style.backgroundColor=this.style.color=\'$0\';" onmouseout="this.style.backgroundColor=this.style.color=\'\';this.firstChild.style.color=\'\';"><span>#</span>$1</span>';
			$this->parsed = preg_replace($pcre, $pcre_replace, $this->parsed);
			
		}
		
		function set_colors($keywords = -1, $comments = -1, $tag = -1, $text = -1, $code)
		{
			if($keywords != -1) $this->color_keyword = $keywords;
			if($comments != -1) $this->color_comment = $comments;
			if($tag != -1) 		$this->color_tag 	 = $tag;
			if($text != -1) 	$this->color_text 	 = $text;
			if($code != -1) 	$this->color_code 	 = $code;
		}
		
		function parse($text = -1)
		{
			// Set text to parse
			if($text == -1)
				$text = $this->text;
			else 
				$this->text = $text;
						
			// Set $parsed to zero
			$this->parsed = $this->text;
			$this->parsed = str_replace("\r\n", "\n", $this->parsed);
			$parsed = &$this->parsed;
			
			// Convert > and <
			$parsed = str_replace(array('&', '<', '>'), array('&amp;', '&lt;', '&gt;'), $parsed);
			$parsed = str_replace('"', '&quot;', $parsed);
			
			// Rewrite PHP's ugly 'echo"Foo";' to 'echo "Foo";'
			$this->parsed = preg_replace('/(\s|^|,|\)|\(|{|;|}|&lt;\/?|=)(echo)(&quot;|\')/i', '$1$2 $3', $this->parsed);
			
			// Parse text
			$this->hl_keywords();
			$this->hl_tags();
			
			// Swapped 27.07.06 Phillip Berndt, POSSIBLE BUG CREATED!!
			$this->hl_comments();
			$this->hl_entities();
			// End of change
			
			// Convert special chars
			$parsed = str_replace('  ', '&nbsp; ', $parsed);
			$parsed = str_replace("\t", '&nbsp; &nbsp; ', $parsed);
			if(!$this->inPhpBB)
				$parsed = nl2br($parsed);
			
			// Return text
			return $this->parsed;
		}
		
		function put_default_css()
		{
			?>
				/*
					PhpBB Highlight Script
					Copyright (c) by Phillip 'Firebird' Berndt
					www.pberndt.com

					Version 1.5
				*/
				.highlight
				{
					color: #000000;
				}
				
				.highlight .keyword
				{
					color: #0000FF;
					font-weight: bold;
				}
				
				.highlight .unknowntag
				{
					color: #00589C;
				}
				
				.highlight .entity
				{
					color: #860000;
				}
				
				.highlight .codetag
				{
					color: #353535;
				}
				
				.highlight .number
				{
					color: #EE0000;
				}
				
				.highlight .comment, .highlight .comment .tag, .highlight .comment .text, .highlight .comment .code, .highlight .comment .keyword, .highlight .comment .entity, .highlight .comment .number, .highlight .comment .codetag, .highlight .comment .unknowntag, .highlight .comment a
				{
					color: #666666;
				}
				
				.highlight .text, .highlight .text .comment, .highlight .text .tag, .highlight .text .keyword, .highlight .text .code, .highlight .text .entity, .highlight .text .number, .highlight .text .codetag, .highlight .text .unknowntag, .highlight .comment .unknowntag, .highlight .text a
				{
					color: #009400;
				}

				.highlight .code, .highlight .code a
				{
					color: #222222;
					border: none;
				}	
				
				.highlight .htmlColor
				{
					cursor: pointer;
				}		
				
				.highlight a
				{
					text-decoration: underline;
				}		
			<?
		}
	}

	// BBCode callback for preg_replace
	function bbencode_highlight_callback($cb_data)
	{
		global $db;
		
		static $bbcode_tpl;
		if(!$bbcode_tpl)
		{
			$bbcode_tpl = $cb_data;
			return;
		}
		
		static $highlight;
		if(!$highlight)
		{
			$highlight = new highlighter();
			$highlight->add_default_keywords(3);
			//$highlight->add_default_keywords(1);
			$highlight->inPhpBB(true);
		}
		
		// Read code
		$text = $cb_data[1];
		$highlighting = true;
		
		$text = trim($text);
		
		// We need the plain code, so revoke HTML replacements
		$text = html_entity_decode($text);
		$text = preg_replace('/&#([0-9]{1,4});/ie', '@chr($1)', $text);
		
		// Remove leading empty line
		if(substr($text, 0, 1) == chr(13)) $text = substr($text, 2);

		if($highlighting)
			 $text = $highlight->parse($text);
		else $text = htmlspecialchars($text);
		
		// Remove leading empty line
		if(substr($text, 0, 1) == chr(13)) $text = substr($text, 2);
				
		// Encode Smilies
		$sql = 'SELECT * FROM ' . SMILIES_TABLE;
		if( !$result = $db->sql_query($sql) )
		{
			message_die(GENERAL_ERROR, "Couldn't obtain smilies data", "", __LINE__, __FILE__, $sql);
		}
		$smilies = $db->sql_fetchrowset($result);
		
		foreach($smilies as $smilie)
		{
			$smilie_encoded = '';
			for($i=0;$i<strlen($smilie['code']);$i++) $smilie_encoded .= '&#'.ord($smilie['code'][$i]).';';
			$text = preg_replace('/(?<!&quot)'.preg_quote($smilie['code'], '/').'/', $smilie_encoded, $text);
		}
		
		// We need some code to verify that URL's BBCode doesn't apply here
	   	$text = str_replace('[', '&#'.ord('[').';', $text);
	   	$text = str_replace(']', '&#'.ord(']').';', $text);
	   							
		// Add line numbers
		$lines = '';
		foreach(split("<br|\n", $text) as $line)
			$lines .= (str_pad(++$lineNumber, 3, '0', STR_PAD_LEFT).'<br/>');
		
		// Define Height for Code Tag
		$blockHeight = ($lineNumber < 25 ? 'max-' : '').'height:400px';
		$overFlow	 = 'overflow:auto;';
		
		// Just for IE, which has problems with too small code tags
		if(preg_match('/MSIE.*\)(?!Opera .*)$/', $_SERVER['HTTP_USER_AGENT']) &&
		   $lineNumber < 2)
		   {
				$blockHeight = 'height:36px';
				$overFlow	 = 'overflow:scroll;';
		   }	

		// For one-liners don't use line numbers
		if($lineNumber < 2) $lines = '';
		
		// Define an id for this code block
		if(!isset($GLOBALS['highlighter_codeTagId']))
			 $GLOBALS['highlighter_codeTagId'] = 0;
		$codeTagId = ++$GLOBALS['highlighter_codeTagId'];
		
		// The script for resizing
		$copyCodeBlock = (preg_match('/MSIE.*\)(?!Opera .*)$/', $_SERVER['HTTP_USER_AGENT'])) ? '<img src="includes/highlight_code.php?file=copy" alt="Kopieren" height="9" width="9" onclick="hl_copyClipboard(document.getElementById(\''.
	   	 'code'.$codeTagId.'\'));" />&nbsp;' : '';
	    $openCode = str_replace('Code:', $copyCodeBlock.'<img src="includes/highlight_code.php?file=plus" alt="Maximieren/Minimieren" height="9" width="9" onclick="this.src = changeCodeBlock(document.getElementById(\''.
	   	 'code'.$codeTagId.'\'));" /> Code:', $bbcode_tpl['code_open']);
					
		// Return the formated text
		return $openCode.
			'<div id="code'.$codeTagId.'" style="'.$overFlow.$blockHeight.';width:expression(document.body.clientWidth*.7);">'.$sizingScript.'<table><tr><td valign="top"><code><span style="background-color: #eeeeeee; color: #808080; font-size: 11px" >'.$lines.'</span></code></td>'.
			'<td nowrap><span style="color: #000000; font-size:8pt; font-size: 11px;"><code class="highlight">'.$text.'</code></div></td></tr></table></div>'.
			$bbcode_tpl['code_close'];
	}
	
	// BBCode highlight function for phpBB
	function bbencode_do_highlight($text, $uid, $bbcode_tpl)
	{
		// Highlight code tags
		bbencode_highlight_callback($bbcode_tpl);
		$text = preg_replace_callback('/\[code:1:'.$uid.'\](.*)\[\/code:1:'.$uid.'\]/siU', 'bbencode_highlight_callback', $text);
		
		// We do _always_ need our script to be sent out
		static $codeSent;
		if(!$codeSent)
		{
			if(preg_match('/MSIE.*\)(?!Opera .*)$/', $_SERVER['HTTP_USER_AGENT']))
				$text .= '<script type="text/javascript">function changeCodeBlock(o) {if(o.style.overflow == "auto"){o.style.overflow="";o.style.width="";o.style.height="";return "includes/highlight_code.php?file=minus";}else{o.style.overflow = "auto";o.style.width=document.body.clientWidth*.7;if(o.offsetHeight)o.style.height=Math.min(o.offsetHeight + 17, 400)+"px";else o.style.height = "400px";return "includes/highlight_code.php?file=plus";}}function hl_copyClipboard(o){if(!confirm("Codebox in Zwischenablage kopieren?"))return;if(!clipboardData.setData("text",o.firstChild.firstChild.firstChild.childNodes[1].innerText))alert("Kopieren fehlgeschlagen");}</script>';
			else 
				$text .= '<script type="text/javascript">function changeCodeBlock(o) {if(o.style.overflow == "auto"){o.style.overflow="";o.style.width="";o.style.height="";return "includes/highlight_code.php?file=minus";}else{o.style.overflow = "auto";o.style.width=document.body.clientWidth*.7;if(o.offsetHeight)o.style.height=Math.min(o.offsetHeight, 400)+"px";else o.style.height = "400px";return "includes/highlight_code.php?file=plus";}}</script>';	
		}
		
		$codeSent = true;
		
		return $text;
	}
	
	// If called directly, output CSS or images
	if(basename($_SERVER['PHP_SELF']) == basename(__FILE__))
	{
		switch($_GET['file'])
		{
			case 'minus':
				header('Content-type: image/gif');
				die(base64_decode('R0lGODlhCQAJAJEAAAAAAP///+/v7////yH5BAEAAAMALAAAAAAJAAkAAAIQhI+iK8brXgPzTHllfKiDAgA7'));
			case 'plus':
				header('Content-type: image/gif');
				die(base64_decode('R0lGODlhCQAJAJEAAAAAAP///+/v7////yH5BAEAAAMALAAAAAAJAAkAAAIRhI+iK7bwoJINIktzjizeUwAAOw=='));
			case 'copy':
				header('Content-type: image/gif');
				die(base64_decode('R0lGODlhCQAJAIAAAO/v7wAAACH5BAAAAAAALAAAAAAJAAkAQAIRjI+JAMFsYGyO1vkkzLPqDBUAOw=='));
			default:
				header('Content-type: text/css');
				$hl_class = new highlighter();
				die($hl_class->put_default_css());	
		}
	}
?>
