diff --git a/extras/12_to_1219_update.php b/extras/12_to_1219_update.php
deleted file mode 100644
index 5bf9482..0000000
--- a/extras/12_to_1219_update.php
+++ /dev/null
@@ -1,189 +0,0 @@
-<?php
-/***********************************************************************
-
-  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
-
-************************************************************************/
-
-
-// This script updates the forum database from version 1.2.* to 1.2.19
-// Copy this file to the forum root directory and run it. Then remove it from
-// the root directory.
-
-
-$update_from = array('1.2', '1.2.1', '1.2.2', '1.2.3', '1.2.4', '1.2.5', '1.2.6', '1.2.7', '1.2.8', '1.2.9', '1.2.10', '1.2.11', '1.2.12', '1.2.13', '1.2.14', '1.2.15', '1.2.16', '1.2.17', '1.2.18');
-$update_to = '1.2.19';
-
-
-define('PUN_ROOT', './');
-@include PUN_ROOT.'config.php';
-
-// If PUN isn't defined, config.php is missing or corrupt or we are outside the root directory
-if (!defined('PUN'))
-	exit('This file must be run from the forum root directory.');
-
-// Enable debug mode
-define('PUN_DEBUG', 1);
-
-// Disable error reporting for uninitialized variables
-error_reporting(E_ERROR | E_WARNING | E_PARSE);
-
-// Turn off magic_quotes_runtime
-set_magic_quotes_runtime(0);
-
-// Turn off PHP time limit
-@set_time_limit(0);
-
-
-// Load the functions script
-require PUN_ROOT.'include/functions.php';
-
-
-// Load DB abstraction layer and try to connect
-require PUN_ROOT.'include/dblayer/common_db.php';
-
-
-// Check current version
-$result1 = $db->query('SELECT cur_version FROM '.$db->prefix.'options');
-$result2 = $db->query('SELECT conf_value FROM '.$db->prefix.'config WHERE conf_name=\'o_cur_version\'');
-$cur_version = ($result1) ? $db->result($result1) : (($result2 && $db->num_rows($result2)) ? $db->result($result2) : 'beta');
-
-if (!in_array($cur_version, $update_from))
-	error('Version mismatch. This script updates version '.implode(', ', $update_from).' to version '.$update_to.'. The database \''.$db_name.'\' doesn\'t seem to be running a supported version.', __FILE__, __LINE__);
-
-
-// Get the forum config
-$result = $db->query('SELECT * FROM '.$db->prefix.'config');
-while ($cur_config_item = $db->fetch_row($result))
-	$pun_config[$cur_config_item[0]] = $cur_config_item[1];
-
-
-if (!isset($_POST['form_sent']))
-{
-
-?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-
-<html dir="ltr">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
-<title>FluxBB Update</title>
-<link rel="stylesheet" type="text/css" href="style/Oxygen.css" />
-</head>
-<body>
-
-<div id="punwrap">
-<div id="puninstall" class="pun" style="margin: 10% 20% auto 20%">
-
-<div class="blockform">
-	<h2><span>FluxBB Update</span></h2>
-	<div class="box">
-		<form method="post" action="<?php echo $_SERVER['PHP_SELF'] ?>" onsubmit="this.start.disabled=true">
-			<div><input type="hidden" name="form_sent" value="1" /></div>
-			<div class="inform">
-				<p style="font-size: 1.1em">This script will update your current PunBB/FluxBB <?php echo $cur_version ?> forum database to FluxBB <?php echo $update_to ?>. The update procedure might take anything from a second to a few minutes depending on the speed of the server and the size of the forum database. Don't forget to make a backup of the database before continuing.</p>
-				<p style="font-size: 1.1em">Did you read the update instructions in the documentation? If not, start there.</p>
-			</div>
-			<p><input type="submit" name="start" value="Start upgrade" /></p>
-		</form>
-	</div>
-</div>
-
-</div>
-</div>
-
-</body>
-</html>
-<?php
-
-}
-else
-{
-	// If we're upgrading from 1.2
-	if ($cur_version == '1.2')
-	{
-		// Insert new config option o_additional_navlinks
-		$db->query('INSERT INTO '.$db->prefix.'config (conf_name, conf_value) VALUES(\'o_additional_navlinks\', NULL)') or error('Unable to alter DB structure.', __FILE__, __LINE__, $db->error());
-	}
-
-	// We need to add a unique index to avoid users having multiple rows in the online table
-	if ($db_type == 'mysql' || $db_type == 'mysqli')
-	{
-		$result = $db->query('SHOW INDEX FROM '.$db->prefix.'online') or error('Unable to check DB structure.', __FILE__, __LINE__, $db->error());
-
-		if ($db->num_rows($result) == 1)
-			$db->query('ALTER TABLE '.$db->prefix.'online ADD UNIQUE INDEX '.$db->prefix.'online_user_id_ident_idx(user_id,ident)') or error('Unable to alter DB structure.', __FILE__, __LINE__, $db->error());
-	}
-
-	// This feels like a good time to synchronize the forums
-	$result = $db->query('SELECT id FROM '.$db->prefix.'forums') or error('Unable to fetch forum info.', __FILE__, __LINE__, $db->error());
-
-	while ($row = $db->fetch_row($result))
-		update_forum($row[0]);
-
-
-	// We'll empty the search cache table as well (using DELETE FROM since SQLite does not support TRUNCATE TABLE)
-	$db->query('DELETE FROM '.$db->prefix.'search_cache') or error('Unable to flush search results.', __FILE__, __LINE__, $db->error());
-
-
-	// Finally, we update the version number
-	$db->query('UPDATE '.$db->prefix.'config SET conf_value=\''.$update_to.'\' WHERE conf_name=\'o_cur_version\'') or error('Unable to update version.', __FILE__, __LINE__, $db->error());
-
-
-	// Delete all .php files in the cache (someone might have visited the forums while we were updating and thus, generated incorrect cache files)
-	$d = dir(PUN_ROOT.'cache');
-	while (($entry = $d->read()) !== false)
-	{
-		if (substr($entry, strlen($entry)-4) == '.php')
-			@unlink(PUN_ROOT.'cache/'.$entry);
-	}
-	$d->close();
-
-?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-
-<html dir="ltr">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
-<title>FluxBB Update</title>
-<link rel="stylesheet" type="text/css" href="style/Oxygen.css" />
-</head>
-<body>
-
-<div id="punwrap">
-<div id="puninstall" class="pun" style="margin: 10% 20% auto 20%">
-
-<div class="block">
-	<h2><span>Update completed</span></h2>
-	<div class="box">
-		<div class="inbox">
-			<p>Update successful! Your forum database has now been updated to version <?php echo $update_to ?>. You should now remove this script from the forum root directory and follow the rest of the instructions in the documentation.</p>
-		</div>
-	</div>
-</div>
-
-</div>
-</div>
-
-</body>
-</html>
-<?php
-
-}
diff --git a/extras/12_to_1223_update.php b/extras/12_to_1223_update.php
new file mode 100644
index 0000000..76c28d6
--- /dev/null
+++ b/extras/12_to_1223_update.php
@@ -0,0 +1,189 @@
+<?php
+/***********************************************************************
+
+  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
+
+************************************************************************/
+
+
+// This script updates the forum database from version 1.2.* to 1.2.22
+// Copy this file to the forum root directory and run it. Then remove it from
+// the root directory.
+
+
+$update_from = array('1.2', '1.2.1', '1.2.2', '1.2.3', '1.2.4', '1.2.5', '1.2.6', '1.2.7', '1.2.8', '1.2.9', '1.2.10', '1.2.11', '1.2.12', '1.2.13', '1.2.14', '1.2.15', '1.2.16', '1.2.17', '1.2.18', '1.2.19', '1.2.20', '1.2.21', '1.2.22');
+$update_to = '1.2.23';
+
+
+define('PUN_ROOT', './');
+@include PUN_ROOT.'config.php';
+
+// If PUN isn't defined, config.php is missing or corrupt or we are outside the root directory
+if (!defined('PUN'))
+	exit('This file must be run from the forum root directory.');
+
+// Enable debug mode
+define('PUN_DEBUG', 1);
+
+// Disable error reporting for uninitialized variables
+error_reporting(E_ERROR | E_WARNING | E_PARSE);
+
+// Turn off magic_quotes_runtime
+set_magic_quotes_runtime(0);
+
+// Turn off PHP time limit
+@set_time_limit(0);
+
+
+// Load the functions script
+require PUN_ROOT.'include/functions.php';
+
+
+// Load DB abstraction layer and try to connect
+require PUN_ROOT.'include/dblayer/common_db.php';
+
+
+// Check current version
+$result1 = $db->query('SELECT cur_version FROM '.$db->prefix.'options');
+$result2 = $db->query('SELECT conf_value FROM '.$db->prefix.'config WHERE conf_name=\'o_cur_version\'');
+$cur_version = ($result1) ? $db->result($result1) : (($result2 && $db->num_rows($result2)) ? $db->result($result2) : 'beta');
+
+if (!in_array($cur_version, $update_from))
+	error('Version mismatch. This script updates version '.implode(', ', $update_from).' to version '.$update_to.'. The database \''.$db_name.'\' doesn\'t seem to be running a supported version.', __FILE__, __LINE__);
+
+
+// Get the forum config
+$result = $db->query('SELECT * FROM '.$db->prefix.'config');
+while ($cur_config_item = $db->fetch_row($result))
+	$pun_config[$cur_config_item[0]] = $cur_config_item[1];
+
+
+if (!isset($_POST['form_sent']))
+{
+
+?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<html dir="ltr">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>FluxBB Update</title>
+<link rel="stylesheet" type="text/css" href="style/Oxygen.css" />
+</head>
+<body>
+
+<div id="punwrap">
+<div id="puninstall" class="pun" style="margin: 10% 20% auto 20%">
+
+<div class="blockform">
+	<h2><span>FluxBB Update</span></h2>
+	<div class="box">
+		<form method="post" action="<?php echo $_SERVER['PHP_SELF'] ?>" onsubmit="this.start.disabled=true">
+			<div><input type="hidden" name="form_sent" value="1" /></div>
+			<div class="inform">
+				<p style="font-size: 1.1em">This script will update your current PunBB/FluxBB <?php echo $cur_version ?> forum database to FluxBB <?php echo $update_to ?>. The update procedure might take anything from a second to a few minutes depending on the speed of the server and the size of the forum database. Don't forget to make a backup of the database before continuing.</p>
+				<p style="font-size: 1.1em">Did you read the update instructions in the documentation? If not, start there.</p>
+			</div>
+			<p><input type="submit" name="start" value="Start upgrade" /></p>
+		</form>
+	</div>
+</div>
+
+</div>
+</div>
+
+</body>
+</html>
+<?php
+
+}
+else
+{
+	// If we're upgrading from 1.2
+	if ($cur_version == '1.2')
+	{
+		// Insert new config option o_additional_navlinks
+		$db->query('INSERT INTO '.$db->prefix.'config (conf_name, conf_value) VALUES(\'o_additional_navlinks\', NULL)') or error('Unable to alter DB structure.', __FILE__, __LINE__, $db->error());
+	}
+
+	// We need to add a unique index to avoid users having multiple rows in the online table
+	if ($db_type == 'mysql' || $db_type == 'mysqli')
+	{
+		$result = $db->query('SHOW INDEX FROM '.$db->prefix.'online') or error('Unable to check DB structure.', __FILE__, __LINE__, $db->error());
+
+		if ($db->num_rows($result) == 1)
+			$db->query('ALTER TABLE '.$db->prefix.'online ADD UNIQUE INDEX '.$db->prefix.'online_user_id_ident_idx(user_id,ident)') or error('Unable to alter DB structure.', __FILE__, __LINE__, $db->error());
+	}
+
+	// This feels like a good time to synchronize the forums
+	$result = $db->query('SELECT id FROM '.$db->prefix.'forums') or error('Unable to fetch forum info.', __FILE__, __LINE__, $db->error());
+
+	while ($row = $db->fetch_row($result))
+		update_forum($row[0]);
+
+
+	// We'll empty the search cache table as well (using DELETE FROM since SQLite does not support TRUNCATE TABLE)
+	$db->query('DELETE FROM '.$db->prefix.'search_cache') or error('Unable to flush search results.', __FILE__, __LINE__, $db->error());
+
+
+	// Finally, we update the version number
+	$db->query('UPDATE '.$db->prefix.'config SET conf_value=\''.$update_to.'\' WHERE conf_name=\'o_cur_version\'') or error('Unable to update version.', __FILE__, __LINE__, $db->error());
+
+
+	// Delete all .php files in the cache (someone might have visited the forums while we were updating and thus, generated incorrect cache files)
+	$d = dir(PUN_ROOT.'cache');
+	while (($entry = $d->read()) !== false)
+	{
+		if (substr($entry, strlen($entry)-4) == '.php')
+			@unlink(PUN_ROOT.'cache/'.$entry);
+	}
+	$d->close();
+
+?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<html dir="ltr">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>FluxBB Update</title>
+<link rel="stylesheet" type="text/css" href="style/Oxygen.css" />
+</head>
+<body>
+
+<div id="punwrap">
+<div id="puninstall" class="pun" style="margin: 10% 20% auto 20%">
+
+<div class="block">
+	<h2><span>Update completed</span></h2>
+	<div class="box">
+		<div class="inbox">
+			<p>Update successful! Your forum database has now been updated to version <?php echo $update_to ?>. You should now remove this script from the forum root directory and follow the rest of the instructions in the documentation.</p>
+		</div>
+	</div>
+</div>
+
+</div>
+</div>
+
+</body>
+</html>
+<?php
+
+}
diff --git a/upload/admin_index.php b/upload/admin_index.php
index 51fd44c..e7164cb 100644
--- a/upload/admin_index.php
+++ b/upload/admin_index.php
@@ -43,20 +43,11 @@ if ($action == 'check_upgrade')
 	if (!ini_get('allow_url_fopen'))
 		message('Unable to check for upgrade since \'allow_url_fopen\' is disabled on this system.');
 
-	$fp = @fopen('http://fluxbb.org/latest_version', 'r');
-	$latest_version = trim(@fread($fp, 16));
-	@fclose($fp);
-
-	if ($latest_version == '')
+	$latest_version = trim(@file_get_contents('http://fluxbb.org/latest_version'));
+	if (empty($latest_version))
 		message('Check for upgrade failed for unknown reasons.');
 
-	$cur_version = str_replace(array('.', 'dev', 'beta', ' '), '', strtolower($pun_config['o_cur_version']));
-	$cur_version = (strlen($cur_version) == 2) ? intval($cur_version) * 10 : intval($cur_version);
-
-	$latest_version = str_replace('.', '', strtolower($latest_version));
-	$latest_version = (strlen($latest_version) == 2) ? intval($latest_version) * 10 : intval($latest_version);
-
-	if ($cur_version >= $latest_version)
+	if (version_compare($pun_config['o_cur_version'], $latest_version, '>='))
 		message('You are running the latest version of FluxBB.');
 	else
 		message('A new version of FluxBB has been released. You can download the latest version at <a href="http://fluxbb.org/">FluxBB.org</a>.');
diff --git a/upload/admin_prune.php b/upload/admin_prune.php
index b383954..a4b5424 100644
--- a/upload/admin_prune.php
+++ b/upload/admin_prune.php
@@ -42,6 +42,7 @@ if (isset($_GET['action']) || isset($_POST['prune']) || isset($_POST['prune_comp
 		confirm_referrer('admin_prune.php');
 
 		$prune_from = $_POST['prune_from'];
+		$prune_sticky = isset($_POST['prune_sticky']) ? '1' : '0';
 		$prune_days = intval($_POST['prune_days']);
 		$prune_date = ($prune_days) ? time() - ($prune_days*86400) : -1;
 
@@ -56,14 +57,14 @@ if (isset($_GET['action']) || isset($_POST['prune']) || isset($_POST['prune_comp
 			{
 				$fid = $db->result($result, $i);
 
-				prune($fid, $_POST['prune_sticky'], $prune_date);
+				prune($fid, $prune_sticky, $prune_date);
 				update_forum($fid);
 			}
 		}
 		else
 		{
 			$prune_from = intval($prune_from);
-			prune($prune_from, $_POST['prune_sticky'], $prune_date);
+			prune($prune_from, $prune_sticky, $prune_date);
 			update_forum($prune_from);
 		}
 
@@ -93,7 +94,7 @@ if (isset($_GET['action']) || isset($_POST['prune']) || isset($_POST['prune_comp
 	// Concatenate together the query for counting number or topics to prune
 	$sql = 'SELECT COUNT(id) FROM '.$db->prefix.'topics WHERE last_post<'.$prune_date.' AND moved_to IS NULL';
 
-	if ($_POST['prune_sticky'] == '0')
+	if (!$prune_sticky)
 		$sql .= ' AND sticky=\'0\'';
 
 	if ($prune_from != 'all')
@@ -127,7 +128,7 @@ if (isset($_GET['action']) || isset($_POST['prune']) || isset($_POST['prune_comp
 			<form method="post" action="admin_prune.php?action=foo">
 				<div class="inform">
 					<input type="hidden" name="prune_days" value="<?php echo $prune_days ?>" />
-					<input type="hidden" name="prune_sticky" value="<?php echo $_POST['prune_sticky'] ?>" />
+					<input type="hidden" name="prune_sticky" value="<?php echo $prune_sticky ?>" />
 					<input type="hidden" name="prune_from" value="<?php echo $prune_from ?>" />
 					<fieldset>
 						<legend>Confirm prune posts</legend>
diff --git a/upload/header.php b/upload/header.php
index 1834b7b..680108d 100644
--- a/upload/header.php
+++ b/upload/header.php
@@ -33,6 +33,8 @@ header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
 header('Cache-Control: post-check=0, pre-check=0', false);
 header('Pragma: no-cache');		// For HTTP/1.0 compability
 
+// Send the Content-type header in case the web server is setup to send something else
+header('Content-type: text/html; charset='.$lang_common['lang_encoding']);
 
 // Load the template
 if (defined('PUN_ADMIN_CONSOLE'))
diff --git a/upload/include/common.php b/upload/include/common.php
index fa42209..6de3f37 100644
--- a/upload/include/common.php
+++ b/upload/include/common.php
@@ -55,7 +55,8 @@ $pun_start = ((float)$usec + (float)$sec);
 error_reporting(E_ALL ^ E_NOTICE);
 
 // Turn off magic_quotes_runtime
-set_magic_quotes_runtime(0);
+if (get_magic_quotes_runtime())
+	set_magic_quotes_runtime(0);
 
 // Strip slashes from GET/POST/COOKIE (if magic_quotes_gpc is enabled)
 if (get_magic_quotes_gpc())
diff --git a/upload/include/functions.php b/upload/include/functions.php
index 7ceb082..cbd3389 100644
--- a/upload/include/functions.php
+++ b/upload/include/functions.php
@@ -36,8 +36,8 @@ function check_cookie(&$pun_user)
 	$cookie = array('user_id' => 1, 'password_hash' => 'Guest');
 
 	// If a cookie is set, we get the user_id and password hash from it
-	if (isset($_COOKIE[$cookie_name]))
-		list($cookie['user_id'], $cookie['password_hash']) = @unserialize($_COOKIE[$cookie_name]);
+	if (isset($_COOKIE[$cookie_name]) && preg_match('/a:2:{i:0;s:\d+:"(\d+)";i:1;s:\d+:"([0-9a-f]+)";}/', $_COOKIE[$cookie_name], $matches))
+		list(, $cookie['user_id'], $cookie['password_hash']) = $matches;
 
 	if ($cookie['user_id'] > 1)
 	{
@@ -104,6 +104,11 @@ function check_cookie(&$pun_user)
 				$db->query('UPDATE '.$db->prefix.'online SET logged='.$now.$idle_sql.' WHERE user_id='.$pun_user['id']) or error('Unable to update online list', __FILE__, __LINE__, $db->error());
 			}
 		}
+		else
+		{
+			if (!$pun_user['logged'])
+				$pun_user['logged'] = $pun_user['last_visit'];
+		}
 
 		$pun_user['is_guest'] = false;
 	}
diff --git a/upload/include/parser.php b/upload/include/parser.php
index 7aea952..df10ef8 100644
--- a/upload/include/parser.php
+++ b/upload/include/parser.php
@@ -100,11 +100,6 @@ function preparse_bbcode($text, &$errors, $is_signature = false)
 			message($lang_prof_reg['Signature quote/code']);
 	}
 
-	if (preg_match('#\[url\](.*?)([\[]+?)(.*?)\[/url\]#', $text) || preg_match('#\[url=(.*?)([\[]+?)(.*?)\](.*?)\[/url\]#', $text) || preg_match('#\[url=(.*?)\](.*?)([\[]+?)(.*?)\[/url\]#', $text))
-		message('BBCode can not be nested within [url] tags.');
-	if (preg_match('#\[email\](.*?)([\[]+?)(.*?)\[/email\]#', $text) || preg_match('#\[email=(.*?)([\[]+?)(.*?)\](.*?)\[/email\]#', $text) || preg_match('#\[email=(.*?)\](.*?)([\[]+?)(.*?)\[/email\]#', $text))
-		message('BBCode can not be nested within [email] tags.');
-
 	return trim($text);
 }
 
@@ -319,10 +314,10 @@ function do_bbcode($text)
 	$pattern = array('#\[b\](.*?)\[/b\]#s',
 					 '#\[i\](.*?)\[/i\]#s',
 					 '#\[u\](.*?)\[/u\]#s',
-					 '#\[url\]([^\[]*?)\[/url\]#e',
-					 '#\[url=([^\[]*?)\](.*?)\[/url\]#e',
-					 '#\[email\]([^\[]*?)\[/email\]#',
-					 '#\[email=([^\[]*?)\](.*?)\[/email\]#',
+					 '#\[url\]([^\[<]*?)\[/url\]#e',
+					 '#\[url=([^\[<]*?)\](.*?)\[/url\]#e',
+					 '#\[email\]([^\[<]*?)\[/email\]#',
+					 '#\[email=([^\[<]*?)\](.*?)\[/email\]#',
 					 '#\[color=([a-zA-Z]*|\#?[0-9a-fA-F]{6})](.*?)\[/color\]#s');
 
 	$replace = array('<strong>$1</strong>',
diff --git a/upload/install.php b/upload/install.php
index bc0781b..2ce3f50 100644
--- a/upload/install.php
+++ b/upload/install.php
@@ -24,7 +24,7 @@
 
 
 // The FluxBB version this script installs
-$fluxbb_version = '1.2.19';
+$fluxbb_version = '1.2.23';
 
 
 define('PUN_ROOT', './');
@@ -289,6 +289,15 @@ else
 
 		exit;
 	}
+	
+	
+	// 
+	// Calls htmlspecialchars with a few options already set 
+	// 
+	function pun_htmlspecialchars($str) 
+	{ 
+		return htmlspecialchars($str, ENT_QUOTES, 'UTF-8'); 
+	}
 
 
 	$db_type = $_POST['req_db_type'];
@@ -348,7 +357,7 @@ else
 			break;
 
 		default:
-			error('\''.$db_type.'\' is not a valid database type.');
+			error('\''.pun_htmlspecialchars($db_type).'\' is not a valid database type.');
 	}
 
 	// Create the database object (and connect/select db)
@@ -1424,7 +1433,7 @@ else
 		<div class="fakeform">
 			<div class="inform">
 				<div class="forminfo">
-					<p>To finalize the installation all you need to do is to <strong>copy and paste the text in the text box below into a file called config.php and then upload this file to the root directory of your FluxBB installation</strong>. Make sure there are no linebreaks or spaces before &lt;?php. You can later edit config.php if you reconfigure your setup (e.g. change the database password or ).</p>
+					<p>To finalize the installation all you need to do is to <strong>copy and paste the text in the text box below into a file called config.php and then upload this file to the root directory of your FluxBB installation</strong>. Make sure there are no linebreaks or spaces before &lt;?php. You can later edit config.php if you reconfigure your setup (e.g. change the database password).</p>
 <?php if ($alerts != ''): ?>					<?php echo $alerts."\n" ?>
 <?php endif; ?>				</div>
 				<fieldset>
diff --git a/upload/misc.php b/upload/misc.php
index 637ea6a..934c7ad 100644
--- a/upload/misc.php
+++ b/upload/misc.php
@@ -253,7 +253,7 @@ else if (isset($_GET['subscribe']))
 		message($lang_common['Bad request']);
 
 	// Make sure the user can view the topic
-	$result = $db->query('SELECT 1 FROM '.$db->prefix.'topics AS t LEFT JOIN '.$db->prefix.'forum_perms AS fp ON (fp.forum_id=t.forum_id AND fp.group_id=1) WHERE (fp.read_forum IS NULL OR fp.read_forum=1) AND t.id='.$topic_id.' AND t.moved_to IS NULL') or error('Unable to fetch topic info', __FILE__, __LINE__, $db->error());
+	$result = $db->query('SELECT 1 FROM '.$db->prefix.'topics AS t LEFT JOIN '.$db->prefix.'forum_perms AS fp ON (fp.forum_id=t.forum_id AND fp.group_id='.$pun_user['g_id'].') WHERE (fp.read_forum IS NULL OR fp.read_forum=1) AND t.id='.$topic_id.' AND t.moved_to IS NULL') or error('Unable to fetch topic info', __FILE__, __LINE__, $db->error());
 	if (!$db->num_rows($result))
 		message($lang_common['Bad request']);
 
diff --git a/upload/post.php b/upload/post.php
index 2dee57a..e248753 100644
--- a/upload/post.php
+++ b/upload/post.php
@@ -140,6 +140,18 @@ if (isset($_POST['form_sent']))
 			require PUN_ROOT.'include/email.php';
 			if (!is_valid_email($email))
 				$errors[] = $lang_common['Invalid e-mail'];
+
+			// Check it it's a banned e-mail address
+			// we should only check guests because members addresses are already verified
+			if ($pun_user['is_guest'] && is_banned_email($email))
+			{
+				if ($pun_config['p_allow_banned_email'] == '0')
+					$errors[] = $lang_prof_reg['Banned e-mail'];
+
+				$banned_email = true;	// Used later when we send an alert e-mail
+			}
+			else
+				$banned_email = false;
 		}
 	}
 
@@ -313,6 +325,15 @@ if (isset($_POST['form_sent']))
 			update_forum($fid);
 		}
 
+		// If we previously found out that the e-mail was banned
+		if ($banned_email && $pun_config['o_mailing_list'] != '')
+		{		
+			$mail_subject = 'Alert - Banned e-mail detected';
+			$mail_message = 'User \''.$username.'\' posted with banned e-mail address: '.$email."\n\n".'Post URL: '.$pun_config['o_base_url'].'/viewtopic.php?pid='.$new_pid.'#p'.$new_pid."\n\n".'-- '."\n".'Forum Mailer'."\n".'(Do not reply to this message)';
+
+			pun_mail($pun_config['o_mailing_list'], $mail_subject, $mail_message);
+		}
+
 		// If the posting user is logged in, increment his/her post count
 		if (!$pun_user['is_guest'])
 		{
diff --git a/upload/profile.php b/upload/profile.php
index 163a085..2bd9e84 100644
--- a/upload/profile.php
+++ b/upload/profile.php
@@ -347,6 +347,7 @@ else if ($action == 'upload_avatar' || $action == 'upload_avatar2')
 
 		if (is_uploaded_file($uploaded_file['tmp_name']))
 		{
+			// Preliminary file check, adequate in most cases
 			$allowed_types = array('image/gif', 'image/jpeg', 'image/pjpeg', 'image/png', 'image/x-png');
 			if (!in_array($uploaded_file['type'], $allowed_types))
 				message($lang_profile['Bad type']);
@@ -355,31 +356,33 @@ else if ($action == 'upload_avatar' || $action == 'upload_avatar2')
 			if ($uploaded_file['size'] > $pun_config['o_avatars_size'])
 				message($lang_profile['Too large'].' '.$pun_config['o_avatars_size'].' '.$lang_profile['bytes'].'.');
 
+			// Move the file to the avatar directory. We do this before checking the width/height to circumvent open_basedir restrictions.
+			if (!@move_uploaded_file($uploaded_file['tmp_name'], $pun_config['o_avatars_dir'].'/'.$id.'.tmp'))
+				message($lang_profile['Move failed'].' <a href="mailto:'.$pun_config['o_admin_email'].'">'.$pun_config['o_admin_email'].'</a>.');
+
+			list($width, $height, $type,) = @getimagesize($pun_config['o_avatars_dir'].'/'.$id.'.tmp');
+
 			// Determine type
 			$extensions = null;
-			if ($uploaded_file['type'] == 'image/gif')
+			if ($type == IMAGETYPE_GIF)
 				$extensions = array('.gif', '.jpg', '.png');
-			else if ($uploaded_file['type'] == 'image/jpeg' || $uploaded_file['type'] == 'image/pjpeg')
+			else if ($type == IMAGETYPE_JPEG)
 				$extensions = array('.jpg', '.gif', '.png');
-			else
+			else if ($type == IMAGETYPE_PNG)
 				$extensions = array('.png', '.gif', '.jpg');
-
-			// Move the file to the avatar directory. We do this before checking the width/height to circumvent open_basedir restrictions.
-			if (!@move_uploaded_file($uploaded_file['tmp_name'], $pun_config['o_avatars_dir'].'/'.$id.'.tmp'))
-				message($lang_profile['Move failed'].' <a href="mailto:'.$pun_config['o_admin_email'].'">'.$pun_config['o_admin_email'].'</a>.');
+			else
+			{
+				// Invalid type
+				@unlink($pun_config['o_avatars_dir'].'/'.$id.'.tmp');
+				message($lang_profile['Bad type']);
+			}
 
 			// Now check the width/height
-			list($width, $height, $type,) = getimagesize($pun_config['o_avatars_dir'].'/'.$id.'.tmp');
 			if (empty($width) || empty($height) || $width > $pun_config['o_avatars_width'] || $height > $pun_config['o_avatars_height'])
 			{
 				@unlink($pun_config['o_avatars_dir'].'/'.$id.'.tmp');
 				message($lang_profile['Too wide or high'].' '.$pun_config['o_avatars_width'].'x'.$pun_config['o_avatars_height'].' '.$lang_profile['pixels'].'.');
 			}
-			else if ($type == 1 && $uploaded_file['type'] != 'image/gif')	// Prevent dodgy uploads
-			{
-				@unlink($pun_config['o_avatars_dir'].'/'.$id.'.tmp');
-				message($lang_profile['Bad type']);
-			}			
 
 			// Delete any old avatars and put the new one in place
 			@unlink($pun_config['o_avatars_dir'].'/'.$id.$extensions[0]);
diff --git a/upload/register.php b/upload/register.php
index 24c0bca..2015191 100644
--- a/upload/register.php
+++ b/upload/register.php
@@ -163,7 +163,7 @@ else if (isset($_POST['form_sent']))
 	// Check if someone else already has registered with that e-mail address
 	$dupe_list = array();
 
-	$result = $db->query('SELECT username FROM '.$db->prefix.'users WHERE email=\''.$email1.'\'') or error('Unable to fetch user info', __FILE__, __LINE__, $db->error());
+	$result = $db->query('SELECT username FROM '.$db->prefix.'users WHERE email=\''.$db->escape($email1).'\'') or error('Unable to fetch user info', __FILE__, __LINE__, $db->error());
 	if ($db->num_rows($result))
 	{
 		if ($pun_config['p_allow_dupe_email'] == '0')
@@ -196,7 +196,7 @@ else if (isset($_POST['form_sent']))
 	$password_hash = pun_hash($password1);
 
 	// Add the user
-	$db->query('INSERT INTO '.$db->prefix.'users (username, group_id, password, email, email_setting, save_pass, timezone, language, style, registered, registration_ip, last_visit) VALUES(\''.$db->escape($username).'\', '.$intial_group_id.', \''.$password_hash.'\', \''.$email1.'\', '.$email_setting.', '.$save_pass.', '.$timezone.' , \''.$db->escape($language).'\', \''.$pun_config['o_default_style'].'\', '.$now.', \''.get_remote_address().'\', '.$now.')') or error('Unable to create user', __FILE__, __LINE__, $db->error());
+	$db->query('INSERT INTO '.$db->prefix.'users (username, group_id, password, email, email_setting, save_pass, timezone, language, style, registered, registration_ip, last_visit) VALUES(\''.$db->escape($username).'\', '.$intial_group_id.', \''.$password_hash.'\', \''.$db->escape($email1).'\', '.$email_setting.', '.$save_pass.', '.$timezone.' , \''.$db->escape($language).'\', \''.$pun_config['o_default_style'].'\', '.$now.', \''.get_remote_address().'\', '.$now.')') or error('Unable to create user', __FILE__, __LINE__, $db->error());
 	$new_uid = $db->insert_id();
 
 
diff --git a/upload/search.php b/upload/search.php
index 0ac39c5..985d2f7 100644
--- a/upload/search.php
+++ b/upload/search.php
@@ -33,6 +33,7 @@ require PUN_ROOT.'include/common.php';
 
 // Load the search.php language file
 require PUN_ROOT.'lang/'.$pun_user['language'].'/search.php';
+require PUN_ROOT.'lang/'.$pun_user['language'].'/forum.php';
 
 
 if ($pun_user['g_read_board'] == '0')
@@ -459,8 +460,7 @@ if (isset($_GET['action']) || isset($_GET['search_id']))
 			$sql = 'SELECT p.id AS pid, p.poster AS pposter, p.posted AS pposted, p.poster_id, '.$substr_sql.'(p.message, 1, 1000) AS message, t.id AS tid, t.poster, t.subject, t.last_post, t.last_post_id, t.last_poster, t.num_replies, t.forum_id FROM '.$db->prefix.'posts AS p INNER JOIN '.$db->prefix.'topics AS t ON t.id=p.topic_id WHERE p.id IN('.$search_results.') ORDER BY '.$sort_by_sql;
 		}
 		else
-			$sql = 'SELECT t.id AS tid, t.poster, t.subject, t.last_post, t.last_post_id, t.last_poster, t.num_replies, t.closed, t.forum_id FROM '.$db->prefix.'topics AS t WHERE t.id IN('.$search_results.') ORDER BY '.$sort_by_sql;
-
+			$sql = 'SELECT t.id AS tid, t.poster, t.subject, t.last_post, t.last_post_id, t.last_poster, t.num_replies, t.closed, t.sticky, t.forum_id FROM '.$db->prefix.'topics AS t WHERE t.id IN('.$search_results.') ORDER BY '.$sort_by_sql;
 
 		// Determine the topic or post offset (based on $_GET['p'])
 		$per_page = ($show_as == 'posts') ? $pun_user['disp_posts'] : $pun_user['disp_topics'];
@@ -496,7 +496,7 @@ if (isset($_GET['action']) || isset($_GET['search_id']))
 
 <?php
 
-		//Set background switching on for show as posts
+		// Set background switching on for show as posts
 		$bg_switch = true;
 
 		if ($show_as == 'topics')
@@ -525,11 +525,11 @@ if (isset($_GET['action']) || isset($_GET['search_id']))
 		$result = $db->query('SELECT id, forum_name FROM '.$db->prefix.'forums') or error('Unable to fetch forum list', __FILE__, __LINE__, $db->error());
 
 		$forum_list = array();
-		while ($forum_list[] = $db->fetch_row($result))
-			;
+		while ($forum_list[] = $db->fetch_row($result));
 
 		// Finally, lets loop through the results and output them
-		for ($i = 0; $i < count($search_set); ++$i)
+		$count_search_set = count($search_set);
+		for ($i = 0; $i < $count_search_set; ++$i)
 		{
 			@reset($forum_list);
 			while (list(, $temp) = @each($forum_list))
@@ -623,6 +623,13 @@ if (isset($_GET['action']) || isset($_GET['search_id']))
 				else
 					$subject_new_posts = null;
 
+				if ($search_set[$i]['sticky'] == '1')
+				{
+					$subject = '<span class="stickytext">'.$lang_forum['Sticky'].': </span>'.$subject;
+					$item_status .= ' isticky';
+					$icon_text .= ' '.$lang_forum['Sticky'];
+				}
+
 				$num_pages_topic = ceil(($search_set[$i]['num_replies'] + 1) / $pun_user['disp_posts']);
 
 				if ($num_pages_topic > 1)
diff --git a/upload/userlist.php b/upload/userlist.php
index 8452406..7e4acb2 100644
--- a/upload/userlist.php
+++ b/upload/userlist.php
@@ -42,7 +42,7 @@ require PUN_ROOT.'lang/'.$pun_user['language'].'/search.php';
 $show_post_count = ($pun_config['o_show_post_count'] == '1' || $pun_user['g_id'] < PUN_GUEST) ? true : false;
 
 $username = (isset($_GET['username']) && $pun_user['g_search_users'] == '1') ? pun_trim($_GET['username']) : '';
-$show_group = (!isset($_GET['show_group']) || intval($_GET['show_group']) < -1 && intval($_GET['show_group']) > 2) ? -1 : intval($_GET['show_group']);
+$show_group = !isset($_GET['show_group']) ? -1 : intval($_GET['show_group']);
 $sort_by = (!isset($_GET['sort_by']) || $_GET['sort_by'] != 'username' && $_GET['sort_by'] != 'registered' && ($_GET['sort_by'] != 'num_posts' || !$show_post_count)) ? 'username' : $_GET['sort_by'];
 $sort_dir = (!isset($_GET['sort_dir']) || $_GET['sort_dir'] != 'ASC' && $_GET['sort_dir'] != 'DESC') ? 'ASC' : strtoupper($_GET['sort_dir']);
 
