diff -urN punbb-1.2.2/upload/admin_bans.php punbb-1.2.15/upload/admin_bans.php
--- punbb-1.2.2/upload/admin_bans.php	Tue Feb  1 16:16:46 2005
+++ punbb-1.2.15/upload/admin_bans.php	Sat Oct 14 18:40:30 2006
@@ -44,7 +44,7 @@
 		if (isset($_GET['add_ban']))
 		{
 			$add_ban = intval($_GET['add_ban']);
-			if ($add_ban < 1)
+			if ($add_ban < 2)
 				message($lang_common['Bad request']);
 
 			$user_id = $add_ban;
@@ -61,7 +61,7 @@
 
 			if ($ban_user != '')
 			{
-				$result = $db->query('SELECT id, group_id, username, email FROM '.$db->prefix.'users WHERE username=\''.$db->escape($ban_user).'\'') or error('Unable to fetch user info', __FILE__, __LINE__, $db->error());
+				$result = $db->query('SELECT id, group_id, username, email FROM '.$db->prefix.'users WHERE username=\''.$db->escape($ban_user).'\' AND id>1') or error('Unable to fetch user info', __FILE__, __LINE__, $db->error());
 				if ($db->num_rows($result))
 					list($user_id, $group_id, $ban_user, $ban_email) = $db->fetch_row($result);
 				else
@@ -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 != '')
@@ -244,7 +246,7 @@
 	if ($_POST['mode'] == 'add')
 		$db->query('INSERT INTO '.$db->prefix.'bans (username, ip, email, message, expire) VALUES('.$ban_user.', '.$ban_ip.', '.$ban_email.', '.$ban_message.', '.$ban_expire.')') or error('Unable to add ban', __FILE__, __LINE__, $db->error());
 	else
-		$db->query('UPDATE '.$db->prefix.'bans SET username='.$ban_user.', ip='.$ban_ip.', email='.$ban_email.', message='.$ban_message.', expire='.$ban_expire.' WHERE id='.$_POST['ban_id']) or error('Unable to update ban', __FILE__, __LINE__, $db->error());
+		$db->query('UPDATE '.$db->prefix.'bans SET username='.$ban_user.', ip='.$ban_ip.', email='.$ban_email.', message='.$ban_message.', expire='.$ban_expire.' WHERE id='.intval($_POST['ban_id'])) or error('Unable to update ban', __FILE__, __LINE__, $db->error());
 
 	// Regenerate the bans cache
 	require_once PUN_ROOT.'include/cache.php';
diff -urN punbb-1.2.2/upload/admin_categories.php punbb-1.2.15/upload/admin_categories.php
--- punbb-1.2.2/upload/admin_categories.php	Tue Jan 11 20:41:14 2005
+++ punbb-1.2.15/upload/admin_categories.php	Tue Apr 10 23:37:36 2007
@@ -118,12 +118,12 @@
 					<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>
 				</div>
-				<p><input type="submit" name="del_cat_comply" value="Delete" />&nbsp;&nbsp;&nbsp;<a href="javascript:history.go(-1)" />Go back</a></p>
+				<p><input type="submit" name="del_cat_comply" value="Delete" /><a href="javascript:history.go(-1)">Go back</a></p>
 			</form>
 		</div>
 	</div>
@@ -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.2/upload/admin_censoring.php punbb-1.2.15/upload/admin_censoring.php
--- punbb-1.2.2/upload/admin_censoring.php	Tue Jan 11 20:41:14 2005
+++ punbb-1.2.15/upload/admin_censoring.php	Thu Apr  7 21:38:24 2005
@@ -57,7 +57,7 @@
 {
 	confirm_referrer('admin_censoring.php');
 
-	$id = key($_POST['update']);
+	$id = intval(key($_POST['update']));
 
 	$search_for = trim($_POST['search_for'][$id]);
 	$replace_with = trim($_POST['replace_with'][$id]);
@@ -76,7 +76,7 @@
 {
 	confirm_referrer('admin_censoring.php');
 
-	$id = key($_POST['remove']);
+	$id = intval(key($_POST['remove']));
 
 	$db->query('DELETE FROM '.$db->prefix.'censoring WHERE id='.$id) or error('Unable to delete censor word', __FILE__, __LINE__, $db->error());
 
diff -urN punbb-1.2.2/upload/admin_forums.php punbb-1.2.15/upload/admin_forums.php
--- punbb-1.2.2/upload/admin_forums.php	Fri Feb 18 22:05:02 2005
+++ punbb-1.2.15/upload/admin_forums.php	Tue Apr 10 23:37:36 2007
@@ -117,7 +117,7 @@
 						</div>
 					</fieldset>
 				</div>
-				<p><input type="submit" name="del_forum_comply" value="Delete" />&nbsp;&nbsp;&nbsp;<a href="javascript:history.go(-1)" />Go back</a></p>
+				<p><input type="submit" name="del_forum_comply" value="Delete" /><a href="javascript:history.go(-1)">Go back</a></p>
 			</form>
 		</div>
 	</div>
@@ -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.2/upload/admin_groups.php punbb-1.2.15/upload/admin_groups.php
--- punbb-1.2.2/upload/admin_groups.php	Fri Feb 18 22:05:02 2005
+++ punbb-1.2.15/upload/admin_groups.php	Sat Oct 14 18:41:54 2006
@@ -209,15 +209,15 @@
 
 	$title = trim($_POST['req_title']);
 	$user_title = trim($_POST['user_title']);
-	$read_board = isset($_POST['read_board']) ? $_POST['read_board'] : '1';
-	$post_replies = isset($_POST['post_replies']) ? $_POST['post_replies'] : '1';
-	$post_topics = isset($_POST['post_topics']) ? $_POST['post_topics'] : '1';
-	$edit_posts = isset($_POST['edit_posts']) ? $_POST['edit_posts'] : ($is_admin_group) ? '1' : '0';
-	$delete_posts = isset($_POST['delete_posts']) ? $_POST['delete_posts'] : ($is_admin_group) ? '1' : '0';
-	$delete_topics = isset($_POST['delete_topics']) ? $_POST['delete_topics'] : ($is_admin_group) ? '1' : '0';
-	$set_title = isset($_POST['set_title']) ? $_POST['set_title'] : ($is_admin_group) ? '1' : '0';
-	$search = isset($_POST['search']) ? $_POST['search'] : '1';
-	$search_users = isset($_POST['search_users']) ? $_POST['search_users'] : '1';
+	$read_board = isset($_POST['read_board']) ? intval($_POST['read_board']) : '1';
+	$post_replies = isset($_POST['post_replies']) ? intval($_POST['post_replies']) : '1';
+	$post_topics = isset($_POST['post_topics']) ? intval($_POST['post_topics']) : '1';
+	$edit_posts = isset($_POST['edit_posts']) ? intval($_POST['edit_posts']) : ($is_admin_group) ? '1' : '0';
+	$delete_posts = isset($_POST['delete_posts']) ? intval($_POST['delete_posts']) : ($is_admin_group) ? '1' : '0';
+	$delete_topics = isset($_POST['delete_topics']) ? intval($_POST['delete_topics']) : ($is_admin_group) ? '1' : '0';
+	$set_title = isset($_POST['set_title']) ? intval($_POST['set_title']) : ($is_admin_group) ? '1' : '0';
+	$search = isset($_POST['search']) ? intval($_POST['search']) : '1';
+	$search_users = isset($_POST['search_users']) ? intval($_POST['search_users']) : '1';
 	$edit_subjects_interval = isset($_POST['edit_subjects_interval']) ? intval($_POST['edit_subjects_interval']) : '0';
 	$post_flood = isset($_POST['post_flood']) ? intval($_POST['post_flood']) : '0';
 	$search_flood = isset($_POST['search_flood']) ? intval($_POST['search_flood']) : '0';
@@ -229,8 +229,8 @@
 
 	if ($_POST['mode'] == 'add')
 	{
-		$db->query('SELECT 1 FROM '.$db->prefix.'groups WHERE g_title=\''.$db->escape($title).'\'') or error('Unable to check group title collision', __FILE__, __LINE__, $db->error());
-		if ($db->num_rows())
+		$result = $db->query('SELECT 1 FROM '.$db->prefix.'groups WHERE g_title=\''.$db->escape($title).'\'') or error('Unable to check group title collision', __FILE__, __LINE__, $db->error());
+		if ($db->num_rows($result))
 			message('There is already a group with the title \''.pun_htmlspecialchars($title).'\'.');
 
 		$db->query('INSERT INTO '.$db->prefix.'groups (g_title, g_user_title, g_read_board, g_post_replies, g_post_topics, g_edit_posts, g_delete_posts, g_delete_topics, g_set_title, g_search, g_search_users, g_edit_subjects_interval, g_post_flood, g_search_flood) VALUES(\''.$db->escape($title).'\', '.$user_title.', '.$read_board.', '.$post_replies.', '.$post_topics.', '.$edit_posts.', '.$delete_posts.', '.$delete_topics.', '.$set_title.', '.$search.', '.$search_users.', '.$edit_subjects_interval.', '.$post_flood.', '.$search_flood.')') or error('Unable to add group', __FILE__, __LINE__, $db->error());
@@ -242,7 +242,13 @@
 			$db->query('INSERT INTO '.$db->prefix.'forum_perms (group_id, forum_id, read_forum, post_replies, post_topics) VALUES('.$new_group_id.', '.$cur_forum_perm['forum_id'].', '.$cur_forum_perm['read_forum'].', '.$cur_forum_perm['post_replies'].', '.$cur_forum_perm['post_topics'].')') or error('Unable to insert group forum permissions', __FILE__, __LINE__, $db->error());
 	}
 	else
-		$db->query('UPDATE '.$db->prefix.'groups SET g_title=\''.$db->escape($title).'\', g_user_title='.$user_title.', g_read_board='.$read_board.', g_post_replies='.$post_replies.', g_post_topics='.$post_topics.', g_edit_posts='.$edit_posts.', g_delete_posts='.$delete_posts.', g_delete_topics='.$delete_topics.', g_set_title='.$set_title.', g_search='.$search.', g_search_users='.$search_users.', g_edit_subjects_interval='.$edit_subjects_interval.', g_post_flood='.$post_flood.', g_search_flood='.$search_flood.' WHERE g_id='.$_POST['group_id']) or error('Unable to update group', __FILE__, __LINE__, $db->error());
+	{
+		$result = $db->query('SELECT 1 FROM '.$db->prefix.'groups WHERE g_title=\''.$db->escape($title).'\' AND g_id!='.intval($_POST['group_id'])) or error('Unable to check group title collision', __FILE__, __LINE__, $db->error());
+		if ($db->num_rows($result))
+			message('There is already a group with the title \''.pun_htmlspecialchars($title).'\'.');
+
+		$db->query('UPDATE '.$db->prefix.'groups SET g_title=\''.$db->escape($title).'\', g_user_title='.$user_title.', g_read_board='.$read_board.', g_post_replies='.$post_replies.', g_post_topics='.$post_topics.', g_edit_posts='.$edit_posts.', g_delete_posts='.$delete_posts.', g_delete_topics='.$delete_topics.', g_set_title='.$set_title.', g_search='.$search.', g_search_users='.$search_users.', g_edit_subjects_interval='.$edit_subjects_interval.', g_post_flood='.$post_flood.', g_search_flood='.$search_flood.' WHERE g_id='.intval($_POST['group_id'])) or error('Unable to update group', __FILE__, __LINE__, $db->error());
+	}
 
 	// Regenerate the quickjump cache
 	require_once PUN_ROOT.'include/cache.php';
@@ -258,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.2/upload/admin_index.php punbb-1.2.15/upload/admin_index.php
--- punbb-1.2.2/upload/admin_index.php	Sun Jan 23 18:36:42 2005
+++ punbb-1.2.15/upload/admin_index.php	Fri Sep  2 16:03:20 2005
@@ -64,7 +64,7 @@
 
 
 // Show phpinfo() output
-else if ($action == 'phpinfo')
+else if ($action == 'phpinfo' && $pun_user['g_id'] == PUN_ADMIN)
 {
 	// Is phpinfo() a disabled function?
 	if (strpos(strtolower((string)@ini_get('disable_functions')), 'phpinfo') !== false)
@@ -86,14 +86,14 @@
 	$load_averages = @explode(' ', $load_averages);
 	$server_load = isset($load_averages[2]) ? $load_averages[0].' '.$load_averages[1].' '.$load_averages[2] : 'Not available';
 }
-else if (preg_match('/averages?: ([0-9\.]+),[\s]+([0-9\.]+),[\s]+([0-9\.]+)/i', @exec('uptime'), $load_averages))
+else if (!in_array(PHP_OS, array('WINNT', 'WIN32')) && preg_match('/averages?: ([0-9\.]+),[\s]+([0-9\.]+),[\s]+([0-9\.]+)/i', @exec('uptime'), $load_averages))
 	$server_load = $load_averages[1].' '.$load_averages[2].' '.$load_averages[3];
 else
 	$server_load = 'Not available';
 
 
 // Get number of current visitors
-$result = $db->query('SELECT COUNT(user_id) FROM '.$db->prefix.'online') or error('Unable to fetch online count', __FILE__, __LINE__, $db->error());
+$result = $db->query('SELECT COUNT(user_id) FROM '.$db->prefix.'online WHERE idle=0') or error('Unable to fetch online count', __FILE__, __LINE__, $db->error());
 $num_online = $db->result($result);
 
 
diff -urN punbb-1.2.2/upload/admin_loader.php punbb-1.2.15/upload/admin_loader.php
--- punbb-1.2.2/upload/admin_loader.php	Thu Feb 24 22:15:54 2005
+++ punbb-1.2.15/upload/admin_loader.php	Tue Apr 10 23:37:36 2007
@@ -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.2/upload/admin_maintenance.php punbb-1.2.15/upload/admin_maintenance.php
--- punbb-1.2.2/upload/admin_maintenance.php	Sun Jan 30 12:58:04 2005
+++ punbb-1.2.15/upload/admin_maintenance.php	Wed Jan 31 00:31:44 2007
@@ -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.2/upload/admin_options.php punbb-1.2.15/upload/admin_options.php
--- punbb-1.2.2/upload/admin_options.php	Sun Jan 23 20:08:54 2005
+++ punbb-1.2.15/upload/admin_options.php	Wed Apr 11 13:35:46 2007
@@ -37,15 +37,18 @@
 
 if (isset($_POST['form_sent']))
 {
-	// Lazy referer check (in case base_url isn't correct)
-	if (!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);
@@ -117,14 +123,14 @@
 	while (list($key, $input) = @each($form))
 	{
 		// Only update values that have changed
-		if ($pun_config['o_'.$key] != $input)
+		if (array_key_exists('o_'.$key, $pun_config) && $pun_config['o_'.$key] != $input)
 		{
 			if ($input != '' || is_int($input))
 				$value = '\''.$db->escape($input).'\'';
 			else
 				$value = 'NULL';
 
-			$db->query('UPDATE '.$db->prefix.'config SET conf_value='.$value.' WHERE conf_name=\'o_'.$key.'\'') or error('Unable to update board config', __FILE__, __LINE__, $db->error());
+			$db->query('UPDATE '.$db->prefix.'config SET conf_value='.$value.' WHERE conf_name=\'o_'.$db->escape($key).'\'') or error('Unable to update board config', __FILE__, __LINE__, $db->error());
 		}
 	}
 
@@ -229,11 +235,13 @@
 		$d = dir(PUN_ROOT.'lang');
 		while (($entry = $d->read()) !== false)
 		{
-			if ($entry != '.' && $entry != '..' && is_dir(PUN_ROOT.'lang/'.$entry))
+			if ($entry != '.' && $entry != '..' && is_dir(PUN_ROOT.'lang/'.$entry) && file_exists(PUN_ROOT.'lang/'.$entry.'/common.php'))
 				$languages[] = $entry;
 		}
 		$d->close();
 
+		@natsort($languages);
+
 		while (list(, $temp) = @each($languages))
 		{
 			if ($pun_config['o_default_lang'] == $temp)
@@ -261,6 +269,8 @@
 				$styles[] = substr($entry, 0, strlen($entry)-4);
 		}
 		$d->close();
+
+		@natsort($styles);
 
 		while (list(, $temp) = @each($styles))
 		{
diff -urN punbb-1.2.2/upload/admin_permissions.php punbb-1.2.15/upload/admin_permissions.php
--- punbb-1.2.2/upload/admin_permissions.php	Tue Jan 11 20:41:14 2005
+++ punbb-1.2.15/upload/admin_permissions.php	Fri Sep  2 01:36:12 2005
@@ -39,23 +39,13 @@
 {
 	confirm_referrer('admin_permissions.php');
 
-	$form = array_map('trim', $_POST['form']);
-
-	$form['sig_length'] = intval($form['sig_length']);
-	$form['sig_lines'] = intval($form['sig_lines']);
+	$form = array_map('intval', $_POST['form']);
 
 	while (list($key, $input) = @each($form))
 	{
 		// Only update values that have changed
-		if ($pun_config['p_'.$key] != $input)
-		{
-			if ($input != '' || is_int($input))
-				$value = '\''.$db->escape($input).'\'';
-			else
-				$value = 'NULL';
-
-			$db->query('UPDATE '.$db->prefix.'config SET conf_value='.$value.' WHERE conf_name=\'p_'.$key.'\'') or error('Unable to update board config', __FILE__, __LINE__, $db->error());
-		}
+		if (array_key_exists('p_'.$key, $pun_config) && $pun_config['p_'.$key] != $input)
+			$db->query('UPDATE '.$db->prefix.'config SET conf_value='.$input.' WHERE conf_name=\'p_'.$db->escape($key).'\'') or error('Unable to update board config', __FILE__, __LINE__, $db->error());
 	}
 
 	// Regenerate the config cache
diff -urN punbb-1.2.2/upload/admin_prune.php punbb-1.2.15/upload/admin_prune.php
--- punbb-1.2.2/upload/admin_prune.php	Tue Jan 11 20:41:14 2005
+++ punbb-1.2.15/upload/admin_prune.php	Tue Apr 10 23:37:36 2007
@@ -62,6 +62,7 @@
 		}
 		else
 		{
+			$prune_from = intval($prune_from);
 			prune($prune_from, $_POST['prune_sticky'], $prune_date);
 			update_forum($prune_from);
 		}
@@ -83,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);
@@ -97,6 +98,7 @@
 
 	if ($prune_from != 'all')
 	{
+		$prune_from = intval($prune_from);
 		$sql .= ' AND forum_id='.$prune_from;
 
 		// Fetch the forum name (just for cosmetic reasons)
@@ -135,7 +137,7 @@
 						</div>
 					</fieldset>
 				</div>
-				<p><input type="submit" name="prune_comply" value="Prune" />&nbsp;&nbsp;&nbsp;<a href="javascript:history.go(-1)" />Go back</a></p>
+				<p><input type="submit" name="prune_comply" value="Prune" /><a href="javascript:history.go(-1)">Go back</a></p>
 			</form>
 		</div>
 	</div>
diff -urN punbb-1.2.2/upload/admin_ranks.php punbb-1.2.15/upload/admin_ranks.php
--- punbb-1.2.2/upload/admin_ranks.php	Tue Jan 11 20:41:14 2005
+++ punbb-1.2.15/upload/admin_ranks.php	Tue Apr 10 23:37:36 2007
@@ -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
@@ -69,7 +69,7 @@
 {
 	confirm_referrer('admin_ranks.php');
 
-	$id = key($_POST['update']);
+	$id = intval(key($_POST['update']));
 
 	$rank = trim($_POST['rank'][$id]);
 	$min_posts = trim($_POST['min_posts'][$id]);
@@ -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.'.');
 
@@ -100,7 +100,7 @@
 {
 	confirm_referrer('admin_ranks.php');
 
-	$id = key($_POST['remove']);
+	$id = intval(key($_POST['remove']));
 
 	$db->query('DELETE FROM '.$db->prefix.'ranks WHERE id='.$id) or error('Unable to delete rank', __FILE__, __LINE__, $db->error());
 
diff -urN punbb-1.2.2/upload/admin_reports.php punbb-1.2.15/upload/admin_reports.php
--- punbb-1.2.2/upload/admin_reports.php	Tue Jan 11 20:41:14 2005
+++ punbb-1.2.15/upload/admin_reports.php	Fri Mar 11 20:17:28 2005
@@ -40,7 +40,7 @@
 {
 	confirm_referrer('admin_reports.php');
 
-	$zap_id = key($_POST['zap_id']);
+	$zap_id = intval(key($_POST['zap_id']));
 
 	$result = $db->query('SELECT zapped FROM '.$db->prefix.'reports WHERE id='.$zap_id) or error('Unable to fetch report info', __FILE__, __LINE__, $db->error());
 	$zapped = $db->result($result);
diff -urN punbb-1.2.2/upload/admin_users.php punbb-1.2.15/upload/admin_users.php
--- punbb-1.2.2/upload/admin_users.php	Tue Feb  1 16:16:46 2005
+++ punbb-1.2.15/upload/admin_users.php	Tue Apr 10 23:37:36 2007
@@ -49,7 +49,7 @@
 ?>
 <div class="linkst">
 	<div class="inbox">
-		<div><a href="javascript:history.go(-1)" />Go back</a></div>
+		<div><a href="javascript:history.go(-1)">Go back</a></div>
 	</div>
 </div>
 
@@ -98,7 +98,7 @@
 
 <div class="linksb">
 	<div class="inbox">
-		<div><a href="javascript:history.go(-1)" />Go back</a></div>
+		<div><a href="javascript:history.go(-1)">Go back</a></div>
 	</div>
 </div>
 <?php
@@ -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.');
 
 
@@ -121,7 +121,7 @@
 ?>
 <div class="linkst">
 	<div class="inbox">
-		<div><a href="javascript:history.go(-1)" />Go back</a></div>
+		<div><a href="javascript:history.go(-1)">Go back</a></div>
 	</div>
 </div>
 
@@ -202,7 +202,7 @@
 
 <div class="linksb">
 	<div class="inbox">
-		<div><a href="javascript:history.go(-1)" />Go back</a></div>
+		<div><a href="javascript:history.go(-1)">Go back</a></div>
 	</div>
 </div>
 <?php
@@ -217,6 +217,7 @@
 
 	// trim() all elements in $form
 	$form = array_map('trim', $form);
+	$conditions = array();
 
 	$posts_greater = trim($_POST['posts_greater']);
 	$posts_less = trim($_POST['posts_less']);
@@ -256,8 +257,8 @@
 	$like_command = ($db_type == 'pgsql') ? 'ILIKE' : 'LIKE';
 	while (list($key, $input) = @each($form))
 	{
-		if ($input != '')
-			$conditions[] = 'u.'.$key.' '.$like_command.' \''.str_replace('*', '%', $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)).'\'';
 	}
 
 	if ($posts_greater != '')
@@ -266,9 +267,9 @@
 		$conditions[] = 'u.num_posts<'.$posts_less;
 
 	if ($user_group != 'all')
-		$conditions[] = 'u.group_id='.$user_group;
+		$conditions[] = 'u.group_id='.intval($user_group);
 
-	if (!isset($conditions))
+	if (empty($conditions))
 		message('You didn\'t enter any search terms.');
 
 
@@ -278,7 +279,7 @@
 ?>
 <div class="linkst">
 	<div class="inbox">
-		<div><a href="javascript:history.go(-1)" />Go back</a></div>
+		<div><a href="javascript:history.go(-1)">Go back</a></div>
 	</div>
 </div>
 
@@ -300,7 +301,7 @@
 			<tbody>
 <?php
 
-	$result = $db->query('SELECT u.id, u.username, u.email, u.title, u.num_posts, u.admin_note, g.g_id, g.g_user_title FROM '.$db->prefix.'users AS u LEFT JOIN '.$db->prefix.'groups AS g ON g.g_id=u.group_id WHERE u.id>1 AND '.implode(' AND ', $conditions).' ORDER BY '.$order_by.' '.$direction) or error('Unable to fetch user info', __FILE__, __LINE__, $db->error());
+	$result = $db->query('SELECT u.id, u.username, u.email, u.title, u.num_posts, u.admin_note, g.g_id, g.g_user_title FROM '.$db->prefix.'users AS u LEFT JOIN '.$db->prefix.'groups AS g ON g.g_id=u.group_id WHERE u.id>1 AND '.implode(' AND ', $conditions).' ORDER BY '.$db->escape($order_by).' '.$db->escape($direction)) or error('Unable to fetch user info', __FILE__, __LINE__, $db->error());
 	if ($db->num_rows($result))
 	{
 		while ($user_data = $db->fetch_assoc($result))
@@ -338,7 +339,7 @@
 
 <div class="linksb">
 	<div class="inbox">
-		<div><a href="javascript:history.go(-1)" />Go back</a></div>
+		<div><a href="javascript:history.go(-1)">Go back</a></div>
 	</div>
 </div>
 <?php
diff -urN punbb-1.2.2/upload/edit.php punbb-1.2.15/upload/edit.php
--- punbb-1.2.2/upload/edit.php	Tue Jan 11 20:41:14 2005
+++ punbb-1.2.15/upload/edit.php	Fri Sep  2 16:05:32 2005
@@ -175,7 +175,7 @@
 else if (isset($_POST['preview']))
 {
 	require_once PUN_ROOT.'include/parser.php';
-	$message = parse_message(trim($_POST['req_message']), $hide_smilies);
+	$preview_message = parse_message($message, $hide_smilies);
 
 ?>
 <div id="postpreview" class="blockpost">
@@ -184,7 +184,7 @@
 		<div class="inbox">
 			<div class="postright">
 				<div class="postmsg">
-					<?php echo $message."\n" ?>
+					<?php echo $preview_message."\n" ?>
 				</div>
 			</div>
 		</div>
@@ -208,7 +208,7 @@
 <?php if ($can_edit_subject): ?>						<label><?php echo $lang_common['Subject'] ?><br />
 						<input class="longinput" type="text" name="req_subject" size="80" maxlength="70" tabindex="<?php echo $cur_index++ ?>" value="<?php echo pun_htmlspecialchars(isset($_POST['req_subject']) ? $_POST['req_subject'] : $cur_post['subject']) ?>" /><br /></label>
 <?php endif; ?>						<label><?php echo $lang_common['Message'] ?><br />
-						<textarea name="req_message" rows="20" cols="95" tabindex="<?php echo $cur_index++ ?>"><?php echo pun_htmlspecialchars(isset($_POST['req_message']) ? $_POST['req_message'] : $cur_post['message']) ?></textarea><br /></label>
+						<textarea name="req_message" rows="20" cols="95" tabindex="<?php echo $cur_index++ ?>"><?php echo pun_htmlspecialchars(isset($_POST['req_message']) ? $message : $cur_post['message']) ?></textarea><br /></label>
 						<ul class="bblinks">
 							<li><a href="help.php#bbcode" onclick="window.open(this.href); return false;"><?php echo $lang_common['BBCode'] ?></a>: <?php echo ($pun_config['p_message_bbcode'] == '1') ? $lang_common['on'] : $lang_common['off']; ?></li>
 							<li><a href="help.php#img" onclick="window.open(this.href); return false;"><?php echo $lang_common['img tag'] ?></a>: <?php echo ($pun_config['p_message_img_tag'] == '1') ? $lang_common['on'] : $lang_common['off']; ?></li>
diff -urN punbb-1.2.2/upload/extern.php punbb-1.2.15/upload/extern.php
--- punbb-1.2.2/upload/extern.php	Tue Jan 11 20:41:14 2005
+++ punbb-1.2.15/upload/extern.php	Mon Jan 15 02:51:06 2007
@@ -116,8 +116,8 @@
 	exit('The file \'config.php\' doesn\'t exist or is corrupt. Please run install.php to install PunBB first.');
 
 
-// Disable error reporting for uninitialized variables
-error_reporting(E_ALL);
+// Make sure PHP reports all errors except E_NOTICE
+error_reporting(E_ALL ^ E_NOTICE);
 
 // Turn off magic_quotes_runtime
 set_magic_quotes_runtime(0);
@@ -129,10 +129,14 @@
 // Load DB abstraction layer and try to connect
 require PUN_ROOT.'include/dblayer/common_db.php';
 
-// Get the forum config
-$result = $db->query('SELECT * FROM '.$db->prefix.'config') or error('Unable to fetch forum config', __FILE__, __LINE__, $db->error());
-while ($cur_config_item = $db->fetch_row($result))
-	$pun_config[$cur_config_item[0]] = $cur_config_item[1];
+// Load cached config
+@include PUN_ROOT.'cache/cache_config.php';
+if (!defined('PUN_CONFIG_LOADED'))
+{
+    require PUN_ROOT.'include/cache.php';
+    generate_config_cache();
+    require PUN_ROOT.'cache/cache_config.php';
+}
 
 // Make sure we (guests) have permission to read the forums
 $result = $db->query('SELECT g_read_board FROM '.$db->prefix.'groups WHERE g_id=3') or error('Unable to fetch group info', __FILE__, __LINE__, $db->error());
@@ -144,6 +148,10 @@
 @include PUN_ROOT.'lang/'.$pun_config['o_default_lang'].'/common.php';
 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.2/upload/footer.php punbb-1.2.15/upload/footer.php
--- punbb-1.2.2/upload/footer.php	Tue Feb 22 23:31:02 2005
+++ punbb-1.2.15/upload/footer.php	Tue Apr 10 18:19:26 2007
@@ -139,18 +139,6 @@
 // END SUBST - <pun_footer>
 
 
-// START SUBST - <pun_include "*">
-while (preg_match('/<pun_include "(.*?)">/', $tpl_main, $cur_include))
-{
-	ob_start();
-	include PUN_ROOT.$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.2/upload/header.php punbb-1.2.15/upload/header.php
--- punbb-1.2.2/upload/header.php	Tue Feb  1 16:16:46 2005
+++ punbb-1.2.15/upload/header.php	Tue Apr 10 18:19:26 2007
@@ -15,7 +15,7 @@
   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 G>eneral Public License
+  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
@@ -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>
@@ -68,10 +83,7 @@
 if (defined('PUN_ADMIN_CONSOLE'))
 	echo '<link rel="stylesheet" type="text/css" href="style/imports/base_admin.css" />'."\n";
 
-if (isset($destination_url))
-	echo '<meta http-equiv="refresh" content="'.$delay.';URL='.$destination.'" />'."\n";
-
-else if (isset($required_fields))
+if (isset($required_fields))
 {
 	// Output JavaScript to validate form (make sure required fields are filled out)
 
@@ -134,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>
 
 
@@ -171,10 +183,8 @@
 			$tpl_temp .= "\n\t\t\t\t".'<li class="maintenancelink"><strong><a href="admin_options.php#maintenance">Maintenance mode is enabled!</a></strong></li>';
 	}
 
-	if (basename($_SERVER['PHP_SELF']) == 'index.php')
+	if (in_array(basename($_SERVER['PHP_SELF']), array('index.php', 'search.php')))
 		$tpl_temp .= "\n\t\t\t".'</ul>'."\n\t\t\t".'<ul class="conr">'."\n\t\t\t\t".'<li><a href="search.php?action=show_new">'.$lang_common['Show new posts'].'</a></li>'."\n\t\t\t\t".'<li><a href="misc.php?action=markread">'.$lang_common['Mark all as read'].'</a></li>'."\n\t\t\t".'</ul>'."\n\t\t\t".'<div class="clearer"></div>'."\n\t\t".'</div>';
-	else if (isset($_SERVER['QUERY_STRING']) && $_SERVER['QUERY_STRING'] == 'action=show_new')
-		$tpl_temp .= "\n\t\t\t".'</ul>'."\n\t\t\t".'<p class="conr"><a href="misc.php?action=markread">'.$lang_common['Mark all as read'].'</a></p>'."\n\t\t\t".'<div class="clearer"></div>'."\n\t\t".'</div>';
 	else
 		$tpl_temp .= "\n\t\t\t".'</ul>'."\n\t\t\t".'<div class="clearer"></div>'."\n\t\t".'</div>';
 }
diff -urN punbb-1.2.2/upload/help.php punbb-1.2.15/upload/help.php
--- punbb-1.2.2/upload/help.php	Wed Jan 12 21:17:34 2005
+++ punbb-1.2.15/upload/help.php	Fri Mar 18 23:20:46 2005
@@ -86,7 +86,7 @@
 		&nbsp;&nbsp;&nbsp;&nbsp;[quote]<?php echo $lang_help['Quote text'] ?>[/quote]<br /><br />
 		<?php echo $lang_help['produces quote box'] ?><br /><br />
 		<div class="postmsg">
-			<blockquote><div class="incqbox"></h4><p><?php echo $lang_help['Quote text'] ?></p></div></blockquote>
+			<blockquote><div class="incqbox"><p><?php echo $lang_help['Quote text'] ?></p></div></blockquote>
 		</div>
 	</div>
 </div>
diff -urN punbb-1.2.2/upload/include/cache.php punbb-1.2.15/upload/include/cache.php
--- punbb-1.2.2/upload/include/cache.php	Sun Jan 30 18:40:38 2005
+++ punbb-1.2.15/upload/include/cache.php	Thu Jul  7 19:00:10 2005
@@ -129,7 +129,7 @@
 	global $db;
 
 	// Get the rank list from the DB
-	$result = $db->query('SELECT * FROM '.$db->prefix.'ranks', true) or error('Unable to fetch rank list', __FILE__, __LINE__, $db->error());
+	$result = $db->query('SELECT * FROM '.$db->prefix.'ranks ORDER BY min_posts', true) or error('Unable to fetch rank list', __FILE__, __LINE__, $db->error());
 
 	$output = array();
 	while ($cur_rank = $db->fetch_assoc($result))
@@ -174,7 +174,7 @@
 		if (!$fh)
 			error('Unable to write quickjump cache file to cache directory. Please make sure PHP has write access to the directory \'cache\'', __FILE__, __LINE__);
 
-		$output = '<?php'."\n\n".'define(\'PUN_QJ_LOADED\', 1);'."\n\n".'?>';
+		$output = '<?php'."\n\n".'if (!defined(\'PUN\')) exit;'."\n".'define(\'PUN_QJ_LOADED\', 1);'."\n\n".'?>';
 		$output .= "\t\t\t\t".'<form id="qjump" method="get" action="viewforum.php">'."\n\t\t\t\t\t".'<div><label><?php echo $lang_common[\'Jump to\'] ?>'."\n\n\t\t\t\t\t".'<br /><select name="id" onchange="window.location=(\'viewforum.php?id=\'+this.options[this.selectedIndex].value)">'."\n";
 
 
diff -urN punbb-1.2.2/upload/include/common.php punbb-1.2.15/upload/include/common.php
--- punbb-1.2.2/upload/include/common.php	Tue Jan 11 20:41:14 2005
+++ punbb-1.2.15/upload/include/common.php	Mon Apr  9 16:15:22 2007
@@ -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
@@ -43,8 +51,8 @@
 list($usec, $sec) = explode(' ', microtime());
 $pun_start = ((float)$usec + (float)$sec);
 
-// Enable full error, warning and notice reporting
-error_reporting(E_ALL);
+// Make sure PHP reports all errors except E_NOTICE. PunBB supports E_ALL, but a lot of scripts it may interact with, do not.
+error_reporting(E_ALL ^ E_NOTICE);
 
 // Turn off magic_quotes_runtime
 set_magic_quotes_runtime(0);
@@ -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';
 
@@ -117,7 +122,7 @@
 // Attempt to load the common language file
 @include PUN_ROOT.'lang/'.$pun_user['language'].'/common.php';
 if (!isset($lang_common))
-	exit('There is no valid language pack \''.$pun_user['language'].'\' installed. Please reinstall a language of that name.');
+	exit('There is no valid language pack \''.pun_htmlspecialchars($pun_user['language']).'\' installed. Please reinstall a language of that name.');
 
 // Check if we are to display a maintenance message
 if ($pun_config['o_maintenance'] && $pun_user['g_id'] > PUN_ADMIN && !defined('PUN_TURN_OFF_MAINT'))
diff -urN punbb-1.2.2/upload/include/dblayer/common_db.php punbb-1.2.15/upload/include/dblayer/common_db.php
--- punbb-1.2.2/upload/include/dblayer/common_db.php	Tue Jan 11 20:41:14 2005
+++ punbb-1.2.15/upload/include/dblayer/common_db.php	Fri Mar 18 23:07:50 2005
@@ -23,6 +23,11 @@
 ************************************************************************/
 
 
+// Make sure no one attempts to run this script "directly"
+if (!defined('PUN'))
+	exit;
+
+
 //
 // Return current timestamp (with microseconds) as a float (used in dblayer)
 //
diff -urN punbb-1.2.2/upload/include/dblayer/mysql.php punbb-1.2.15/upload/include/dblayer/mysql.php
--- punbb-1.2.2/upload/include/dblayer/mysql.php	Tue Jan 11 20:41:14 2005
+++ punbb-1.2.15/upload/include/dblayer/mysql.php	Tue Apr 10 23:37:36 2007
@@ -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.2/upload/include/dblayer/mysqli.php punbb-1.2.15/upload/include/dblayer/mysqli.php
--- punbb-1.2.2/upload/include/dblayer/mysqli.php	Tue Jan 11 20:41:14 2005
+++ punbb-1.2.15/upload/include/dblayer/mysqli.php	Tue Apr 10 23:37:36 2007
@@ -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.2/upload/include/dblayer/pgsql.php punbb-1.2.15/upload/include/dblayer/pgsql.php
--- punbb-1.2.2/upload/include/dblayer/pgsql.php	Fri Jan 28 22:16:44 2005
+++ punbb-1.2.15/upload/include/dblayer/pgsql.php	Tue Apr 10 23:37:36 2007
@@ -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.2/upload/include/dblayer/sqlite.php punbb-1.2.15/upload/include/dblayer/sqlite.php
--- punbb-1.2.2/upload/include/dblayer/sqlite.php	Fri Jan 28 22:16:44 2005
+++ punbb-1.2.15/upload/include/dblayer/sqlite.php	Tue Apr 10 23:37:36 2007
@@ -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.2/upload/include/email.php punbb-1.2.15/upload/include/email.php
--- punbb-1.2.2/upload/include/email.php	Fri Feb 18 22:05:02 2005
+++ punbb-1.2.15/upload/include/email.php	Mon Apr  9 18:41:04 2007
@@ -33,7 +33,10 @@
 //
 function is_valid_email($email)
 {
-	return preg_match('#^.{1,}@.{2,}\..{2,}$#', $email);
+	if (strlen($email) > 50)
+		return false;
+
+	return preg_match('/^(([^<>()[\]\\.,;:\s@"\']+(\.[^<>()[\]\\.,;:\s@"\']+)*)|("[^"\']+"))@((\[\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\])|(([a-zA-Z\d\-]+\.)+[a-zA-Z]{2,}))$/', $email);
 }
 
 
@@ -65,28 +68,30 @@
 
 	// Default sender/return address
 	if (!$from)
-		$from = '"'.$pun_config['o_board_title'].' '.$lang_common['Mailer'].'" <'.$pun_config['o_webmaster_email'].'>';
-
-	// Make sure the from line doesn't contain a colon (the character, that is :D)
-	$from = str_replace(':', ' ', $from);
+		$from = '"'.str_replace('"', '', $pun_config['o_board_title'].' '.$lang_common['Mailer']).'" <'.$pun_config['o_webmaster_email'].'>';
 
-	// Detect what linebreak we should use for the headers
-	if (strtoupper(substr(PHP_OS, 0, 3) == 'WIN'))
-		$eol = "\r\n";
-	else if (strtoupper(substr(PHP_OS, 0, 3) == 'MAC'))
-		$eol = "\r";
-	else
-		$eol = "\n";
+	// Do a little spring cleaning
+	$to = trim(preg_replace('#[\n\r]+#s', '', $to));
+	$subject = trim(preg_replace('#[\n\r]+#s', '', $subject));
+	$from = trim(preg_replace('#[\n\r:]+#s', '', $from));
 
-	$headers = 'From: '.$from.$eol.'Date: '.date('r').$eol.'MIME-Version: 1.0'.$eol.'Content-transfer-encoding: 8bit'.$eol.'Content-type: text/plain; charset='.$lang_common['lang_encoding'].$eol.'X-Mailer: PunBB Mailer';
+	$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);
 	else
+	{
+		// Change the linebreaks used in the headers according to OS
+		if (strtoupper(substr(PHP_OS, 0, 3)) == 'MAC')
+			$headers = str_replace("\r\n", "\r", $headers);
+		else if (strtoupper(substr(PHP_OS, 0, 3)) != 'WIN')
+			$headers = str_replace("\r\n", "\n", $headers);
+
 		mail($to, $subject, $message, $headers);
+	}
 }
 
 
diff -urN punbb-1.2.2/upload/include/functions.php punbb-1.2.15/upload/include/functions.php
--- punbb-1.2.2/upload/include/functions.php	Mon Feb 21 21:00:14 2005
+++ punbb-1.2.15/upload/include/functions.php	Tue Apr 10 18:19:26 2007
@@ -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
@@ -46,7 +46,7 @@
 		$pun_user = $db->fetch_assoc($result);
 
 		// If user authorisation failed
-		if (!isset($pun_user['id']) || md5($cookie_seed.$pun_user['password']) != $cookie['password_hash'])
+		if (!isset($pun_user['id']) || md5($cookie_seed.$pun_user['password']) !== $cookie['password_hash'])
 		{
 			pun_setcookie(0, random_pass(8), $expire);
 			set_default_user();
@@ -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);
 }
 
 
@@ -168,7 +201,10 @@
 		}
 
 		if ($cur_ban['username'] != '' && !strcasecmp($pun_user['username'], $cur_ban['username']))
+		{
+			$db->query('DELETE FROM '.$db->prefix.'online WHERE ident=\''.$db->escape($pun_user['username']).'\'') or error('Unable to delete from online list', __FILE__, __LINE__, $db->error());
 			message($lang_common['Ban message'].' '.(($cur_ban['expire'] != '') ? $lang_common['Ban message 2'].' '.strtolower(format_time($cur_ban['expire'], true)).'. ' : '').(($cur_ban['message'] != '') ? $lang_common['Ban message 3'].'<br /><br /><strong>'.pun_htmlspecialchars($cur_ban['message']).'</strong><br /><br />' : '<br /><br />').$lang_common['Ban message 4'].' <a href="mailto:'.$pun_config['o_admin_email'].'">'.$pun_config['o_admin_email'].'</a>.', true);
+		}
 
 		if ($cur_ban['ip'] != '')
 		{
@@ -179,7 +215,10 @@
 				$cur_ban_ips[$i] = $cur_ban_ips[$i].'.';
 
 				if (substr($user_ip, 0, strlen($cur_ban_ips[$i])) == $cur_ban_ips[$i])
+				{
+					$db->query('DELETE FROM '.$db->prefix.'online WHERE ident=\''.$db->escape($pun_user['username']).'\'') or error('Unable to delete from online list', __FILE__, __LINE__, $db->error());
 					message($lang_common['Ban message'].' '.(($cur_ban['expire'] != '') ? $lang_common['Ban message 2'].' '.strtolower(format_time($cur_ban['expire'], true)).'. ' : '').(($cur_ban['message'] != '') ? $lang_common['Ban message 3'].'<br /><br /><strong>'.pun_htmlspecialchars($cur_ban['message']).'</strong><br /><br />' : '<br /><br />').$lang_common['Ban message 4'].' <a href="mailto:'.$pun_config['o_admin_email'].'">'.$pun_config['o_admin_email'].'</a>.', true);
+				}
 			}
 		}
 	}
@@ -203,7 +242,7 @@
 	$now = time();
 
 	// Fetch all online list entries that are older than "o_timeout_online"
-	$result = $db->query('SELECT * FROM '.$db->prefix.'online WHERE logged<'.($now-$pun_config['o_timeout_online'])) or error('Unable to delete from online list', __FILE__, __LINE__, $db->error());
+	$result = $db->query('SELECT * FROM '.$db->prefix.'online WHERE logged<'.($now-$pun_config['o_timeout_online'])) or error('Unable to fetch old entries from online list', __FILE__, __LINE__, $db->error());
 	while ($cur_user = $db->fetch_assoc($result))
 	{
 		// If the entry is a guest, delete it
@@ -675,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'];
 }
 
 
@@ -739,7 +757,7 @@
 
 	if (strpos($lang_common['lang_encoding'], '8859') !== false)
 	{
-		$fishy_chars = array(chr(0x81), chr(0x8D), chr(0x8F), chr(0x90), chr(0x9D), chr(0xA0), chr(0xCA));
+		$fishy_chars = array(chr(0x81), chr(0x8D), chr(0x8F), chr(0x90), chr(0x9D), chr(0xA0));
 		return trim(str_replace($fishy_chars, ' ', $str));
 	}
 	else
@@ -764,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>
@@ -802,18 +835,6 @@
 	$db->end_transaction();
 
 
-	// START SUBST - <pun_include "*">
-	while (preg_match('<pun_include "(.*?)">', $tpl_maint, $cur_include))
-	{
-		ob_start();
-		include PUN_ROOT.$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();
 
@@ -840,6 +861,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>
@@ -854,7 +890,7 @@
 	ob_start();
 
 ?>
-<meta http-equiv="refresh" content="<?php echo $pun_config['o_redirect_delay'] ?>;URL=<?php echo $destination_url ?>" />
+<meta http-equiv="refresh" content="<?php echo $pun_config['o_redirect_delay'] ?>;URL=<?php echo str_replace(array('<', '>', '"'), array('&lt;', '&gt;', '&quot;'), $destination_url) ?>" />
 <title><?php echo pun_htmlspecialchars($pun_config['o_board_title']).' / '.$lang_common['Redirecting'] ?></title>
 <link rel="stylesheet" type="text/css" href="style/<?php echo $pun_user['style'].'.css' ?>" />
 <?php
@@ -892,18 +928,6 @@
 	// END SUBST - <pun_footer>
 
 
-	// START SUBST - <pun_include "*">
-	while (preg_match('<pun_include "(.*?)">', $tpl_redir, $cur_include))
-	{
-		ob_start();
-		include PUN_ROOT.$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();
 
@@ -931,7 +955,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>
@@ -1034,6 +1058,35 @@
 </div>
 <?php
 
+}
+
+
+//
+// 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
+		}
+	}
 }
 
 
diff -urN punbb-1.2.2/upload/include/parser.php punbb-1.2.15/upload/include/parser.php
--- punbb-1.2.2/upload/include/parser.php	Sun Jan 30 14:52:38 2005
+++ punbb-1.2.15/upload/include/parser.php	Sat May 20 17:42:34 2006
@@ -45,29 +45,29 @@
 	$b = array('[b]', '[i]', '[u]', '[/b]', '[/i]', '[/u]');
 	$text = str_replace($a, $b, $text);
 
-	// Do the more complex BBCodes (and strip excessive whitespace)
-	$a = array( '#\[url=(.*?)\]\s*#i',
+	// Do the more complex BBCodes (also strip excessive whitespace and useless quotes)
+	$a = array( '#\[url=("|\'|)(.*?)\\1\]\s*#i',
 				'#\[url\]\s*#i',
 				'#\s*\[/url\]#i',
-				'#\[email=(.*?)\]\s*#i',
+				'#\[email=("|\'|)(.*?)\\1\]\s*#i',
 				'#\[email\]\s*#i',
 				'#\s*\[/email\]#i',
 				'#\[img\]\s*(.*?)\s*\[/img\]#is',
-				'#\[colou?r=(.*?)\](.*?)\[/colou?r\]#is');
+				'#\[colou?r=("|\'|)(.*?)\\1\](.*?)\[/colou?r\]#is');
 
-	$b = array(	'[url=$1]',
+	$b = array(	'[url=$2]',
 				'[url]',
 				'[/url]',
-				'[email=$1]',
+				'[email=$2]',
 				'[email]',
 				'[/email]',
 				'[img]$1[/img]',
-				'[color=$1]$2[/color]');
+				'[color=$2]$3[/color]');
 
 	if (!$is_signature)
 	{
 		// For non-signatures, we have to do the quote and code tags as well
-		$a[] = '#\[quote=(&quot;|"|\'|)(.*)\\1\]\s*#i';
+		$a[] = '#\[quote=(&quot;|"|\'|)(.*?)\\1\]\s*#i';
 		$a[] = '#\[quote\]\s*#i';
 		$a[] = '#\s*\[/quote\]\s*#i';
 		$a[] = '#\[code\][\r\n]*(.*?)\s*\[/code\]\s*#is';
@@ -182,8 +182,13 @@
 		// We found a [code]
 		else if ($c_start < min($c_end, $q_start, $q_end))
 		{
+			// Make sure there's a [/code] and that any new [code] doesn't occur before the end tag
 			$tmp = strpos($text, '[/code]');
-			if ($tmp === false)
+			$tmp2 = strpos(substr($text, $c_start+6), '[code]');
+			if ($tmp2 !== false)
+				$tmp2 += $c_start+6;
+
+			if ($tmp === false || ($tmp2 !== false && $tmp2 < $tmp))
 			{
 				$error = $lang_common['BBCode error'].' '.$lang_common['BBCode error 2'];
 				return;
@@ -259,7 +264,7 @@
 {
 	global $pun_user;
 
-	$full_url = str_replace(' ', '%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://
@@ -299,13 +304,20 @@
 {
 	global $lang_common, $pun_user;
 
+	if (strpos($text, 'quote') !== false)
+	{
+		$text = str_replace('[quote]', '</p><blockquote><div class="incqbox"><p>', $text);
+		$text = preg_replace('#\[quote=(&quot;|"|\'|)(.*)\\1\]#seU', '"</p><blockquote><div class=\"incqbox\"><h4>".str_replace(array(\'[\', \'\\"\'), array(\'&#91;\', \'"\'), \'$2\')." ".$lang_common[\'wrote\'].":</h4><p>"', $text);
+		$text = preg_replace('#\[\/quote\]\s*#', '</p></div></blockquote><p>', $text);
+	}
+
 	$pattern = array('#\[b\](.*?)\[/b\]#s',
 					 '#\[i\](.*?)\[/i\]#s',
 					 '#\[u\](.*?)\[/u\]#s',
-					 '#\[url\](.*?)\[/url\]#e',
-					 '#\[url=(.*?)\](.*?)\[/url\]#e',
-					 '#\[email\](.*?)\[/email\]#',
-					 '#\[email=(.*?)\](.*?)\[/email\]#',
+					 '#\[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>',
@@ -319,13 +331,6 @@
 
 	// This thing takes a while! :)
 	$text = preg_replace($pattern, $replace, $text);
-
-	if (strpos($text, 'quote') !== false)
-	{
-		$text = str_replace('[quote]', '</p><blockquote><div class="incqbox"><p>', $text);
-		$text = preg_replace('#\[quote=(&quot;|"|\'|)(.*)\\1\]#seU', '"</p><blockquote><div class=\"incqbox\"><h4>".str_replace(\'[\', \'&#91;\', \'$2\')." ".$lang_common[\'wrote\'].":</h4><p>"', $text);
-		$text = preg_replace('#\[\/quote\]\s*#', '</p></div></blockquote><p>', $text);
-	}
 
 	return $text;
 }
diff -urN punbb-1.2.2/upload/include/search_idx.php punbb-1.2.15/upload/include/search_idx.php
--- punbb-1.2.2/upload/include/search_idx.php	Sun Jan 30 12:58:04 2005
+++ punbb-1.2.15/upload/include/search_idx.php	Mon Oct 31 23:37:20 2005
@@ -43,8 +43,8 @@
 
 	if (empty($noise_match))
 	{
-		$noise_match = 		array('quote', 'code', 'url', 'img', 'email', 'color', 'colour', '^', '$', '&', '(', ')', '<', '>', '`', '\'', '"', '|', ',', '@', '_', '?', '%', '~', '+', '[', ']', '{', '}', ':', '\\', '/', '=', '#', ';', '!', '*');
-		$noise_replace =	array('',      '',     '',    '',    '',      '',      '',       ' ', ' ', ' ', ' ', ' ', ' ', ' ', '',  '',   ' ', ' ', ' ', ' ', '',  ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '' ,  ' ', ' ', ' ', ' ', ' ', ' ');
+		$noise_match = 		array('[quote', '[code', '[url', '[img', '[email', '[color', '[colour', 'quote]', 'code]', 'url]', 'img]', 'email]', 'color]', 'colour]', '^', '$', '&', '(', ')', '<', '>', '`', '\'', '"', '|', ',', '@', '_', '?', '%', '~', '+', '[', ']', '{', '}', ':', '\\', '/', '=', '#', ';', '!', '*');
+		$noise_replace =	array('',       '',      '',     '',     '',       '',       '',        '',       '',      '',     '',     '',       '',       '',        ' ', ' ', ' ', ' ', ' ', ' ', ' ', '',  '',   ' ', ' ', ' ', ' ', '',  ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '' ,  ' ', ' ', ' ', ' ', ' ', ' ');
 
 		$stopwords = (array)@file(PUN_ROOT.'lang/'.$pun_user['language'].'/stopwords.txt');
 		$stopwords = array_map('trim', $stopwords);
@@ -69,10 +69,8 @@
 	{
 		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.2/upload/include/template/admin.tpl punbb-1.2.15/upload/include/template/admin.tpl
--- punbb-1.2.2/upload/include/template/admin.tpl	Tue Jan 11 20:41:14 2005
+++ punbb-1.2.15/upload/include/template/admin.tpl	Sun Apr  8 19:30:40 2007
@@ -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.2/upload/include/template/help.tpl punbb-1.2.15/upload/include/template/help.tpl
--- punbb-1.2.2/upload/include/template/help.tpl	Tue Jan 11 20:41:14 2005
+++ punbb-1.2.15/upload/include/template/help.tpl	Sun Apr  8 19:30:40 2007
@@ -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.2/upload/include/template/main.tpl punbb-1.2.15/upload/include/template/main.tpl
--- punbb-1.2.2/upload/include/template/main.tpl	Tue Jan 11 20:41:14 2005
+++ punbb-1.2.15/upload/include/template/main.tpl	Sun Apr  8 19:30:40 2007
@@ -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.2/upload/include/template/maintenance.tpl punbb-1.2.15/upload/include/template/maintenance.tpl
--- punbb-1.2.2/upload/include/template/maintenance.tpl	Tue Jan 11 20:41:14 2005
+++ punbb-1.2.15/upload/include/template/maintenance.tpl	Sun Apr  8 19:30:40 2007
@@ -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.2/upload/include/template/redirect.tpl punbb-1.2.15/upload/include/template/redirect.tpl
--- punbb-1.2.2/upload/include/template/redirect.tpl	Tue Jan 11 20:41:14 2005
+++ punbb-1.2.15/upload/include/template/redirect.tpl	Sun Apr  8 19:30:40 2007
@@ -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.2/upload/install.php punbb-1.2.15/upload/install.php
--- punbb-1.2.2/upload/install.php	Thu Feb 24 22:30:58 2005
+++ punbb-1.2.15/upload/install.php	Wed Apr 11 13:39:52 2007
@@ -24,7 +24,7 @@
 
 
 // The PunBB version this script installs
-$punbb_version = '1.2.2';
+$punbb_version = '1.2.15';
 
 
 define('PUN_ROOT', './');
@@ -165,7 +165,7 @@
 				<fieldset>
 					<legend>Enter then name of your database</legend>
 					<div class="infldset">
-						<p>The name of the database that PunBB will be installed into. The database must exist. For SQLite, this is the relative path to the database file. If it doesn't exists, PunBB will attempt to create it.</p>
+						<p>The name of the database that PunBB will be installed into. The database must exist. For SQLite, this is the relative path to the database file. If the SQLite database file does not exist, PunBB will attempt to create it.</p>
 						<label for="req_db_name"><strong>Database name</strong><br /><input id="req_db_name" type="text" name="req_db_name" size="30" maxlength="50" /><br /></label>
 					</div>
 				</fieldset>
@@ -324,7 +324,7 @@
 	if (preg_match('#\[b\]|\[/b\]|\[u\]|\[/u\]|\[i\]|\[/i\]|\[color|\[/color\]|\[quote\]|\[/quote\]|\[code\]|\[/code\]|\[img\]|\[/img\]|\[url|\[/url\]|\[email|\[/email\]#i', $username))
 		error('Usernames may not contain any of the text formatting tags (BBCode) that the forum uses. Please go back and correct.');
 
-	if (!preg_match('/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$/', $email))
+	if (strlen($email) > 50 || !preg_match('/^(([^<>()[\]\\.,;:\s@"\']+(\.[^<>()[\]\\.,;:\s@"\']+)*)|("[^"\']+"))@((\[\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\])|(([a-zA-Z\d\-]+\.)+[a-zA-Z]{2,}))$/', $email))
 		error('The administrator e-mail address you entered is invalid. Please go back and correct.');
 
 
@@ -346,6 +346,9 @@
 		case 'sqlite':
 			require PUN_ROOT.'include/dblayer/sqlite.php';
 			break;
+
+		default:
+			error('\''.$db_type.'\' is not a valid database type.');
 	}
 
 	// Create the database object (and connect/select db)
@@ -525,7 +528,7 @@
 			break;
 	}
 
-	$db->query($sql) or error('Unable to create table '.$db_prefix.'online. Please check your settings and try again.',  __FILE__, __LINE__, $db->error());
+	$db->query($sql) or error('Unable to create table '.$db_prefix.'config. Please check your settings and try again.',  __FILE__, __LINE__, $db->error());
 
 
 
@@ -754,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,
@@ -771,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,
@@ -788,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,
@@ -849,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)
@@ -864,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)
@@ -879,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)
@@ -898,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;
@@ -907,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;
@@ -916,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;
@@ -1231,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)';
@@ -1420,7 +1424,7 @@
 		<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 PunBB installation</strong>. Make sure there are no linebreaks or spaces before &lt;?php and after ?&gt; in the file. 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 PunBB 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>
 <?php if ($alerts != ''): ?>					<?php echo $alerts."\n" ?>
 <?php endif; ?>				</div>
 				<fieldset>
diff -urN punbb-1.2.2/upload/login.php punbb-1.2.15/upload/login.php
--- punbb-1.2.2/upload/login.php	Mon Feb 21 23:33:52 2005
+++ punbb-1.2.15/upload/login.php	Sat May 20 17:52:04 2006
@@ -40,7 +40,9 @@
 	$form_username = trim($_POST['req_username']);
 	$form_password = trim($_POST['req_password']);
 
-	$result = $db->query('SELECT id, group_id, password, save_pass FROM '.$db->prefix.'users WHERE username=\''.$db->escape($form_username).'\'') or error('Unable to fetch user info', __FILE__, __LINE__, $db->error());
+	$username_sql = ($db_type == 'mysql' || $db_type == 'mysqli') ? 'username=\''.$db->escape($form_username).'\'' : 'LOWER(username)=LOWER(\''.$db->escape($form_username).'\')';
+
+	$result = $db->query('SELECT id, group_id, password, save_pass FROM '.$db->prefix.'users WHERE '.$username_sql) or error('Unable to fetch user info', __FILE__, __LINE__, $db->error());
 	list($user_id, $group_id, $db_password_hash, $save_pass) = $db->fetch_row($result);
 
 	$authorized = false;
@@ -76,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']);
 }
 
 
@@ -151,7 +153,7 @@
 			message($lang_login['Forget mail'].' <a href="mailto:'.$pun_config['o_admin_email'].'">'.$pun_config['o_admin_email'].'</a>.');
 		}
 		else
-			message($lang_login['No e-mail match'].' '.$email.'.');
+			message($lang_login['No e-mail match'].' '.htmlspecialchars($email).'.');
 	}
 
 
@@ -189,7 +191,7 @@
 	header('Location: index.php');
 
 // Try to determine if the data in HTTP_REFERER is valid (if not, we redirect to index.php after login)
-$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_common['Login'];
 $required_fields = array('req_username' => $lang_common['Username'], 'req_password' => $lang_common['Password']);
diff -urN punbb-1.2.2/upload/misc.php punbb-1.2.15/upload/misc.php
--- punbb-1.2.2/upload/misc.php	Tue Jan 11 20:41:14 2005
+++ punbb-1.2.15/upload/misc.php	Tue Apr 10 18:42:56 2007
@@ -76,7 +76,7 @@
 		message($lang_common['No permission']);
 
 	$recipient_id = intval($_GET['email']);
-	if ($recipient_id < 1)
+	if ($recipient_id < 2)
 		message($lang_common['Bad request']);
 
 	$result = $db->query('SELECT username, email, email_setting FROM '.$db->prefix.'users WHERE id='.$recipient_id) or error('Unable to fetch user info', __FILE__, __LINE__, $db->error());
@@ -118,14 +118,14 @@
 
 		require_once PUN_ROOT.'include/email.php';
 
-		pun_mail($recipient_email, $mail_subject, $mail_message, $pun_user['username'].' <'.$pun_user['email'].'>');
+		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']);
@@ -245,7 +245,7 @@
 
 else if (isset($_GET['subscribe']))
 {
-	if ($pun_user['is_guest'])
+	if ($pun_user['is_guest'] || $pun_config['o_subscriptions'] != '1')
 		message($lang_common['No permission']);
 
 	$topic_id = intval($_GET['subscribe']);
@@ -264,7 +264,7 @@
 
 else if (isset($_GET['unsubscribe']))
 {
-	if ($pun_user['is_guest'])
+	if ($pun_user['is_guest'] || $pun_config['o_subscriptions'] != '1')
 		message($lang_common['No permission']);
 
 	$topic_id = intval($_GET['unsubscribe']);
diff -urN punbb-1.2.2/upload/moderate.php punbb-1.2.15/upload/moderate.php
--- punbb-1.2.2/upload/moderate.php	Thu Feb 24 22:16:34 2005
+++ punbb-1.2.15/upload/moderate.php	Tue Apr 10 23:37:36 2007
@@ -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
 	{
@@ -50,7 +50,7 @@
 		$ip = $db->result($result);
 	}
 
-	message('The IP address is: '.$ip.'<br />The host name is: '.gethostbyaddr($ip).'<br /><br /><a href="admin_users.php?show_users='.$ip.'">Show more users for this IP</a>');
+	message('The IP address is: '.$ip.'<br />The host name is: '.@gethostbyaddr($ip).'<br /><br /><a href="admin_users.php?show_users='.$ip.'">Show more users for this IP</a>');
 }
 
 
@@ -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,14 +287,20 @@
 	{
 		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']);
-		$move_to_forum = intval($_POST['move_to_forum']);
+		$move_to_forum = isset($_POST['move_to_forum']) ? intval($_POST['move_to_forum']) : 0;
 		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());
 
@@ -351,7 +363,7 @@
 						<br /><select name="move_to_forum">
 <?php
 
-	$result = $db->query('SELECT c.id AS cid, c.cat_name, f.id AS fid, f.forum_name FROM '.$db->prefix.'categories AS c INNER JOIN '.$db->prefix.'forums AS f ON c.id=f.cat_id WHERE f.redirect_url IS NULL ORDER BY c.disp_position, c.id, f.disp_position') or error('Unable to fetch category/forum list', __FILE__, __LINE__, $db->error());
+	$result = $db->query('SELECT c.id AS cid, c.cat_name, f.id AS fid, f.forum_name FROM '.$db->prefix.'categories AS c INNER JOIN '.$db->prefix.'forums AS f ON c.id=f.cat_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 f.redirect_url IS NULL ORDER BY c.disp_position, c.id, f.disp_position', true) or error('Unable to fetch category/forum list', __FILE__, __LINE__, $db->error());
 
 	$cur_category = 0;
 	while ($cur_forum = $db->fetch_assoc($result))
@@ -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(',', array_keys($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.2/upload/post.php punbb-1.2.15/upload/post.php
--- punbb-1.2.2/upload/post.php	Sat Jan 22 01:32:28 2005
+++ punbb-1.2.15/upload/post.php	Mon Jan 15 15:59:04 2007
@@ -33,7 +33,7 @@
 
 $tid = isset($_GET['tid']) ? intval($_GET['tid']) : 0;
 $fid = isset($_GET['fid']) ? intval($_GET['fid']) : 0;
-if ($tid < 1 && $fid < 1)
+if ($tid < 1 && $fid < 1 || $tid > 0 && $fid > 0)
 	message($lang_common['Bad request']);
 
 // Fetch some info about the topic and/or the forum
@@ -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);
@@ -207,73 +207,76 @@
 
 			update_forum($cur_posting['id']);
 
-
-			// Get the post time for the previous post in this topic
-			$result = $db->query('SELECT posted FROM '.$db->prefix.'posts WHERE topic_id='.$tid.' ORDER BY id DESC LIMIT 1, 1') or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());
-			$previous_post_time = $db->result($result);
-
-			// Get any subscribed users that should be notified (banned users are excluded)
-			$result = $db->query('SELECT u.id, u.email, u.notify_with_post, u.language FROM '.$db->prefix.'users AS u INNER JOIN '.$db->prefix.'subscriptions AS s ON u.id=s.user_id LEFT JOIN '.$db->prefix.'forum_perms AS fp ON (fp.forum_id='.$cur_posting['id'].' AND fp.group_id=u.group_id) LEFT JOIN '.$db->prefix.'online AS o ON u.id=o.user_id LEFT JOIN '.$db->prefix.'bans AS b ON u.username=b.username WHERE b.username IS NULL AND COALESCE(o.logged, u.last_visit)>'.$previous_post_time.' AND (fp.read_forum IS NULL OR fp.read_forum=1) AND s.topic_id='.$tid.' AND u.id!='.intval($pun_user['id'])) or error('Unable to fetch subscription info', __FILE__, __LINE__, $db->error());
-			if ($db->num_rows($result))
+			// Should we send out notifications?
+			if ($pun_config['o_subscriptions'] == '1')
 			{
-				require_once PUN_ROOT.'include/email.php';
+				// Get the post time for the previous post in this topic
+				$result = $db->query('SELECT posted FROM '.$db->prefix.'posts WHERE topic_id='.$tid.' ORDER BY id DESC LIMIT 1, 1') or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());
+				$previous_post_time = $db->result($result);
+
+				// Get any subscribed users that should be notified (banned users are excluded)
+				$result = $db->query('SELECT u.id, u.email, u.notify_with_post, u.language FROM '.$db->prefix.'users AS u INNER JOIN '.$db->prefix.'subscriptions AS s ON u.id=s.user_id LEFT JOIN '.$db->prefix.'forum_perms AS fp ON (fp.forum_id='.$cur_posting['id'].' AND fp.group_id=u.group_id) LEFT JOIN '.$db->prefix.'online AS o ON u.id=o.user_id LEFT JOIN '.$db->prefix.'bans AS b ON u.username=b.username WHERE b.username IS NULL AND COALESCE(o.logged, u.last_visit)>'.$previous_post_time.' AND (fp.read_forum IS NULL OR fp.read_forum=1) AND s.topic_id='.$tid.' AND u.id!='.intval($pun_user['id'])) or error('Unable to fetch subscription info', __FILE__, __LINE__, $db->error());
+				if ($db->num_rows($result))
+				{
+					require_once PUN_ROOT.'include/email.php';
 
-				$notification_emails = array();
+					$notification_emails = array();
 
-				// Loop through subscribed users and send e-mails
-				while ($cur_subscriber = $db->fetch_assoc($result))
-				{
-					// Is the subscription e-mail for $cur_subscriber['language'] cached or not?
-					if (!isset($notification_emails[$cur_subscriber['language']]))
+					// Loop through subscribed users and send e-mails
+					while ($cur_subscriber = $db->fetch_assoc($result))
 					{
-						if (file_exists(PUN_ROOT.'lang/'.$cur_subscriber['language'].'/mail_templates/new_reply.tpl'))
+						// Is the subscription e-mail for $cur_subscriber['language'] cached or not?
+						if (!isset($notification_emails[$cur_subscriber['language']]))
 						{
-							// Load the "new reply" template
-							$mail_tpl = trim(file_get_contents(PUN_ROOT.'lang/'.$cur_subscriber['language'].'/mail_templates/new_reply.tpl'));
-
-							// Load the "new reply full" template (with post included)
-							$mail_tpl_full = trim(file_get_contents(PUN_ROOT.'lang/'.$cur_subscriber['language'].'/mail_templates/new_reply_full.tpl'));
-
-							// The first row contains the subject (it also starts with "Subject:")
-							$first_crlf = strpos($mail_tpl, "\n");
-							$mail_subject = trim(substr($mail_tpl, 8, $first_crlf-8));
-							$mail_message = trim(substr($mail_tpl, $first_crlf));
-
-							$first_crlf = strpos($mail_tpl_full, "\n");
-							$mail_subject_full = trim(substr($mail_tpl_full, 8, $first_crlf-8));
-							$mail_message_full = trim(substr($mail_tpl_full, $first_crlf));
-
-							$mail_subject = str_replace('<topic_subject>', '\''.$cur_posting['subject'].'\'', $mail_subject);
-							$mail_message = str_replace('<topic_subject>', '\''.$cur_posting['subject'].'\'', $mail_message);
-							$mail_message = str_replace('<replier>', $username, $mail_message);
-							$mail_message = str_replace('<post_url>', $pun_config['o_base_url'].'/viewtopic.php?pid='.$new_pid.'#p'.$new_pid, $mail_message);
-							$mail_message = str_replace('<unsubscribe_url>', $pun_config['o_base_url'].'/misc.php?unsubscribe='.$tid, $mail_message);
-							$mail_message = str_replace('<board_mailer>', $pun_config['o_board_title'].' '.$lang_common['Mailer'], $mail_message);
-
-							$mail_subject_full = str_replace('<topic_subject>', '\''.$cur_posting['subject'].'\'', $mail_subject_full);
-							$mail_message_full = str_replace('<topic_subject>', '\''.$cur_posting['subject'].'\'', $mail_message_full);
-							$mail_message_full = str_replace('<replier>', $username, $mail_message_full);
-							$mail_message_full = str_replace('<message>', $message, $mail_message_full);
-							$mail_message_full = str_replace('<post_url>', $pun_config['o_base_url'].'/viewtopic.php?pid='.$new_pid.'#p'.$new_pid, $mail_message_full);
-							$mail_message_full = str_replace('<unsubscribe_url>', $pun_config['o_base_url'].'/misc.php?unsubscribe='.$tid, $mail_message_full);
-							$mail_message_full = str_replace('<board_mailer>', $pun_config['o_board_title'].' '.$lang_common['Mailer'], $mail_message_full);
-
-							$notification_emails[$cur_subscriber['language']][0] = $mail_subject;
-							$notification_emails[$cur_subscriber['language']][1] = $mail_message;
-							$notification_emails[$cur_subscriber['language']][2] = $mail_subject_full;
-							$notification_emails[$cur_subscriber['language']][3] = $mail_message_full;
+							if (file_exists(PUN_ROOT.'lang/'.$cur_subscriber['language'].'/mail_templates/new_reply.tpl'))
+							{
+								// Load the "new reply" template
+								$mail_tpl = trim(file_get_contents(PUN_ROOT.'lang/'.$cur_subscriber['language'].'/mail_templates/new_reply.tpl'));
+
+								// Load the "new reply full" template (with post included)
+								$mail_tpl_full = trim(file_get_contents(PUN_ROOT.'lang/'.$cur_subscriber['language'].'/mail_templates/new_reply_full.tpl'));
+
+								// The first row contains the subject (it also starts with "Subject:")
+								$first_crlf = strpos($mail_tpl, "\n");
+								$mail_subject = trim(substr($mail_tpl, 8, $first_crlf-8));
+								$mail_message = trim(substr($mail_tpl, $first_crlf));
+
+								$first_crlf = strpos($mail_tpl_full, "\n");
+								$mail_subject_full = trim(substr($mail_tpl_full, 8, $first_crlf-8));
+								$mail_message_full = trim(substr($mail_tpl_full, $first_crlf));
+
+								$mail_subject = str_replace('<topic_subject>', '\''.$cur_posting['subject'].'\'', $mail_subject);
+								$mail_message = str_replace('<topic_subject>', '\''.$cur_posting['subject'].'\'', $mail_message);
+								$mail_message = str_replace('<replier>', $username, $mail_message);
+								$mail_message = str_replace('<post_url>', $pun_config['o_base_url'].'/viewtopic.php?pid='.$new_pid.'#p'.$new_pid, $mail_message);
+								$mail_message = str_replace('<unsubscribe_url>', $pun_config['o_base_url'].'/misc.php?unsubscribe='.$tid, $mail_message);
+								$mail_message = str_replace('<board_mailer>', $pun_config['o_board_title'].' '.$lang_common['Mailer'], $mail_message);
+
+								$mail_subject_full = str_replace('<topic_subject>', '\''.$cur_posting['subject'].'\'', $mail_subject_full);
+								$mail_message_full = str_replace('<topic_subject>', '\''.$cur_posting['subject'].'\'', $mail_message_full);
+								$mail_message_full = str_replace('<replier>', $username, $mail_message_full);
+								$mail_message_full = str_replace('<message>', $message, $mail_message_full);
+								$mail_message_full = str_replace('<post_url>', $pun_config['o_base_url'].'/viewtopic.php?pid='.$new_pid.'#p'.$new_pid, $mail_message_full);
+								$mail_message_full = str_replace('<unsubscribe_url>', $pun_config['o_base_url'].'/misc.php?unsubscribe='.$tid, $mail_message_full);
+								$mail_message_full = str_replace('<board_mailer>', $pun_config['o_board_title'].' '.$lang_common['Mailer'], $mail_message_full);
+
+								$notification_emails[$cur_subscriber['language']][0] = $mail_subject;
+								$notification_emails[$cur_subscriber['language']][1] = $mail_message;
+								$notification_emails[$cur_subscriber['language']][2] = $mail_subject_full;
+								$notification_emails[$cur_subscriber['language']][3] = $mail_message_full;
 
-							$mail_subject = $mail_message = $mail_subject_full = $mail_message_full = null;
+								$mail_subject = $mail_message = $mail_subject_full = $mail_message_full = null;
+							}
 						}
-					}
 
-					// We have to double check here because the templates could be missing
-					if (isset($notification_emails[$cur_subscriber['language']]))
-					{
-						if ($cur_subscriber['notify_with_post'] == '0')
-							pun_mail($cur_subscriber['email'], $notification_emails[$cur_subscriber['language']][0], $notification_emails[$cur_subscriber['language']][1]);
-						else
-							pun_mail($cur_subscriber['email'], $notification_emails[$cur_subscriber['language']][2], $notification_emails[$cur_subscriber['language']][3]);
+						// We have to double check here because the templates could be missing
+						if (isset($notification_emails[$cur_subscriber['language']]))
+						{
+							if ($cur_subscriber['notify_with_post'] == '0')
+								pun_mail($cur_subscriber['email'], $notification_emails[$cur_subscriber['language']][0], $notification_emails[$cur_subscriber['language']][1]);
+							else
+								pun_mail($cur_subscriber['email'], $notification_emails[$cur_subscriber['language']][2], $notification_emails[$cur_subscriber['language']][3]);
+						}
 					}
 				}
 			}
@@ -335,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']);
 
@@ -437,7 +440,7 @@
 else if (isset($_POST['preview']))
 {
 	require_once PUN_ROOT.'include/parser.php';
-	$message = parse_message($message, $hide_smilies);
+	$preview_message = parse_message($message, $hide_smilies);
 
 ?>
 <div id="postpreview" class="blockpost">
@@ -446,7 +449,7 @@
 		<div class="inbox">
 			<div class="postright">
 				<div class="postmsg">
-					<?php echo $message."\n" ?>
+					<?php echo $preview_message."\n" ?>
 				</div>
 			</div>
 		</div>
@@ -488,7 +491,7 @@
 if ($fid): ?>
 						<label><strong><?php echo $lang_common['Subject'] ?></strong><br /><input class="longinput" type="text" name="req_subject" value="<?php if (isset($_POST['req_subject'])) echo pun_htmlspecialchars($subject); ?>" size="80" maxlength="70" tabindex="<?php echo $cur_index++ ?>" /><br /></label>
 <?php endif; ?>						<label><strong><?php echo $lang_common['Message'] ?></strong><br />
-						<textarea name="req_message" rows="20" cols="95" tabindex="<?php echo $cur_index++ ?>"><?php echo isset($_POST['req_message']) ? pun_htmlspecialchars(trim($_POST['req_message'])) : (isset($quote) ? $quote : ''); ?></textarea><br /></label>
+						<textarea name="req_message" rows="20" cols="95" tabindex="<?php echo $cur_index++ ?>"><?php echo isset($_POST['req_message']) ? pun_htmlspecialchars($message) : (isset($quote) ? $quote : ''); ?></textarea><br /></label>
 						<ul class="bblinks">
 							<li><a href="help.php#bbcode" onclick="window.open(this.href); return false;"><?php echo $lang_common['BBCode'] ?></a>: <?php echo ($pun_config['p_message_bbcode'] == '1') ? $lang_common['on'] : $lang_common['off']; ?></li>
 							<li><a href="help.php#img" onclick="window.open(this.href); return false;"><?php echo $lang_common['img tag'] ?></a>: <?php echo ($pun_config['p_message_img_tag'] == '1') ? $lang_common['on'] : $lang_common['off']; ?></li>
diff -urN punbb-1.2.2/upload/profile.php punbb-1.2.15/upload/profile.php
--- punbb-1.2.2/upload/profile.php	Thu Feb 24 22:16:34 2005
+++ punbb-1.2.15/upload/profile.php	Tue Apr 10 23:37:36 2007
@@ -59,7 +59,7 @@
 		$result = $db->query('SELECT activate_string, activate_key FROM '.$db->prefix.'users WHERE id='.$id) or error('Unable to fetch new password', __FILE__, __LINE__, $db->error());
 		list($new_password_hash, $new_password_key) = $db->fetch_row($result);
 
-		if ($key != $new_password_key)
+		if ($key == '' || $key != $new_password_key)
 			message($lang_profile['Pass key bad'].' <a href="mailto:'.$pun_config['o_admin_email'].'">'.$pun_config['o_admin_email'].'</a>.');
 		else
 		{
@@ -190,17 +190,20 @@
 		$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
 		{
-			$db->query('UPDATE '.$db->prefix.'users SET email=\''.$new_email.'\', activate_string=NULL, activate_key=NULL WHERE id='.$id) or error('Unable to update e-mail address', __FILE__, __LINE__, $db->error());
+			$db->query('UPDATE '.$db->prefix.'users SET email=activate_string, activate_string=NULL, activate_key=NULL WHERE id='.$id) or error('Unable to update e-mail address', __FILE__, __LINE__, $db->error());
 
 			message($lang_profile['E-mail updated'], true);
 		}
 	}
 	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 +267,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 +282,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>
@@ -303,6 +307,9 @@
 
 	if (isset($_POST['form_sent']))
 	{
+		if (!isset($_FILES['req_file']))
+			message($lang_profile['No file']);
+			
 		$uploaded_file = $_FILES['req_file'];
 
 		// Make sure the upload went smooth
@@ -359,12 +366,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');
-			if ($width > $pun_config['o_avatars_width'] || $height > $pun_config['o_avatars_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]);
@@ -527,6 +539,9 @@
 	$result = $db->query('SELECT group_id, username FROM '.$db->prefix.'users WHERE id='.$id) or error('Unable to fetch user info', __FILE__, __LINE__, $db->error());
 	list($group_id, $username) = $db->fetch_row($result);
 
+	if ($group_id == PUN_ADMIN)
+		message('Administrators cannot be deleted. In order to delete this user, you must first move him/her to a different user group.');
+
 	if (isset($_POST['delete_user_comply']))
 	{
 		// If the user is a moderator or an administrator, we remove him/her from the moderator list in all forums as well
@@ -704,6 +719,14 @@
 					message($lang_common['Invalid e-mail']);
 			}
 
+			// Make sure we got a valid language string
+			if (isset($form['language']))
+			{
+				$form['language'] = preg_replace('#[\.\\\/]#', '', $form['language']);
+				if (!file_exists(PUN_ROOT.'lang/'.$form['language'].'/common.php'))
+						message($lang_common['Bad request']);
+			}
+
 			break;
 		}
 
@@ -729,7 +752,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;
@@ -740,7 +763,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;
@@ -795,7 +818,7 @@
 		{
 			$form = extract_elements(array('email_setting', 'save_pass', 'notify_with_post'));
 
-			$form['email_setting'] == intval($form['email_setting']);
+			$form['email_setting'] = intval($form['email_setting']);
 			if ($form['email_setting'] < 0 && $form['email_setting'] > 2) $form['email_setting'] = 1;
 
 			if (!isset($form['save_pass']) || $form['save_pass'] != '1') $form['save_pass'] = '0';
@@ -817,6 +840,7 @@
 
 
 	// Singlequotes around non-empty values and NULL for empty values
+	$temp = array();
 	while (list($key, $input) = @each($form))
 	{
 		$value = ($input !== '') ? '\''.$db->escape($input).'\'' : 'NULL';
@@ -824,6 +848,9 @@
 		$temp[] = $key.'='.$value;
 	}
 
+	if (empty($temp))
+		message($lang_common['Bad request']);
+
 
 	$db->query('UPDATE '.$db->prefix.'users SET '.implode(',', $temp).' WHERE id='.$id) or error('Unable to update profile', __FILE__, __LINE__, $db->error());
 
@@ -864,7 +891,7 @@
 }
 
 
-$result = $db->query('SELECT u.username, u.email, u.title, u.realname, u.url, u.jabber, u.icq, u.msn, u.aim, u.yahoo, u.location, u.use_avatar, u.signature, u.disp_topics, u.disp_posts, u.email_setting, u.save_pass, u.notify_with_post, u.show_smilies, u.show_img, u.show_img_sig, u.show_avatars, u.show_sig, u.timezone, u.style, u.num_posts, u.last_post, u.registered, u.registration_ip, u.admin_note, g.g_id, g.g_user_title FROM '.$db->prefix.'users AS u LEFT JOIN '.$db->prefix.'groups AS g ON g.g_id=u.group_id WHERE u.id='.$id) or error('Unable to fetch user info', __FILE__, __LINE__, $db->error());
+$result = $db->query('SELECT u.username, u.email, u.title, u.realname, u.url, u.jabber, u.icq, u.msn, u.aim, u.yahoo, u.location, u.use_avatar, u.signature, u.disp_topics, u.disp_posts, u.email_setting, u.save_pass, u.notify_with_post, u.show_smilies, u.show_img, u.show_img_sig, u.show_avatars, u.show_sig, u.timezone, u.language, u.style, u.num_posts, u.last_post, u.registered, u.registration_ip, u.admin_note, g.g_id, g.g_user_title FROM '.$db->prefix.'users AS u LEFT JOIN '.$db->prefix.'groups AS g ON g.g_id=u.group_id WHERE u.id='.$id) or error('Unable to fetch user info', __FILE__, __LINE__, $db->error());
 if (!$db->num_rows($result))
 	message($lang_common['Bad request']);
 
@@ -966,7 +993,7 @@
 					<div class="infldset">
 						<dl>
 							<dt><?php echo $lang_profile['Jabber'] ?>: </dt>
-							<dd><?php echo ($user['jabber'] !='') ? $user['jabber'] : $lang_profile['Unknown']; ?></dd>
+							<dd><?php echo ($user['jabber'] !='') ? pun_htmlspecialchars($user['jabber']) : $lang_profile['Unknown']; ?></dd>
 							<dt><?php echo $lang_profile['ICQ'] ?>: </dt>
 							<dd><?php echo ($user['icq'] !='') ? $user['icq'] : $lang_profile['Unknown']; ?></dd>
 							<dt><?php echo $lang_profile['MSN'] ?>: </dt>
@@ -1128,7 +1155,7 @@
 		$d = dir(PUN_ROOT.'lang');
 		while (($entry = $d->read()) !== false)
 		{
-			if ($entry != '.' && $entry != '..' && is_dir(PUN_ROOT.'lang/'.$entry))
+			if ($entry != '.' && $entry != '..' && is_dir(PUN_ROOT.'lang/'.$entry) && file_exists(PUN_ROOT.'lang/'.$entry.'/common.php'))
 				$languages[] = $entry;
 		}
 		$d->close();
@@ -1136,6 +1163,7 @@
 		// Only display the language selection box if there's more than one language available
 		if (count($languages) > 1)
 		{
+			natsort($languages);
 
 ?>
 							<label><?php echo $lang_prof_reg['Language'] ?>: <?php echo $lang_prof_reg['Language info'] ?>
@@ -1144,7 +1172,7 @@
 
 			while (list(, $temp) = @each($languages))
 			{
-				if ($pun_user['language'] == $temp)
+				if ($user['language'] == $temp)
 					echo "\t\t\t\t\t\t\t\t".'<option value="'.$temp.'" selected="selected">'.$temp.'</option>'."\n";
 				else
 					echo "\t\t\t\t\t\t\t\t".'<option value="'.$temp.'">'.$temp.'</option>'."\n";
@@ -1232,7 +1260,7 @@
 						<legend><?php echo $lang_profile['Contact details legend'] ?></legend>
 						<div class="infldset">
 							<input type="hidden" name="form_sent" value="1" />
-							<label><?php echo $lang_profile['Jabber'] ?><br /><input id="jabber" type="text" name="form[jabber]" value="<?php echo $user['jabber'] ?>" size="40" maxlength="75" /><br /></label>
+							<label><?php echo $lang_profile['Jabber'] ?><br /><input id="jabber" type="text" name="form[jabber]" value="<?php echo pun_htmlspecialchars($user['jabber']) ?>" size="40" maxlength="75" /><br /></label>
 							<label><?php echo $lang_profile['ICQ'] ?><br /><input id="icq" type="text" name="form[icq]" value="<?php echo $user['icq'] ?>" size="12" maxlength="12" /><br /></label>
 							<label><?php echo $lang_profile['MSN'] ?><br /><input id="msn" type="text" name="form[msn]" value="<?php echo pun_htmlspecialchars($user['msn']) ?>" size="40" maxlength="50" /><br /></label>
 							<label><?php echo $lang_profile['AOL IM'] ?><br /><input id="aim" type="text" name="form[aim]" value="<?php echo pun_htmlspecialchars($user['aim']) ?>" size="20" maxlength="30" /><br /></label>
@@ -1347,6 +1375,7 @@
 			echo "\t\t\t".'<div><input type="hidden" name="form[style]" value="'.$styles[0].'" /></div>'."\n";
 		else if (count($styles) > 1)
 		{
+			natsort($styles);
 
 ?>
 				<div class="inform">
@@ -1485,6 +1514,8 @@
 		}
 		else
 		{
+			if ($pun_user['id'] != $id)
+			{
 
 ?>
 						<legend><?php echo $lang_profile['Group membership legend'] ?></legend>
@@ -1492,15 +1523,15 @@
 							<select id="group_id" name="group_id">
 <?php
 
-			$result = $db->query('SELECT g_id, g_title FROM '.$db->prefix.'groups WHERE g_id!='.PUN_GUEST.' ORDER BY g_title') or error('Unable to fetch user group list', __FILE__, __LINE__, $db->error());
+				$result = $db->query('SELECT g_id, g_title FROM '.$db->prefix.'groups WHERE g_id!='.PUN_GUEST.' ORDER BY g_title') or error('Unable to fetch user group list', __FILE__, __LINE__, $db->error());
 
-			while ($cur_group = $db->fetch_assoc($result))
-			{
-				if ($cur_group['g_id'] == $user['g_id'] || ($cur_group['g_id'] == $pun_config['o_default_user_group'] && $user['g_id'] == ''))
-					echo "\t\t\t\t\t\t\t\t".'<option value="'.$cur_group['g_id'].'" selected="selected">'.pun_htmlspecialchars($cur_group['g_title']).'</option>'."\n";
-				else
-					echo "\t\t\t\t\t\t\t\t".'<option value="'.$cur_group['g_id'].'">'.pun_htmlspecialchars($cur_group['g_title']).'</option>'."\n";
-			}
+				while ($cur_group = $db->fetch_assoc($result))
+				{
+					if ($cur_group['g_id'] == $user['g_id'] || ($cur_group['g_id'] == $pun_config['o_default_user_group'] && $user['g_id'] == ''))
+						echo "\t\t\t\t\t\t\t\t".'<option value="'.$cur_group['g_id'].'" selected="selected">'.pun_htmlspecialchars($cur_group['g_title']).'</option>'."\n";
+					else
+						echo "\t\t\t\t\t\t\t\t".'<option value="'.$cur_group['g_id'].'">'.pun_htmlspecialchars($cur_group['g_title']).'</option>'."\n";
+				}
 
 ?>
 							</select>
@@ -1510,6 +1541,11 @@
 				</div>
 				<div class="inform">
 					<fieldset>
+<?php
+
+			}
+
+?>
 						<legend><?php echo $lang_profile['Delete ban legend'] ?></legend>
 						<div class="infldset">
 							<input type="submit" name="delete_user" value="<?php echo $lang_profile['Delete user'] ?>" />&nbsp;&nbsp;<input type="submit" name="ban" value="<?php echo $lang_profile['Ban user'] ?>" />
diff -urN punbb-1.2.2/upload/register.php punbb-1.2.15/upload/register.php
--- punbb-1.2.2/upload/register.php	Thu Feb 24 22:16:34 2005
+++ punbb-1.2.15/upload/register.php	Mon Jan 15 00:58:18 2007
@@ -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']));
 
@@ -125,7 +132,7 @@
 	}
 
 	// 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 UPPER(username)=UPPER(\''.$db->escape($username).'\') OR UPPER(username)=UPPER(\''.$db->escape(preg_replace('/[^\w]/', '', $username)).'\')') or error('Unable to fetch user info', __FILE__, __LINE__, $db->error());
 
 	if ($db->num_rows($result))
 	{
@@ -166,12 +173,21 @@
 			$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']);
-	if ($email_setting < 0 && $email_setting > 2) $email_setting = 1;
+	if ($email_setting < 0 || $email_setting > 2) $email_setting = 1;
 
 	// Insert the new user into the database. We do this now to get the last inserted id for later use.
 	$now = time();
@@ -337,7 +353,7 @@
 		$d = dir(PUN_ROOT.'lang');
 		while (($entry = $d->read()) !== false)
 		{
-			if ($entry != '.' && $entry != '..' && is_dir(PUN_ROOT.'lang/'.$entry))
+			if ($entry != '.' && $entry != '..' && is_dir(PUN_ROOT.'lang/'.$entry) && file_exists(PUN_ROOT.'lang/'.$entry.'/common.php'))
 				$languages[] = $entry;
 		}
 		$d->close();
diff -urN punbb-1.2.2/upload/search.php punbb-1.2.15/upload/search.php
--- punbb-1.2.2/upload/search.php	Tue Feb  1 16:16:46 2005
+++ punbb-1.2.15/upload/search.php	Wed Apr 11 09:28:00 2007
@@ -51,6 +51,7 @@
 	$action = (isset($_GET['action'])) ? $_GET['action'] : null;
 	$forum = (isset($_GET['forum'])) ? intval($_GET['forum']) : -1;
 	$sort_dir = (isset($_GET['sort_dir'])) ? (($_GET['sort_dir'] == 'DESC') ? 'DESC' : 'ASC') : 'DESC';
+	if (isset($search_id)) unset($search_id);
 
 	// If a search_id was supplied
 	if (isset($_GET['search_id']))
@@ -65,6 +66,12 @@
 		$keywords = (isset($_GET['keywords'])) ? strtolower(trim($_GET['keywords'])) : null;
 		$author = (isset($_GET['author'])) ? strtolower(trim($_GET['author'])) : null;
 
+		if (preg_match('#^[\*%]+$#', $keywords) || strlen(str_replace(array('*', '%'), '', $keywords)) < 3)
+			$keywords = '';
+
+		if (preg_match('#^[\*%]+$#', $author) || strlen(str_replace(array('*', '%'), '', $author)) < 3)
+			$author = '';
+
 		if (!$keywords && !$author)
 			message($lang_search['No terms']);
 
@@ -115,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))
 		{
@@ -163,6 +170,7 @@
 
 				$word_count = 0;
 				$match_type = 'and';
+				$result_list = array();
 				@reset($keywords_array);
 				while (list(, $cur_word) = @each($keywords_array))
 				{
@@ -318,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)
@@ -327,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)
@@ -380,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))
@@ -421,7 +430,6 @@
 	// Fetch results to display
 	if ($search_results != '')
 	{
-		$group_by_sql = '';
 		switch ($sort_by)
 		{
 			case 1:
@@ -441,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')
@@ -457,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'])
@@ -704,7 +706,7 @@
 if ($pun_config['o_search_all_forums'] == '1' || $pun_user['g_id'] < PUN_GUEST)
 	echo "\t\t\t\t\t\t\t".'<option value="-1">'.$lang_search['All forums'].'</option>'."\n";
 
-$result = $db->query('SELECT c.id AS cid, c.cat_name, f.id AS fid, f.forum_name, f.redirect_url FROM '.$db->prefix.'categories AS c INNER JOIN '.$db->prefix.'forums AS f ON c.id=f.cat_id LEFT JOIN '.$db->prefix.'forum_perms AS fp ON (fp.forum_id=f.id AND fp.group_id='.$pun_user['group_id'].') WHERE (fp.read_forum IS NULL OR fp.read_forum=1) AND f.redirect_url IS NULL ORDER BY c.disp_position, c.id, f.disp_position', true) or error('Unable to fetch category/forum list', __FILE__, __LINE__, $db->error());
+$result = $db->query('SELECT c.id AS cid, c.cat_name, f.id AS fid, f.forum_name, f.redirect_url FROM '.$db->prefix.'categories AS c INNER JOIN '.$db->prefix.'forums AS f ON c.id=f.cat_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 f.redirect_url IS NULL ORDER BY c.disp_position, c.id, f.disp_position', true) or error('Unable to fetch category/forum list', __FILE__, __LINE__, $db->error());
 
 $cur_category = 0;
 while ($cur_forum = $db->fetch_assoc($result))
diff -urN punbb-1.2.2/upload/style/imports/base.css punbb-1.2.15/upload/style/imports/base.css
--- punbb-1.2.2/upload/style/imports/base.css	Tue Feb  1 16:16:46 2005
+++ punbb-1.2.15/upload/style/imports/base.css	Mon Jan 15 00:52:30 2007
@@ -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.2/upload/userlist.php punbb-1.2.15/upload/userlist.php
--- punbb-1.2.2/upload/userlist.php	Mon Jan 17 21:35:36 2005
+++ punbb-1.2.15/upload/userlist.php	Tue Apr 10 23:37:36 2007
@@ -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)-1 FROM '.$db->prefix.'users AS u'.(!empty($where_sql) ? ' WHERE '.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);
 
 
@@ -154,7 +154,7 @@
 <?php
 
 // Grab the users
-$result = $db->query('SELECT u.id, u.username, u.title, u.num_posts, u.registered, g.g_id, g.g_user_title FROM '.$db->prefix.'users AS u INNER JOIN '.$db->prefix.'groups AS g ON g.g_id=u.group_id WHERE u.id>1'.(!empty($where_sql) ? ' AND '.implode(' AND ', $where_sql) : '').' ORDER BY '.$sort_by.' '.$sort_dir.' LIMIT '.$start_from.', 50') or error('Unable to fetch user list', __FILE__, __LINE__, $db->error());
+$result = $db->query('SELECT u.id, u.username, u.title, u.num_posts, u.registered, g.g_id, g.g_user_title FROM '.$db->prefix.'users AS u LEFT JOIN '.$db->prefix.'groups AS g ON g.g_id=u.group_id WHERE u.id>1'.(!empty($where_sql) ? ' AND '.implode(' AND ', $where_sql) : '').' ORDER BY '.$sort_by.' '.$sort_dir.' LIMIT '.$start_from.', 50') or error('Unable to fetch user list', __FILE__, __LINE__, $db->error());
 if ($db->num_rows($result))
 {
 	while ($user_data = $db->fetch_assoc($result))
diff -urN punbb-1.2.2/upload/viewforum.php punbb-1.2.15/upload/viewforum.php
--- punbb-1.2.2/upload/viewforum.php	Tue Feb  1 16:16:46 2005
+++ punbb-1.2.15/upload/viewforum.php	Thu Sep 22 00:39:32 2005
@@ -242,7 +242,7 @@
 
 <div class="linksb">
 	<div class="inbox">
-		<p class="pagelink conl"><?php echo $lang_common['Pages'].': '.paginate($num_pages, $p, 'viewforum.php?id='.$id) ?></p>
+		<p class="pagelink conl"><?php echo $paging_links ?></p>
 <?php echo $post_link ?>
 		<ul><li><a href="index.php"><?php echo $lang_common['Index'] ?></a>&nbsp;</li><li>&raquo;&nbsp;<?php echo pun_htmlspecialchars($cur_forum['forum_name']) ?></li></ul>
 		<div class="clearer"></div>
diff -urN punbb-1.2.2/upload/viewtopic.php punbb-1.2.15/upload/viewtopic.php
--- punbb-1.2.2/upload/viewtopic.php	Tue Feb  1 16:16:46 2005
+++ punbb-1.2.15/upload/viewtopic.php	Sat Apr  9 02:35:36 2005
@@ -183,7 +183,7 @@
 $post_count = 0;	// Keep track of post numbers
 
 // Retrieve the posts (and their respective poster/online status)
-$result = $db->query('SELECT DISTINCT u.email, u.title, u.url, u.location, u.use_avatar, u.signature, u.email_setting, u.num_posts, u.registered, u.admin_note, p.id, p.poster AS username, p.poster_id, p.poster_ip, p.poster_email, p.message, p.hide_smilies, p.posted, p.edited, p.edited_by, g.g_id, g.g_user_title, o.user_id AS is_online FROM '.$db->prefix.'posts AS p INNER JOIN '.$db->prefix.'users AS u ON u.id=p.poster_id INNER JOIN '.$db->prefix.'groups AS g ON g.g_id=u.group_id LEFT JOIN '.$db->prefix.'online AS o ON (o.user_id=u.id AND o.idle=0) WHERE p.topic_id='.$id.' ORDER BY p.id LIMIT '.$start_from.','.$pun_user['disp_posts'], true) or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());
+$result = $db->query('SELECT u.email, u.title, u.url, u.location, u.use_avatar, u.signature, u.email_setting, u.num_posts, u.registered, u.admin_note, p.id, p.poster AS username, p.poster_id, p.poster_ip, p.poster_email, p.message, p.hide_smilies, p.posted, p.edited, p.edited_by, g.g_id, g.g_user_title, o.user_id AS is_online FROM '.$db->prefix.'posts AS p INNER JOIN '.$db->prefix.'users AS u ON u.id=p.poster_id INNER JOIN '.$db->prefix.'groups AS g ON g.g_id=u.group_id LEFT JOIN '.$db->prefix.'online AS o ON (o.user_id=u.id AND o.user_id!=1 AND o.idle=0) WHERE p.topic_id='.$id.' ORDER BY p.id LIMIT '.$start_from.','.$pun_user['disp_posts'], true) or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());
 while ($cur_post = $db->fetch_assoc($result))
 {
 	$post_count++;
