diff -urN punbb-1.2.8/upload/admin_bans.php punbb-1.2.16/upload/admin_bans.php
--- punbb-1.2.8/upload/admin_bans.php	2005-09-22 09:50:20.000000000 +0200
+++ punbb-1.2.16/upload/admin_bans.php	2006-10-14 18:40:28.000000000 +0200
@@ -192,6 +192,8 @@
 
 	if ($ban_user == '' && $ban_ip == '' && $ban_email == '')
 		message('You must enter either a username, an IP address or an e-mail address (at least).');
+	else if (strtolower($ban_user) == 'guest')
+		message('The guest user cannot be banned.');
 
 	// Validate IP/IP range (it's overkill, I know)
 	if ($ban_ip != '')
diff -urN punbb-1.2.8/upload/admin_categories.php punbb-1.2.16/upload/admin_categories.php
--- punbb-1.2.8/upload/admin_categories.php	2005-09-22 09:50:21.000000000 +0200
+++ punbb-1.2.16/upload/admin_categories.php	2007-04-10 23:37:34.000000000 +0200
@@ -118,7 +118,7 @@
 					<fieldset>
 						<legend>Confirm delete category</legend>
 						<div class="infldset">
-							<p>Are you sure that you want to delete the category "<?php echo $cat_name ?>"?</p>
+							<p>Are you sure that you want to delete the category "<?php echo pun_htmlspecialchars($cat_name) ?>"?</p>
 							<p>WARNING! Deleting a category will delete all forums and posts (if any) in that category!</p>
 						</div>
 					</fieldset>
@@ -151,7 +151,7 @@
 		if ($cat_name[$i] == '')
 			message('You must enter a category name.');
 
-		if (!preg_match('#^\d+$#', $cat_order[$i]))
+		if (!@preg_match('#^\d+$#', $cat_order[$i]))
 			message('Position must be an integer value.');
 
 		list($cat_id, $position) = $db->fetch_row($result);
diff -urN punbb-1.2.8/upload/admin_forums.php punbb-1.2.16/upload/admin_forums.php
--- punbb-1.2.8/upload/admin_forums.php	2005-09-22 09:50:21.000000000 +0200
+++ punbb-1.2.16/upload/admin_forums.php	2007-04-10 23:37:34.000000000 +0200
@@ -137,10 +137,10 @@
 
 	while (list($forum_id, $disp_position) = @each($_POST['position']))
 	{
-		if (!preg_match('#^\d+$#', $disp_position))
+		if (!@preg_match('#^\d+$#', $disp_position))
 			message('Position must be a positive integer value.');
 
-		$db->query('UPDATE '.$db->prefix.'forums SET disp_position='.$disp_position.' WHERE id='.$forum_id) or error('Unable to update forum', __FILE__, __LINE__, $db->error());
+		$db->query('UPDATE '.$db->prefix.'forums SET disp_position='.$disp_position.' WHERE id='.intval($forum_id)) or error('Unable to update forum', __FILE__, __LINE__, $db->error());
 	}
 
 	// Regenerate the quickjump cache
@@ -186,9 +186,9 @@
 			$result = $db->query('SELECT g_id, g_read_board, g_post_replies, g_post_topics FROM '.$db->prefix.'groups WHERE g_id!='.PUN_ADMIN) or error('Unable to fetch user group list', __FILE__, __LINE__, $db->error());
 			while ($cur_group = $db->fetch_assoc($result))
 			{
-				$read_forum_new = ($cur_group['g_read_board'] == '1') ? isset($_POST['read_forum_new'][$cur_group['g_id']]) ? $_POST['read_forum_new'][$cur_group['g_id']] : '0' : $_POST['read_forum_old'][$cur_group['g_id']];
-				$post_replies_new = isset($_POST['post_replies_new'][$cur_group['g_id']]) ? $_POST['post_replies_new'][$cur_group['g_id']] : '0';
-				$post_topics_new = isset($_POST['post_topics_new'][$cur_group['g_id']]) ? $_POST['post_topics_new'][$cur_group['g_id']] : '0';
+				$read_forum_new = ($cur_group['g_read_board'] == '1') ? isset($_POST['read_forum_new'][$cur_group['g_id']]) ? '1' : '0' : intval($_POST['read_forum_old'][$cur_group['g_id']]);
+				$post_replies_new = isset($_POST['post_replies_new'][$cur_group['g_id']]) ? '1' : '0';
+				$post_topics_new = isset($_POST['post_topics_new'][$cur_group['g_id']]) ? '1' : '0';
 
 				// Check if the new settings differ from the old
 				if ($read_forum_new != $_POST['read_forum_old'][$cur_group['g_id']] || $post_replies_new != $_POST['post_replies_old'][$cur_group['g_id']] || $post_topics_new != $_POST['post_topics_old'][$cur_group['g_id']])
diff -urN punbb-1.2.8/upload/admin_groups.php punbb-1.2.16/upload/admin_groups.php
--- punbb-1.2.8/upload/admin_groups.php	2005-09-22 09:50:22.000000000 +0200
+++ punbb-1.2.16/upload/admin_groups.php	2006-10-14 18:41:53.000000000 +0200
@@ -264,7 +264,7 @@
 	confirm_referrer('admin_groups.php');
 
 	$group_id = intval($_POST['default_group']);
-	if ($group_id < 1)
+	if ($group_id < 4)
 		message($lang_common['Bad request']);
 
 	$db->query('UPDATE '.$db->prefix.'config SET conf_value='.$group_id.' WHERE conf_name=\'o_default_user_group\'') or error('Unable to update board config', __FILE__, __LINE__, $db->error());
diff -urN punbb-1.2.8/upload/admin_loader.php punbb-1.2.16/upload/admin_loader.php
--- punbb-1.2.8/upload/admin_loader.php	2005-09-22 09:50:20.000000000 +0200
+++ punbb-1.2.16/upload/admin_loader.php	2007-04-10 23:37:34.000000000 +0200
@@ -37,7 +37,7 @@
 
 // The plugin to load should be supplied via GET
 $plugin = isset($_GET['plugin']) ? $_GET['plugin'] : '';
-if (!preg_match('/^AM?P_(\w*?)\.php$/i', $plugin))
+if (!@preg_match('/^AM?P_(\w*?)\.php$/i', $plugin))
 	message($lang_common['Bad request']);
 
 // AP_ == Admins only, AMP_ == admins and moderators
diff -urN punbb-1.2.8/upload/admin_maintenance.php punbb-1.2.16/upload/admin_maintenance.php
--- punbb-1.2.8/upload/admin_maintenance.php	2005-09-22 09:50:21.000000000 +0200
+++ punbb-1.2.16/upload/admin_maintenance.php	2007-01-30 23:31:43.000000000 +0100
@@ -52,7 +52,7 @@
 		// This is the only potentially "dangerous" thing we can do here, so we check the referer
 		confirm_referrer('admin_maintenance.php');
 
-		$truncate_sql = ($db_type != 'sqlite') ? 'TRUNCATE TABLE ' : 'DELETE FROM ';
+		$truncate_sql = ($db_type != 'sqlite' && $db_type != 'pgsql') ? 'TRUNCATE TABLE ' : 'DELETE FROM ';
 		$db->query($truncate_sql.$db->prefix.'search_matches') or error('Unable to empty search index match table', __FILE__, __LINE__, $db->error());
 		$db->query($truncate_sql.$db->prefix.'search_words') or error('Unable to empty search index words table', __FILE__, __LINE__, $db->error());
 
@@ -65,7 +65,7 @@
 				break;
 
 			case 'pgsql';
-				$result = $db->query('SELECT setval(\'search_words_id_seq\', 1, false)') or error('Unable to update sequence', __FILE__, __LINE__, $db->error());
+				$result = $db->query('SELECT setval(\''.$db->prefix.'search_words_id_seq\', 1, false)') or error('Unable to update sequence', __FILE__, __LINE__, $db->error());
 		}
 	}
 
diff -urN punbb-1.2.8/upload/admin_options.php punbb-1.2.16/upload/admin_options.php
--- punbb-1.2.8/upload/admin_options.php	2005-09-22 09:50:20.000000000 +0200
+++ punbb-1.2.16/upload/admin_options.php	2007-04-11 13:35:44.000000000 +0200
@@ -37,15 +37,18 @@
 
 if (isset($_POST['form_sent']))
 {
-	// Lazy referer check (in case base_url isn't correct)
-	if (!isset($_SERVER['HTTP_REFERER']) || !preg_match('#/admin_options\.php#i', $_SERVER['HTTP_REFERER']))
-		message($lang_common['Bad referrer']);
+	// Custom referrer check (so we can output a custom error message)
+	if (!preg_match('#^'.preg_quote(str_replace('www.', '', $pun_config['o_base_url']).'/admin_options.php', '#').'#i', str_replace('www.', '', (isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ''))))
+		message('Bad HTTP_REFERER. If you have moved these forums from one location to another or switched domains, you need to update the Base URL manually in the database (look for o_base_url in the config table) and then clear the cache by deleting all .php files in the /cache directory.');
 
 	$form = array_map('trim', $_POST['form']);
 
 	if ($form['board_title'] == '')
 		message('You must enter a board title.');
 
+	// Clean default_lang
+	$form['default_lang'] = preg_replace('#[\.\\\/]#', '', $form['default_lang']);
+
 	require PUN_ROOT.'include/email.php';
 
 	$form['admin_email'] = strtolower($form['admin_email']);
@@ -63,6 +66,9 @@
 	if (substr($form['base_url'], -1) == '/')
 		$form['base_url'] = substr($form['base_url'], 0, -1);
 
+	// Clean avatars_dir
+	$form['avatars_dir'] = str_replace("\0", '', $form['avatars_dir']);
+
 	// Make sure avatars_dir doesn't end with a slash
 	if (substr($form['avatars_dir'], -1) == '/')
 		$form['avatars_dir'] = substr($form['avatars_dir'], 0, -1);
diff -urN punbb-1.2.8/upload/admin_prune.php punbb-1.2.16/upload/admin_prune.php
--- punbb-1.2.8/upload/admin_prune.php	2005-09-22 09:50:20.000000000 +0200
+++ punbb-1.2.16/upload/admin_prune.php	2007-04-10 23:37:34.000000000 +0200
@@ -84,7 +84,7 @@
 
 
 	$prune_days = $_POST['req_prune_days'];
-	if (!preg_match('#^\d+$#', $prune_days))
+	if (!@preg_match('#^\d+$#', $prune_days))
 		message('Days to prune must be a positive integer.');
 
 	$prune_date = time() - ($prune_days*86400);
diff -urN punbb-1.2.8/upload/admin_ranks.php punbb-1.2.16/upload/admin_ranks.php
--- punbb-1.2.8/upload/admin_ranks.php	2005-09-22 09:50:22.000000000 +0200
+++ punbb-1.2.16/upload/admin_ranks.php	2007-04-10 23:37:34.000000000 +0200
@@ -46,7 +46,7 @@
 	if ($rank == '')
 		message('You must enter a rank title.');
 
-	if (!preg_match('#^\d+$#', $min_posts))
+	if (!@preg_match('#^\d+$#', $min_posts))
 		message('Minimum posts must be a positive integer value.');
 
 	// Make sure there isn't already a rank with the same min_posts value
@@ -77,11 +77,11 @@
 	if ($rank == '')
 		message('You must enter a rank title.');
 
-	if (!preg_match('#^\d+$#', $min_posts))
+	if (!@preg_match('#^\d+$#', $min_posts))
 		message('Minimum posts must be a positive integer value.');
 
 	// Make sure there isn't already a rank with the same min_posts value
-	$result = $db->query('SELECT 1 FROM '.$db->prefix.'ranks WHERE id!='.$id.' && min_posts='.$min_posts) or error('Unable to fetch rank info', __FILE__, __LINE__, $db->error());
+	$result = $db->query('SELECT 1 FROM '.$db->prefix.'ranks WHERE id!='.$id.' AND min_posts='.$min_posts) or error('Unable to fetch rank info', __FILE__, __LINE__, $db->error());
 	if ($db->num_rows($result))
 		message('There is already a rank with a minimun posts value of '.$min_posts.'.');
 
diff -urN punbb-1.2.8/upload/admin_users.php punbb-1.2.16/upload/admin_users.php
--- punbb-1.2.8/upload/admin_users.php	2005-09-22 09:50:21.000000000 +0200
+++ punbb-1.2.16/upload/admin_users.php	2007-04-10 23:37:34.000000000 +0200
@@ -111,7 +111,7 @@
 {
 	$ip = $_GET['show_users'];
 
-	if (!preg_match('/[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/', $ip))
+	if (!@preg_match('/[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/', $ip))
 		message('The supplied IP address is not correctly formatted.');
 
 
@@ -257,7 +257,7 @@
 	$like_command = ($db_type == 'pgsql') ? 'ILIKE' : 'LIKE';
 	while (list($key, $input) = @each($form))
 	{
-		if ($input != '')
+		if ($input != '' && in_array($key, array('username', 'email', 'title', 'realname', 'url', 'jabber', 'icq', 'msn', 'aim', 'yahoo', 'location', 'signature', 'admin_note')))
 			$conditions[] = 'u.'.$db->escape($key).' '.$like_command.' \''.$db->escape(str_replace('*', '%', $input)).'\'';
 	}
 
@@ -267,7 +267,7 @@
 		$conditions[] = 'u.num_posts<'.$posts_less;
 
 	if ($user_group != 'all')
-		$conditions[] = 'u.group_id='.$db->escape($user_group);
+		$conditions[] = 'u.group_id='.intval($user_group);
 
 	if (empty($conditions))
 		message('You didn\'t enter any search terms.');
diff -urN punbb-1.2.8/upload/extern.php punbb-1.2.16/upload/extern.php
--- punbb-1.2.8/upload/extern.php	2005-09-22 09:50:21.000000000 +0200
+++ punbb-1.2.16/upload/extern.php	2007-01-15 01:51:05.000000000 +0100
@@ -149,6 +149,10 @@
 if (!isset($lang_common))
 	exit('There is no valid language pack \''.$pun_config['o_default_lang'].'\' installed. Please reinstall a language of that name.');
 
+// Check if we are to display a maintenance message
+if ($pun_config['o_maintenance'] && !defined('PUN_TURN_OFF_MAINT'))
+	maintenance_message();
+
 if (!isset($_GET['action']))
 	exit('No parameters supplied. See extern.php for instructions.');
 
diff -urN punbb-1.2.8/upload/footer.php punbb-1.2.16/upload/footer.php
--- punbb-1.2.8/upload/footer.php	2005-09-22 09:50:20.000000000 +0200
+++ punbb-1.2.16/upload/footer.php	2007-04-10 18:19:24.000000000 +0200
@@ -139,21 +139,6 @@
 // END SUBST - <pun_footer>
 
 
-// START SUBST - <pun_include "*">
-while (preg_match('#<pun_include "([^/\\\\]*?)">#', $tpl_main, $cur_include))
-{
-	if (!file_exists(PUN_ROOT.'include/user/'.$cur_include[1]))
-		error('Unable to process user include &lt;pun_include "'.htmlspecialchars($cur_include[1]).'"&gt; from template main.tpl. There is no such file in folder /include/user/');
-
-	ob_start();
-	include PUN_ROOT.'include/user/'.$cur_include[1];
-	$tpl_temp = ob_get_contents();
-	$tpl_main = str_replace($cur_include[0], $tpl_temp, $tpl_main);
-    ob_end_clean();
-}
-// END SUBST - <pun_include "*">
-
-
 // Close the db connection (and free up any result data)
 $db->close();
 
diff -urN punbb-1.2.8/upload/header.php punbb-1.2.16/upload/header.php
--- punbb-1.2.8/upload/header.php	2005-09-22 09:50:21.000000000 +0200
+++ punbb-1.2.16/upload/header.php	2007-04-10 18:19:24.000000000 +0200
@@ -43,6 +43,21 @@
 	$tpl_main = file_get_contents(PUN_ROOT.'include/template/main.tpl');
 
 
+// START SUBST - <pun_include "*">
+while (preg_match('#<pun_include "([^/\\\\]*?)\.(php[45]?|inc|html?|txt)">#', $tpl_main, $cur_include))
+{
+	if (!file_exists(PUN_ROOT.'include/user/'.$cur_include[1].'.'.$cur_include[2]))
+		error('Unable to process user include '.htmlspecialchars($cur_include[0]).' from template main.tpl. There is no such file in folder /include/user/');
+
+	ob_start();
+	include PUN_ROOT.'include/user/'.$cur_include[1].'.'.$cur_include[2];
+	$tpl_temp = ob_get_contents();
+	$tpl_main = str_replace($cur_include[0], $tpl_temp, $tpl_main);
+    ob_end_clean();
+}
+// END SUBST - <pun_include "*">
+
+
 // START SUBST - <pun_content_direction>
 $tpl_main = str_replace('<pun_content_direction>', $lang_common['lang_direction'], $tpl_main);
 // END SUBST - <pun_content_direction>
@@ -131,7 +146,7 @@
 
 
 // START SUBST - <pun_page>
-$tpl_main = str_replace('<pun_page>', basename($_SERVER['PHP_SELF'], '.php'), $tpl_main);
+$tpl_main = str_replace('<pun_page>', htmlspecialchars(basename($_SERVER['PHP_SELF'], '.php')), $tpl_main);
 // END SUBST - <pun_title>
 
 
diff -urN punbb-1.2.8/upload/include/common.php punbb-1.2.16/upload/include/common.php
--- punbb-1.2.8/upload/include/common.php	2005-09-22 09:50:21.000000000 +0200
+++ punbb-1.2.16/upload/include/common.php	2007-04-09 16:15:20.000000000 +0200
@@ -32,6 +32,14 @@
 if (!defined('PUN_ROOT'))
 	exit('The constant PUN_ROOT must be defined and point to a valid PunBB installation root directory.');
 
+
+// Load the functions script
+require PUN_ROOT.'include/functions.php';
+
+// Reverse the effect of register_globals
+unregister_globals();
+
+
 @include PUN_ROOT.'config.php';
 
 // If PUN isn't defined, config.php is missing or corrupt
@@ -77,9 +85,6 @@
 define('PUN_MEMBER', 4);
 
 
-// Load the functions script
-require PUN_ROOT.'include/functions.php';
-
 // Load DB abstraction layer and connect
 require PUN_ROOT.'include/dblayer/common_db.php';
 
diff -urN punbb-1.2.8/upload/include/dblayer/mysql.php punbb-1.2.16/upload/include/dblayer/mysql.php
--- punbb-1.2.8/upload/include/dblayer/mysql.php	2005-09-22 09:50:21.000000000 +0200
+++ punbb-1.2.16/upload/include/dblayer/mysql.php	2007-04-10 23:37:34.000000000 +0200
@@ -156,7 +156,9 @@
 
 	function escape($str)
 	{
-		if (function_exists('mysql_real_escape_string'))
+		if (is_array($str))
+			return '';
+		else if (function_exists('mysql_real_escape_string'))
 			return mysql_real_escape_string($str, $this->link_id);
 		else
 			return mysql_escape_string($str);
diff -urN punbb-1.2.8/upload/include/dblayer/mysqli.php punbb-1.2.16/upload/include/dblayer/mysqli.php
--- punbb-1.2.8/upload/include/dblayer/mysqli.php	2005-09-22 09:50:21.000000000 +0200
+++ punbb-1.2.16/upload/include/dblayer/mysqli.php	2007-04-10 23:37:34.000000000 +0200
@@ -159,7 +159,7 @@
 
 	function escape($str)
 	{
-		return mysqli_real_escape_string($this->link_id, $str);
+		return is_array($str) ? '' : mysqli_real_escape_string($this->link_id, $str);
 	}
 
 
diff -urN punbb-1.2.8/upload/include/dblayer/pgsql.php punbb-1.2.16/upload/include/dblayer/pgsql.php
--- punbb-1.2.8/upload/include/dblayer/pgsql.php	2005-09-22 09:50:21.000000000 +0200
+++ punbb-1.2.16/upload/include/dblayer/pgsql.php	2007-04-10 23:37:34.000000000 +0200
@@ -217,7 +217,7 @@
 
 	function escape($str)
 	{
-		return pg_escape_string($str);
+		return is_array($str) ? '' : pg_escape_string($str);
 	}
 
 
diff -urN punbb-1.2.8/upload/include/dblayer/sqlite.php punbb-1.2.16/upload/include/dblayer/sqlite.php
--- punbb-1.2.8/upload/include/dblayer/sqlite.php	2005-09-22 09:50:21.000000000 +0200
+++ punbb-1.2.16/upload/include/dblayer/sqlite.php	2007-04-10 23:37:34.000000000 +0200
@@ -219,7 +219,7 @@
 
 	function escape($str)
 	{
-		return sqlite_escape_string($str);
+		return is_array($str) ? '' : sqlite_escape_string($str);
 	}
 
 
diff -urN punbb-1.2.8/upload/include/email.php punbb-1.2.16/upload/include/email.php
--- punbb-1.2.8/upload/include/email.php	2005-09-22 09:50:21.000000000 +0200
+++ punbb-1.2.16/upload/include/email.php	2007-04-09 18:41:02.000000000 +0200
@@ -77,8 +77,8 @@
 
 	$headers = 'From: '.$from."\r\n".'Date: '.date('r')."\r\n".'MIME-Version: 1.0'."\r\n".'Content-transfer-encoding: 8bit'."\r\n".'Content-type: text/plain; charset='.$lang_common['lang_encoding']."\r\n".'X-Mailer: PunBB Mailer';
 
-	// Make sure all linebreaks are CRLF in message
-	$message = str_replace("\n", "\r\n", pun_linebreaks($message));
+	// Make sure all linebreaks are CRLF in message (and strip out any NULL bytes)
+	$message = str_replace(array("\n", "\0"), array("\r\n", ''), pun_linebreaks($message));
 
 	if ($pun_config['o_smtp_host'] != '')
 		smtp_mail($to, $subject, $message, $headers);
diff -urN punbb-1.2.8/upload/include/functions.php punbb-1.2.16/upload/include/functions.php
--- punbb-1.2.8/upload/include/functions.php	2005-09-22 09:50:21.000000000 +0200
+++ punbb-1.2.16/upload/include/functions.php	2007-11-19 18:08:44.000000000 +0100
@@ -27,7 +27,7 @@
 //
 function check_cookie(&$pun_user)
 {
-	global $db, $pun_config, $cookie_name, $cookie_seed;
+	global $db, $db_type, $pun_config, $cookie_name, $cookie_seed;
 
 	$now = time();
 	$expire = $now + 31536000;	// The cookie expires after a year
@@ -75,7 +75,22 @@
 		{
 			// Update the online list
 			if (!$pun_user['logged'])
-				$db->query('INSERT INTO '.$db->prefix.'online (user_id, ident, logged) VALUES('.$pun_user['id'].', \''.$db->escape($pun_user['username']).'\', '.$now.')') or error('Unable to insert into online list', __FILE__, __LINE__, $db->error());
+			{
+				$pun_user['logged'] = $now;
+
+				// With MySQL/MySQLi, REPLACE INTO avoids a user having two rows in the online table
+				switch ($db_type)
+				{
+					case 'mysql':
+					case 'mysqli':
+						$db->query('REPLACE INTO '.$db->prefix.'online (user_id, ident, logged) VALUES('.$pun_user['id'].', \''.$db->escape($pun_user['username']).'\', '.$pun_user['logged'].')') or error('Unable to insert into online list', __FILE__, __LINE__, $db->error());
+						break;
+
+					default:
+						$db->query('INSERT INTO '.$db->prefix.'online (user_id, ident, logged) VALUES('.$pun_user['id'].', \''.$db->escape($pun_user['username']).'\', '.$pun_user['logged'].')') or error('Unable to insert into online list', __FILE__, __LINE__, $db->error());
+						break;
+				}
+			}
 			else
 			{
 				// Special case: We've timed out, but no other user has browsed the forums since we timed out
@@ -102,7 +117,7 @@
 //
 function set_default_user()
 {
-	global $db, $pun_user, $pun_config;
+	global $db, $db_type, $pun_user, $pun_config;
 
 	$remote_addr = get_remote_address();
 
@@ -115,7 +130,22 @@
 
 	// Update online list
 	if (!$pun_user['logged'])
-		$db->query('INSERT INTO '.$db->prefix.'online (user_id, ident, logged) VALUES(1, \''.$db->escape($remote_addr).'\', '.time().')') or error('Unable to insert into online list', __FILE__, __LINE__, $db->error());
+	{
+		$pun_user['logged'] = time();
+
+		// With MySQL/MySQLi, REPLACE INTO avoids a user having two rows in the online table
+		switch ($db_type)
+		{
+			case 'mysql':
+			case 'mysqli':
+				$db->query('REPLACE INTO '.$db->prefix.'online (user_id, ident, logged) VALUES(1, \''.$db->escape($remote_addr).'\', '.$pun_user['logged'].')') or error('Unable to insert into online list', __FILE__, __LINE__, $db->error());
+				break;
+
+			default:
+				$db->query('INSERT INTO '.$db->prefix.'online (user_id, ident, logged) VALUES(1, \''.$db->escape($remote_addr).'\', '.$pun_user['logged'].')') or error('Unable to insert into online list', __FILE__, __LINE__, $db->error());
+				break;
+		}
+	}
 	else
 		$db->query('UPDATE '.$db->prefix.'online SET logged='.time().' WHERE ident=\''.$db->escape($remote_addr).'\'') or error('Unable to update online list', __FILE__, __LINE__, $db->error());
 
@@ -138,7 +168,10 @@
 	// Enable sending of a P3P header by removing // from the following line (try this if login is failing in IE6)
 //	@header('P3P: CP="CUR ADM"');
 
-	setcookie($cookie_name, serialize(array($user_id, md5($cookie_seed.$password_hash))), $expire, $cookie_path, $cookie_domain, $cookie_secure);
+	if (version_compare(PHP_VERSION, '5.2.0', '>='))
+		setcookie($cookie_name, serialize(array($user_id, md5($cookie_seed.$password_hash))), $expire, $cookie_path, $cookie_domain, $cookie_secure, true);
+	else
+		setcookie($cookie_name, serialize(array($user_id, md5($cookie_seed.$password_hash))), $expire, $cookie_path.'; HttpOnly', $cookie_domain, $cookie_secure);
 }
 
 
@@ -319,13 +352,13 @@
 
 
 //
-// Update posts, topics, last_post, last_post_id and last_poster for a forum (redirect topics are not included)
+// Update posts, topics, last_post, last_post_id and last_poster for a forum
 //
 function update_forum($forum_id)
 {
 	global $db;
 
-	$result = $db->query('SELECT COUNT(id), SUM(num_replies) FROM '.$db->prefix.'topics WHERE moved_to IS NULL AND forum_id='.$forum_id) or error('Unable to fetch forum topic count', __FILE__, __LINE__, $db->error());
+	$result = $db->query('SELECT COUNT(id), SUM(num_replies) FROM '.$db->prefix.'topics WHERE forum_id='.$forum_id) or error('Unable to fetch forum topic count', __FILE__, __LINE__, $db->error());
 	list($num_topics, $num_posts) = $db->fetch_row($result);
 
 	$num_posts = $num_posts + $num_topics;		// $num_posts is only the sum of all replies (we have to add the topic posts)
@@ -338,7 +371,7 @@
 		$db->query('UPDATE '.$db->prefix.'forums SET num_topics='.$num_topics.', num_posts='.$num_posts.', last_post='.$last_post.', last_post_id='.$last_post_id.', last_poster=\''.$db->escape($last_poster).'\' WHERE id='.$forum_id) or error('Unable to update last_post/last_post_id/last_poster', __FILE__, __LINE__, $db->error());
 	}
 	else	// There are no topics
-		$db->query('UPDATE '.$db->prefix.'forums SET num_topics=0, num_posts=0, last_post=NULL, last_post_id=NULL, last_poster=NULL WHERE id='.$forum_id) or error('Unable to update last_post/last_post_id/last_poster', __FILE__, __LINE__, $db->error());
+		$db->query('UPDATE '.$db->prefix.'forums SET num_topics='.$num_topics.', num_posts='.$num_posts.', last_post=NULL, last_post_id=NULL, last_poster=NULL WHERE id='.$forum_id) or error('Unable to update last_post/last_post_id/last_poster', __FILE__, __LINE__, $db->error());
 }
 
 
@@ -681,28 +714,7 @@
 //
 function get_remote_address()
 {
-	$remote_address = $_SERVER['REMOTE_ADDR'];
-
-	// If HTTP_X_FORWARDED_FOR is set, we try to grab the first non-LAN IP
-	if (!empty($_SERVER['HTTP_X_FORWARDED_FOR']))
-	{
-		if (preg_match_all('/[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/', $_SERVER['HTTP_X_FORWARDED_FOR'], $address_list))
-		{
-			$lan_ips = array('/^0\./', '/^127\.0\.0\.1/', '/^192\.168\..*/', '/^172\.((1[6-9])|(2[0-9])|(3[0-1]))\..*/', '/^10\..*/', '/^224\..*/', '/^240\..*/');
-			$address_list = preg_replace($lan_ips, null, $address_list[0]);
-
-			while (list(, $cur_address) = each($address_list))
-			{
-				if ($cur_address)
-				{
-					$remote_address = $cur_address;
-					break;
-				}
-			}
-		}
-	}
-
-	return $remote_address;
+	return $_SERVER['REMOTE_ADDR'];
 }
 
 
@@ -770,6 +782,21 @@
 	$tpl_maint = trim(file_get_contents(PUN_ROOT.'include/template/maintenance.tpl'));
 
 
+	// START SUBST - <pun_include "*">
+	while (preg_match('#<pun_include "([^/\\\\]*?)\.(php[45]?|inc|html?|txt)">#', $tpl_maint, $cur_include))
+	{
+		if (!file_exists(PUN_ROOT.'include/user/'.$cur_include[1].'.'.$cur_include[2]))
+			error('Unable to process user include '.htmlspecialchars($cur_include[0]).' from template maintenance.tpl. There is no such file in folder /include/user/');
+
+		ob_start();
+		include PUN_ROOT.'include/user/'.$cur_include[1].'.'.$cur_include[2];
+		$tpl_temp = ob_get_contents();
+		$tpl_maint = str_replace($cur_include[0], $tpl_temp, $tpl_maint);
+	    ob_end_clean();
+	}
+	// END SUBST - <pun_include "*">
+
+
 	// START SUBST - <pun_content_direction>
 	$tpl_maint = str_replace('<pun_content_direction>', $lang_common['lang_direction'], $tpl_maint);
 	// END SUBST - <pun_content_direction>
@@ -808,21 +835,6 @@
 	$db->end_transaction();
 
 
-	// START SUBST - <pun_include "*">
-	while (preg_match('#<pun_include "([^/\\\\]*?)">#', $tpl_maint, $cur_include))
-	{
-		if (!file_exists(PUN_ROOT.'include/user/'.$cur_include[1]))
-			error('Unable to process user include &lt;pun_include "'.htmlspecialchars($cur_include[1]).'"&gt; from template maintenance.tpl. There is no such file in folder /include/user/');
-
-		ob_start();
-		include PUN_ROOT.'include/user/'.$cur_include[1];
-		$tpl_temp = ob_get_contents();
-		$tpl_maint = str_replace($cur_include[0], $tpl_temp, $tpl_maint);
-	    ob_end_clean();
-	}
-	// END SUBST - <pun_include "*">
-
-
 	// Close the db connection (and free up any result data)
 	$db->close();
 
@@ -837,8 +849,12 @@
 {
 	global $db, $pun_config, $lang_common, $pun_user;
 
-	if ($destination_url == '')
-		$destination_url = 'index.php';
+	// Prefix with o_base_url (unless it's there already)
+	if (strpos($destination_url, $pun_config['o_base_url']) !== 0)
+		$destination_url = $pun_config['o_base_url'].'/'.$destination_url;
+
+	// Do a little spring cleaning
+	$destination_url = preg_replace('/([\r\n])|(%0[ad])|(;[\s]*data[\s]*:)/i', '', $destination_url);
 
 	// If the delay is 0 seconds, we might as well skip the redirect all together
 	if ($pun_config['o_redirect_delay'] == '0')
@@ -849,6 +865,21 @@
 	$tpl_redir = trim(file_get_contents(PUN_ROOT.'include/template/redirect.tpl'));
 
 
+	// START SUBST - <pun_include "*">
+	while (preg_match('#<pun_include "([^/\\\\]*?)\.(php[45]?|inc|html?|txt)">#', $tpl_redir, $cur_include))
+	{
+		if (!file_exists(PUN_ROOT.'include/user/'.$cur_include[1].'.'.$cur_include[2]))
+			error('Unable to process user include '.htmlspecialchars($cur_include[0]).' from template redirect.tpl. There is no such file in folder /include/user/');
+
+		ob_start();
+		include PUN_ROOT.'include/user/'.$cur_include[1].'.'.$cur_include[2];
+		$tpl_temp = ob_get_contents();
+		$tpl_redir = str_replace($cur_include[0], $tpl_temp, $tpl_redir);
+	    ob_end_clean();
+	}
+	// END SUBST - <pun_include "*">
+
+
 	// START SUBST - <pun_content_direction>
 	$tpl_redir = str_replace('<pun_content_direction>', $lang_common['lang_direction'], $tpl_redir);
 	// END SUBST - <pun_content_direction>
@@ -901,21 +932,6 @@
 	// END SUBST - <pun_footer>
 
 
-	// START SUBST - <pun_include "*">
-	while (preg_match('#<pun_include "([^/\\\\]*?)">#', $tpl_redir, $cur_include))
-	{
-		if (!file_exists(PUN_ROOT.'include/user/'.$cur_include[1]))
-			error('Unable to process user include &lt;pun_include "'.htmlspecialchars($cur_include[1]).'"&gt; from template redirect.tpl. There is no such file in folder /include/user/');
-
-		ob_start();
-		include PUN_ROOT.'include/user/'.$cur_include[1];
-		$tpl_temp = ob_get_contents();
-		$tpl_redir = str_replace($cur_include[0], $tpl_temp, $tpl_redir);
-	    ob_end_clean();
-	}
-	// END SUBST - <pun_include "*">
-
-
 	// Close the db connection (and free up any result data)
 	$db->close();
 
@@ -943,7 +959,7 @@
 
 ?>
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html dir="ltr">
+<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr">
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
 <title><?php echo pun_htmlspecialchars($pun_config['o_board_title']) ?> / Error</title>
@@ -1050,6 +1066,35 @@
 
 
 //
+// Unset any variables instantiated as a result of register_globals being enabled
+//
+function unregister_globals()
+{
+	$register_globals = @ini_get('register_globals');
+	if ($register_globals === "" || $register_globals === "0" || strtolower($register_globals) === "off")
+		return;
+
+	// Prevent script.php?GLOBALS[foo]=bar
+	if (isset($_REQUEST['GLOBALS']) || isset($_FILES['GLOBALS']))
+		exit('I\'ll have a steak sandwich and... a steak sandwich.');
+	
+	// Variables that shouldn't be unset
+	$no_unset = array('GLOBALS', '_GET', '_POST', '_COOKIE', '_REQUEST', '_SERVER', '_ENV', '_FILES');
+
+	// Remove elements in $GLOBALS that are present in any of the superglobals
+	$input = array_merge($_GET, $_POST, $_COOKIE, $_SERVER, $_ENV, $_FILES, isset($_SESSION) && is_array($_SESSION) ? $_SESSION : array());
+	foreach ($input as $k => $v)
+	{
+		if (!in_array($k, $no_unset) && isset($GLOBALS[$k]))
+		{
+			unset($GLOBALS[$k]);
+			unset($GLOBALS[$k]);	// Double unset to circumvent the zend_hash_del_key_or_index hole in PHP <4.4.3 and <5.1.4
+		}
+	}
+}
+
+
+//
 // Dump contents of variable(s)
 //
 function dump()
diff -urN punbb-1.2.8/upload/include/parser.php punbb-1.2.16/upload/include/parser.php
--- punbb-1.2.8/upload/include/parser.php	2005-09-22 09:50:21.000000000 +0200
+++ punbb-1.2.16/upload/include/parser.php	2006-05-20 17:42:32.000000000 +0200
@@ -264,7 +264,7 @@
 {
 	global $pun_user;
 
-	$full_url = str_replace(array(' ', '\'', '`'), array('%20', '', ''), $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://
diff -urN punbb-1.2.8/upload/include/search_idx.php punbb-1.2.16/upload/include/search_idx.php
--- punbb-1.2.8/upload/include/search_idx.php	2005-09-22 09:50:21.000000000 +0200
+++ punbb-1.2.16/upload/include/search_idx.php	2005-10-31 22:37:19.000000000 +0100
@@ -69,11 +69,9 @@
 	{
 		while (list($i, $word) = @each($words))
 		{
+			$words[$i] = trim($word, '.');
 			$num_chars = pun_strlen($word);
 
-			if (strrpos($word, '.') == ($num_chars-1))
-				$words[$i] = substr($word, 0, -1);
-
 			if ($num_chars < 3 || $num_chars > 20 || in_array($word, $stopwords))
 				unset($words[$i]);
 		}
diff -urN punbb-1.2.8/upload/include/template/admin.tpl punbb-1.2.16/upload/include/template/admin.tpl
--- punbb-1.2.8/upload/include/template/admin.tpl	2005-09-22 09:50:21.000000000 +0200
+++ punbb-1.2.16/upload/include/template/admin.tpl	2007-04-08 19:30:39.000000000 +0200
@@ -1,6 +1,6 @@
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 
-<html dir="<pun_content_direction>">
+<html xmlns="http://www.w3.org/1999/xhtml" dir="<pun_content_direction>">
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=<pun_char_encoding>" />
 <pun_head>
diff -urN punbb-1.2.8/upload/include/template/help.tpl punbb-1.2.16/upload/include/template/help.tpl
--- punbb-1.2.8/upload/include/template/help.tpl	2005-09-22 09:50:21.000000000 +0200
+++ punbb-1.2.16/upload/include/template/help.tpl	2007-04-08 19:30:39.000000000 +0200
@@ -1,6 +1,6 @@
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 
-<html dir="<pun_content_direction>">
+<html xmlns="http://www.w3.org/1999/xhtml" dir="<pun_content_direction>">
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=<pun_char_encoding>" />
 <pun_head>
diff -urN punbb-1.2.8/upload/include/template/main.tpl punbb-1.2.16/upload/include/template/main.tpl
--- punbb-1.2.8/upload/include/template/main.tpl	2005-09-22 09:50:21.000000000 +0200
+++ punbb-1.2.16/upload/include/template/main.tpl	2007-04-08 19:30:39.000000000 +0200
@@ -1,6 +1,6 @@
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 
-<html dir="<pun_content_direction>">
+<html xmlns="http://www.w3.org/1999/xhtml" dir="<pun_content_direction>">
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=<pun_char_encoding>" />
 <pun_head>
diff -urN punbb-1.2.8/upload/include/template/maintenance.tpl punbb-1.2.16/upload/include/template/maintenance.tpl
--- punbb-1.2.8/upload/include/template/maintenance.tpl	2005-09-22 09:50:21.000000000 +0200
+++ punbb-1.2.16/upload/include/template/maintenance.tpl	2007-04-08 19:30:39.000000000 +0200
@@ -1,6 +1,6 @@
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 
-<html dir="<pun_content_direction>">
+<html xmlns="http://www.w3.org/1999/xhtml" dir="<pun_content_direction>">
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=<pun_char_encoding>" />
 <pun_head>
diff -urN punbb-1.2.8/upload/include/template/redirect.tpl punbb-1.2.16/upload/include/template/redirect.tpl
--- punbb-1.2.8/upload/include/template/redirect.tpl	2005-09-22 09:50:21.000000000 +0200
+++ punbb-1.2.16/upload/include/template/redirect.tpl	2007-04-08 19:30:39.000000000 +0200
@@ -1,6 +1,6 @@
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 
-<html dir="<pun_content_direction>">
+<html xmlns="http://www.w3.org/1999/xhtml" dir="<pun_content_direction>">
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=<pun_char_encoding>" />
 <pun_head>
diff -urN punbb-1.2.8/upload/install.php punbb-1.2.16/upload/install.php
--- punbb-1.2.8/upload/install.php	2005-09-22 09:50:21.000000000 +0200
+++ punbb-1.2.16/upload/install.php	2007-11-19 00:21:02.000000000 +0100
@@ -24,7 +24,7 @@
 
 
 // The PunBB version this script installs
-$punbb_version = '1.2.8';
+$punbb_version = '1.2.16';
 
 
 define('PUN_ROOT', './');
@@ -757,7 +757,7 @@
 					poster_id INT(10) UNSIGNED NOT NULL DEFAULT 1,
 					poster_ip VARCHAR(15),
 					poster_email VARCHAR(50),
-					message TEXT NOT NULL DEFAULT '',
+					message TEXT,
 					hide_smilies TINYINT(1) NOT NULL DEFAULT 0,
 					posted INT(10) UNSIGNED NOT NULL DEFAULT 0,
 					edited INT(10) UNSIGNED,
@@ -774,7 +774,7 @@
 					poster_id INT NOT NULL DEFAULT 1,
 					poster_ip VARCHAR(15),
 					poster_email VARCHAR(50),
-					message TEXT NOT NULL DEFAULT '',
+					message TEXT,
 					hide_smilies SMALLINT NOT NULL DEFAULT 0,
 					posted INT NOT NULL DEFAULT 0,
 					edited INT,
@@ -791,7 +791,7 @@
 					poster_id INTEGER NOT NULL DEFAULT 1,
 					poster_ip VARCHAR(15),
 					poster_email VARCHAR(50),
-					message TEXT NOT NULL DEFAULT '',
+					message TEXT,
 					hide_smilies INTEGER NOT NULL DEFAULT 0,
 					posted INTEGER NOT NULL DEFAULT 0,
 					edited INTEGER,
@@ -852,7 +852,7 @@
 					forum_id INT(10) UNSIGNED NOT NULL DEFAULT 0,
 					reported_by INT(10) UNSIGNED NOT NULL DEFAULT 0,
 					created INT(10) UNSIGNED NOT NULL DEFAULT 0,
-					message TEXT NOT NULL DEFAULT '',
+					message TEXT,
 					zapped INT(10) UNSIGNED,
 					zapped_by INT(10) UNSIGNED,
 					PRIMARY KEY (id)
@@ -867,7 +867,7 @@
 					forum_id INT NOT NULL DEFAULT 0,
 					reported_by INT NOT NULL DEFAULT 0,
 					created INT NOT NULL DEFAULT 0,
-					message TEXT NOT NULL DEFAULT '',
+					message TEXT,
 					zapped INT,
 					zapped_by INT,
 					PRIMARY KEY (id)
@@ -882,7 +882,7 @@
 					forum_id INTEGER NOT NULL DEFAULT 0,
 					reported_by INTEGER NOT NULL DEFAULT 0,
 					created INTEGER NOT NULL DEFAULT 0,
-					message TEXT NOT NULL DEFAULT '',
+					message TEXT,
 					zapped INTEGER,
 					zapped_by INTEGER,
 					PRIMARY KEY (id)
@@ -901,7 +901,7 @@
 			$sql = 'CREATE TABLE '.$db_prefix."search_cache (
 					id INT(10) UNSIGNED NOT NULL DEFAULT 0,
 					ident VARCHAR(200) NOT NULL DEFAULT '',
-					search_data TEXT NOT NULL DEFAULT '',
+					search_data TEXT,
 					PRIMARY KEY (id)
 					) TYPE=MyISAM;";
 			break;
@@ -910,7 +910,7 @@
 			$sql = 'CREATE TABLE '.$db_prefix."search_cache (
 					id INT NOT NULL DEFAULT 0,
 					ident VARCHAR(200) NOT NULL DEFAULT '',
-					search_data TEXT NOT NULL DEFAULT '',
+					search_data TEXT,
 					PRIMARY KEY (id)
 					)";
 			break;
@@ -919,7 +919,7 @@
 			$sql = 'CREATE TABLE '.$db_prefix."search_cache (
 					id INTEGER NOT NULL DEFAULT 0,
 					ident VARCHAR(200) NOT NULL DEFAULT '',
-					search_data TEXT NOT NULL DEFAULT '',
+					search_data TEXT,
 					PRIMARY KEY (id)
 					)";
 			break;
@@ -1234,6 +1234,7 @@
 		case 'mysql':
 		case 'mysqli':
 			// We use MySQL's ALTER TABLE ... ADD INDEX syntax instead of CREATE INDEX to avoid problems with users lacking the INDEX privilege
+			$queries[] = 'ALTER TABLE '.$db_prefix.'online ADD UNIQUE INDEX '.$db_prefix.'online_user_id_ident_idx(user_id,ident)';
 			$queries[] = 'ALTER TABLE '.$db_prefix.'online ADD INDEX '.$db_prefix.'online_user_id_idx(user_id)';
 			$queries[] = 'ALTER TABLE '.$db_prefix.'posts ADD INDEX '.$db_prefix.'posts_topic_id_idx(topic_id)';
 			$queries[] = 'ALTER TABLE '.$db_prefix.'posts ADD INDEX '.$db_prefix.'posts_multi_idx(poster_id, topic_id)';
diff -urN punbb-1.2.8/upload/login.php punbb-1.2.16/upload/login.php
--- punbb-1.2.8/upload/login.php	2005-09-22 09:50:20.000000000 +0200
+++ punbb-1.2.16/upload/login.php	2006-05-20 17:52:02.000000000 +0200
@@ -78,7 +78,7 @@
 	$expire = ($save_pass == '1') ? time() + 31536000 : 0;
 	pun_setcookie($user_id, $form_password_hash, $expire);
 
-	redirect($_POST['redirect_url'], $lang_login['Login redirect']);
+	redirect(htmlspecialchars($_POST['redirect_url']), $lang_login['Login redirect']);
 }
 
 
diff -urN punbb-1.2.8/upload/misc.php punbb-1.2.16/upload/misc.php
--- punbb-1.2.8/upload/misc.php	2005-09-22 09:50:21.000000000 +0200
+++ punbb-1.2.16/upload/misc.php	2007-04-10 18:42:55.000000000 +0200
@@ -120,12 +120,12 @@
 
 		pun_mail($recipient_email, $mail_subject, $mail_message, '"'.str_replace('"', '', $pun_user['username']).'" <'.$pun_user['email'].'>');
 
-		redirect($_POST['redirect_url'], $lang_misc['E-mail sent redirect']);
+		redirect(htmlspecialchars($_POST['redirect_url']), $lang_misc['E-mail sent redirect']);
 	}
 
 
 	// Try to determine if the data in HTTP_REFERER is valid (if not, we redirect to the users profile after the e-mail is sent)
-	$redirect_url = (isset($_SERVER['HTTP_REFERER']) && preg_match('#^'.preg_quote($pun_config['o_base_url']).'/(.*?)\.php#i', $_SERVER['HTTP_REFERER'])) ? $_SERVER['HTTP_REFERER'] : 'index.php';
+	$redirect_url = (isset($_SERVER['HTTP_REFERER']) && preg_match('#^'.preg_quote($pun_config['o_base_url']).'/(.*?)\.php#i', $_SERVER['HTTP_REFERER'])) ? htmlspecialchars($_SERVER['HTTP_REFERER']) : 'index.php';
 
 	$page_title = pun_htmlspecialchars($pun_config['o_board_title']).' / '.$lang_misc['Send e-mail to'].' '.pun_htmlspecialchars($recipient);
 	$required_fields = array('req_subject' => $lang_misc['E-mail subject'], 'req_message' => $lang_misc['E-mail message']);
diff -urN punbb-1.2.8/upload/moderate.php punbb-1.2.16/upload/moderate.php
--- punbb-1.2.8/upload/moderate.php	2005-09-22 09:50:21.000000000 +0200
+++ punbb-1.2.16/upload/moderate.php	2007-04-10 23:37:34.000000000 +0200
@@ -35,7 +35,7 @@
 		message($lang_common['No permission']);
 
 	// Is get_host an IP address or a post ID?
-	if (preg_match('/[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/', $_GET['get_host']))
+	if (@preg_match('/[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/', $_GET['get_host']))
 		$ip = $_GET['get_host'];
 	else
 	{
@@ -98,7 +98,13 @@
 		{
 			confirm_referrer('moderate.php');
 
-			if (preg_match('/[^0-9,]/', $posts))
+			if (@preg_match('/[^0-9,]/', $posts))
+				message($lang_common['Bad request']);
+
+			// Verify that the post IDs are valid
+			$result = $db->query('SELECT 1 FROM '.$db->prefix.'posts WHERE id IN('.$posts.') AND topic_id='.$tid) or error('Unable to check posts', __FILE__, __LINE__, $db->error());
+
+			if ($db->num_rows($result) != substr_count($posts, ',') + 1)
 				message($lang_common['Bad request']);
 
 			// Delete the posts
@@ -281,7 +287,7 @@
 	{
 		confirm_referrer('moderate.php');
 
-		if (preg_match('/[^0-9,]/', $_POST['topics']))
+		if (@preg_match('/[^0-9,]/', $_POST['topics']))
 			message($lang_common['Bad request']);
 
 		$topics = explode(',', $_POST['topics']);
@@ -289,6 +295,12 @@
 		if (empty($topics) || $move_to_forum < 1)
 			message($lang_common['Bad request']);
 
+		// Verify that the topic IDs are valid
+		$result = $db->query('SELECT 1 FROM '.$db->prefix.'topics WHERE id IN('.implode(',',$topics).') AND forum_id='.$fid) or error('Unable to check topics', __FILE__, __LINE__, $db->error());
+
+		if ($db->num_rows($result) != count($topics))
+			message($lang_common['Bad request']);
+
 		// Delete any redirect topics if there are any (only if we moved/copied the topic back to where it where it was once moved from)
 		$db->query('DELETE FROM '.$db->prefix.'topics WHERE forum_id='.$move_to_forum.' AND moved_to IN('.implode(',',$topics).')') or error('Unable to delete redirect topics', __FILE__, __LINE__, $db->error());
 
@@ -400,11 +412,17 @@
 	{
 		confirm_referrer('moderate.php');
 
-		if (preg_match('/[^0-9,]/', $topics))
+		if (@preg_match('/[^0-9,]/', $topics))
 			message($lang_common['Bad request']);
 
 		require PUN_ROOT.'include/search_idx.php';
 
+		// Verify that the topic IDs are valid
+		$result = $db->query('SELECT 1 FROM '.$db->prefix.'topics WHERE id IN('.$topics.') AND forum_id='.$fid) or error('Unable to check topics', __FILE__, __LINE__, $db->error());
+
+		if ($db->num_rows($result) != substr_count($topics, ',') + 1)
+			message($lang_common['Bad request']);
+
 		// Delete the topics and any redirect topics
 		$db->query('DELETE FROM '.$db->prefix.'topics WHERE id IN('.$topics.') OR moved_to IN('.$topics.')') or error('Unable to delete topic', __FILE__, __LINE__, $db->error());
 
@@ -472,7 +490,7 @@
 		if (empty($topics))
 			message($lang_misc['No topics selected']);
 
-		$db->query('UPDATE '.$db->prefix.'topics SET closed='.$action.' WHERE id IN('.implode(',', $topics).')') or error('Unable to close topics', __FILE__, __LINE__, $db->error());
+		$db->query('UPDATE '.$db->prefix.'topics SET closed='.$action.' WHERE id IN('.implode(',', $topics).') AND forum_id='.$fid) or error('Unable to close topics', __FILE__, __LINE__, $db->error());
 
 		$redirect_msg = ($action) ? $lang_misc['Close topics redirect'] : $lang_misc['Open topics redirect'];
 		redirect('moderate.php?fid='.$fid, $redirect_msg);
@@ -486,7 +504,7 @@
 		if ($topic_id < 1)
 			message($lang_common['Bad request']);
 
-		$db->query('UPDATE '.$db->prefix.'topics SET closed='.$action.' WHERE id='.$topic_id) or error('Unable to close topic', __FILE__, __LINE__, $db->error());
+		$db->query('UPDATE '.$db->prefix.'topics SET closed='.$action.' WHERE id='.$topic_id.' AND forum_id='.$fid) or error('Unable to close topic', __FILE__, __LINE__, $db->error());
 
 		$redirect_msg = ($action) ? $lang_misc['Close topic redirect'] : $lang_misc['Open topic redirect'];
 		redirect('viewtopic.php?id='.$topic_id, $redirect_msg);
@@ -503,7 +521,7 @@
 	if ($stick < 1)
 		message($lang_common['Bad request']);
 
-	$db->query('UPDATE '.$db->prefix.'topics SET sticky=\'1\' WHERE id='.$stick) or error('Unable to stick topic', __FILE__, __LINE__, $db->error());
+	$db->query('UPDATE '.$db->prefix.'topics SET sticky=\'1\' WHERE id='.$stick.' AND forum_id='.$fid) or error('Unable to stick topic', __FILE__, __LINE__, $db->error());
 
 	redirect('viewtopic.php?id='.$stick, $lang_misc['Stick topic redirect']);
 }
@@ -518,7 +536,7 @@
 	if ($unstick < 1)
 		message($lang_common['Bad request']);
 
-	$db->query('UPDATE '.$db->prefix.'topics SET sticky=\'0\' WHERE id='.$unstick) or error('Unable to unstick topic', __FILE__, __LINE__, $db->error());
+	$db->query('UPDATE '.$db->prefix.'topics SET sticky=\'0\' WHERE id='.$unstick.' AND forum_id='.$fid) or error('Unable to unstick topic', __FILE__, __LINE__, $db->error());
 
 	redirect('viewtopic.php?id='.$unstick, $lang_misc['Unstick topic redirect']);
 }
diff -urN punbb-1.2.8/upload/post.php punbb-1.2.16/upload/post.php
--- punbb-1.2.8/upload/post.php	2005-09-22 09:50:21.000000000 +0200
+++ punbb-1.2.16/upload/post.php	2007-01-15 14:59:02.000000000 +0100
@@ -128,7 +128,7 @@
 			$errors[] = $lang_register['Username censor'];
 
 		// Check that the username (or a too similar username) is not already registered
-		$result = $db->query('SELECT username FROM '.$db->prefix.'users WHERE username=\''.$db->escape($username).'\' OR username=\''.$db->escape(preg_replace('/[^\w]/', '', $username)).'\'') or error('Unable to fetch user info', __FILE__, __LINE__, $db->error());
+		$result = $db->query('SELECT username FROM '.$db->prefix.'users WHERE (username=\''.$db->escape($username).'\' OR username=\''.$db->escape(preg_replace('/[^\w]/', '', $username)).'\') AND id>1') or error('Unable to fetch user info', __FILE__, __LINE__, $db->error());
 		if ($db->num_rows($result))
 		{
 			$busy = $db->result($result);
@@ -338,7 +338,7 @@
 		if ($qid < 1)
 			message($lang_common['Bad request']);
 
-		$result = $db->query('SELECT poster, message FROM '.$db->prefix.'posts WHERE id='.$qid) or error('Unable to fetch quote info', __FILE__, __LINE__, $db->error());
+		$result = $db->query('SELECT poster, message FROM '.$db->prefix.'posts WHERE id='.$qid.' AND topic_id='.$tid) or error('Unable to fetch quote info', __FILE__, __LINE__, $db->error());
 		if (!$db->num_rows($result))
 			message($lang_common['Bad request']);
 
diff -urN punbb-1.2.8/upload/profile.php punbb-1.2.16/upload/profile.php
--- punbb-1.2.8/upload/profile.php	2005-09-22 09:53:04.000000000 +0200
+++ punbb-1.2.16/upload/profile.php	2007-11-19 00:14:16.000000000 +0100
@@ -87,6 +87,9 @@
 
 	if (isset($_POST['form_sent']))
 	{
+		if ($pun_user['g_id'] < PUN_GUEST)
+			confirm_referrer('profile.php');
+
 		$old_password = isset($_POST['req_old_password']) ? trim($_POST['req_old_password']) : '';
 		$new_password1 = trim($_POST['req_new_password1']);
 		$new_password2 = trim($_POST['req_new_password2']);
@@ -190,7 +193,7 @@
 		$result = $db->query('SELECT activate_string, activate_key FROM '.$db->prefix.'users WHERE id='.$id) or error('Unable to fetch activation data', __FILE__, __LINE__, $db->error());
 		list($new_email, $new_email_key) = $db->fetch_row($result);
 
-		if ($key != $new_email_key)
+		if ($key == '' || $key != $new_email_key)
 			message($lang_profile['E-mail key bad'].' <a href="mailto:'.$pun_config['o_admin_email'].'">'.$pun_config['o_admin_email'].'</a>.');
 		else
 		{
@@ -201,6 +204,9 @@
 	}
 	else if (isset($_POST['form_sent']))
 	{
+		if (pun_hash($_POST['req_password']) !== $pun_user['password'])
+			message($lang_profile['Wrong pass']);
+
 		require PUN_ROOT.'include/email.php';
 
 		// Validate the email-address
@@ -264,7 +270,7 @@
 	}
 
 	$page_title = pun_htmlspecialchars($pun_config['o_board_title']).' / '.$lang_common['Profile'];
-	$required_fields = array('req_new_email' => $lang_profile['New e-mail']);
+	$required_fields = array('req_new_email' => $lang_profile['New e-mail'], 'req_password' => $lang_common['Password']);
 	$focus_element = array('change_email', 'req_new_email');
 	require PUN_ROOT.'header.php';
 
@@ -279,6 +285,7 @@
 					<div class="infldset">
 						<input type="hidden" name="form_sent" value="1" />
 						<label><strong><?php echo $lang_profile['New e-mail'] ?></strong><br /><input type="text" name="req_new_email" size="50" maxlength="50" /><br /></label>
+						<label><strong><?php echo $lang_common['Password'] ?></strong><br /><input type="password" name="req_password" size="16" maxlength="16" /><br /></label>
 						<p><?php echo $lang_profile['E-mail instructions'] ?></p>
 					</div>
 				</fieldset>
@@ -362,12 +369,17 @@
 				message($lang_profile['Move failed'].' <a href="mailto:'.$pun_config['o_admin_email'].'">'.$pun_config['o_admin_email'].'</a>.');
 
 			// Now check the width/height
-			list($width, $height, ,) = getimagesize($pun_config['o_avatars_dir'].'/'.$id.'.tmp');
+			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]);
@@ -743,7 +755,7 @@
 			}
 
 			// Add http:// if the URL doesn't contain it already
-			if ($form['url'] != '' && !stristr($form['url'], 'http://'))
+			if ($form['url'] != '' && strpos(strtolower($form['url']), 'http://') !== 0)
 				$form['url'] = 'http://'.$form['url'];
 
 			break;
@@ -754,7 +766,7 @@
 			$form = extract_elements(array('jabber', 'icq', 'msn', 'aim', 'yahoo'));
 
 			// If the ICQ UIN contains anything other than digits it's invalid
-			if ($form['icq'] != '' && preg_match('/[^0-9]/', $form['icq']))
+			if ($form['icq'] != '' && @preg_match('/[^0-9]/', $form['icq']))
 				message($lang_prof_reg['Bad ICQ']);
 
 			break;
diff -urN punbb-1.2.8/upload/register.php punbb-1.2.16/upload/register.php
--- punbb-1.2.8/upload/register.php	2005-09-22 09:50:22.000000000 +0200
+++ punbb-1.2.16/upload/register.php	2007-01-14 23:58:16.000000000 +0100
@@ -79,6 +79,13 @@
 
 else if (isset($_POST['form_sent']))
 {
+	// Check that someone from this IP didn't register a user within the last hour (DoS prevention)
+	$result = $db->query('SELECT 1 FROM '.$db->prefix.'users WHERE registration_ip=\''.get_remote_address().'\' AND registered>'.(time() - 3600)) or error('Unable to fetch user info', __FILE__, __LINE__, $db->error());
+
+	if ($db->num_rows($result))
+		message('A new user was registered with the same IP address as you within the last hour. To prevent registration flooding, at least an hour has to pass between registrations from the same IP. Sorry for the inconvenience.');
+
+
 	$username = pun_trim($_POST['req_username']);
 	$email1 = strtolower(trim($_POST['req_email1']));
 
@@ -166,8 +173,17 @@
 			$dupe_list[] = $cur_dupe['username'];
 	}
 
-	$timezone = intval($_POST['timezone']);
-	$language = isset($_POST['language']) ? $_POST['language'] : $pun_config['o_default_lang'];
+	// Make sure we got a valid language string
+	if (isset($_POST['language']))
+	{
+		$language = preg_replace('#[\.\\\/]#', '', $_POST['language']);
+		if (!file_exists(PUN_ROOT.'lang/'.$language.'/common.php'))
+				message($lang_common['Bad request']);
+	}
+	else
+		$language = $pun_config['o_default_lang'];
+
+	$timezone = round($_POST['timezone'], 1);
 	$save_pass = (!isset($_POST['save_pass']) || $_POST['save_pass'] != '1') ? '0' : '1';
 
 	$email_setting = intval($_POST['email_setting']);
diff -urN punbb-1.2.8/upload/search.php punbb-1.2.16/upload/search.php
--- punbb-1.2.8/upload/search.php	2005-09-22 09:50:20.000000000 +0200
+++ punbb-1.2.16/upload/search.php	2007-04-11 09:27:58.000000000 +0200
@@ -122,7 +122,7 @@
 		$keyword_results = $author_results = array();
 
 		// Search a specific forum?
-		$forum_sql = ($forum != -1) ? ' AND t.forum_id = '.$forum : '';
+		$forum_sql = ($forum != -1 || ($forum == -1 && $pun_config['o_search_all_forums'] == '0')) ? ' AND t.forum_id = '.$forum : '';
 
 		if (!empty($author) || !empty($keywords))
 		{
@@ -170,6 +170,7 @@
 
 				$word_count = 0;
 				$match_type = 'and';
+				$result_list = array();
 				@reset($keywords_array);
 				while (list(, $cur_word) = @each($keywords_array))
 				{
@@ -325,7 +326,7 @@
 				if ($pun_user['is_guest'])
 					message($lang_common['No permission']);
 
-				$result = $db->query('SELECT t.id FROM '.$db->prefix.'topics AS t INNER JOIN '.$db->prefix.'forums AS f ON f.id=t.forum_id LEFT JOIN '.$db->prefix.'forum_perms AS fp ON (fp.forum_id=f.id AND fp.group_id='.$pun_user['g_id'].') WHERE (fp.read_forum IS NULL OR fp.read_forum=1) AND t.last_post>'.$pun_user['last_visit']) or error('Unable to fetch topic list', __FILE__, __LINE__, $db->error());
+				$result = $db->query('SELECT t.id FROM '.$db->prefix.'topics AS t INNER JOIN '.$db->prefix.'forums AS f ON f.id=t.forum_id LEFT JOIN '.$db->prefix.'forum_perms AS fp ON (fp.forum_id=f.id AND fp.group_id='.$pun_user['g_id'].') WHERE (fp.read_forum IS NULL OR fp.read_forum=1) AND t.last_post>'.$pun_user['last_visit'].' AND t.moved_to IS NULL') or error('Unable to fetch topic list', __FILE__, __LINE__, $db->error());
 				$num_hits = $db->num_rows($result);
 
 				if (!$num_hits)
@@ -334,7 +335,7 @@
 			// If it's a search for todays posts
 			else if ($action == 'show_24h')
 			{
-				$result = $db->query('SELECT t.id FROM '.$db->prefix.'topics AS t INNER JOIN '.$db->prefix.'forums AS f ON f.id=t.forum_id LEFT JOIN '.$db->prefix.'forum_perms AS fp ON (fp.forum_id=f.id AND fp.group_id='.$pun_user['g_id'].') WHERE (fp.read_forum IS NULL OR fp.read_forum=1) AND t.last_post>'.(time() - 86400)) or error('Unable to fetch topic list', __FILE__, __LINE__, $db->error());
+				$result = $db->query('SELECT t.id FROM '.$db->prefix.'topics AS t INNER JOIN '.$db->prefix.'forums AS f ON f.id=t.forum_id LEFT JOIN '.$db->prefix.'forum_perms AS fp ON (fp.forum_id=f.id AND fp.group_id='.$pun_user['g_id'].') WHERE (fp.read_forum IS NULL OR fp.read_forum=1) AND t.last_post>'.(time() - 86400).' AND t.moved_to IS NULL') or error('Unable to fetch topic list', __FILE__, __LINE__, $db->error());
 				$num_hits = $db->num_rows($result);
 
 				if (!$num_hits)
@@ -387,6 +388,7 @@
 
 
 		// Prune "old" search results
+		$old_searches = array();
 		$result = $db->query('SELECT ident FROM '.$db->prefix.'online') or error('Unable to fetch online list', __FILE__, __LINE__, $db->error());
 
 		if ($db->num_rows($result))
@@ -428,7 +430,6 @@
 	// Fetch results to display
 	if ($search_results != '')
 	{
-		$group_by_sql = '';
 		switch ($sort_by)
 		{
 			case 1:
@@ -448,14 +449,8 @@
 				break;
 
 			default:
-			{
 				$sort_by_sql = ($show_as == 'topics') ? 't.posted' : 'p.posted';
-
-				if ($show_as == 'topics')
-					$group_by_sql = ', t.posted';
-
 				break;
-			}
 		}
 
 		if ($show_as == 'posts')
@@ -464,7 +459,7 @@
 			$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.'posts AS p INNER JOIN '.$db->prefix.'topics AS t ON t.id=p.topic_id WHERE t.id IN('.$search_results.') GROUP BY t.id, t.poster, t.subject, t.last_post, t.last_post_id, t.last_poster, t.num_replies, t.closed, t.forum_id'.$group_by_sql.' 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.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'])
diff -urN punbb-1.2.8/upload/style/imports/base.css punbb-1.2.16/upload/style/imports/base.css
--- punbb-1.2.8/upload/style/imports/base.css	2005-09-22 09:50:22.000000000 +0200
+++ punbb-1.2.16/upload/style/imports/base.css	2007-01-14 23:52:29.000000000 +0100
@@ -43,12 +43,19 @@
 
 DIV>DIV>DIV.postfootleft, DIV>DIV>DIV.postfootright {PADDING-TOP: 1px; MARGIN-TOP: -1px}
 
-/* 3.2 This is only visible to IE Windows and cures various bugs. Do not alter comments */
-
-/* Begin IEWin Fix \*/
-* HTML .inbox, * HTML .inform, * HTML .pun, * HTML .intd, * HTML .tclcon {HEIGHT: 1px}
+/* 3.2 This is only visible to IE6 Windows and cures various bugs. Do not alter comments */
+
+/* Begin IE6Win Fix \*/
+* HTML .inbox, * HTML .inform, * HTML .pun, * HTML .intd, * HTML .tclcon {HEIGHT: 1px}
 * HTML .inbox DIV.postmsg {WIDTH: 98%}
-/* End of IEWin Fix */
+/* End of IE6Win Fix */
+
+/* 3.3 This is the equivelant of 3.2 but for IE7. It is visible to other browsers
+but does no harm */
+
+/*Begin IE7Win Fix */
+.pun, .pun .inbox, .pun .inform, .pun .intd, .pun .tclcon {min-height: 1px}
+/* End of IE7Win Fix */
 
 /****************************************************************/
 /* 4. HIDDEN ELEMENTS */
@@ -168,7 +175,8 @@
 DIV.postleft, DIV.postfootleft {
 	FLOAT:left;
 	WIDTH: 18em;
-	OVERFLOW: hidden
+	OVERFLOW: hidden;
+	POSITION: relative;
 }
 	
 DIV.postright, DIV.postfootright {
diff -urN punbb-1.2.8/upload/userlist.php punbb-1.2.16/upload/userlist.php
--- punbb-1.2.8/upload/userlist.php	2005-09-22 09:50:20.000000000 +0200
+++ punbb-1.2.16/upload/userlist.php	2007-04-10 23:37:34.000000000 +0200
@@ -41,7 +41,7 @@
 // Determine if we are allowed to view post counts
 $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') ? $_GET['username'] : '';
+$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']);
 $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']);
@@ -116,7 +116,7 @@
 	$where_sql[] = 'u.group_id='.$show_group;
 
 // Fetch user count
-$result = $db->query('SELECT COUNT(id) FROM '.$db->prefix.'users AS u'.(!empty($where_sql) ? ' WHERE u.id>1 AND '.implode(' AND ', $where_sql) : '')) or error('Unable to fetch user list count', __FILE__, __LINE__, $db->error());
+$result = $db->query('SELECT COUNT(id) FROM '.$db->prefix.'users AS u WHERE u.id>1'.(!empty($where_sql) ? ' AND '.implode(' AND ', $where_sql) : '')) or error('Unable to fetch user list count', __FILE__, __LINE__, $db->error());
 $num_users = $db->result($result);
 
 
