Index: trunk/web/punbb/include/parser.php
===================================================================
--- trunk/web/punbb/include/parser.php	(revision 10)
+++ trunk/web/punbb/include/parser.php	(revision 1)
@@ -1,9 +1,25 @@
 <?php
-
-/**
- * Copyright (C) 2008-2011 FluxBB
- * based on code by Rickard Andersson copyright (C) 2002-2008 PunBB
- * License: http://www.gnu.org/licenses/gpl.html GPL version 2 or higher
- */
+/***********************************************************************
+
+  Copyright (C) 2002-2005  Rickard Andersson (rickard@punbb.org)
+
+  This file is part of PunBB.
+
+  PunBB 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.
+
+  PunBB 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.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+  MA  02111-1307  USA
+
+************************************************************************/
 
 // Make sure no one attempts to run this script "directly"
@@ -11,52 +27,14 @@
 	exit;
 
-// Global variables
-/* regular expression to match nested BBCode LIST tags
-'%
-\[list                # match opening bracket and tag name of outermost LIST tag
-(?:=([1a*]))?+        # optional attribute capture in group 1
-\]                    # closing bracket of outermost opening LIST tag
-(                     # capture contents of LIST tag in group 2
-  (?:                 # non capture group for either contents or whole nested LIST
-	[^\[]*+           # unroll the loop! consume everything up to next [ (normal *)
-	(?:               # (See "Mastering Regular Expressions" chapter 6 for details)
-	  (?!             # negative lookahead ensures we are NOT on [LIST*] or [/LIST]
-		\[list        # opening LIST tag
-		(?:=[1a*])?+  # with optional attribute
-		\]            # closing bracket of opening LIST tag
-		|             # or...
-		\[/list\]     # a closing LIST tag
-	  )               # end negative lookahead assertion (we are not on a LIST tag)
-	  \[              # match the [ which is NOT the start of LIST tag (special)
-	  [^\[]*+         # consume everything up to next [ (normal *)
-	)*+               # finish up "unrolling the loop" technique (special (normal*))*
-  |                   # or...
-	(?R)              # recursively match a whole nested LIST element
-  )*                  # as many times as necessary until deepest nested LIST tag grabbed
-)                     # end capturing contents of LIST tag into group 2
-\[/list\]             # match outermost closing LIST tag
-%iex' */
-$re_list = '%\[list(?:=([1a*]))?+\]((?:[^\[]*+(?:(?!\[list(?:=[1a*])?+\]|\[/list\])\[[^\[]*+)*+|(?R))*)\[/list\]%ie';
-
-// Here you can add additional smilies if you like (please note that you must escape single quote and backslash)
-$smilies = array(
-	':)' => 'smile.png',
-	'=)' => 'smile.png',
-	':|' => 'neutral.png',
-	'=|' => 'neutral.png',
-	':(' => 'sad.png',
-	'=(' => 'sad.png',
-	':D' => 'big_smile.png',
-	'=D' => 'big_smile.png',
-	':o' => 'yikes.png',
-	':O' => 'yikes.png',
-	';)' => 'wink.png',
-	':/' => 'hmm.png',
-	':P' => 'tongue.png',
-	':p' => 'tongue.png',
-	':lol:' => 'lol.png',
-	':mad:' => 'mad.png',
-	':rolleyes:' => 'roll.png',
-	':cool:' => 'cool.png');
+
+// Load cache smiley
+@include_once PUN_ROOT.'cache/cache_smilies.php';
+if (!defined('PUN_CACHE_SMILEY'))
+{
+	require_once PUN_ROOT.'include/cache_smilies.php';
+	generate_smiley_cache();
+	require PUN_ROOT.'cache/cache_smilies.php';
+}
+
 
 //
@@ -65,800 +43,384 @@
 function preparse_bbcode($text, &$errors, $is_signature = false)
 {
-	global $pun_config, $lang_common, $lang_post, $re_list;
-
-	if ($is_signature)
-	{
-		global $lang_profile;
-
-		if (preg_match('%\[/?(?:quote|code|list|h)\b[^\]]*\]%i', $text))
-			$errors[] = $lang_profile['Signature quote/code/list/h'];
-	}
+	// Change all simple BBCodes to lower case
+	$a = array('[B]', '[I]', '[U]', '[/B]', '[/I]', '[/U]');
+	$b = array('[b]', '[i]', '[u]', '[/b]', '[/i]', '[/u]');
+	$text = str_replace($a, $b, $text);
+
+	// Do the more complex BBCodes (also strip excessive whitespace and useless quotes)
+	$a = array( '#\[url=("|\'|)(.*?)\\1\]\s*#i',
+				'#\[url\]\s*#i',
+				'#\s*\[/url\]#i',
+				'#\[email=("|\'|)(.*?)\\1\]\s*#i',
+				'#\[email\]\s*#i',
+				'#\s*\[/email\]#i',
+				'#\[img\]\s*(.*?)\s*\[/img\]#is',
+				'#\[colou?r=("|\'|)(.*?)\\1\](.*?)\[/colou?r\]#is');
+
+	$b = array(	'[url=$2]',
+				'[url]',
+				'[/url]',
+				'[email=$2]',
+				'[email]',
+				'[/email]',
+				'[img]$1[/img]',
+				'[color=$2]$3[/color]');
+
+	if (!$is_signature)
+	{
+		// For non-signatures, we have to do the quote and code tags as well
+		$a[] = '#\[quote=(&quot;|"|\'|)(.*?)\\1\]\s*#i';
+		$a[] = '#\[quote\]\s*#i';
+		$a[] = '#\s*\[/quote\]\s*#i';
+		$a[] = '#\[code\][\r\n]*(.*?)\s*\[/code\]\s*#is';
+
+		$b[] = '[quote=$1$2$1]';
+		$b[] = '[quote]';
+		$b[] = '[/quote]'."\n";
+		$b[] = '[code]$1[/code]'."\n";
+	}
+
+	// Run this baby!
+	$text = preg_replace($a, $b, $text);
+
+	if (!$is_signature)
+	{
+		$overflow = check_tag_order($text, $error);
+
+		if ($error)
+			// A BBCode error was spotted in check_tag_order()
+			$errors[] = $error;
+		else if ($overflow)
+			// The quote depth level was too high, so we strip out the inner most quote(s)
+			$text = substr($text, 0, $overflow[0]).substr($text, $overflow[1], (strlen($text) - $overflow[0]));
+	}
+	else
+	{
+		global $lang_prof_reg;
+
+		if (preg_match('#\[quote=(&quot;|"|\'|)(.*)\\1\]|\[quote\]|\[/quote\]|\[code\]|\[/code\]#i', $text))
+			message($lang_prof_reg['Signature quote/code']);
+	}
+
+	return trim($text);
+}
+
+
+//
+// Parse text and make sure that [code] and [quote] syntax is correct
+//
+function check_tag_order($text, &$error)
+{
+	global $lang_common;
+
+	// The maximum allowed quote depth
+	$max_depth = 3;
+
+	$cur_index = 0;
+	$q_depth = 0;
+
+	while (true)
+	{
+		// Look for regular code and quote tags
+		$c_start = strpos($text, '[code]');
+		$c_end = strpos($text, '[/code]');
+		$q_start = strpos($text, '[quote]');
+		$q_end = strpos($text, '[/quote]');
+
+		// Look for [quote=username] style quote tags
+		if (preg_match('#\[quote=(&quot;|"|\'|)(.*)\\1\]#sU', $text, $matches))
+			$q2_start = strpos($text, $matches[0]);
+		else
+			$q2_start = 65536;
+
+		// Deal with strpos() returning false when the string is not found
+		// (65536 is one byte longer than the maximum post length)
+		if ($c_start === false) $c_start = 65536;
+		if ($c_end === false) $c_end = 65536;
+		if ($q_start === false) $q_start = 65536;
+		if ($q_end === false) $q_end = 65536;
+
+		// If none of the strings were found
+		if (min($c_start, $c_end, $q_start, $q_end, $q2_start) == 65536)
+			break;
+
+		// We are interested in the first quote (regardless of the type of quote)
+		$q3_start = ($q_start < $q2_start) ? $q_start : $q2_start;
+
+		// We found a [quote] or a [quote=username]
+		if ($q3_start < min($q_end, $c_start, $c_end))
+		{
+			$step = ($q_start < $q2_start) ? 7 : strlen($matches[0]);
+
+			$cur_index += $q3_start + $step;
+
+			// Did we reach $max_depth?
+			if ($q_depth == $max_depth)
+				$overflow_begin = $cur_index - $step;
+
+			++$q_depth;
+			$text = substr($text, $q3_start + $step);
+		}
+
+		// We found a [/quote]
+		else if ($q_end < min($q_start, $c_start, $c_end))
+		{
+			if ($q_depth == 0)
+			{
+				$error = $lang_common['BBCode error'].' '.$lang_common['BBCode error 1'];
+				return;
+			}
+
+			$q_depth--;
+			$cur_index += $q_end+8;
+
+			// Did we reach $max_depth?
+			if ($q_depth == $max_depth)
+				$overflow_end = $cur_index;
+
+			$text = substr($text, $q_end+8);
+		}
+
+		// We found a [code]
+		else if ($c_start < min($c_end, $q_start, $q_end))
+		{
+			// Make sure there's a [/code] and that any new [code] doesn't occur before the end tag
+			$tmp = strpos($text, '[/code]');
+			$tmp2 = strpos(substr($text, $c_start+6), '[code]');
+			if ($tmp2 !== false)
+				$tmp2 += $c_start+6;
+				
+			if ($tmp === false || ($tmp2 !== false && $tmp2 < $tmp))
+			{
+				$error = $lang_common['BBCode error'].' '.$lang_common['BBCode error 2'];
+				return;
+			}
+			else
+				$text = substr($text, $tmp+7);
+
+			$cur_index += $tmp+7;
+		}
+
+		// We found a [/code] (this shouldn't happen since we handle both start and end tag in the if clause above)
+		else if ($c_end < min($c_start, $q_start, $q_end))
+		{
+			$error = $lang_common['BBCode error'].' '.$lang_common['BBCode error 3'];
+			return;
+		}
+	}
+
+	// If $q_depth <> 0 something is wrong with the quote syntax
+	if ($q_depth)
+	{
+		$error = $lang_common['BBCode error'].' '.$lang_common['BBCode error 4'];
+		return;
+	}
+	else if ($q_depth < 0)
+	{
+		$error = $lang_common['BBCode error'].' '.$lang_common['BBCode error 5'];
+		return;
+	}
+
+	// If the quote depth level was higher than $max_depth we return the index for the
+	// beginning and end of the part we should strip out
+	if (isset($overflow_begin))
+		return array($overflow_begin, $overflow_end);
+	else
+		return null;
+}
+
+
+//
+// Split text into chunks ($inside contains all text inside $start and $end, and $outside contains all text outside)
+//
+function split_text($text, $start, $end)
+{
+	global $pun_config;
+
+	$tokens = explode($start, $text);
+
+	$outside[] = $tokens[0];
+
+	$num_tokens = count($tokens);
+	for ($i = 1; $i < $num_tokens; ++$i)
+	{
+		$temp = explode($end, $tokens[$i]);
+		$inside[] = $temp[0];
+		$outside[] = $temp[1];
+	}
+
+	if ($pun_config['o_indent_num_spaces'] != 8 && $start == '[code]')
+	{
+		$spaces = str_repeat(' ', $pun_config['o_indent_num_spaces']);
+		$inside = str_replace("\t", $spaces, $inside);
+	}
+
+	return array($inside, $outside);
+}
+
+
+//
+// Truncate URL if longer than 55 characters (add http:// or ftp:// if missing)
+//
+function handle_url_tag($url, $link = '')
+{
+	global $pun_user;
+
+	$full_url = str_replace(array(' ', '\'', '`'), array('%20', '', ''), $url);
+	if (strpos($url, 'www.') === 0)			// If it starts with www, we add http://
+		$full_url = 'http://'.$full_url;
+	else if (strpos($url, 'ftp.') === 0)	// Else if it starts with ftp, we add ftp://
+		$full_url = 'ftp://'.$full_url;
+	else if (!preg_match('#^([a-z0-9]{3,6})://#', $url, $bah)) 	// Else if it doesn't start with abcdef://, we add http://
+		$full_url = 'http://'.$full_url;
+
+	// Ok, not very pretty :-)
+	$link = ($link == '' || $link == $url) ? ((strlen($url) > 55) ? substr($url, 0 , 39).' &hellip; '.substr($url, -10) : $url) : stripslashes($link);
+
+	return '<a href="'.$full_url.'" target=\"_blank\">'.$link.'</a>';
+}
+
+
+//
+// Turns an URL from the [img] tag into an <img> tag or a <a href...> tag
+//
+function handle_img_tag($url, $is_signature = false)
+{
+	global $lang_common, $pun_config, $pun_user;
+
+	$img_tag = '<a href="'.$url.'">&lt;'.$lang_common['Image link'].'&gt;</a>';
+
+	if ($is_signature && $pun_user['show_img_sig'] != '0')
+		$img_tag = '<img class="sigimage" src="'.$url.'" alt="'.htmlspecialchars($url).'" />';
+	else if (!$is_signature && $pun_user['show_img'] != '0')
+		$img_tag = '<img class="postimg" src="'.$url.'" alt="'.htmlspecialchars($url).'" />';
+
+	return $img_tag;
+}
+
+
+//
+// Convert BBCodes to their HTML equivalent
+//
+function do_bbcode($text)
+{
+	global $lang_common, $pun_user;
+
+	if (strpos($text, 'quote') !== false)
+	{
+		$text = str_replace('[quote]', '</p><blockquote><div class="incqbox"><p>', $text);
+		$text = preg_replace('#\[quote=(&quot;|"|\'|)(.*)\\1\]#seU', '"</p><blockquote><div class=\"incqbox\"><h4>".str_replace(array(\'[\', \'\\"\'), array(\'&#91;\', \'"\'), \'$2\')." ".$lang_common[\'wrote\'].":</h4><p>"', $text);
+		$text = preg_replace('#\[\/quote\]\s*#', '</p></div></blockquote><p>', $text);
+	}
+	
+	$pattern = array('#\[b\](.*?)\[/b\]#s',
+					 '#\[i\](.*?)\[/i\]#s',
+					 '#\[u\](.*?)\[/u\]#s',
+					 '#\[url\]([^\[]*?)\[/url\]#e',
+					 '#\[url=([^\[]*?)\](.*?)\[/url\]#e',
+					 '#\[email\]([^\[]*?)\[/email\]#',
+					 '#\[email=([^\[]*?)\](.*?)\[/email\]#',
+					 '#\[color=([a-zA-Z]*|\#?[0-9a-fA-F]{6})](.*?)\[/color\]#s',
+					 '#\[font=(.*?)](.*?)\[/font\]#s',
+					 '#\[align=(.*?)\](.*?)\[/align\]#s',
+					 '#\[hr /\]#',
+					 '#\[hr\]#',
+					 '#\[s\](.*?)\[/s\]#s',
+					 '#\[h\](.*?)\[/h\]#s',
+                               '#\[size=([0-9]{1,2})](.*?)\[/size\]#s');
+
+	$replace = array('<strong>$1</strong>',
+					 '<em>$1</em>',
+					 '<span class="bbu">$1</span>',
+					 'handle_url_tag(\'$1\')',
+					 'handle_url_tag(\'$1\', \'$2\')',
+					 '<a href="mailto:$1">$1</a>',
+					 '<a href="mailto:$1">$2</a>',
+					 '<span style="color: $1">$2</span>',
+					 '<span style="font-family: $1">$2</span>',
+					 '<div align="$1">$2</div>',
+					 '<hr />',
+					 '<hr />',
+					 '<del>$1</del>',
+					 '<span style="background-color: #FFFF00; color: #000000">$1</span>',
+                               '<span style="font-size: $1pt;">$2</span>');
+
+	// This thing takes a while! :)
+	$text = preg_replace($pattern, $replace, $text);
+
+	return $text;
+}
+
+
+//
+// Make hyperlinks clickable
+//
+function do_clickable($text)
+{
+	global $pun_user;
+
+	$text = ' '.$text;
+
+	$text = preg_replace('#([\s\(\)])(https?|ftp|news){1}://([\w\-]+\.([\w\-]+\.)*[\w]+(:[0-9]+)?(/[^"\s\(\)<\[]*)?)#ie', '\'$1\'.handle_url_tag(\'$2://$3\')', $text);
+	$text = preg_replace('#([\s\(\)])(www|ftp)\.(([\w\-]+\.)*[\w]+(:[0-9]+)?(/[^"\s\(\)<\[]*)?)#ie', '\'$1\'.handle_url_tag(\'$2.$3\', \'$2.$3\')', $text);
+
+	return substr($text, 1);
+}
+
+
+//
+// Convert a series of smilies to images
+//
+function do_smilies($text)
+{
+	global $smiley_text, $smiley_img;
+
+	$text = ' '.$text.' ';
+
+	$num_smilies = count($smiley_text);
+	for ($i = 0; $i < $num_smilies; ++$i)
+		$text = preg_replace("#(?<=.\W|\W.|^\W)".preg_quote($smiley_text[$i], '#')."(?=.\W|\W.|\W$)#m", '$1<img src="'.PUN_ROOT.'img/smilies/'.$smiley_img[$i].'" alt="'.substr($smiley_img[$i], 0, strrpos($smiley_img[$i], '.')).'" />$2', $text);
+
+	return substr($text, 1, -1);
+}
+
+
+//
+// Parse message text
+//
+function parse_message($text, $hide_smilies)
+{
+	global $pun_config, $lang_common, $pun_user;
+
+	if ($pun_config['o_censoring'] == '1')
+		$text = censor_words($text);
+
+	// Convert applicable characters to HTML entities
+	$text = pun_htmlspecialchars($text);
 
 	// If the message contains a code tag we have to split it up (text within [code][/code] shouldn't be touched)
 	if (strpos($text, '[code]') !== false && strpos($text, '[/code]') !== false)
-		list($inside, $text) = extract_blocks($text, '[code]', '[/code]', $errors);
-
-	// Tidy up lists
-	$temp = preg_replace($re_list, 'preparse_list_tag(\'$2\', \'$1\', $errors)', $text);
-
-	// If the regex failed
-	if ($temp === null)
-		$errors[] = $lang_common['BBCode list size error'];
-	else
-		$text = str_replace('*'."\0".']', '*]', $temp);
+	{
+		list($inside, $outside) = split_text($text, '[code]', '[/code]');
+		$outside = array_map('ltrim', $outside);
+		$text = implode('<">', $outside);
+	}
 
 	if ($pun_config['o_make_links'] == '1')
 		$text = do_clickable($text);
 
-	// If we split up the message before we have to concatenate it together again (code tags)
-	if (isset($inside))
-	{
-		$outside = explode("\1", $text);
-		$text = '';
-
-		$num_tokens = count($outside);
-		for ($i = 0; $i < $num_tokens; ++$i)
-		{
-			$text .= $outside[$i];
-			if (isset($inside[$i]))
-				$text .= '[code]'.$inside[$i].'[/code]';
-		}
-
-		unset($inside);
-	}
-
-	$temp_text = false;
-	if (empty($errors))
-		$temp_text = preparse_tags($text, $errors, $is_signature);
-
-	if ($temp_text !== false)
-		$text = $temp_text;
-
-	// Remove empty tags
-	while (($new_text = strip_empty_bbcode($text, $errors)) !== false)
-	{
-		if ($new_text != $text)
-		{
-			$text = $new_text;
-			if ($new_text == '')
-			{
-				$errors[] = $lang_post['Empty after strip'];
-				break;
-			}
-		}
-		else
-			break;
-	}
-
-	return pun_trim($text);
-}
-
-
-//
-// Strip empty bbcode tags from some text
-//
-function strip_empty_bbcode($text, &$errors)
-{
-	// If the message contains a code tag we have to split it up (empty tags within [code][/code] are fine)
-	if (strpos($text, '[code]') !== false && strpos($text, '[/code]') !== false)
-		list($inside, $text) = extract_blocks($text, '[code]', '[/code]', $errors);
-
-	// Remove empty tags
-	while (($new_text = preg_replace('%\[(b|u|s|ins|del|em|i|h|colou?r|quote|img|url|email|list|topic|post|forum|user)(?:\=[^\]]*)?\]\s*\[/\1\]%', '', $text)) !== NULL)
-	{
-		if ($new_text != $text)
-			$text = $new_text;
-		else
-			break;
-	}
-
-	// If we split up the message before we have to concatenate it together again (code tags)
-    if (isset($inside)) {
-        $parts = explode("\1", $text);
-        $text = '';
-        foreach ($parts as $i => $part)
-        {
-            $text .= $part;
-            if (isset($inside[$i]))
-                $text .= '[code]'.$inside[$i].'[/code]';
-        }
-    }
-
-	// Remove empty code tags
-	while (($new_text = preg_replace('%\[(code)\]\s*\[/\1\]%', '', $text)) !== NULL)
-	{
-		if ($new_text != $text)
-			$text = $new_text;
-		else
-			break;
-	}
-
-	return $text;
-}
-
-
-//
-// Check the structure of bbcode tags and fix simple mistakes where possible
-//
-function preparse_tags($text, &$errors, $is_signature = false)
-{
-	global $lang_common, $pun_config;
-
-	// Start off by making some arrays of bbcode tags and what we need to do with each one
-
-	// List of all the tags
-	$tags = array('quote', 'code', 'b', 'i', 'u', 's', 'ins', 'del', 'em', 'color', 'colour', 'url', 'email', 'img', 'list', '*', 'h', 'topic', 'post', 'forum', 'user');
-	// List of tags that we need to check are open (You could not put b,i,u in here then illegal nesting like [b][i][/b][/i] would be allowed)
-	$tags_opened = $tags;
-	// and tags we need to check are closed (the same as above, added it just in case)
-	$tags_closed = $tags;
-	// Tags we can nest and the depth they can be nested to
-	$tags_nested = array('quote' => $pun_config['o_quote_depth'], 'list' => 5, '*' => 5);
-	// Tags to ignore the contents of completely (just code)
-	$tags_ignore = array('code');
-	// Block tags, block tags can only go within another block tag, they cannot be in a normal tag
-	$tags_block = array('quote', 'code', 'list', 'h', '*');
-	// Inline tags, we do not allow new lines in these
-	$tags_inline = array('b', 'i', 'u', 's', 'ins', 'del', 'em', 'color', 'colour', 'h', 'topic', 'post', 'forum', 'user');
-	// Tags we trim interior space
-	$tags_trim = array('img');
-	// Tags we remove quotes from the argument
-	$tags_quotes = array('url', 'email', 'img', 'topic', 'post', 'forum', 'user');
-	// Tags we limit bbcode in
-	$tags_limit_bbcode = array(
-		'*' 	=> array('b', 'i', 'u', 's', 'ins', 'del', 'em', 'color', 'colour', 'url', 'email', 'list', 'img', 'code', 'topic', 'post', 'forum', 'user'),
-		'list' 	=> array('*'),
-		'url' 	=> array('img'),
-		'email' => array('img'),
-		'topic' => array('img'),
-		'post'  => array('img'),
-		'forum' => array('img'),
-		'user'  => array('img'),
-		'img' 	=> array(),
-		'h'		=> array('b', 'i', 'u', 's', 'ins', 'del', 'em', 'color', 'colour', 'url', 'email', 'topic', 'post', 'forum', 'user'),
-	);
-	// Tags we can automatically fix bad nesting
-	$tags_fix = array('quote', 'b', 'i', 'u', 's', 'ins', 'del', 'em', 'color', 'colour', 'url', 'email', 'h', 'topic', 'post', 'forum', 'user');
-
-	$split_text = preg_split('%(\[[\*a-zA-Z0-9-/]*?(?:=.*?)?\])%', $text, -1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);
-
-	$open_tags = array('fluxbb-bbcode');
-	$open_args = array('');
-	$opened_tag = 0;
-	$new_text = '';
-	$current_ignore = '';
-	$current_nest = '';
-	$current_depth = array();
-	$limit_bbcode = $tags;
-	$count_ignored = array();
-
-	foreach ($split_text as $current)
-	{
-		if ($current == '')
-			continue;
-
-		// Are we dealing with a tag?
-		if (substr($current, 0, 1) != '[' || substr($current, -1, 1) != ']')
-		{
-			// It's not a bbcode tag so we put it on the end and continue
-			// If we are nested too deeply don't add to the end
-			if ($current_nest)
-				continue;
-
-			$current = str_replace("\r\n", "\n", $current);
-			$current = str_replace("\r", "\n", $current);
-			if (in_array($open_tags[$opened_tag], $tags_inline) && strpos($current, "\n") !== false)
-			{
-				// Deal with new lines
-				$split_current = preg_split('%(\n\n+)%', $current, -1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);
-				$current = '';
-
-				if (!pun_trim($split_current[0], "\n")) // The first part is a linebreak so we need to handle any open tags first
-					array_unshift($split_current, '');
-
-				for ($i = 1; $i < count($split_current); $i += 2)
-				{
-					$temp_opened = array();
-					$temp_opened_arg = array();
-					$temp = $split_current[$i - 1];
-					while (!empty($open_tags))
-					{
-						$temp_tag = array_pop($open_tags);
-						$temp_arg = array_pop($open_args);
-
-						if (in_array($temp_tag , $tags_inline))
-						{
-							array_push($temp_opened, $temp_tag);
-							array_push($temp_opened_arg, $temp_arg);
-							$temp .= '[/'.$temp_tag.']';
-						}
-						else
-						{
-							array_push($open_tags, $temp_tag);
-							array_push($open_args, $temp_arg);
-							break;
-						}
-					}
-					$current .= $temp.$split_current[$i];
-					$temp = '';
-					while (!empty($temp_opened))
-					{
-						$temp_tag = array_pop($temp_opened);
-						$temp_arg = array_pop($temp_opened_arg);
-						if (empty($temp_arg))
-							$temp .= '['.$temp_tag.']';
-						else
-							$temp .= '['.$temp_tag.'='.$temp_arg.']';
-						array_push($open_tags, $temp_tag);
-						array_push($open_args, $temp_arg);
-					}
-					$current .= $temp;
-				}
-
-				if (array_key_exists($i - 1, $split_current))
-					$current .= $split_current[$i - 1];
-			}
-
-			if (in_array($open_tags[$opened_tag], $tags_trim))
-				$new_text .= pun_trim($current);
-			else
-				$new_text .= $current;
-
-			continue;
-		}
-
-		// Get the name of the tag
-		$current_arg = '';
-		if (strpos($current, '/') === 1)
-		{
-			$current_tag = substr($current, 2, -1);
-		}
-		else if (strpos($current, '=') === false)
-		{
-			$current_tag = substr($current, 1, -1);
-		}
-		else
-		{
-			$current_tag = substr($current, 1, strpos($current, '=')-1);
-			$current_arg = substr($current, strpos($current, '=')+1, -1);
-		}
-		$current_tag = strtolower($current_tag);
-
-		// Is the tag defined?
-		if (!in_array($current_tag, $tags))
-		{
-			// It's not a bbcode tag so we put it on the end and continue
-			if (!$current_nest)
-				$new_text .= $current;
-
-			continue;
-		}
-
-		// We definitely have a bbcode tag
-
-		// Make the tag string lower case
-		if ($equalpos = strpos($current,'='))
-		{
-			// We have an argument for the tag which we don't want to make lowercase
-			if (strlen(substr($current, $equalpos)) == 2)
-			{
-				// Empty tag argument
-				$errors[] = sprintf($lang_common['BBCode error empty attribute'], $current_tag);
-				return false;
-			}
-			$current = strtolower(substr($current, 0, $equalpos)).substr($current, $equalpos);
-		}
-		else
-			$current = strtolower($current);
-
-		// This is if we are currently in a tag which escapes other bbcode such as code
-		// We keep a cound of ignored bbcodes (code tags) so we can nest them, but
-		// only balanced sets of tags can be nested
-		if ($current_ignore)
-		{
-			// Increase the current ignored tags counter
-			if ('['.$current_ignore.']' == $current)
-			{
-				if (!isset($count_ignored[$current_tag]))
-					$count_ignored[$current_tag] = 2;
-				else
-					$count_ignored[$current_tag]++;
-			}
-
-			// Decrease the current ignored tags counter
-			if ('[/'.$current_ignore.']' == $current)
-				$count_ignored[$current_tag]--;
-
-			if ('[/'.$current_ignore.']' == $current && $count_ignored[$current_tag] == 0)
-			{
-				// We've finished the ignored section
-				$current = '[/'.$current_tag.']';
-				$current_ignore = '';
-				$count_ignored = array();
-			}
-
-			$new_text .= $current;
-
-			continue;
-		}
-
-		if ($current_nest)
-		{
-			// We are currently too deeply nested so lets see if we are closing the tag or not
-			if ($current_tag != $current_nest)
-				continue;
-
-			if (substr($current, 1, 1) == '/')
-				$current_depth[$current_nest]--;
-			else
-				$current_depth[$current_nest]++;
-
-			if ($current_depth[$current_nest] <= $tags_nested[$current_nest])
-				$current_nest = '';
-
-			continue;
-		}
-
-		// Check the current tag is allowed here
-		if (!in_array($current_tag, $limit_bbcode) && $current_tag != $open_tags[$opened_tag])
-		{
-			$errors[] = sprintf($lang_common['BBCode error invalid nesting'], $current_tag, $open_tags[$opened_tag]);
-			return false;
-		}
-
-		if (substr($current, 1, 1) == '/')
-		{
-			// This is if we are closing a tag
-			if ($opened_tag == 0 || !in_array($current_tag, $open_tags))
-			{
-				// We tried to close a tag which is not open
-				if (in_array($current_tag, $tags_opened))
-				{
-					$errors[] = sprintf($lang_common['BBCode error no opening tag'], $current_tag);
-					return false;
-				}
-			}
-			else
-			{
-				// Check nesting
-				while (true)
-				{
-					// Nesting is ok
-					if ($open_tags[$opened_tag] == $current_tag)
-					{
-						array_pop($open_tags);
-						array_pop($open_args);
-						$opened_tag--;
-						break;
-					}
-
-					// Nesting isn't ok, try to fix it
-					if (in_array($open_tags[$opened_tag], $tags_closed) && in_array($current_tag, $tags_closed))
-					{
-						if (in_array($current_tag, $open_tags))
-						{
-							$temp_opened = array();
-							$temp_opened_arg = array();
-							$temp = '';
-							while (!empty($open_tags))
-							{
-								$temp_tag = array_pop($open_tags);
-								$temp_arg = array_pop($open_args);
-
-								if (!in_array($temp_tag, $tags_fix))
-								{
-									// We couldn't fix nesting
-									$errors[] = sprintf($lang_common['BBCode error no closing tag'], array_pop($temp_opened));
-									return false;
-								}
-								array_push($temp_opened, $temp_tag);
-								array_push($temp_opened_arg, $temp_arg);
-
-								if ($temp_tag == $current_tag)
-									break;
-								else
-									$temp .= '[/'.$temp_tag.']';
-							}
-							$current = $temp.$current;
-							$temp = '';
-							array_pop($temp_opened);
-							array_pop($temp_opened_arg);
-
-							while (!empty($temp_opened))
-							{
-								$temp_tag = array_pop($temp_opened);
-								$temp_arg = array_pop($temp_opened_arg);
-								if (empty($temp_arg))
-									$temp .= '['.$temp_tag.']';
-								else
-									$temp .= '['.$temp_tag.'='.$temp_arg.']';
-								array_push($open_tags, $temp_tag);
-								array_push($open_args, $temp_arg);
-							}
-							$current .= $temp;
-							$opened_tag--;
-							break;
-						}
-						else
-						{
-							// We couldn't fix nesting
-							$errors[] = sprintf($lang_common['BBCode error no opening tag'], $current_tag);
-							return false;
-						}
-					}
-					else if (in_array($open_tags[$opened_tag], $tags_closed))
-						break;
-					else
-					{
-						array_pop($open_tags);
-						array_pop($open_args);
-						$opened_tag--;
-					}
-				}
-			}
-
-			if (in_array($current_tag, array_keys($tags_nested)))
-			{
-				if (isset($current_depth[$current_tag]))
-					$current_depth[$current_tag]--;
-			}
-
-			if (in_array($open_tags[$opened_tag], array_keys($tags_limit_bbcode)))
-				$limit_bbcode = $tags_limit_bbcode[$open_tags[$opened_tag]];
-			else
-				$limit_bbcode = $tags;
-
-			$new_text .= $current;
-
-			continue;
-		}
-		else
-		{
-			// We are opening a tag
-			if (in_array($current_tag, array_keys($tags_limit_bbcode)))
-				$limit_bbcode = $tags_limit_bbcode[$current_tag];
-			else
-				$limit_bbcode = $tags;
-
-			if (in_array($current_tag, $tags_block) && !in_array($open_tags[$opened_tag], $tags_block) && $opened_tag != 0)
-			{
-				// We tried to open a block tag within a non-block tag
-				$errors[] = sprintf($lang_common['BBCode error invalid nesting'], $current_tag, $open_tags[$opened_tag]);
-				return false;
-			}
-
-			if (in_array($current_tag, $tags_ignore))
-			{
-				// It's an ignore tag so we don't need to worry about what's inside it
-				$current_ignore = $current_tag;
-				$new_text .= $current;
-				continue;
-			}
-
-			// Deal with nested tags
-			if (in_array($current_tag, $open_tags) && !in_array($current_tag, array_keys($tags_nested)))
-			{
-				// We nested a tag we shouldn't
-				$errors[] = sprintf($lang_common['BBCode error invalid self-nesting'], $current_tag);
-				return false;
-			}
-			else if (in_array($current_tag, array_keys($tags_nested)))
-			{
-				// We are allowed to nest this tag
-
-				if (isset($current_depth[$current_tag]))
-					$current_depth[$current_tag]++;
-				else
-					$current_depth[$current_tag] = 1;
-
-				// See if we are nested too deep
-				if ($current_depth[$current_tag] > $tags_nested[$current_tag])
-				{
-					$current_nest = $current_tag;
-					continue;
-				}
-			}
-
-			// Remove quotes from arguments for certain tags
-			if (strpos($current, '=') !== false && in_array($current_tag, $tags_quotes))
-			{
-				$current = preg_replace('%\['.$current_tag.'=("|\'|)(.*?)\\1\]\s*%i', '['.$current_tag.'=$2]', $current);
-			}
-
-			if (in_array($current_tag, array_keys($tags_limit_bbcode)))
-				$limit_bbcode = $tags_limit_bbcode[$current_tag];
-
-			$open_tags[] = $current_tag;
-			$open_args[] = $current_arg;
-			$opened_tag++;
-			$new_text .= $current;
-			continue;
-		}
-	}
-
-	// Check we closed all the tags we needed to
-	foreach ($tags_closed as $check)
-	{
-		if (in_array($check, $open_tags))
-		{
-			// We left an important tag open
-			$errors[] = sprintf($lang_common['BBCode error no closing tag'], $check);
-			return false;
-		}
-	}
-
-	if ($current_ignore)
-	{
-		// We left an ignore tag open
-		$errors[] = sprintf($lang_common['BBCode error no closing tag'], $current_ignore);
-		return false;
-	}
-
-	return $new_text;
-}
-
-
-//
-// Preparse the contents of [list] bbcode
-//
-function preparse_list_tag($content, $type = '*', &$errors)
-{
-	global $lang_common, $re_list;
-
-	if (strlen($type) != 1)
-		$type = '*';
-
-	if (strpos($content,'[list') !== false)
-	{
-		$content = preg_replace($re_list, 'preparse_list_tag(\'$2\', \'$1\', $errors)', $content);
-	}
-
-	$items = explode('[*]', str_replace('\"', '"', $content));
-
-	$content = '';
-	foreach ($items as $item)
-	{
-		if (pun_trim($item) != '')
-			$content .= '[*'."\0".']'.str_replace('[/*]', '', pun_trim($item)).'[/*'."\0".']'."\n";
-	}
-
-	return '[list='.$type.']'."\n".$content.'[/list]';
-}
-
-
-//
-// Truncate URL if longer than 55 characters (add http:// or ftp:// if missing)
-//
-function handle_url_tag($url, $link = '', $bbcode = false)
-{
-	$url = pun_trim($url);
-	$full_url = str_replace(array(' ', '\'', '`', '"'), array('%20', '', '', ''), $url);
-	if (strpos($url, 'www.') === 0) // If it starts with www, we add http://
-		$full_url = 'http://'.$full_url;
-	else if (strpos($url, 'ftp.') === 0) // Else if it starts with ftp, we add ftp://
-		$full_url = 'ftp://'.$full_url;
-	else if (strpos($url, '/') === 0) // Allow for relative URLs that start with a slash
-		$full_url = get_base_url(true).$full_url;
-	else if (!preg_match('#^([a-z0-9]{3,6})://#', $url)) // Else if it doesn't start with abcdef://, we add http://
-		$full_url = 'http://'.$full_url;
-
-	// Ok, not very pretty :-)
-	if ($bbcode)
-	{
-		if ($full_url == $link)
-			return '[url]'.$link.'[/url]';
-		else
-			return '[url='.$full_url.']'.$link.'[/url]';
-	}
-	else
-	{
-		if ($link == '' || $link == $url)
-		{
-			$url = pun_htmlspecialchars_decode($url);
-			$link = utf8_strlen($url) > 55 ? utf8_substr($url, 0 , 39).' âŠ '.utf8_substr($url, -10) : $url;
-			$link = pun_htmlspecialchars($link);
-		}
-		else
-			$link = stripslashes($link);
-
-		return '<a href="'.$full_url.'">'.$link.'</a>';
-	}
-}
-
-
-//
-// Turns an URL from the [img] tag into an <img> tag or a <a href...> tag
-//
-function handle_img_tag($url, $is_signature = false, $alt = null)
-{
-	global $lang_common, $pun_user;
-
-	if ($alt == null)
-		$alt = basename($url);
-
-	$img_tag = '<a href="'.$url.'">&lt;'.$lang_common['Image link'].' - '.$alt.'&gt;</a>';
-
-	if ($is_signature && $pun_user['show_img_sig'] != '0')
-		$img_tag = '<img class="sigimage" src="'.$url.'" alt="'.$alt.'" />';
-	else if (!$is_signature && $pun_user['show_img'] != '0')
-		$img_tag = '<span class="postimg"><img src="'.$url.'" alt="'.$alt.'" /></span>';
-
-	return $img_tag;
-}
-
-
-//
-// Parse the contents of [list] bbcode
-//
-function handle_list_tag($content, $type = '*')
-{
-	global $re_list;
-
-	if (strlen($type) != 1)
-		$type = '*';
-
-	if (strpos($content,'[list') !== false)
-	{
-		$content = preg_replace($re_list, 'handle_list_tag(\'$2\', \'$1\')', $content);
-	}
-
-	$content = preg_replace('#\s*\[\*\](.*?)\[/\*\]\s*#s', '<li><p>$1</p></li>', pun_trim($content));
-
-	if ($type == '*')
-		$content = '<ul>'.$content.'</ul>';
-	else
-		if ($type == 'a')
-			$content = '<ol class="alpha">'.$content.'</ol>';
-		else
-			$content = '<ol class="decimal">'.$content.'</ol>';
-
-	return '</p>'.$content.'<p>';
-}
-
-
-//
-// Convert BBCodes to their HTML equivalent
-//
-function do_bbcode($text, $is_signature = false)
-{
-	global $lang_common, $pun_user, $pun_config, $re_list;
-
-	if (strpos($text, '[quote') !== false)
-	{
-		$text = preg_replace('%\[quote\]\s*%', '</p><div class="quotebox"><blockquote><div><p>', $text);
-		$text = preg_replace('%\[quote=(&quot;|&\#039;|"|\'|)(.*?)\\1\]%se', '"</p><div class=\"quotebox\"><cite>".str_replace(array(\'[\', \'\\"\'), array(\'&#91;\', \'"\'), \'$2\')." ".$lang_common[\'wrote\']."</cite><blockquote><div><p>"', $text);
-		$text = preg_replace('%\s*\[\/quote\]%S', '</p></div></blockquote></div><p>', $text);
-	}
-
-	if (!$is_signature)
-	{
-		$pattern[] = $re_list;
-		$replace[] = 'handle_list_tag(\'$2\', \'$1\')';
-	}
-
-	$pattern[] = '%\[b\](.*?)\[/b\]%ms';
-	$pattern[] = '%\[i\](.*?)\[/i\]%ms';
-	$pattern[] = '%\[u\](.*?)\[/u\]%ms';
-	$pattern[] = '%\[s\](.*?)\[/s\]%ms';
-	$pattern[] = '%\[del\](.*?)\[/del\]%ms';
-	$pattern[] = '%\[ins\](.*?)\[/ins\]%ms';
-	$pattern[] = '%\[em\](.*?)\[/em\]%ms';
-	$pattern[] = '%\[colou?r=([a-zA-Z]{3,20}|\#[0-9a-fA-F]{6}|\#[0-9a-fA-F]{3})](.*?)\[/colou?r\]%ms';
-	$pattern[] = '%\[h\](.*?)\[/h\]%ms';
-
-	$replace[] = '<strong>$1</strong>';
-	$replace[] = '<em>$1</em>';
-	$replace[] = '<span class="bbu">$1</span>';
-	$replace[] = '<span class="bbs">$1</span>';
-	$replace[] = '<del>$1</del>';
-	$replace[] = '<ins>$1</ins>';
-	$replace[] = '<em>$1</em>';
-	$replace[] = '<span style="color: $1">$2</span>';
-	$replace[] = '</p><h5>$1</h5><p>';
-
-	if (($is_signature && $pun_config['p_sig_img_tag'] == '1') || (!$is_signature && $pun_config['p_message_img_tag'] == '1'))
-	{
-		$pattern[] = '%\[img\]((ht|f)tps?://)([^\s<"]*?)\[/img\]%e';
-		$pattern[] = '%\[img=([^\[]*?)\]((ht|f)tps?://)([^\s<"]*?)\[/img\]%e';
-		if ($is_signature)
-		{
-			$replace[] = 'handle_img_tag(\'$1$3\', true)';
-			$replace[] = 'handle_img_tag(\'$2$4\', true, \'$1\')';
-		}
-		else
-		{
-			$replace[] = 'handle_img_tag(\'$1$3\', false)';
-			$replace[] = 'handle_img_tag(\'$2$4\', false, \'$1\')';
-		}
-	}
-
-	$pattern[] = '%\[url\]([^\[]*?)\[/url\]%e';
-	$pattern[] = '%\[url=([^\[]+?)\](.*?)\[/url\]%e';
-	$pattern[] = '%\[email\]([^\[]*?)\[/email\]%';
-	$pattern[] = '%\[email=([^\[]+?)\](.*?)\[/email\]%';
-	$pattern[] = '%\[topic\]([^\[]*?)\[/topic\]%e';
-	$pattern[] = '%\[topic=([^\[]+?)\](.*?)\[/topic\]%e';
-	$pattern[] = '%\[post\]([^\[]*?)\[/post\]%e';
-	$pattern[] = '%\[post=([^\[]+?)\](.*?)\[/post\]%e';
-	$pattern[] = '%\[forum\]([^\[]*?)\[/forum\]%e';
-	$pattern[] = '%\[forum=([^\[]+?)\](.*?)\[/forum\]%e';
-	$pattern[] = '%\[user\]([^\[]*?)\[/user\]%e';
-	$pattern[] = '%\[user=([^\[]+?)\](.*?)\[/user\]%e';
-
-	$replace[] = 'handle_url_tag(\'$1\')';
-	$replace[] = 'handle_url_tag(\'$1\', \'$2\')';
-	$replace[] = '<a href="mailto:$1">$1</a>';
-	$replace[] = '<a href="mailto:$1">$2</a>';
-	$replace[] = 'handle_url_tag(\''.get_base_url(true).'/viewtopic.php?id=$1\')';
-	$replace[] = 'handle_url_tag(\''.get_base_url(true).'/viewtopic.php?id=$1\', \'$2\')';
-	$replace[] = 'handle_url_tag(\''.get_base_url(true).'/viewtopic.php?pid=$1#p$1\')';
-	$replace[] = 'handle_url_tag(\''.get_base_url(true).'/viewtopic.php?pid=$1#p$1\', \'$2\')';
-	$replace[] = 'handle_url_tag(\''.get_base_url(true).'/viewforum.php?id=$1\')';
-	$replace[] = 'handle_url_tag(\''.get_base_url(true).'/viewforum.php?id=$1\', \'$2\')';
-	$replace[] = 'handle_url_tag(\''.get_base_url(true).'/profile.php?id=$1\')';
-	$replace[] = 'handle_url_tag(\''.get_base_url(true).'/profile.php?id=$1\', \'$2\')';
-
-	// This thing takes a while! :)
-	$text = preg_replace($pattern, $replace, $text);
-
-	return $text;
-}
-
-
-//
-// Make hyperlinks clickable
-//
-function do_clickable($text)
-{
-	$text = ' '.$text;
-
-	$text = ucp_preg_replace('%(?<=[\s\]\)])(<)?(\[)?(\()?([\'"]?)(https?|ftp|news){1}://([\p{L}\p{N}\-]+\.([\p{L}\p{N}\-]+\.)*[\p{L}\p{N}]+(:[0-9]+)?(/[^\s\[]*[^\s.,?!\[;:-])?)\4(?(3)(\)))(?(2)(\]))(?(1)(>))(?![^\s]*\[/(?:url|img)\])%uie', 'stripslashes(\'$1$2$3$4\').handle_url_tag(\'$5://$6\', \'$5://$6\', true).stripslashes(\'$4$10$11$12\')', $text);
-	$text = ucp_preg_replace('%(?<=[\s\]\)])(<)?(\[)?(\()?([\'"]?)(www|ftp)\.(([\p{L}\p{N}\-]+\.)*[\p{L}\p{N}]+(:[0-9]+)?(/[^\s\[]*[^\s.,?!\[;:-])?)\4(?(3)(\)))(?(2)(\]))(?(1)(>))(?![^\s]*\[/(?:url|img)\])%uie', 'stripslashes(\'$1$2$3$4\').handle_url_tag(\'$5.$6\', \'$5.$6\', true).stripslashes(\'$4$10$11$12\')', $text);
-
-	return substr($text, 1);
-}
-
-
-//
-// Convert a series of smilies to images
-//
-function do_smilies($text)
-{
-	global $pun_config, $smilies;
-
-	$text = ' '.$text.' ';
-
-	foreach ($smilies as $smiley_text => $smiley_img)
-	{
-		if (strpos($text, $smiley_text) !== false)
-			$text = ucp_preg_replace('%(?<=[>\s])'.preg_quote($smiley_text, '%').'(?=[^\p{L}\p{N}])%um', '<img src="'.pun_htmlspecialchars(get_base_url(true).'/img/smilies/'.$smiley_img).'" width="15" height="15" alt="'.substr($smiley_img, 0, strrpos($smiley_img, '.')).'" />', $text);
-	}
-
-	return substr($text, 1, -1);
-}
-
-
-//
-// Parse message text
-//
-function parse_message($text, $hide_smilies)
-{
-	global $pun_config, $lang_common, $pun_user;
-
-	if ($pun_config['o_censoring'] == '1')
-		$text = censor_words($text);
-
-	// Convert applicable characters to HTML entities
-	$text = pun_htmlspecialchars($text);
-
-	// If the message contains a code tag we have to split it up (text within [code][/code] shouldn't be touched)
-	if (strpos($text, '[code]') !== false && strpos($text, '[/code]') !== false)
-		list($inside, $text) = extract_blocks($text, '[code]', '[/code]', $errors);
-
-	if ($pun_config['p_message_bbcode'] == '1' && strpos($text, '[') !== false && strpos($text, ']') !== false)
-		$text = do_bbcode($text);
-
 	if ($pun_config['o_smilies'] == '1' && $pun_user['show_smilies'] == '1' && $hide_smilies == '0')
 		$text = do_smilies($text);
+
+	if ($pun_config['p_message_bbcode'] == '1' && strpos($text, '[') !== false && strpos($text, ']') !== false)
+	{
+		$text = do_bbcode($text);
+
+		if ($pun_config['p_message_img_tag'] == '1')
+		{
+//			$text = preg_replace('#\[img\]((ht|f)tps?://)([^\s<"]*?)\.(jpg|jpeg|png|gif)\[/img\]#e', 'handle_img_tag(\'$1$3.$4\')', $text);
+			$text = preg_replace('#\[img\]((ht|f)tps?://)([^\s<"]*?)\[/img\]#e', 'handle_img_tag(\'$1$3\')', $text);
+		}
+	}
 
 	// Deal with newlines, tabs and multiple spaces
@@ -868,22 +430,35 @@
 
 	// If we split up the message before we have to concatenate it together again (code tags)
-    if (isset($inside)) {
-        $parts = explode("\1", $text);
-        $text = '';
-        foreach ($parts as $i => $part)
-        {
-            $text .= $part;
-            if (isset($inside[$i]))
-            {
-                $num_lines = (substr_count($inside[$i], "\n"));
-                $text .= '</p><div class="codebox"><pre'.(($num_lines > 28) ? ' class="vscroll"' : '').'><code>'.pun_trim($inside[$i], "\n\r").'</code></pre></div><p>';
-            }
-        }
-    }
+	if (isset($inside))
+	{
+		$outside = explode('<">', $text);
+		$text = '';
+
+		$num_tokens = count($outside);
+
+		for ($i = 0; $i < $num_tokens; ++$i)
+		{
+			$text .= $outside[$i];
+			if (isset($inside[$i]))
+			{
+				$num_lines = ((substr_count($inside[$i], "\n")) + 3) * 1.5;
+				$height_str = ($num_lines > 35) ? '35em' : $num_lines.'em';
+				$text .= '</p><div class="codebox"><div class="incqbox"><h4>'.$lang_common['Code'].':</h4><div class="scrollbox" style="height: '.$height_str.'"><pre>'.$inside[$i].'</pre></div></div></div><p>';
+			}
+		}
+	}
 
 	// Add paragraph tag around post, but make sure there are no empty paragraphs
-	$text = preg_replace('%<br />\s*?<br />((\s*<br />)*)%i', "</p>$1<p>", $text);
-	$text = str_replace('<p><br />', '<p>', $text);
 	$text = str_replace('<p></p>', '', '<p>'.$text.'</p>');
+
+	// Mod: Flash MP3 Player (8 nouvelles lignes suivent)
+	$player_url     = 'dewplayer-multi.swf';
+	$player_bgcolor = 'ffffff';
+	$player_width   = 240;
+	$player_height  = 20;
+	$player_param   = '?bgcolor='.$player_bgcolor.'&amp;mp3=$1';  // Pour plus d'options: http://www.alsacreations.fr/?dewplayer
+	$player_alternative = '<strong>Flash non dÃ©tÃ©ctÃ©</strong>';
+	$player_code = "\n\t\t\t\t\t<object type=\"application/x-shockwave-flash\" data=\"".$player_url.$player_param."\" width=\"".$player_width."\" height=\"".$player_height."\">\n\t\t\t\t\t  <param name=\"movie\" value=\"".$player_url.$player_param."\" />\n\t\t\t\t\t  <param name=\"bgcolor\" value=\"#".$player_bgcolor."\" />\n\t\t\t\t\t  ".$player_alternative."\n\t\t\t\t\t</object>\n\t\t\t\t\t";
+	$text = preg_replace("/\[mp3 url=([^ ]+)\]/", $player_code, $text);
 
 	return $text;
@@ -901,13 +476,22 @@
 		$text = censor_words($text);
 
-	// Convert applicable characters to HTML entities
 	$text = pun_htmlspecialchars($text);
 
+	if ($pun_config['o_make_links'] == '1')
+		$text = do_clickable($text);
+
+	if ($pun_config['o_smilies_sig'] == '1' && $pun_user['show_smilies'] != '0')
+		$text = do_smilies($text);
+
 	if ($pun_config['p_sig_bbcode'] == '1' && strpos($text, '[') !== false && strpos($text, ']') !== false)
-		$text = do_bbcode($text, true);
-
-	if ($pun_config['o_smilies_sig'] == '1' && $pun_user['show_smilies'] == '1')
-		$text = do_smilies($text);
-
+	{
+		$text = do_bbcode($text);
+
+		if ($pun_config['p_sig_img_tag'] == '1')
+		{
+//			$text = preg_replace('#\[img\]((ht|f)tps?://)([^\s<"]*?)\.(jpg|jpeg|png|gif)\[/img\]#e', 'handle_img_tag(\'$1$3.$4\', true)', $text);
+			$text = preg_replace('#\[img\]((ht|f)tps?://)([^\s<"]*?)\[/img\]#e', 'handle_img_tag(\'$1$3\', true)', $text);
+		}
+	}
 
 	// Deal with newlines, tabs and multiple spaces
@@ -916,9 +500,5 @@
 	$text = str_replace($pattern, $replace, $text);
 
-	// Add paragraph tag around post, but make sure there are no empty paragraphs
-	$text = preg_replace('%<br />\s*?<br />((\s*<br />)*)%i', "</p>$1<p>", $text);
-	$text = str_replace('<p><br />', '<p>', $text);
-	$text = str_replace('<p></p>', '', '<p>'.$text.'</p>');
-
 	return $text;
 }
+?>
