[Xfce4-commits] <forum:master> Update to fluxbb 1.5.4.

Nick Schermer noreply at xfce.org
Fri Sep 20 21:58:01 CEST 2013


Updating branch refs/heads/master
         to b297a9518bc426eb7a5617b62ee81e6e926a333c (commit)
       from 45b0f67e93c4d565197a90a544db6e120e1f09c1 (commit)

commit b297a9518bc426eb7a5617b62ee81e6e926a333c
Author: Nick Schermer <nick at xfce.org>
Date:   Fri Sep 20 21:55:48 2013 +0200

    Update to fluxbb 1.5.4.

 admin_options.php              |    9 ++++
 admin_users.php                |    4 +-
 db_update.php                  |    6 +--
 delete.php                     |    3 ++
 edit.php                       |    3 ++
 extern.php                     |   13 ++---
 include/cache.php              |  103 +++++++++++++++++++---------------------
 include/common.php             |    4 +-
 include/dblayer/pgsql.php      |    6 +--
 include/email.php              |    4 +-
 include/functions.php          |   47 ++++++++++++++++--
 include/parser.php             |   80 ++++++++++++++++---------------
 include/srand.php              |   77 ++++++++++++++++--------------
 index.php                      |    2 +-
 install.php                    |   60 ++++-------------------
 lang/English/admin_options.php |    5 +-
 lang/English/admin_users.php   |    2 +-
 lang/English/install.php       |   46 +++++++-----------
 lang/English/profile.php       |    2 +-
 lang/English/topic.php         |    2 +-
 login.php                      |    2 +-
 misc.php                       |    2 +
 moderate.php                   |   11 ++++-
 profile.php                    |   23 ++++++---
 readme.md                      |   28 +++++++++++
 register.php                   |    2 +-
 style/Air.css                  |    3 +-
 style/Earth.css                |    3 +-
 style/Fire.css                 |    3 +-
 viewtopic.php                  |   13 +++--
 30 files changed, 307 insertions(+), 261 deletions(-)

diff --git a/admin_options.php b/admin_options.php
index c4decaa..e3a7894 100644
--- a/admin_options.php
+++ b/admin_options.php
@@ -92,6 +92,15 @@ if (isset($_POST['form_sent']))
 	// Make sure base_url doesn't end with a slash
 	if (substr($form['base_url'], -1) == '/')
 		$form['base_url'] = substr($form['base_url'], 0, -1);
+		
+	// Convert IDN to Punycode if needed
+	if (preg_match('/[^\x00-\x7F]/', $form['base_url']))
+	{
+		if (!function_exists('idn_to_ascii'))
+			message($lang_admin_options['Base URL problem']);
+		else
+			$form['base_url'] = idn_to_ascii($form['base_url']);
+	}
 
 	$languages = forum_list_langs();
 	if (!in_array($form['default_lang'], $languages))
diff --git a/admin_users.php b/admin_users.php
index 7ea3c63..29703c8 100644
--- a/admin_users.php
+++ b/admin_users.php
@@ -208,7 +208,7 @@ if (isset($_GET['show_users']))
 ?>
 				<tr>
 					<td class="tcl"><?php echo '<a href="profile.php?id='.$user_data[$cur_poster['poster_id']]['id'].'">'.pun_htmlspecialchars($user_data[$cur_poster['poster_id']]['username']).'</a>' ?></td>
-					<td class="tc2"><a href="mailto:<?php echo $user_data[$cur_poster['poster_id']]['email'] ?>"><?php echo $user_data[$cur_poster['poster_id']]['email'] ?></a></td>
+					<td class="tc2"><a href="mailto:<?php echo pun_htmlspecialchars($user_data[$cur_poster['poster_id']]['email']) ?>"><?php echo pun_htmlspecialchars($user_data[$cur_poster['poster_id']]['email']) ?></a></td>
 					<td class="tc3"><?php echo $user_title ?></td>
 					<td class="tc4"><?php echo forum_number_format($user_data[$cur_poster['poster_id']]['num_posts']) ?></td>
 					<td class="tc5"><?php echo ($user_data[$cur_poster['poster_id']]['admin_note'] != '') ? pun_htmlspecialchars($user_data[$cur_poster['poster_id']]['admin_note']) : ' ' ?></td>
@@ -871,7 +871,7 @@ else if (isset($_GET['find_user']))
 ?>
 				<tr>
 					<td class="tcl"><?php echo '<a href="profile.php?id='.$user_data['id'].'">'.pun_htmlspecialchars($user_data['username']).'</a>' ?></td>
-					<td class="tc2"><a href="mailto:<?php echo $user_data['email'] ?>"><?php echo $user_data['email'] ?></a></td>
+					<td class="tc2"><a href="mailto:<?php echo pun_htmlspecialchars($user_data['email']) ?>"><?php echo pun_htmlspecialchars($user_data['email']) ?></a></td>
 					<td class="tc3"><?php echo $user_title ?></td>
 					<td class="tc4"><?php echo forum_number_format($user_data['num_posts']) ?></td>
 					<td class="tc5"><?php echo ($user_data['admin_note'] != '') ? pun_htmlspecialchars($user_data['admin_note']) : ' ' ?></td>
diff --git a/db_update.php b/db_update.php
index 9c3d3b3..9626a0e 100644
--- a/db_update.php
+++ b/db_update.php
@@ -7,9 +7,9 @@
  */
 
 // The FluxBB version this script updates to
-define('UPDATE_TO', '1.5.3');
+define('UPDATE_TO', '1.5.4');
 
-define('UPDATE_TO_DB_REVISION', 18);
+define('UPDATE_TO_DB_REVISION', 20);
 define('UPDATE_TO_SI_REVISION', 2);
 define('UPDATE_TO_PARSER_REVISION', 2);
 
@@ -794,7 +794,7 @@ switch ($stage)
 			if (substr($base_url, -1) == '/')
 				$base_url = substr($base_url, 0, -1);
 
-			$db->query('INSERT INTO '.$db->prefix.'config (conf_name, conf_value) VALUES (\'o_base_url\', \''.$db->escape($base_url).'\')') or error('Unable to insert config value \'o_quote_depth\'', __FILE__, __LINE__, $db->error());
+			$db->query('INSERT INTO '.$db->prefix.'config (conf_name, conf_value) VALUES (\'o_base_url\', \''.$db->escape($base_url).'\')') or error('Unable to insert config value \'o_base_url\'', __FILE__, __LINE__, $db->error());
 		}
 
 		if (strpos($cur_version, '1.2') === 0)
diff --git a/delete.php b/delete.php
index 88bab6d..46e2d9b 100644
--- a/delete.php
+++ b/delete.php
@@ -42,6 +42,9 @@ if (($pun_user['g_delete_posts'] == '0' ||
 	!$is_admmod)
 	message($lang_common['No permission'], false, '403 Forbidden');
 
+if ($is_admmod && $pun_user['g_id'] != PUN_ADMIN && in_array($cur_post['poster_id'], get_admin_ids()))
+	message($lang_common['No permission'], false, '403 Forbidden');
+
 // Load the delete.php language file
 require PUN_ROOT.'lang/'.$pun_user['language'].'/delete.php';
 
diff --git a/edit.php b/edit.php
index f3346cf..0d9d331 100644
--- a/edit.php
+++ b/edit.php
@@ -44,6 +44,9 @@ if (($pun_user['g_edit_posts'] == '0' ||
 	!$is_admmod)
 	message($lang_common['No permission'], false, '403 Forbidden');
 
+if ($is_admmod && $pun_user['g_id'] != PUN_ADMIN && in_array($cur_post['poster_id'], get_admin_ids()))
+	message($lang_common['No permission'], false, '403 Forbidden');
+
 // Load the post.php language file
 require PUN_ROOT.'lang/'.$pun_user['language'].'/post.php';
 
diff --git a/extern.php b/extern.php
index eb4bc94..d43574b 100644
--- a/extern.php
+++ b/extern.php
@@ -438,16 +438,11 @@ if ($action == 'feed')
 			// Output feed as PHP code
 			if (isset($cache_id))
 			{
-				$fh = @fopen(FORUM_CACHE_DIR.'cache_'.$cache_id.'.php', 'wb');
-				if (!$fh)
-					error('Unable to write feed cache file to cache directory. Please make sure PHP has write access to the directory \''.pun_htmlspecialchars(FORUM_CACHE_DIR).'\'', __FILE__, __LINE__);
+				if (!defined('FORUM_CACHE_FUNCTIONS_LOADED'))
+					require PUN_ROOT.'include/cache.php';
 
-				fwrite($fh, '<?php'."\n\n".'$feed = '.var_export($feed, true).';'."\n\n".'$cache_expire = '.($now + ($pun_config['o_feed_ttl'] * 60)).';'."\n\n".'?>');
-
-				fclose($fh);
-
-				if (function_exists('apc_delete_file'))
-					@apc_delete_file(FORUM_CACHE_DIR.'cache_'.$cache_id.'.php');
+				$content = '<?php'."\n\n".'$feed = '.var_export($feed, true).';'."\n\n".'$cache_expire = '.($now + ($pun_config['o_feed_ttl'] * 60)).';'."\n\n".'?>';
+				fluxbb_write_cache_file('cache_'.$cache_id.'.php', $content);
 			}
 		}
 
diff --git a/include/cache.php b/include/cache.php
index 276aaa4..244095f 100644
--- a/include/cache.php
+++ b/include/cache.php
@@ -26,16 +26,8 @@ function generate_config_cache()
 		$output[$cur_config_item[0]] = $cur_config_item[1];
 
 	// Output config as PHP code
-	$fh = @fopen(FORUM_CACHE_DIR.'cache_config.php', 'wb');
-	if (!$fh)
-		error('Unable to write configuration cache file to cache directory. Please make sure PHP has write access to the directory \''.pun_htmlspecialchars(FORUM_CACHE_DIR).'\'', __FILE__, __LINE__);
-
-	fwrite($fh, '<?php'."\n\n".'define(\'PUN_CONFIG_LOADED\', 1);'."\n\n".'$pun_config = '.var_export($output, true).';'."\n\n".'?>');
-
-	fclose($fh);
-
-	if (function_exists('apc_delete_file'))
-		@apc_delete_file(FORUM_CACHE_DIR.'cache_config.php');
+	$content = '<?php'."\n\n".'define(\'PUN_CONFIG_LOADED\', 1);'."\n\n".'$pun_config = '.var_export($output, true).';'."\n\n".'?>';
+	fluxbb_write_cache_file('cache_config.php', $content);
 }
 
 
@@ -54,16 +46,8 @@ function generate_bans_cache()
 		$output[] = $cur_ban;
 
 	// Output ban list as PHP code
-	$fh = @fopen(FORUM_CACHE_DIR.'cache_bans.php', 'wb');
-	if (!$fh)
-		error('Unable to write bans cache file to cache directory. Please make sure PHP has write access to the directory \''.pun_htmlspecialchars(FORUM_CACHE_DIR).'\'', __FILE__, __LINE__);
-
-	fwrite($fh, '<?php'."\n\n".'define(\'PUN_BANS_LOADED\', 1);'."\n\n".'$pun_bans = '.var_export($output, true).';'."\n\n".'?>');
-
-	fclose($fh);
-
-	if (function_exists('apc_delete_file'))
-		@apc_delete_file(FORUM_CACHE_DIR.'cache_bans.php');
+	$content = '<?php'."\n\n".'define(\'PUN_BANS_LOADED\', 1);'."\n\n".'$pun_bans = '.var_export($output, true).';'."\n\n".'?>';
+	fluxbb_write_cache_file('cache_bans.php', $content);
 }
 
 
@@ -72,7 +56,7 @@ function generate_bans_cache()
 //
 function generate_quickjump_cache($group_id = false)
 {
-	global $db, $lang_common, $pun_user;
+	global $db, $lang_common;
 
 	$groups = array();
 
@@ -99,10 +83,6 @@ function generate_quickjump_cache($group_id = false)
 	foreach ($groups as $group_id => $read_board)
 	{
 		// Output quick jump as PHP code
-		$fh = @fopen(FORUM_CACHE_DIR.'cache_quickjump_'.$group_id.'.php', 'wb');
-		if (!$fh)
-			error('Unable to write quick jump cache file to cache directory. Please make sure PHP has write access to the directory \''.pun_htmlspecialchars(FORUM_CACHE_DIR).'\'', __FILE__, __LINE__);
-
 		$output = '<?php'."\n\n".'if (!defined(\'PUN\')) exit;'."\n".'define(\'PUN_QJ_LOADED\', 1);'."\n".'$forum_id = isset($forum_id) ? $forum_id : 0;'."\n\n".'?>';
 
 		if ($read_board == '1')
@@ -133,12 +113,7 @@ function generate_quickjump_cache($group_id = false)
 			}
 		}
 
-		fwrite($fh, $output);
-
-		fclose($fh);
-
-		if (function_exists('apc_delete_file'))
-			@apc_delete_file(FORUM_CACHE_DIR.'cache_quickjump_'.$group_id.'.php');
+		fluxbb_write_cache_file('cache_quickjump_'.$group_id.'.php', $output);
 	}
 }
 
@@ -161,16 +136,8 @@ function generate_censoring_cache()
 	}
 
 	// Output censored words as PHP code
-	$fh = @fopen(FORUM_CACHE_DIR.'cache_censoring.php', 'wb');
-	if (!$fh)
-		error('Unable to write censoring cache file to cache directory. Please make sure PHP has write access to the directory \''.pun_htmlspecialchars(FORUM_CACHE_DIR).'\'', __FILE__, __LINE__);
-
-	fwrite($fh, '<?php'."\n\n".'define(\'PUN_CENSOR_LOADED\', 1);'."\n\n".'$search_for = '.var_export($search_for, true).';'."\n\n".'$replace_with = '.var_export($replace_with, true).';'."\n\n".'?>');
-
-	fclose($fh);
-
-	if (function_exists('apc_delete_file'))
-		@apc_delete_file(FORUM_CACHE_DIR.'cache_censoring.php');
+	$content = '<?php'."\n\n".'define(\'PUN_CENSOR_LOADED\', 1);'."\n\n".'$search_for = '.var_export($search_for, true).';'."\n\n".'$replace_with = '.var_export($replace_with, true).';'."\n\n".'?>';
+	fluxbb_write_cache_file('cache_censoring.php', $content);
 }
 
 
@@ -197,16 +164,8 @@ function generate_stopwords_cache()
 	$stopwords = array_filter($stopwords);
 
 	// Output stopwords as PHP code
-	$fh = @fopen(FORUM_CACHE_DIR.'cache_stopwords.php', 'wb');
-	if (!$fh)
-		error('Unable to write stopwords cache file to cache directory. Please make sure PHP has write access to the directory \''.pun_htmlspecialchars(FORUM_CACHE_DIR).'\'', __FILE__, __LINE__);
-
-	fwrite($fh, '<?php'."\n\n".'$cache_id = \''.generate_stopwords_cache_id().'\';'."\n".'if ($cache_id != generate_stopwords_cache_id()) return;'."\n\n".'define(\'PUN_STOPWORDS_LOADED\', 1);'."\n\n".'$stopwords = '.var_export($stopwords, true).';'."\n\n".'?>');
-
-	fclose($fh);
-
-	if (function_exists('apc_delete_file'))
-		@apc_delete_file(FORUM_CACHE_DIR.'cache_stopwords.php');
+	$content = '<?php'."\n\n".'$cache_id = \''.generate_stopwords_cache_id().'\';'."\n".'if ($cache_id != generate_stopwords_cache_id()) return;'."\n\n".'define(\'PUN_STOPWORDS_LOADED\', 1);'."\n\n".'$stopwords = '.var_export($stopwords, true).';'."\n\n".'?>';
+	fluxbb_write_cache_file('cache_stopwords.php', $content);
 }
 
 
@@ -226,16 +185,50 @@ function generate_users_info_cache()
 	$stats['last_user'] = $db->fetch_assoc($result);
 
 	// Output users info as PHP code
-	$fh = @fopen(FORUM_CACHE_DIR.'cache_users_info.php', 'wb');
+	$content = '<?php'."\n\n".'define(\'PUN_USERS_INFO_LOADED\', 1);'."\n\n".'$stats = '.var_export($stats, true).';'."\n\n".'?>';
+	fluxbb_write_cache_file('cache_users_info.php', $content);
+}
+
+
+//
+// Generate the admins cache PHP script
+//
+function generate_admins_cache()
+{
+	global $db;
+
+	// Get admins from the DB
+	$result = $db->query('SELECT id FROM '.$db->prefix.'users WHERE group_id='.PUN_ADMIN) or error('Unable to fetch users info', __FILE__, __LINE__, $db->error());
+
+	$output = array();
+	while ($row = $db->fetch_row($result))
+		$output[] = $row[0];
+
+	// Output admin list as PHP code
+	$content = '<?php'."\n\n".'define(\'PUN_ADMINS_LOADED\', 1);'."\n\n".'$pun_admins = '.var_export($output, true).';'."\n\n".'?>';
+	fluxbb_write_cache_file('cache_admins.php', $content);
+}
+
+
+//
+// Safely write out a cache file.
+//
+function fluxbb_write_cache_file($file, $content)
+{
+	$fh = @fopen(FORUM_CACHE_DIR.$file, 'wb');
 	if (!$fh)
-		error('Unable to write users info cache file to cache directory. Please make sure PHP has write access to the directory \''.pun_htmlspecialchars(FORUM_CACHE_DIR).'\'', __FILE__, __LINE__);
+		error('Unable to write cache file '.pun_htmlspecialchars($file).' to cache directory. Please make sure PHP has write access to the directory \''.pun_htmlspecialchars(FORUM_CACHE_DIR).'\'', __FILE__, __LINE__);
+
+	flock($fh, LOCK_EX);
+	ftruncate($fh, 0);
 
-	fwrite($fh, '<?php'."\n\n".'define(\'PUN_USERS_INFO_LOADED\', 1);'."\n\n".'$stats = '.var_export($stats, true).';'."\n\n".'?>');
+	fwrite($fh, $content);
 
+	flock($fh, LOCK_UN);
 	fclose($fh);
 
 	if (function_exists('apc_delete_file'))
-		@apc_delete_file(FORUM_CACHE_DIR.'cache_users_info.php');
+		@apc_delete_file(FORUM_CACHE_DIR.$file);
 }
 
 
diff --git a/include/common.php b/include/common.php
index 3196313..ded5be3 100644
--- a/include/common.php
+++ b/include/common.php
@@ -10,9 +10,9 @@ if (!defined('PUN_ROOT'))
 	exit('The constant PUN_ROOT must be defined and point to a valid FluxBB installation root directory.');
 
 // Define the version and database revision that this code was written for
-define('FORUM_VERSION', '1.5.3');
+define('FORUM_VERSION', '1.5.4');
 
-define('FORUM_DB_REVISION', 18);
+define('FORUM_DB_REVISION', 20);
 define('FORUM_SI_REVISION', 2);
 define('FORUM_PARSER_REVISION', 2);
 
diff --git a/include/dblayer/pgsql.php b/include/dblayer/pgsql.php
index a3d7574..c48170a 100644
--- a/include/dblayer/pgsql.php
+++ b/include/dblayer/pgsql.php
@@ -115,7 +115,7 @@ class DBLayer
 
 			++$this->num_queries;
 
-			$this->last_query_text[$this->query_result] = $sql;
+			$this->last_query_text[intval($this->query_result)] = $sql;
 
 			return $this->query_result;
 		}
@@ -171,9 +171,9 @@ class DBLayer
 	{
 		$query_id = $this->query_result;
 
-		if ($query_id && $this->last_query_text[$query_id] != '')
+		if ($query_id && $this->last_query_text[intval($query_id)] != '')
 		{
-			if (preg_match('%^INSERT INTO ([a-z0-9\_\-]+)%is', $this->last_query_text[$query_id], $table_name))
+			if (preg_match('%^INSERT INTO ([a-z0-9\_\-]+)%is', $this->last_query_text[intval($query_id)], $table_name))
 			{
 				// Hack (don't ask)
 				if (substr($table_name[1], -6) == 'groups')
diff --git a/include/email.php b/include/email.php
index 930e963..88c62a8 100644
--- a/include/email.php
+++ b/include/email.php
@@ -229,14 +229,14 @@ function pun_mail($to, $subject, $message, $reply_to_email = '', $reply_to_name
 	$from = '"'.encode_mail_text($from_name).'" <'.$from_email.'>';
 	$subject = encode_mail_text($subject);
 
-	$headers = 'From: '.$from.PHP_EOL.'Date: '.gmdate('r').PHP_EOL.'MIME-Version: 1.0'.PHP_EOL.'Content-transfer-encoding: 8bit'.PHP_EOL.'Content-type: text/plain; charset=utf-8'.PHP_EOL.'X-Mailer: FluxBB Mailer';
+	$headers = 'From: '.$from."\r\n".'Date: '.gmdate('r')."\r\n".'MIME-Version: 1.0'."\r\n".'Content-transfer-encoding: 8bit'."\r\n".'Content-type: text/plain; charset=utf-8'."\r\n".'X-Mailer: FluxBB Mailer';
 
 	// If we specified a reply-to email, we deal with it here
 	if (!empty($reply_to_email))
 	{
 		$reply_to = '"'.encode_mail_text($reply_to_name).'" <'.$reply_to_email.'>';
 
-		$headers .= PHP_EOL.'Reply-To: '.$reply_to;
+		$headers .= "\r\n".'Reply-To: '.$reply_to;
 	}
 
 	// Make sure all linebreaks are LF in message (and strip out any NULL bytes)
diff --git a/include/functions.php b/include/functions.php
index 8ec3cdb..e6cec48 100644
--- a/include/functions.php
+++ b/include/functions.php
@@ -215,6 +215,7 @@ function get_current_protocol()
 	return $protocol;
 }
 
+
 //
 // Fetch the base_url, optionally support HTTPS and HTTP
 //
@@ -237,6 +238,27 @@ function get_base_url($support_https = false)
 
 
 //
+// Fetch admin IDs
+//
+function get_admin_ids()
+{
+	if (file_exists(FORUM_CACHE_DIR.'cache_admins.php'))
+		include FORUM_CACHE_DIR.'cache_admins.php';
+
+	if (!defined('PUN_ADMINS_LOADED'))
+	{
+		if (!defined('FORUM_CACHE_FUNCTIONS_LOADED'))
+			require PUN_ROOT.'include/cache.php';
+
+		generate_admins_cache();
+		require FORUM_CACHE_DIR.'cache_admins.php';
+	}
+
+	return $pun_admins;
+}
+
+
+//
 // Fill $pun_user with default values (for guests)
 //
 function set_default_user()
@@ -339,7 +361,10 @@ function pun_setcookie($user_id, $password_hash, $expire)
 //
 function forum_setcookie($name, $value, $expire)
 {
-	global $cookie_path, $cookie_domain, $cookie_secure;
+	global $cookie_path, $cookie_domain, $cookie_secure, $pun_config;
+
+	if ($expire - time() - $pun_config['o_timeout_visit'] < 1)
+		$expire = 0;
 
 	// Enable sending of a P3P header
 	header('P3P: CP="CUR ADM"');
@@ -407,7 +432,7 @@ function check_bans()
 		if ($is_banned)
 		{
 			$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);
+			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_htmlspecialchars($pun_config['o_admin_email']).'">'.pun_htmlspecialchars($pun_config['o_admin_email']).'</a>.', true);
 		}
 	}
 
@@ -1313,6 +1338,9 @@ function redirect($destination_url, $message)
 	// If the delay is 0 seconds, we might as well skip the redirect all together
 	if ($pun_config['o_redirect_delay'] == '0')
 	{
+		$db->end_transaction();
+		$db->close();
+
 		header('Location: '.str_replace('&', '&', $destination_url));
 		exit;
 	}
@@ -1945,9 +1973,12 @@ function url_valid($url)
 //
 // This function takes care of possibly disabled unicode properties in PCRE builds
 //
-function ucp_preg_replace($pattern, $replace, $subject)
+function ucp_preg_replace($pattern, $replace, $subject, $callback = false)
 {
-	$replaced = preg_replace($pattern, $replace, $subject);
+	if($callback) 
+		$replaced = preg_replace_callback($pattern, create_function('$matches', 'return '.$replace.';'), $subject);
+	else
+		$replaced = preg_replace($pattern, $replace, $subject);
 
 	// If preg_replace() returns false, this probably means unicode support is not built-in, so we need to modify the pattern a little
 	if ($replaced === false)
@@ -1967,6 +1998,14 @@ function ucp_preg_replace($pattern, $replace, $subject)
 }
 
 //
+// A wrapper for ucp_preg_replace
+//
+function ucp_preg_replace_callback($pattern, $replace, $subject)
+{
+	return ucp_preg_replace($pattern, $replace, $subject, true);
+}
+
+//
 // Replace four-byte characters with a question mark
 //
 // As MySQL cannot properly handle four-byte characters with the default utf-8
diff --git a/include/parser.php b/include/parser.php
index 0097c3d..226e7dd 100644
--- a/include/parser.php
+++ b/include/parser.php
@@ -36,7 +36,7 @@ if (!defined('PUN'))
 )                     # end capturing contents of LIST tag into group 2
 \[/list\]             # match outermost closing LIST tag
 %iex' */
-$re_list = '%\[list(?:=([1a*]))?+\]((?:[^\[]*+(?:(?!\[list(?:=[1a*])?+\]|\[/list\])\[[^\[]*+)*+|(?R))*)\[/list\]%ie';
+$re_list = '%\[list(?:=([1a*]))?+\]((?:[^\[]*+(?:(?!\[list(?:=[1a*])?+\]|\[/list\])\[[^\[]*+)*+|(?R))*)\[/list\]%i';
 
 // Here you can add additional smilies if you like (please note that you must escape single quote and backslash)
 $smilies = array(
@@ -95,7 +95,7 @@ function preparse_bbcode($text, &$errors, $is_signature = false)
 		list($inside, $text) = extract_blocks($text, '[code]', '[/code]');
 
 	// Tidy up lists
-	$temp = preg_replace($re_list, 'preparse_list_tag(\'$2\', \'$1\')', $text);
+	$temp = preg_replace_callback($re_list, create_function('$matches', 'return preparse_list_tag($matches[2], $matches[1]);'), $text);
 
 	// If the regex failed
 	if (is_null($temp))
@@ -640,7 +640,7 @@ function preparse_list_tag($content, $type = '*')
 
 	if (strpos($content,'[list') !== false)
 	{
-		$content = preg_replace($re_list, 'preparse_list_tag(\'$2\', \'$1\')', $content);
+		$content = preg_replace_callback($re_list, create_function('$matches', 'return preparse_list_tag($matches[2], $matches[1]);'), $content);
 	}
 
 	$items = explode('[*]', str_replace('\"', '"', $content));
@@ -734,7 +734,7 @@ function handle_list_tag($content, $type = '*')
 
 	if (strpos($content,'[list') !== false)
 	{
-		$content = preg_replace($re_list, 'handle_list_tag(\'$2\', \'$1\')', $content);
+		$content = preg_replace_callback($re_list, create_function('$matches', 'return handle_list_tag($matches[2], $matches[1]);'), $content);
 	}
 
 	$content = preg_replace('#\s*\[\*\](.*?)\[/\*\]\s*#s', '<li><p>$1</p></li>', pun_trim($content));
@@ -761,14 +761,13 @@ function do_bbcode($text, $is_signature = false)
 	if (strpos($text, '[quote') !== false)
 	{
 		$text = preg_replace('%\[quote\]\s*%', '</p><div class="quotebox"><blockquote><div><p>', $text);
-		$text = preg_replace('%\[quote=("|&\#039;|"|\'|)(.*?)\\1\]%se', '"</p><div class=\"quotebox\"><cite>".str_replace(array(\'[\', \'\\"\'), array(\'[\', \'"\'), \'$2\')." ".$lang_common[\'wrote\']."</cite><blockquote><div><p>"', $text);
+		$text = preg_replace_callback('%\[quote=("|&\#039;|"|\'|)(.*?)\\1\]%s', create_function('$matches', 'global $lang_common; return "</p><div class=\"quotebox\"><cite>".str_replace(array(\'[\', \'\\"\'), array(\'[\', \'"\'), $matches[2])." ".$lang_common[\'wrote\']."</cite><blockquote><div><p>";'), $text);
 		$text = preg_replace('%\s*\[\/quote\]%S', '</p></div></blockquote></div><p>', $text);
 	}
-
 	if (!$is_signature)
 	{
-		$pattern[] = $re_list;
-		$replace[] = 'handle_list_tag(\'$2\', \'$1\')';
+		$pattern_callback[] = $re_list;
+		$replace_callback[] = 'handle_list_tag($matches[2], $matches[1])';
 	}
 
 	$pattern[] = '%\[b\](.*?)\[/b\]%ms';
@@ -793,49 +792,53 @@ function do_bbcode($text, $is_signature = false)
 
 	if (($is_signature && $pun_config['p_sig_img_tag'] == '1') || (!$is_signature && $pun_config['p_message_img_tag'] == '1'))
 	{
-		$pattern[] = '%\[img\]((ht|f)tps?://)([^\s<"]*?)\[/img\]%e';
-		$pattern[] = '%\[img=([^\[]*?)\]((ht|f)tps?://)([^\s<"]*?)\[/img\]%e';
+		$pattern_callback[] = '%\[img\]((ht|f)tps?://)([^\s<"]*?)\[/img\]%';
+		$pattern_callback[] = '%\[img=([^\[]*?)\]((ht|f)tps?://)([^\s<"]*?)\[/img\]%';
 		if ($is_signature)
 		{
-			$replace[] = 'handle_img_tag(\'$1$3\', true)';
-			$replace[] = 'handle_img_tag(\'$2$4\', true, \'$1\')';
+			$replace_callback[] = 'handle_img_tag($matches[1].$matches[3], true)';
+			$replace_callback[] = 'handle_img_tag($matches[2].$matches[4], true, $matches[1])';
 		}
 		else
 		{
-			$replace[] = 'handle_img_tag(\'$1$3\', false)';
-			$replace[] = 'handle_img_tag(\'$2$4\', false, \'$1\')';
+			$replace_callback[] = 'handle_img_tag($matches[1].$matches[3], false)';
+			$replace_callback[] = 'handle_img_tag($matches[2].$matches[4], false, $matches[1])';
 		}
 	}
 
-	$pattern[] = '%\[url\]([^\[]*?)\[/url\]%e';
-	$pattern[] = '%\[url=([^\[]+?)\](.*?)\[/url\]%e';
+	$pattern_callback[] = '%\[url\]([^\[]*?)\[/url\]%';
+	$pattern_callback[] = '%\[url=([^\[]+?)\](.*?)\[/url\]%';
 	$pattern[] = '%\[email\]([^\[]*?)\[/email\]%';
 	$pattern[] = '%\[email=([^\[]+?)\](.*?)\[/email\]%';
-	$pattern[] = '%\[topic\]([1-9]\d*)\[/topic\]%e';
-	$pattern[] = '%\[topic=([1-9]\d*)\](.*?)\[/topic\]%e';
-	$pattern[] = '%\[post\]([1-9]\d*)\[/post\]%e';
-	$pattern[] = '%\[post=([1-9]\d*)\](.*?)\[/post\]%e';
-	$pattern[] = '%\[forum\]([1-9]\d*)\[/forum\]%e';
-	$pattern[] = '%\[forum=([1-9]\d*)\](.*?)\[/forum\]%e';
-	$pattern[] = '%\[user\]([1-9]\d*)\[/user\]%e';
-	$pattern[] = '%\[user=([1-9]\d*)\](.*?)\[/user\]%e';
-
-	$replace[] = 'handle_url_tag(\'$1\')';
-	$replace[] = 'handle_url_tag(\'$1\', \'$2\')';
+	$pattern_callback[] = '%\[topic\]([1-9]\d*)\[/topic\]%';
+	$pattern_callback[] = '%\[topic=([1-9]\d*)\](.*?)\[/topic\]%';
+	$pattern_callback[] = '%\[post\]([1-9]\d*)\[/post\]%';
+	$pattern_callback[] = '%\[post=([1-9]\d*)\](.*?)\[/post\]%';
+	$pattern_callback[] = '%\[forum\]([1-9]\d*)\[/forum\]%';
+	$pattern_callback[] = '%\[forum=([1-9]\d*)\](.*?)\[/forum\]%';
+	$pattern_callback[] = '%\[user\]([1-9]\d*)\[/user\]%';
+	$pattern_callback[] = '%\[user=([1-9]\d*)\](.*?)\[/user\]%';
+
+	$replace_callback[] = 'handle_url_tag($matches[1])';
+	$replace_callback[] = 'handle_url_tag($matches[1], $matches[2])';
 	$replace[] = '<a href="mailto:$1">$1</a>';
 	$replace[] = '<a href="mailto:$1">$2</a>';
-	$replace[] = 'handle_url_tag(\''.get_base_url(true).'/viewtopic.php?id=$1\')';
-	$replace[] = 'handle_url_tag(\''.get_base_url(true).'/viewtopic.php?id=$1\', \'$2\')';
-	$replace[] = 'handle_url_tag(\''.get_base_url(true).'/viewtopic.php?pid=$1#p$1\')';
-	$replace[] = 'handle_url_tag(\''.get_base_url(true).'/viewtopic.php?pid=$1#p$1\', \'$2\')';
-	$replace[] = 'handle_url_tag(\''.get_base_url(true).'/viewforum.php?id=$1\')';
-	$replace[] = 'handle_url_tag(\''.get_base_url(true).'/viewforum.php?id=$1\', \'$2\')';
-	$replace[] = 'handle_url_tag(\''.get_base_url(true).'/profile.php?id=$1\')';
-	$replace[] = 'handle_url_tag(\''.get_base_url(true).'/profile.php?id=$1\', \'$2\')';
+	$replace_callback[] = 'handle_url_tag(\''.get_base_url(true).'/viewtopic.php?id=.$matches[1]\')';
+	$replace_callback[] = 'handle_url_tag(\''.get_base_url(true).'/viewtopic.php?id=.$matches[1],$matches[2]\')';
+	$replace_callback[] = 'handle_url_tag(\''.get_base_url(true).'/viewtopic.php?pid=.$matches[1].#p.$matches[1]\')';
+	$replace_callback[] = 'handle_url_tag(\''.get_base_url(true).'/viewtopic.php?pid=.$matches[1].#p.$matches[1],$matches[2]\')';
+	$replace_callback[] = 'handle_url_tag(\''.get_base_url(true).'/viewforum.php?id=.$matches[1]\')';
+	$replace_callback[] = 'handle_url_tag(\''.get_base_url(true).'/viewforum.php?id=.$matches[1],$matches[2]\')';
+	$replace_callback[] = 'handle_url_tag(\''.get_base_url(true).'/profile.php?id=.$matches[1]\')';
+	$replace_callback[] = 'handle_url_tag(\''.get_base_url(true).'/profile.php?id=.$matches[1],$matches[2]\')';
 
 	// This thing takes a while! :)
 	$text = preg_replace($pattern, $replace, $text);
-
+	$count = count($pattern_callback);
+	for($i = 0 ; $i < $count ; $i++)
+	{
+		$text = preg_replace_callback($pattern_callback[$i], create_function('$matches', 'return '.$replace_callback[$i].';'), $text);
+	}
 	return $text;
 }
 
@@ -846,9 +849,8 @@ function do_bbcode($text, $is_signature = false)
 function do_clickable($text)
 {
 	$text = ' '.$text;
-
-	$text = ucp_preg_replace('%(?<=[\s\]\)])(<)?(\[)?(\()?([\'"]?)(https?|ftp|news){1}://([\p{L}\p{N}\-]+\.([\p{L}\p{N}\-]+\.)*[\p{L}\p{N}]+(:[0-9]+)?(/(?:[^\s\[]*[^\s.,?!\[;:-])?)?)\4(?(3)(\)))(?(2)(\]))(?(1)(>))(?![^\s]*\[/(?:url|img)\])%uie', 'stripslashes(\'$1$2$3$4\').handle_url_tag(\'$5://$6\', \'$5://$6\', true).stripslashes(\'$4$10$11$12\')', $text);
-	$text = ucp_preg_replace('%(?<=[\s\]\)])(<)?(\[)?(\()?([\'"]?)(www|ftp)\.(([\p{L}\p{N}\-]+\.)+[\p{L}\p{N}]+(:[0-9]+)?(/(?:[^\s\[]*[^\s.,?!\[;:-])?)?)\4(?(3)(\)))(?(2)(\]))(?(1)(>))(?![^\s]*\[/(?:url|img)\])%uie', 'stripslashes(\'$1$2$3$4\').handle_url_tag(\'$5.$6\', \'$5.$6\', true).stripslashes(\'$4$10$11$12\')', $text);
+	$text = ucp_preg_replace_callback('%(?<=[\s\]\)])(<)?(\[)?(\()?([\'"]?)(https?|ftp|news){1}://([\p{L}\p{N}\-]+\.([\p{L}\p{N}\-]+\.)*[\p{L}\p{N}]+(:[0-9]+)?(/(?:[^\s\[]*[^\s.,?!\[;:-])?)?)\4(?(3)(\)))(?(2)(\]))(?(1)(>))(?![^\s]*\[/(?:url|img)\])%ui', 'stripslashes($matches[1].$matches[2].$matches[3].$matches[4]).handle_url_tag($matches[5]."://".$matches[6], $matches[5]."://".$matches[6], true).stripslashes($matches[4].$matches[10].$matches[11].$matches[12])', $text);
+	$text = ucp_preg_replace_callback('%(?<=[\s\]\)])(<)?(\[)?(\()?([\'"]?)(www|ftp)\.(([\p{L}\p{N}\-]+\.)+[\p{L}\p{N}]+(:[0-9]+)?(/(?:[^\s\[]*[^\s.,?!\[;:-])?)?)\4(?(3)(\)))(?(2)(\]))(?(1)(>))(?![^\s]*\[/(?:url|img)\])%ui','stripslashes($matches[1].$matches[2].$matches[3].$matches[4]).handle_url_tag($matches[5].".".$matches[6], $matches[5].".".$matches[6], true).stripslashes($matches[4].$matches[10].$matches[11].$matches[12])', $text);
 
 	return substr($text, 1);
 }
diff --git a/include/srand.php b/include/srand.php
index 8243e2e..e0a8bba 100644
--- a/include/srand.php
+++ b/include/srand.php
@@ -45,11 +45,12 @@ function secure_random_bytes($len = 10)
    $SSLstr = '4'; // http://xkcd.com/221/
    if (function_exists('openssl_random_pseudo_bytes') && 
        (version_compare(PHP_VERSION, '5.3.4') >= 0 || 
-	substr(PHP_OS, 0, 3) !== 'WIN'))
+        substr(PHP_OS, 0, 3) !== 'WIN'))
    {
       $SSLstr = openssl_random_pseudo_bytes($len, $strong);
-      if ($strong)
+      if ($strong) {
          return $SSLstr;
+      }
    }
 
    /*
@@ -57,15 +58,16 @@ function secure_random_bytes($len = 10)
     * the operating system's PRNG. This is better than reading /dev/urandom 
     * directly since it avoids reading larger blocks of data than needed. 
     * Older versions of mcrypt_create_iv may be broken or take too much time 
-    * to finish so we only use this function with PHP 5.3 and above.
+    * to finish so we only use this function with PHP 5.3.7 and above.
+    * @see https://bugs.php.net/bug.php?id=55169
     */
    if (function_exists('mcrypt_create_iv') && 
-      (version_compare(PHP_VERSION, '5.3.0') >= 0 || 
-       substr(PHP_OS, 0, 3) !== 'WIN')) 
-   {
+      (version_compare(PHP_VERSION, '5.3.7') >= 0 || 
+       substr(PHP_OS, 0, 3) !== 'WIN')) {
       $str = mcrypt_create_iv($len, MCRYPT_DEV_URANDOM);
-      if ($str !== false)
-         return $str;	
+      if ($str !== false) {
+         return $str;
+      }
    }
 
 
@@ -82,9 +84,10 @@ function secure_random_bytes($len = 10)
    $hash_len = 20; // SHA-1 Hash length
    $total = $len; // total bytes of entropy to collect
 
-   $handle = @fopen('/dev/urandom', 'rb');   
-   if ($handle && function_exists('stream_set_read_buffer'))
+   $handle = @fopen('/dev/urandom', 'rb');
+   if ($handle && function_exists('stream_set_read_buffer')) {
       @stream_set_read_buffer($handle, 0);
+   }
 
    do
    {
@@ -94,52 +97,54 @@ function secure_random_bytes($len = 10)
       //collect any entropy available from the PHP system and filesystem
       $entropy = rand() . uniqid(mt_rand(), true) . $SSLstr;
       $entropy .= implode('', @fstat(@fopen( __FILE__, 'r')));
-      $entropy .= memory_get_usage();
-      if ($handle) 
-      {
-         $entropy .= @fread($handle, $bytes);
+      $entropy .= memory_get_usage() . getmypid();
+      $entropy .= serialize($_ENV) . serialize($_SERVER);
+      if (function_exists('posix_times')) {
+        $entropy .= serialize(posix_times());
+      }
+      if (function_exists('zend_thread_id')) {
+        $entropy .= zend_thread_id();
       }
-      else
-      {	           	
+      if ($handle) {
+         $entropy .= @fread($handle, $bytes);
+      } else  {
          // Measure the time that the operations will take on average
-         for ($i = 0; $i < 3; $i ++) 
+         for ($i = 0; $i < 3; $i++) 
          {
-            $c1 = microtime(true);
+            $c1 = get_microtime();
             $var = sha1(mt_rand());
-            for ($j = 0; $j < 50; $j++)
-            {
+            for ($j = 0; $j < 50; $j++) {
                $var = sha1($var);
             }
-            $c2 = microtime(true);
-    	    $entropy .= $c1 . $c2;
+            $c2 = get_microtime();
+            $entropy .= $c1 . $c2;
          }
 
          // Based on the above measurement determine the total rounds
-         // in order to bound the total running time.	
-         $rounds = (int)($msec_per_round*50 / (int)(($c2-$c1)*1000000));
+         // in order to bound the total running time.
+         $rounds = (int) ($msec_per_round * 50 / (int) (($c2 - $c1) * 1000000));
 
          // Take the additional measurements. On average we can expect
          // at least $bits_per_round bits of entropy from each measurement.
-         $iter = $bytes*(int)(ceil(8 / $bits_per_round));
-         for ($i = 0; $i < $iter; $i ++)
+         $iter = $bytes * (int) (ceil(8 / $bits_per_round));
+         for ($i = 0; $i < $iter; $i++)
          {
-            $c1 = microtime();
+            $c1 = get_microtime();
             $var = sha1(mt_rand());
-            for ($j = 0; $j < $rounds; $j++)
-            {
+            for ($j = 0; $j < $rounds; $j++) {
                $var = sha1($var);
             }
-            $c2 = microtime();
+            $c2 = get_microtime();
             $entropy .= $c1 . $c2;
          }
-            
-      } 
+
+      }
       // We assume sha1 is a deterministic extractor for the $entropy variable.
       $str .= sha1($entropy, true);
    } while ($len > strlen($str));
-   
-   if ($handle) 
+
+   if ($handle) {
       @fclose($handle);
-   
+   }
    return substr($str, 0, $len);
-}
\ No newline at end of file
+}
diff --git a/index.php b/index.php
index 0f257ac..5a6a9a0 100644
--- a/index.php
+++ b/index.php
@@ -185,7 +185,7 @@ if (!defined('PUN_USERS_INFO_LOADED'))
 }
 
 $result = $db->query('SELECT SUM(num_topics), SUM(num_posts) FROM '.$db->prefix.'forums') or error('Unable to fetch topic/post count', __FILE__, __LINE__, $db->error());
-list($stats['total_topics'], $stats['total_posts']) = $db->fetch_row($result);
+list($stats['total_topics'], $stats['total_posts']) = array_map('intval', $db->fetch_row($result));
 
 if ($pun_user['g_view_users'] == '1')
 	$stats['newest_user'] = '<a href="profile.php?id='.$stats['last_user']['id'].'">'.pun_htmlspecialchars($stats['last_user']['username']).'</a>';
diff --git a/install.php b/install.php
index 0a459c3..20eb0f3 100644
--- a/install.php
+++ b/install.php
@@ -7,9 +7,9 @@
  */
 
 // The FluxBB version this script installs
-define('FORUM_VERSION', '1.5.3');
+define('FORUM_VERSION', '1.5.4');
 
-define('FORUM_DB_REVISION', 18);
+define('FORUM_DB_REVISION', 20);
 define('FORUM_SI_REVISION', 2);
 define('FORUM_PARSER_REVISION', 2);
 
@@ -22,6 +22,9 @@ define('PUN_SEARCH_MAX_WORD', 20);
 
 define('PUN_ROOT', dirname(__FILE__).'/');
 
+// Send the Content-type header in case the web server is setup to send something else
+header('Content-type: text/html; charset=utf-8');
+
 // Load the functions script
 require PUN_ROOT.'include/functions.php';
 
@@ -294,7 +297,7 @@ function process_form(the_form)
 	<div class="box">
 		<div id="brdtitle" class="inbox">
 			<h1><span><?php echo $lang_install['FluxBB Installation'] ?></span></h1>
-			<div id="brddesc"><p><?php echo $lang_install['Install message'] ?></p><p><?php echo $lang_install['Welcome'] ?></p></div>
+			<div id="brddesc"><p><?php echo $lang_install['Welcome'] ?></p></div>
 		</div>
 	</div>
 </div>
@@ -359,9 +362,7 @@ foreach ($alerts as $cur_alert)
 				<legend><?php echo $lang_install['Select database'] ?></legend>
 					<div class="infldset">
 						<p><?php echo $lang_install['Info 2'] ?></p>
-<?php if ($dual_mysql): ?>						<p><?php echo $lang_install['Dual MySQL'] ?></p>
-<?php endif; ?><?php if ($mysql_innodb): ?>						<p><?php echo $lang_install['InnoDB'] ?></p>
-<?php endif; ?>						<label class="required"><strong><?php echo $lang_install['Database type'] ?> <span><?php echo $lang_install['Required'] ?></span></strong>
+						<label class="required"><strong><?php echo $lang_install['Database type'] ?> <span><?php echo $lang_install['Required'] ?></span></strong>
 						<br /><select name="req_db_type">
 <?php
 
@@ -423,29 +424,13 @@ foreach ($alerts as $cur_alert)
 					<p><?php echo $lang_install['Info 7'] ?></p>
 				</div>
 				<fieldset>
-					<legend><?php echo $lang_install['Admin enter username'] ?></legend>
+					<legend><?php echo $lang_install['Administration setup'] ?></legend>
 					<div class="infldset">
 						<p><?php echo $lang_install['Info 8'] ?></p>
 						<label class="required"><strong><?php echo $lang_install['Administrator username'] ?> <span><?php echo $lang_install['Required'] ?></span></strong><br /><input type="text" name="req_username" value="<?php echo pun_htmlspecialchars($username) ?>" size="25" maxlength="25" /><br /></label>
-					</div>
-				</fieldset>
-			</div>
-			<div class="inform">
-				<fieldset>
-					<legend><?php echo $lang_install['Admin enter password'] ?></legend>
-					<div class="infldset">
-						<p><?php echo $lang_install['Info 9'] ?></p>
 						<label class="conl required"><strong><?php echo $lang_install['Password'] ?> <span><?php echo $lang_install['Required'] ?></span></strong><br /><input id="req_password1" type="password" name="req_password1" size="16" /><br /></label>
 						<label class="conl required"><strong><?php echo $lang_install['Confirm password'] ?> <span><?php echo $lang_install['Required'] ?></span></strong><br /><input type="password" name="req_password2" size="16" /><br /></label>
 						<div class="clearer"></div>
-					</div>
-				</fieldset>
-			</div>
-			<div class="inform">
-				<fieldset>
-					<legend><?php echo $lang_install['Admin enter email'] ?></legend>
-					<div class="infldset">
-						<p><?php echo $lang_install['Info 10'] ?></p>
 						<label class="required"><strong><?php echo $lang_install['Administrator email'] ?> <span><?php echo $lang_install['Required'] ?></span></strong><br /><input id="req_email" type="text" name="req_email" value="<?php echo pun_htmlspecialchars($email) ?>" size="50" maxlength="80" /><br /></label>
 					</div>
 				</fieldset>
@@ -456,34 +441,17 @@ foreach ($alerts as $cur_alert)
 					<p><?php echo $lang_install['Info 11'] ?></p>
 				</div>
 				<fieldset>
-					<legend><?php echo $lang_install['Enter board title'] ?></legend>
+					<legend><?php echo $lang_install['General information'] ?></legend>
 					<div class="infldset">
-						<p><?php echo $lang_install['Info 12'] ?></p>
 						<label class="required"><strong><?php echo $lang_install['Board title'] ?> <span><?php echo $lang_install['Required'] ?></span></strong><br /><input id="req_title" type="text" name="req_title" value="<?php echo pun_htmlspecialchars($title) ?>" size="60" maxlength="255" /><br /></label>
-					</div>
-				</fieldset>
-			</div>
-			<div class="inform">
-				<fieldset>
-					<legend><?php echo $lang_install['Enter board description'] ?></legend>
-					<div class="infldset">
-						<p><?php echo $lang_install['Info 13'] ?></p>
 						<label><?php echo $lang_install['Board description'] ?><br /><input id="desc" type="text" name="desc" value="<?php echo pun_htmlspecialchars($description) ?>" size="60" maxlength="255" /><br /></label>
-					</div>
-				</fieldset>
-			</div>
-			<div class="inform">
-				<fieldset>
-					<legend><?php echo $lang_install['Enter base URL'] ?></legend>
-					<div class="infldset">
-						<p><?php echo $lang_install['Info 14'] ?></p>
 						<label class="required"><strong><?php echo $lang_install['Base URL'] ?> <span><?php echo $lang_install['Required'] ?></span></strong><br /><input id="req_base_url" type="text" name="req_base_url" value="<?php echo pun_htmlspecialchars($base_url) ?>" size="60" maxlength="100" /><br /></label>
 					</div>
 				</fieldset>
 			</div>
 			<div class="inform">
 				<fieldset>
-					<legend><?php echo $lang_install['Choose the default language'] ?></legend>
+					<legend><?php echo $lang_install['Appearance'] ?></legend>
 					<div class="infldset">
 						<p><?php echo $lang_install['Info 15'] ?></p>
 						<label class="required"><strong><?php echo $lang_install['Default language'] ?> <span><?php echo $lang_install['Required'] ?></span></strong><br /><select id="req_default_lang" name="req_default_lang">
@@ -500,14 +468,6 @@ foreach ($alerts as $cur_alert)
 
 ?>
 						</select><br /></label>
-					</div>
-				</fieldset>
-			</div>
-			<div class="inform">
-				<fieldset>
-					<legend><?php echo $lang_install['Choose the default style'] ?></legend>
-					<div class="infldset">
-						<p><?php echo $lang_install['Info 16'] ?></p>
 						<label class="required"><strong><?php echo $lang_install['Default style'] ?> <span><?php echo $lang_install['Required'] ?></span></strong><br /><select id="req_default_style" name="req_default_style">
 <?php
 
diff --git a/lang/English/admin_options.php b/lang/English/admin_options.php
index 78962e9..bed8177 100644
--- a/lang/English/admin_options.php
+++ b/lang/English/admin_options.php
@@ -23,6 +23,7 @@ $lang_admin_options = array(
 'Board desc help'					=>	'A short description of this bulletin board (shown at the top of every page). This field may contain HTML.',
 'Base URL label'					=>	'Base URL',
 'Base URL help'						=>	'The complete URL of the board without trailing slash (i.e. http://www.mydomain.com/forums). This <strong>must</strong> be correct in order for all admin and moderator features to work. If you get "Bad referer" errors, it\'s probably incorrect.',
+'Base URL problem'          =>  'Your installation does not support automatic conversion of internationalized domain names. As your base URL contains special characters, you <strong>must</strong> use an online converter in order to avoid "Bad referer" errors.',
 'Timezone label'					=>	'Default time zone',
 'Timezone help'						=>	'The default time zone for guests and users attempting to register for the board.',
 'DST label'							=>	'Adjust for DST',
@@ -115,8 +116,8 @@ $lang_admin_options = array(
 
 // Features section
 'Features subhead'					=>	'Features',
-'Quick post label'					=>	'Quick post',
-'Quick post help'					=>	'When enabled, FluxBB will add a quick post form at the bottom of topics. This way users can post directly from the topic view.',
+'Quick post label'					=>	'Quick reply',
+'Quick post help'					=>	'When enabled, FluxBB will add a quick reply form at the bottom of topics. This way users can post directly from the topic view.',
 'Users online label'				=>	'Users online',
 'Users online help'					=>	'Display info on the index page about guests and registered users currently browsing the board.',
 'Censor words label'				=>	'Censor words',
diff --git a/lang/English/admin_users.php b/lang/English/admin_users.php
index 9da2095..66280b7 100644
--- a/lang/English/admin_users.php
+++ b/lang/English/admin_users.php
@@ -47,7 +47,7 @@ $lang_admin_users = array(
 'Website label'				=>	'Website',
 'Jabber label'				=>	'Jabber',
 'ICQ label'					=>	'ICQ',
-'MSN label'					=>	'MSN Messenger',
+'MSN label'					=>	'Microsoft Account',
 'AOL label'					=>	'AOL IM',
 'Yahoo label'				=>	'Yahoo Messenger',
 'Location label'			=>	'Location',
diff --git a/lang/English/install.php b/lang/English/install.php
index e14a177..b79c4b0 100644
--- a/lang/English/install.php
+++ b/lang/English/install.php
@@ -4,7 +4,6 @@
 
 $lang_install = array(
 
-'Install message'				=>	'The file \'config.php\' doesn\'t exist or is corrupt. This implies that FluxBB has not yet been installed.',
 'Choose install language'		=>	'Choose the install script language',
 'Choose install language info'	=>	'The language used for this install script. The default language used for the board itself can be set below.',
 'Install language'				=>	'Install language',
@@ -32,57 +31,44 @@ $lang_install = array(
 'Administrator password 2'		=>	'Administrator password 2',
 'Administrator email'			=>	'Administrator\'s email',
 'Board title'					=>	'Board title',
-'Base URL'						=>	'Base URL',
+'Base URL'						=>	'The URL (without trailing slash) of your FluxBB forum. This must be correct.',
 'Required field'				=>	'is a required field in this form.',
 'FluxBB Installation'			=>	'FluxBB Installation',
 'Welcome'						=>	'You are about to install FluxBB. In order to install FluxBB, you must complete the form set out below. If you encounter any difficulties with the installation, please refer to the documentation.',
 'Install'						=>	'Install FluxBB %s',
 'Errors'						=>	'The following errors need to be corrected:',
 'Database setup'				=>	'Database setup',
-'Info 1'						=>	'Please enter the requested information in order to setup your database for FluxBB. You must know all the information asked for before proceeding with the installation.',
+'Info 1'						=>	'All information we need to create a connection with your database.',
 'Select database'				=>	'Select your database type',
-'Info 2'						=>	'FluxBB currently supports MySQL, PostgreSQL and SQLite. If your database of choice is missing from the drop-down menu below, it means this PHP environment does not have support for that particular database. More information regarding support for particular versions of each database can be found in the FAQ.',
-'Dual MySQL'					=>	'FluxBB has detected that your PHP environment supports two different ways of communicating with MySQL. The two options are called standard and improved. If you are uncertain which one to use, start by trying improved and if that fails, try standard.',
-'InnoDB'						=>	'FluxBB has detected that your MySQL server might support <a href="http://dev.mysql.com/doc/refman/5.0/en/innodb.html">InnoDB</a>. This would be a good choice if you are planning to run a large forum. If you are uncertain, it is recommended that you do not use InnoDB.',
+'Info 2'						=>	'Select a database. We support SQLite, MySQL and PostgreSQL.',
 'Database type'					=>	'Database type',
 'Required'						=>	'(Required)',
 'Database hostname'				=>	'Enter your database server hostname',
-'Info 3'						=>	'The address of the database server (example: localhost, db.myhost.com or 192.168.0.15). You can specify a custom port number if your database doesn\'t run on the default port (example: localhost:3580). For SQLite support, just enter anything or leave it at \'localhost\'.',
-'Database server hostname'		=>'Database server hostname',
+'Info 3'						=>	'You should be able to get this info from your web host, if <code>localhost</code> does not work.',
+'Database server hostname'		=>	'Database server hostname',
 'Database enter name'			=>	'Enter the name of your database',
-'Info 4'						=>	'The name of the database that FluxBB will be installed into. The database must exist. For SQLite, this is the relative path to the database file. For security reasons, it is highly recommended to place the SQLite database in a private (not web accessible) directory whenever possible. If the SQLite database file does not exist, FluxBB will attempt to create it.',
+'Info 4'						=>	'The name of the database you want to install FluxBB on.',
 'Database name'					=>	'Database name',
 'Database enter informations'	=>	'Enter your database username and password',
 'Database username'				=>	'Database username',
-'Info 5'						=>	'Enter the username and password with which you connect to the database. Ignore for SQLite.',
+'Info 5'						=>	'Your MySQL username and password (ignore of SQLite).',
 'Database password'				=>	'Database password',
 'Database enter prefix'			=>	'Enter database table prefix',
-'Info 6'						=>	'If you like, you can specify a table prefix. This way you can run multiple copies of FluxBB in the same database (example: foo_).',
+'Info 6'						=>	'If you want to run multiple FluxBB installations in a single database, change this.',
 'Table prefix'					=>	'Table prefix',
 'Administration setup'			=>	'Administration setup',
-'Info 7'						=>	'Please enter the requested information in order to setup an administrator for your FluxBB installation.',
-'Admin enter username'			=>	'Enter Administrator\'s username',
-'Info 8'						=>	'The username of the forum administrator. You can later create more administrators and moderators. Usernames can be between 2 and 25 characters long.',
-'Admin enter password'			=>	'Enter and confirm Administrator\'s password',
-'Info 9'						=>	'Passwords must be at least 4 characters long. Passwords are case sensitive.',
+'Info 7'						=>	'Create the very first account on your board.',
+'Info 8'						=>	'Your username should be between 2 and 25 characters long. Your password must be at least 4 characters long. Remember that passwords are case-sensitive.',
 'Password'						=>	'Password',
 'Confirm password'				=>	'Confirm password',
-'Admin enter email'				=>	'Enter Administrator\'s email',
-'Info 10'						=>	'The email address of the forum administrator.',
 'Board setup'					=>	'Board setup',
-'Info 11'						=>	'Please enter the requested information in order to setup your FluxBB board.',
-'Enter board title'				=>	'Enter your board\'s title',
-'Info 12'						=>	'The title of this bulletin board (shown at the top of every page).',
-'Enter board description'		=>	'Enter your board\'s description',
-'Info 13'						=>	'A short description of this bulletin board (shown at the top of every page). This field may contain HTML.',
-'Board description'				=>	'Board description',
-'Enter base URL'				=>	'Enter the Base URL of your FluxBB installation',
-'Info 14'						=>	'The URL (without trailing slash) of your FluxBB forum (example: http://forum.myhost.com or http://myhost.com/~myuser). This <strong>must</strong> be correct, otherwise, administrators and moderators will not be able to submit any forms. Please note that the preset value below is just an educated guess by FluxBB.',
-'Choose the default language'	=>	'Choose the default language',
-'Info 15'						=>	'The default language used for guests and users who haven\'t changed from the default in their profile.',
+'Info 11'						=>	'Settings for your board. You can change this later.',
+'General information'			=>	'Enter your board\'s title and description.',
+'Board description'				=>	'Board description (supports HTML)',
+'Info 14'						=>	'The URL (without trailing slash) of your FluxBB forum (example: http://forum.myhost.com). This must be correct. Please note that the preset value below is just an educated guess by FluxBB.',
+'Appearance'					=>	'Appearance',
+'Info 15'						=>	'Make your forum yours. Choose a language and a style for your board.',
 'Default language'				=>	'Default language',
-'Choose the default style'		=>	'Choose the default style',
-'Info 16'						=>	'The default style used for guests and users who haven\'t changed from the default in their profile.',
 'Default style'					=>	'Default style',
 'Start install'					=>	'Start install',
 'DB type not valid'				=>	'\'%s\' is not a valid database type',
diff --git a/lang/English/profile.php b/lang/English/profile.php
index bca8141..c9e63c2 100644
--- a/lang/English/profile.php
+++ b/lang/English/profile.php
@@ -85,7 +85,7 @@ $lang_profile = array(
 'Website not allowed'			=>	'You are not allowed to add a website to your profile yet.',
 'Jabber'						=>	'Jabber',
 'ICQ'							=>	'ICQ',
-'MSN'							=>	'MSN Messenger',
+'MSN'							=>	'Microsoft Account',
 'AOL IM'						=>	'AOL IM',
 'Yahoo'							=>	'Yahoo! Messenger',
 'Avatar'						=>	'Avatar',
diff --git a/lang/English/topic.php b/lang/English/topic.php
index 77860a9..fd28982 100644
--- a/lang/English/topic.php
+++ b/lang/English/topic.php
@@ -23,7 +23,7 @@ $lang_topic = array(
 'Is subscribed'		=>	'You are currently subscribed to this topic',
 'Unsubscribe'		=>	'Unsubscribe',
 'Subscribe'			=>	'Subscribe to this topic',
-'Quick post'		=>	'Quick post',
+'Quick post'		=>	'Quick reply',
 'Mod controls'		=>	'Moderator controls',
 'New icon'			=>	'New post',
 'Re'				=>	'Re:',
diff --git a/login.php b/login.php
index d41accd..4d4683e 100644
--- a/login.php
+++ b/login.php
@@ -168,7 +168,7 @@ else if ($action == 'forget' || $action == 'forget_2')
 					pun_mail($email, $mail_subject, $cur_mail_message);
 				}
 
-				message($lang_login['Forget mail'].' <a href="mailto:'.$pun_config['o_admin_email'].'">'.$pun_config['o_admin_email'].'</a>.', true);
+				message($lang_login['Forget mail'].' <a href="mailto:'.pun_htmlspecialchars($pun_config['o_admin_email']).'">'.pun_htmlspecialchars($pun_config['o_admin_email']).'</a>.', true);
 			}
 			else
 				$errors[] = $lang_login['No email match'].' '.htmlspecialchars($email).'.';
diff --git a/misc.php b/misc.php
index 98e062b..90891ce 100644
--- a/misc.php
+++ b/misc.php
@@ -99,6 +99,8 @@ else if (isset($_GET['email']))
 
 	if (isset($_POST['form_sent']))
 	{
+		confirm_referrer('misc.php');
+
 		// Clean up message and subject from POST
 		$subject = pun_trim($_POST['req_subject']);
 		$message = pun_trim($_POST['req_message']);
diff --git a/moderate.php b/moderate.php
index b56115c..9c7b3cc 100644
--- a/moderate.php
+++ b/moderate.php
@@ -90,7 +90,8 @@ if (isset($_GET['tid']))
 				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());
+			$admins_sql = ($pun_user['g_id'] != PUN_ADMIN) ? ' AND poster_id NOT IN('.implode(',', get_admin_ids()).')' : ''; 
+			$result = $db->query('SELECT 1 FROM '.$db->prefix.'posts WHERE id IN('.$posts.') AND topic_id='.$tid.$admins_sql) or error('Unable to check posts', __FILE__, __LINE__, $db->error());
 
 			if ($db->num_rows($result) != substr_count($posts, ',') + 1)
 				message($lang_common['Bad request']);
@@ -666,6 +667,14 @@ else if (isset($_POST['delete_topics']) || isset($_POST['delete_topics_comply'])
 		if ($db->num_rows($result) != substr_count($topics, ',') + 1)
 			message($lang_common['Bad request']);
 
+		// Verify that the posts are not by admins
+		if ($pun_user['g_id'] != PUN_ADMIN)
+		{
+			$result = $db->query('SELECT 1 FROM '.$db->prefix.'posts WHERE topic_id IN('.$topics.') AND poster_id IN('.implode(',', get_admin_ids()).')') or error('Unable to check posts', __FILE__, __LINE__, $db->error());
+			if ($db->num_rows($result))
+				message($lang_common['No permission'], false, '403 Forbidden');
+		}
+
 		// 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());
 
diff --git a/profile.php b/profile.php
index 5573126..fda07a1 100644
--- a/profile.php
+++ b/profile.php
@@ -52,7 +52,7 @@ if ($action == 'change_pass')
 		$cur_user = $db->fetch_assoc($result);
 
 		if ($key == '' || $key != $cur_user['activate_key'])
-			message($lang_profile['Pass key bad'].' <a href="mailto:'.$pun_config['o_admin_email'].'">'.$pun_config['o_admin_email'].'</a>.');
+			message($lang_profile['Pass key bad'].' <a href="mailto:'.pun_htmlspecialchars($pun_config['o_admin_email']).'">'.pun_htmlspecialchars($pun_config['o_admin_email']).'</a>.');
 		else
 		{
 			$db->query('UPDATE '.$db->prefix.'users SET password=\''.$cur_user['activate_string'].'\', activate_string=NULL, activate_key=NULL'.(!empty($cur_user['salt']) ? ', salt=NULL' : '').' WHERE id='.$id) or error('Unable to update password', __FILE__, __LINE__, $db->error());
@@ -183,7 +183,7 @@ else if ($action == 'change_email')
 		list($new_email, $new_email_key) = $db->fetch_row($result);
 
 		if ($key == '' || $key != $new_email_key)
-			message($lang_profile['Email key bad'].' <a href="mailto:'.$pun_config['o_admin_email'].'">'.$pun_config['o_admin_email'].'</a>.');
+			message($lang_profile['Email key bad'].' <a href="mailto:'.pun_htmlspecialchars($pun_config['o_admin_email']).'">'.pun_htmlspecialchars($pun_config['o_admin_email']).'</a>.');
 		else
 		{
 			$db->query('UPDATE '.$db->prefix.'users SET email=activate_string, activate_string=NULL, activate_key=NULL WHERE id='.$id) or error('Unable to update email address', __FILE__, __LINE__, $db->error());
@@ -275,7 +275,7 @@ else if ($action == 'change_email')
 
 		pun_mail($new_email, $mail_subject, $mail_message);
 
-		message($lang_profile['Activate email sent'].' <a href="mailto:'.$pun_config['o_admin_email'].'">'.$pun_config['o_admin_email'].'</a>.', true);
+		message($lang_profile['Activate email sent'].' <a href="mailto:'.pun_htmlspecialchars($pun_config['o_admin_email']).'">'.pun_htmlspecialchars($pun_config['o_admin_email']).'</a>.', true);
 	}
 
 	$page_title = array(pun_htmlspecialchars($pun_config['o_board_title']), $lang_common['Profile'], $lang_profile['Change email']);
@@ -368,7 +368,7 @@ else if ($action == 'upload_avatar' || $action == 'upload_avatar2')
 
 			// Move the file to the avatar directory. We do this before checking the width/height to circumvent open_basedir restrictions
 			if (!@move_uploaded_file($uploaded_file['tmp_name'], PUN_ROOT.$pun_config['o_avatars_dir'].'/'.$id.'.tmp'))
-				message($lang_profile['Move failed'].' <a href="mailto:'.$pun_config['o_admin_email'].'">'.$pun_config['o_admin_email'].'</a>.');
+				message($lang_profile['Move failed'].' <a href="mailto:'.pun_htmlspecialchars($pun_config['o_admin_email']).'">'.pun_htmlspecialchars($pun_config['o_admin_email']).'</a>.');
 
 			list($width, $height, $type,) = @getimagesize(PUN_ROOT.$pun_config['o_avatars_dir'].'/'.$id.'.tmp');
 
@@ -458,6 +458,9 @@ else if (isset($_POST['update_group_membership']))
 
 	$new_group_id = intval($_POST['group_id']);
 
+	$result = $db->query('SELECT group_id FROM '.$db->prefix.'users WHERE id='.$id) or error('Unable to fetch user group', __FILE__, __LINE__, $db->error());
+	$old_group_id = $db->result($result);
+
 	$db->query('UPDATE '.$db->prefix.'users SET group_id='.$new_group_id.' WHERE id='.$id) or error('Unable to change user group', __FILE__, __LINE__, $db->error());
 
 	// Regenerate the users info cache
@@ -466,6 +469,9 @@ else if (isset($_POST['update_group_membership']))
 
 	generate_users_info_cache();
 
+	if ($old_group_id == PUN_ADMIN || $new_group_id == PUN_ADMIN)
+		generate_admins_cache();
+
 	$result = $db->query('SELECT g_moderator FROM '.$db->prefix.'groups WHERE g_id='.$new_group_id) or error('Unable to fetch group', __FILE__, __LINE__, $db->error());
 	$new_group_mod = $db->result($result);
 
@@ -640,6 +646,9 @@ else if (isset($_POST['delete_user']) || isset($_POST['delete_user_comply']))
 
 		generate_users_info_cache();
 
+		if ($group_id == PUN_ADMIN)
+			generate_admins_cache();
+
 		redirect('index.php', $lang_profile['User delete redirect']);
 	}
 
@@ -1041,7 +1050,7 @@ if ($pun_user['id'] != $id &&																	// If we aren't the user (i.e. edi
 	}
 
 	if ($user['email_setting'] == '0' && !$pun_user['is_guest'] && $pun_user['g_send_email'] == '1')
-		$email_field = '<a href="mailto:'.$user['email'].'">'.$user['email'].'</a>';
+		$email_field = '<a href="mailto:'.pun_htmlspecialchars($user['email']).'">'.pun_htmlspecialchars($user['email']).'</a>';
 	else if ($user['email_setting'] == '1' && !$pun_user['is_guest'] && $pun_user['g_send_email'] == '1')
 		$email_field = '<a href="misc.php?email='.$id.'">'.$lang_common['Send email'].'</a>';
 	else
@@ -1212,14 +1221,14 @@ else
 			else
 				$username_field = '<p>'.sprintf($lang_profile['Username info'], pun_htmlspecialchars($user['username'])).'</p>'."\n";
 
-			$email_field = '<label class="required"><strong>'.$lang_common['Email'].' <span>'.$lang_common['Required'].'</span></strong><br /><input type="text" name="req_email" value="'.$user['email'].'" size="40" maxlength="80" /><br /></label><p><span class="email"><a href="misc.php?email='.$id.'">'.$lang_common['Send email'].'</a></span></p>'."\n";
+			$email_field = '<label class="required"><strong>'.$lang_common['Email'].' <span>'.$lang_common['Required'].'</span></strong><br /><input type="text" name="req_email" value="'.pun_htmlspecialchars($user['email']).'" size="40" maxlength="80" /><br /></label><p><span class="email"><a href="misc.php?email='.$id.'">'.$lang_common['Send email'].'</a></span></p>'."\n";
 		}
 		else
 		{
 			$username_field = '<p>'.$lang_common['Username'].': '.pun_htmlspecialchars($user['username']).'</p>'."\n";
 
 			if ($pun_config['o_regs_verify'] == '1')
-				$email_field = '<p>'.sprintf($lang_profile['Email info'], $user['email'].' - <a href="profile.php?action=change_email&id='.$id.'">'.$lang_profile['Change email'].'</a>').'</p>'."\n";
+				$email_field = '<p>'.sprintf($lang_profile['Email info'], pun_htmlspecialchars($user['email']).' - <a href="profile.php?action=change_email&id='.$id.'">'.$lang_profile['Change email'].'</a>').'</p>'."\n";
 			else
 				$email_field = '<label class="required"><strong>'.$lang_common['Email'].' <span>'.$lang_common['Required'].'</span></strong><br /><input type="text" name="req_email" value="'.$user['email'].'" size="40" maxlength="80" /><br /></label>'."\n";
 		}
diff --git a/readme.md b/readme.md
new file mode 100644
index 0000000..bf844de
--- /dev/null
+++ b/readme.md
@@ -0,0 +1,28 @@
+# FluxBB 1.5 Readme
+
+## About
+
+FluxBB is an open source forum application released under the GNU General Public
+Licence. It is free to download and use and will remain so. FluxBB was conceived and
+designed to be fast and light with less of the "not so essential" features that some
+of the other forums have whilst not sacrificing essential functionality or usability.
+
+## Requirements
+
+* A webserver
+* PHP 4.4.0 or later
+* A database such as MySQL 4.1.2 or later, PostgreSQL 7.0 or later, or SQLite 2
+
+## Recommendations
+
+* Make use of a PHP accelerator such as APC or XCache
+* Make sure PHP has the zlib module installed to allow FluxBB to gzip output
+
+## Links
+
+* Homepage: http://fluxbb.org
+* Documentation: http://fluxbb.org/docs/v1.5
+* Community: http://fluxbb.org/forums/
+* Resources: http://fluxbb.org/resources/
+* IRC: irc://irc.freenode.net/fluxbb
+* Development: http://github.com/fluxbb/fluxbb
\ No newline at end of file
diff --git a/register.php b/register.php
index 50f9bb6..306f5f6 100644
--- a/register.php
+++ b/register.php
@@ -244,7 +244,7 @@ if (isset($_POST['form_sent']))
 
 			pun_mail($email1, $mail_subject, $mail_message);
 
-			message($lang_register['Reg email'].' <a href="mailto:'.$pun_config['o_admin_email'].'">'.$pun_config['o_admin_email'].'</a>.', true);
+			message($lang_register['Reg email'].' <a href="mailto:'.pun_htmlspecialchars($pun_config['o_admin_email']).'">'.pun_htmlspecialchars($pun_config['o_admin_email']).'</a>.', true);
 		}
 
 		// Regenerate the users info cache
diff --git a/style/Air.css b/style/Air.css
index cd0a33b..504698c 100644
--- a/style/Air.css
+++ b/style/Air.css
@@ -964,8 +964,7 @@ MAIN POSTS
 }
 
 .pun .codebox pre {
-	overflow-y:hidden;
-	overflow: auto;
+	overflow: hidden;
 	width: 100%;
 	direction: ltr;
 	text-align: left;
diff --git a/style/Earth.css b/style/Earth.css
index 834b80a..e80a52d 100644
--- a/style/Earth.css
+++ b/style/Earth.css
@@ -963,8 +963,7 @@ MAIN POSTS
 }
 
 .pun .codebox pre {
-	overflow-y:hidden;
-	overflow: auto;
+	overflow: hidden;
 	width: 100%;
 	direction: ltr;
 	text-align: left;
diff --git a/style/Fire.css b/style/Fire.css
index 3ba260a..1a1a0e1 100644
--- a/style/Fire.css
+++ b/style/Fire.css
@@ -963,8 +963,7 @@ MAIN POSTS
 }
 
 .pun .codebox pre {
-	overflow-y:hidden;
-	overflow: auto;
+	overflow: hidden;
 	width: 100%;
 	direction: ltr;
 	text-align: left;
diff --git a/viewtopic.php b/viewtopic.php
index ac78cad..3562021 100644
--- a/viewtopic.php
+++ b/viewtopic.php
@@ -92,6 +92,8 @@ $cur_topic = $db->fetch_assoc($result);
 // Sort out who the moderators are and if we are currently a moderator (or an admin)
 $mods_array = ($cur_topic['moderators'] != '') ? unserialize($cur_topic['moderators']) : array();
 $is_admmod = ($pun_user['g_id'] == PUN_ADMIN || ($pun_user['g_moderator'] == '1' && array_key_exists($pun_user['username'], $mods_array))) ? true : false;
+if ($is_admmod)
+	$admin_ids = get_admin_ids();
 
 // Handle clicking on solve links
 if (isset($_GET['solved']) && !$pun_user['is_guest'])
@@ -330,7 +332,7 @@ while ($cur_post = $db->fetch_assoc($result))
 
 			// Now let's deal with the contact links (Email and URL)
 			if ((($cur_post['email_setting'] == '0' && !$pun_user['is_guest']) || $pun_user['is_admmod']) && $pun_user['g_send_email'] == '1')
-				$user_contacts[] = '<span class="email"><a href="mailto:'.$cur_post['email'].'">'.$lang_common['Email'].'</a></span>';
+				$user_contacts[] = '<span class="email"><a href="mailto:'.pun_htmlspecialchars($cur_post['email']).'">'.$lang_common['Email'].'</a></span>';
 			else if ($cur_post['email_setting'] == '1' && !$pun_user['is_guest'] && $pun_user['g_send_email'] == '1')
 				$user_contacts[] = '<span class="email"><a href="misc.php?email='.$cur_post['poster_id'].'">'.$lang_common['Email'].'</a></span>';
 
@@ -361,7 +363,7 @@ while ($cur_post = $db->fetch_assoc($result))
 			$user_info[] = '<dd><span><a href="moderate.php?get_host='.$cur_post['id'].'" title="'.pun_htmlspecialchars($cur_post['poster_ip']).'">'.$lang_topic['IP address logged'].'</a></span></dd>';
 
 		if ($pun_config['o_show_user_info'] == '1' && $cur_post['poster_email'] != '' && !$pun_user['is_guest'] && $pun_user['g_send_email'] == '1')
-			$user_contacts[] = '<span class="email"><a href="mailto:'.$cur_post['poster_email'].'">'.$lang_common['Email'].'</a></span>';
+			$user_contacts[] = '<span class="email"><a href="mailto:'.pun_htmlspecialchars($cur_post['poster_email']).'">'.$lang_common['Email'].'</a></span>';
 	}
 
 	// Generation post action array (quote, edit, delete etc.)
@@ -387,8 +389,11 @@ while ($cur_post = $db->fetch_assoc($result))
 	else
 	{
 		$post_actions[] = '<li class="postreport"><span><a href="misc.php?report='.$cur_post['id'].'">'.$lang_topic['Report'].'</a></span></li>';
-		$post_actions[] = '<li class="postdelete"><span><a href="delete.php?id='.$cur_post['id'].'">'.$lang_topic['Delete'].'</a></span></li>';
-		$post_actions[] = '<li class="postedit"><span><a href="edit.php?id='.$cur_post['id'].'">'.$lang_topic['Edit'].'</a></span></li>';
+		if ($pun_user['g_id'] == PUN_ADMIN || !in_array($cur_post['poster_id'], $admin_ids))
+		{
+			$post_actions[] = '<li class="postdelete"><span><a href="delete.php?id='.$cur_post['id'].'">'.$lang_topic['Delete'].'</a></span></li>';
+			$post_actions[] = '<li class="postedit"><span><a href="edit.php?id='.$cur_post['id'].'">'.$lang_topic['Edit'].'</a></span></li>';
+		}
 		$post_actions[] = '<li class="postquote"><span><a href="post.php?tid='.$id.'&qid='.$cur_post['id'].'">'.$lang_topic['Quote'].'</a></span></li>';
 	}
 


More information about the Xfce4-commits mailing list