diff -urN punbb-1.2.15/upload/admin_forums.php punbb-1.2.17/upload/admin_forums.php
--- punbb-1.2.15/upload/admin_forums.php	2007-04-10 23:37:34.000000000 +0200
+++ punbb-1.2.17/upload/admin_forums.php	2008-01-15 00:23:25.000000000 +0100
@@ -385,8 +385,13 @@
 <?php
 
 	$result = $db->query('SELECT id, cat_name FROM '.$db->prefix.'categories ORDER BY disp_position') or error('Unable to fetch category list', __FILE__, __LINE__, $db->error());
-	while ($cur_cat = $db->fetch_assoc($result))
-		echo "\t\t\t\t\t\t\t\t\t".'<option value="'.$cur_cat['id'].'">'.pun_htmlspecialchars($cur_cat['cat_name']).'</option>'."\n";
+	if ($db->num_rows($result) > 0)
+	{
+		while ($cur_cat = $db->fetch_assoc($result))
+			echo "\t\t\t\t\t\t\t\t\t".'<option value="'.$cur_cat['id'].'">'.pun_htmlspecialchars($cur_cat['cat_name']).'</option>'."\n";
+	}
+	else
+		echo "\t\t\t\t\t\t\t\t\t".'<option value="0" disabled="disabled">No categories exist</option>'."\n";
 
 ?>
 										</select>
@@ -399,7 +404,15 @@
 				</div>
 			</form>
 		</div>
+<?php
 
+// Display all the categories and forums
+$result = $db->query('SELECT c.id AS cid, c.cat_name, f.id AS fid, f.forum_name, f.disp_position FROM '.$db->prefix.'categories AS c INNER JOIN '.$db->prefix.'forums AS f ON c.id=f.cat_id ORDER BY c.disp_position, c.id, f.disp_position') or error('Unable to fetch category/forum list', __FILE__, __LINE__, $db->error());
+
+if ($db->num_rows($result) > 0)
+{
+
+?>
 		<h2 class="block2"><span>Edit forums</span></h2>
 		<div class="box">
 			<form id="edforum" method="post" action="admin_forums.php?action=edit">
@@ -408,9 +421,6 @@
 
 $tabindex_count = 4;
 
-// Display all the categories and forums
-$result = $db->query('SELECT c.id AS cid, c.cat_name, f.id AS fid, f.forum_name, f.disp_position FROM '.$db->prefix.'categories AS c INNER JOIN '.$db->prefix.'forums AS f ON c.id=f.cat_id ORDER BY c.disp_position, c.id, f.disp_position') or error('Unable to fetch category/forum list', __FILE__, __LINE__, $db->error());
-
 $cur_category = 0;
 while ($cur_forum = $db->fetch_assoc($result))
 {
@@ -449,6 +459,11 @@
 				<p class="submitend"><input type="submit" name="update_positions" value="Update positions" tabindex="<?php echo $tabindex_count ?>" /></p>
 			</form>
 		</div>
+<?php
+
+}
+
+?>
 	</div>
 	<div class="clearer"></div>
 </div>
diff -urN punbb-1.2.15/upload/admin_maintenance.php punbb-1.2.17/upload/admin_maintenance.php
--- punbb-1.2.15/upload/admin_maintenance.php	2007-01-30 23:31:43.000000000 +0100
+++ punbb-1.2.17/upload/admin_maintenance.php	2008-01-19 16:16:24.000000000 +0100
@@ -69,8 +69,6 @@
 		}
 	}
 
-	$end_at = $start_at + $per_page;
-
 ?>
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
@@ -95,7 +93,7 @@
 	require PUN_ROOT.'include/search_idx.php';
 
 	// Fetch posts to process
-	$result = $db->query('SELECT DISTINCT t.id, p.id, p.message FROM '.$db->prefix.'topics AS t INNER JOIN '.$db->prefix.'posts AS p ON t.id=p.topic_id WHERE t.id>='.$start_at.' AND t.id<'.$end_at.' ORDER BY t.id') or error('Unable to fetch topic/post info', __FILE__, __LINE__, $db->error());
+	$result = $db->query('SELECT DISTINCT t.id, p.id, p.message FROM '.$db->prefix.'topics AS t INNER JOIN '.$db->prefix.'posts AS p ON t.id=p.topic_id WHERE t.id>='.$start_at.' ORDER BY t.id LIMIT '.$per_page) or error('Unable to fetch topic/post info', __FILE__, __LINE__, $db->error());
 
 	$cur_topic = 0;
 	while ($cur_post = $db->fetch_row($result))
@@ -118,9 +116,9 @@
 	}
 
 	// Check if there is more work to do
-	$result = $db->query('SELECT id FROM '.$db->prefix.'topics WHERE id>'.$end_at) or error('Unable to fetch topic info', __FILE__, __LINE__, $db->error());
+	$result = $db->query('SELECT id FROM '.$db->prefix.'topics WHERE id>'.$cur_topic.' ORDER BY id ASC LIMIT 1') or error('Unable to fetch topic info', __FILE__, __LINE__, $db->error());
 
-	$query_str = ($db->num_rows($result)) ? '?i_per_page='.$per_page.'&i_start_at='.$end_at : '';
+	$query_str = ($db->num_rows($result)) ? '?i_per_page='.$per_page.'&i_start_at='.$db->result($result) : '';
 
 	$db->end_transaction();
 	$db->close();
diff -urN punbb-1.2.15/upload/edit.php punbb-1.2.17/upload/edit.php
--- punbb-1.2.15/upload/edit.php	2005-09-02 16:05:31.000000000 +0200
+++ punbb-1.2.17/upload/edit.php	2008-01-14 12:57:40.000000000 +0100
@@ -197,7 +197,7 @@
 
 ?>
 <div class="blockform">
-	<h2><?php echo $lang_post['Edit post'] ?></h2>
+	<h2><span><?php echo $lang_post['Edit post'] ?></span></h2>
 	<div class="box">
 		<form id="edit" method="post" action="edit.php?id=<?php echo $id ?>&amp;action=edit" onsubmit="return process_form(this)">
 			<div class="inform">
diff -urN punbb-1.2.15/upload/header.php punbb-1.2.17/upload/header.php
--- punbb-1.2.15/upload/header.php	2007-04-10 18:19:24.000000000 +0200
+++ punbb-1.2.17/upload/header.php	2008-01-14 12:58:26.000000000 +0100
@@ -147,7 +147,7 @@
 
 // START SUBST - <pun_page>
 $tpl_main = str_replace('<pun_page>', htmlspecialchars(basename($_SERVER['PHP_SELF'], '.php')), $tpl_main);
-// END SUBST - <pun_title>
+// END SUBST - <pun_page>
 
 
 // START SUBST - <pun_title>
diff -urN punbb-1.2.15/upload/include/common.php punbb-1.2.17/upload/include/common.php
--- punbb-1.2.15/upload/include/common.php	2007-04-09 16:15:20.000000000 +0200
+++ punbb-1.2.17/upload/include/common.php	2008-02-20 00:09:45.000000000 +0100
@@ -70,8 +70,9 @@
 	$_COOKIE = stripslashes_array($_COOKIE);
 }
 
-// Seed the random number generator
-mt_srand((double)microtime()*1000000);
+// Seed the random number generator (PHP <4.2.0 only)
+if (version_compare(PHP_VERSION, '4.2.0', '<'))
+	mt_srand((double)microtime()*1000000);
 
 // If a cookie name is not specified in config.php, we use the default (punbb_cookie)
 if (empty($cookie_name))
diff -urN punbb-1.2.15/upload/include/functions.php punbb-1.2.17/upload/include/functions.php
--- punbb-1.2.15/upload/include/functions.php	2007-04-10 18:19:24.000000000 +0200
+++ punbb-1.2.17/upload/include/functions.php	2008-02-20 00:09:45.000000000 +0100
@@ -48,7 +48,7 @@
 		// If user authorisation failed
 		if (!isset($pun_user['id']) || md5($cookie_seed.$pun_user['password']) !== $cookie['password_hash'])
 		{
-			pun_setcookie(0, random_pass(8), $expire);
+			pun_setcookie(1, md5(uniqid(rand(), true)), $expire);
 			set_default_user();
 
 			return;
@@ -295,14 +295,14 @@
 				$links[] = '<li id="navsearch"><a href="search.php">'.$lang_common['Search'].'</a>';
 
 			$links[] = '<li id="navprofile"><a href="profile.php?id='.$pun_user['id'].'">'.$lang_common['Profile'].'</a>';
-			$links[] = '<li id="navlogout"><a href="login.php?action=out&amp;id='.$pun_user['id'].'">'.$lang_common['Logout'].'</a>';
+			$links[] = '<li id="navlogout"><a href="login.php?action=out&amp;id='.$pun_user['id'].'&amp;csrf_token='.sha1($pun_user['id'].sha1(get_remote_address())).'">'.$lang_common['Logout'].'</a>';
 		}
 		else
 		{
 			$links[] = '<li id="navsearch"><a href="search.php">'.$lang_common['Search'].'</a>';
 			$links[] = '<li id="navprofile"><a href="profile.php?id='.$pun_user['id'].'">'.$lang_common['Profile'].'</a>';
 			$links[] = '<li id="navadmin"><a href="admin_index.php">'.$lang_common['Admin'].'</a>';
-			$links[] = '<li id="navlogout"><a href="login.php?action=out&amp;id='.$pun_user['id'].'">'.$lang_common['Logout'].'</a>';
+			$links[] = '<li id="navlogout"><a href="login.php?action=out&amp;id='.$pun_user['id'].'&amp;csrf_token='.sha1($pun_user['id'].sha1(get_remote_address())).'">'.$lang_common['Logout'].'</a>';
 		}
 	}
 
@@ -352,13 +352,13 @@
 
 
 //
-// Update posts, topics, last_post, last_post_id and last_poster for a forum (redirect topics are not included)
+// Update posts, topics, last_post, last_post_id and last_poster for a forum
 //
 function update_forum($forum_id)
 {
 	global $db;
 
-	$result = $db->query('SELECT COUNT(id), SUM(num_replies) FROM '.$db->prefix.'topics WHERE moved_to IS NULL AND forum_id='.$forum_id) or error('Unable to fetch forum topic count', __FILE__, __LINE__, $db->error());
+	$result = $db->query('SELECT COUNT(id), SUM(num_replies) FROM '.$db->prefix.'topics WHERE forum_id='.$forum_id) or error('Unable to fetch forum topic count', __FILE__, __LINE__, $db->error());
 	list($num_topics, $num_posts) = $db->fetch_row($result);
 
 	$num_posts = $num_posts + $num_topics;		// $num_posts is only the sum of all replies (we have to add the topic posts)
@@ -371,7 +371,7 @@
 		$db->query('UPDATE '.$db->prefix.'forums SET num_topics='.$num_topics.', num_posts='.$num_posts.', last_post='.$last_post.', last_post_id='.$last_post_id.', last_poster=\''.$db->escape($last_poster).'\' WHERE id='.$forum_id) or error('Unable to update last_post/last_post_id/last_poster', __FILE__, __LINE__, $db->error());
 	}
 	else	// There are no topics
-		$db->query('UPDATE '.$db->prefix.'forums SET num_topics=0, num_posts=0, last_post=NULL, last_post_id=NULL, last_poster=NULL WHERE id='.$forum_id) or error('Unable to update last_post/last_post_id/last_poster', __FILE__, __LINE__, $db->error());
+		$db->query('UPDATE '.$db->prefix.'forums SET num_topics='.$num_topics.', num_posts='.$num_posts.', last_post=NULL, last_post_id=NULL, last_poster=NULL WHERE id='.$forum_id) or error('Unable to update last_post/last_post_id/last_poster', __FILE__, __LINE__, $db->error());
 }
 
 
@@ -849,8 +849,12 @@
 {
 	global $db, $pun_config, $lang_common, $pun_user;
 
-	if ($destination_url == '')
-		$destination_url = 'index.php';
+	// Prefix with o_base_url (unless there's already a valid URI)
+	if (strpos($destination_url, 'http://') !== 0 && strpos($destination_url, 'https://') !== 0 && strpos($destination_url, '/') !== 0)
+		$destination_url = $pun_config['o_base_url'].'/'.$destination_url;
+
+	// Do a little spring cleaning
+	$destination_url = preg_replace('/([\r\n])|(%0[ad])|(;[\s]*data[\s]*:)/i', '', $destination_url);
 
 	// If the delay is 0 seconds, we might as well skip the redirect all together
 	if ($pun_config['o_redirect_delay'] == '0')
@@ -1067,7 +1071,7 @@
 function unregister_globals()
 {
 	$register_globals = @ini_get('register_globals');
-	if ($register_globals === "" || $register_globals === "0" || strtolower($register_globals === "off"))
+	if ($register_globals === "" || $register_globals === "0" || strtolower($register_globals) === "off")
 		return;
 
 	// Prevent script.php?GLOBALS[foo]=bar
diff -urN punbb-1.2.15/upload/install.php punbb-1.2.17/upload/install.php
--- punbb-1.2.15/upload/install.php	2007-04-11 13:39:51.000000000 +0200
+++ punbb-1.2.17/upload/install.php	2008-02-20 00:22:17.000000000 +0100
@@ -24,7 +24,7 @@
 
 
 // The PunBB version this script installs
-$punbb_version = '1.2.15';
+$punbb_version = '1.2.17';
 
 
 define('PUN_ROOT', './');
@@ -1401,7 +1401,7 @@
 
 
 	/// Display config.php and give further instructions
-	$config = '<?php'."\n\n".'$db_type = \''.$db_type."';\n".'$db_host = \''.$db_host."';\n".'$db_name = \''.$db_name."';\n".'$db_username = \''.$db_username."';\n".'$db_password = \''.$db_password."';\n".'$db_prefix = \''.$db_prefix."';\n".'$p_connect = false;'."\n\n".'$cookie_name = '."'punbb_cookie';\n".'$cookie_domain = '."'';\n".'$cookie_path = '."'/';\n".'$cookie_secure = 0;'."\n".'$cookie_seed = \''.substr(md5(time()), -8)."';\n\ndefine('PUN', 1);";
+	$config = '<?php'."\n\n".'$db_type = \''.$db_type."';\n".'$db_host = \''.$db_host."';\n".'$db_name = \''.$db_name."';\n".'$db_username = \''.$db_username."';\n".'$db_password = \''.$db_password."';\n".'$db_prefix = \''.$db_prefix."';\n".'$p_connect = false;'."\n\n".'$cookie_name = '."'punbb_cookie';\n".'$cookie_domain = '."'';\n".'$cookie_path = '."'/';\n".'$cookie_secure = 0;'."\n".'$cookie_seed = \''.substr(sha1(uniqid(rand(), true)), 0, 16)."';\n\ndefine('PUN', 1);";
 
 
 ?>
diff -urN punbb-1.2.15/upload/login.php punbb-1.2.17/upload/login.php
--- punbb-1.2.15/upload/login.php	2006-05-20 17:52:02.000000000 +0200
+++ punbb-1.2.17/upload/login.php	2008-02-20 00:09:45.000000000 +0100
@@ -84,7 +84,7 @@
 
 else if ($action == 'out')
 {
-	if ($pun_user['is_guest'] || !isset($_GET['id']) || $_GET['id'] != $pun_user['id'])
+	if ($pun_user['is_guest'] || !isset($_GET['id']) || $_GET['id'] != $pun_user['id'] || !isset($_GET['csrf_token']) || $_GET['csrf_token'] != sha1($pun_user['id'].sha1(get_remote_address())))
 	{
 		header('Location: index.php');
 		exit;
@@ -97,7 +97,7 @@
 	if (isset($pun_user['logged']))
 		$db->query('UPDATE '.$db->prefix.'users SET last_visit='.$pun_user['logged'].' WHERE id='.$pun_user['id']) or error('Unable to update user visit data', __FILE__, __LINE__, $db->error());
 
-	pun_setcookie(1, random_pass(8), time() + 31536000);
+	pun_setcookie(1, md5(uniqid(rand(), true)), time() + 31536000);
 
 	redirect('index.php', $lang_login['Logout redirect']);
 }
diff -urN punbb-1.2.15/upload/misc.php punbb-1.2.17/upload/misc.php
--- punbb-1.2.15/upload/misc.php	2007-04-10 18:42:55.000000000 +0200
+++ punbb-1.2.17/upload/misc.php	2008-02-03 16:42:49.000000000 +0100
@@ -252,6 +252,11 @@
 	if ($topic_id < 1)
 		message($lang_common['Bad request']);
 
+	// Make sure the user can view the topic
+	$result = $db->query('SELECT 1 FROM '.$db->prefix.'topics AS t LEFT JOIN '.$db->prefix.'forum_perms AS fp ON (fp.forum_id=t.forum_id AND fp.group_id=1) WHERE (fp.read_forum IS NULL OR fp.read_forum=1) AND t.id='.$topic_id.' AND t.moved_to IS NULL') or error('Unable to fetch topic info', __FILE__, __LINE__, $db->error());
+	if (!$db->num_rows($result))
+		message($lang_common['Bad request']);
+
 	$result = $db->query('SELECT 1 FROM '.$db->prefix.'subscriptions WHERE user_id='.$pun_user['id'].' AND topic_id='.$topic_id) or error('Unable to fetch subscription info', __FILE__, __LINE__, $db->error());
 	if ($db->num_rows($result))
 		message($lang_misc['Already subscribed']);
diff -urN punbb-1.2.15/upload/moderate.php punbb-1.2.17/upload/moderate.php
--- punbb-1.2.15/upload/moderate.php	2007-04-10 23:37:34.000000000 +0200
+++ punbb-1.2.17/upload/moderate.php	2008-02-20 00:18:27.000000000 +0100
@@ -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
 	{
@@ -295,10 +295,10 @@
 		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))
+		// 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)
@@ -417,10 +417,10 @@
 
 		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)
+		// 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
diff -urN punbb-1.2.15/upload/profile.php punbb-1.2.17/upload/profile.php
--- punbb-1.2.15/upload/profile.php	2007-04-10 23:37:34.000000000 +0200
+++ punbb-1.2.17/upload/profile.php	2007-11-19 00:14:16.000000000 +0100
@@ -87,6 +87,9 @@
 
 	if (isset($_POST['form_sent']))
 	{
+		if ($pun_user['g_id'] < PUN_GUEST)
+			confirm_referrer('profile.php');
+
 		$old_password = isset($_POST['req_old_password']) ? trim($_POST['req_old_password']) : '';
 		$new_password1 = trim($_POST['req_new_password1']);
 		$new_password2 = trim($_POST['req_new_password2']);
diff -urN punbb-1.2.15/upload/search.php punbb-1.2.17/upload/search.php
--- punbb-1.2.15/upload/search.php	2007-04-11 09:27:58.000000000 +0200
+++ punbb-1.2.17/upload/search.php	2008-02-08 02:29:45.000000000 +0100
@@ -122,7 +122,7 @@
 		$keyword_results = $author_results = array();
 
 		// Search a specific forum?
-		$forum_sql = ($forum != -1 || ($forum == -1 && $pun_config['o_search_all_forums'] == '0')) ? ' AND t.forum_id = '.$forum : '';
+		$forum_sql = ($forum != -1 || ($forum == -1 && $pun_config['o_search_all_forums'] == '0' && $pun_user['g_id'] >= PUN_GUEST)) ? ' AND t.forum_id = '.$forum : '';
 
 		if (!empty($author) || !empty($keywords))
 		{
@@ -160,7 +160,7 @@
 					{
 						$num_chars = pun_strlen($word);
 
-						if ($num_chars < 3 || $num_chars > 20 || in_array($word, $stopwords))
+						if ($word !== 'or' && ($num_chars < 3 || $num_chars > 20 || in_array($word, $stopwords)))
 							unset($keywords_array[$i]);
 					}
 
@@ -199,7 +199,7 @@
 							}
 							else
 							{
-								$cur_word = str_replace('*', '%', $cur_word);
+								$cur_word = $db->escape(str_replace('*', '%', $cur_word));
 								$sql = 'SELECT m.post_id FROM '.$db->prefix.'search_words AS w INNER JOIN '.$db->prefix.'search_matches AS m ON m.word_id = w.id WHERE w.word LIKE \''.$cur_word.'\''.$search_in_cond;
 							}
 
