Browse Source

Merge pull request #155 from emanuele45/master

A bunch of fixes, it may increase over time
emanuele45 12 years ago
parent
commit
e4736d27d5

+ 31 - 8
SSI.php

@@ -147,6 +147,10 @@ loadPermissions();
 // Load the current or SSI theme. (just use $ssi_theme = id_theme;)
 loadTheme(isset($ssi_theme) ? (int) $ssi_theme : 0);
 
+// @todo: probably not the best place, but somewhere it should be set...
+if (!headers_sent())
+	header('Content-Type: text/html; charset=' . (empty($modSettings['global_character_set']) ? (empty($txt['lang_character_set']) ? 'ISO-8859-1' : $txt['lang_character_set']) : $modSettings['global_character_set']));
+
 // Take care of any banning that needs to be done.
 if (isset($_REQUEST['ssi_ban']) || (isset($ssi_ban) && $ssi_ban === true))
 	is_not_banned();
@@ -297,10 +301,13 @@ function ssi_recentPosts($num_recent = 8, $exclude_boards = null, $include_board
 }
 
 // Fetch a post with a particular ID. By default will only show if you have permission to the see the board in question - this can be overriden.
-function ssi_fetchPosts($post_ids, $override_permissions = false, $output_method = 'echo')
+function ssi_fetchPosts($post_ids = array(), $override_permissions = false, $output_method = 'echo')
 {
 	global $user_info, $modSettings;
 
+	if (empty($post_ids))
+		return;
+
 	// Allow the user to request more than one - why not?
 	$post_ids = is_array($post_ids) ? $post_ids : array($post_ids);
 
@@ -319,7 +326,7 @@ function ssi_fetchPosts($post_ids, $override_permissions = false, $output_method
 }
 
 // This removes code duplication in other queries - don't call it direct unless you really know what you're up to.
-function ssi_queryPosts($query_where = '', $query_where_params = array(), $query_limit = '', $query_order = 'm.id_msg DESC', $output_method = 'echo', $limit_body = false)
+function ssi_queryPosts($query_where = '', $query_where_params = array(), $query_limit = 10, $query_order = 'm.id_msg DESC', $output_method = 'echo', $limit_body = false, $override_permissions = false)
 {
 	global $context, $settings, $scripturl, $txt, $db_prefix, $user_info;
 	global $modSettings, $smcFunc;
@@ -336,11 +343,15 @@ function ssi_queryPosts($query_where = '', $query_where_params = array(), $query
 			LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = m.id_member)' . (!$user_info['is_guest'] ? '
 			LEFT JOIN {db_prefix}log_topics AS lt ON (lt.id_topic = m.id_topic AND lt.id_member = {int:current_member})
 			LEFT JOIN {db_prefix}log_mark_read AS lmr ON (lmr.id_board = m.id_board AND lmr.id_member = {int:current_member})' : '') . '
-		' . (empty($query_where) ? '' : 'WHERE ' . $query_where) . '
+		WHERE 1=1 ' . ($override_permissions ? '' : '
+			AND {query_wanna_see_board}') . ($modSettings['postmod_active'] ? '
+			AND m.approved = {int:is_approved}' : '') . '
+		' . (empty($query_where) ? '' : 'AND ' . $query_where) . '
 		ORDER BY ' . $query_order . '
 		' . ($query_limit == '' ? '' : 'LIMIT ' . $query_limit),
 		array_merge($query_where_params, array(
 			'current_member' => $user_info['id'],
+			'is_approved' => 1,
 		))
 	);
 	$posts = array();
@@ -792,8 +803,11 @@ function ssi_randomMember($random_type = '', $output_method = 'echo')
 }
 
 // Fetch a specific member.
-function ssi_fetchMember($member_ids, $output_method = 'echo')
+function ssi_fetchMember($member_ids = array(), $output_method = 'echo')
 {
+	if (empty($member_ids))
+		return;
+
 	// Can have more than one member if you really want...
 	$member_ids = is_array($member_ids) ? $member_ids : array($member_ids);
 
@@ -810,8 +824,11 @@ function ssi_fetchMember($member_ids, $output_method = 'echo')
 }
 
 // Get all members of a group.
-function ssi_fetchGroupMembers($group_id, $output_method = 'echo')
+function ssi_fetchGroupMembers($group_id = null, $output_method = 'echo')
 {
+	if ($group_id === null)
+		return;
+
 	$query_where = '
 		id_group = {int:id_group}
 		OR id_post_group = {int:id_group}
@@ -825,11 +842,14 @@ function ssi_fetchGroupMembers($group_id, $output_method = 'echo')
 }
 
 // Fetch some member data!
-function ssi_queryMembers($query_where, $query_where_params = array(), $query_limit = '', $query_order = 'id_member DESC', $output_method = 'echo')
+function ssi_queryMembers($query_where = null, $query_where_params = array(), $query_limit = '', $query_order = 'id_member DESC', $output_method = 'echo')
 {
 	global $context, $settings, $scripturl, $txt, $db_prefix, $user_info;
 	global $modSettings, $smcFunc, $memberContext;
 
+	if ($query_where === null)
+		return;
+
 	// Fetch the members in question.
 	$request = $smcFunc['db_query']('', '
 		SELECT id_member
@@ -892,6 +912,9 @@ function ssi_boardStats($output_method = 'echo')
 {
 	global $db_prefix, $txt, $scripturl, $modSettings, $smcFunc;
 
+	if (!allowedTo('view_stats'))
+		return;
+
 	$totals = array(
 		'members' => $modSettings['totalMembers'],
 		'posts' => $modSettings['totalMessages'],
@@ -1479,7 +1502,7 @@ function ssi_todaysBirthdays($output_method = 'echo')
 {
 	global $scripturl, $modSettings, $user_info;
 
-	if (empty($modSettings['cal_enabled']) || !allowedTo('calendar_view'))
+	if (empty($modSettings['cal_enabled']) || !allowedTo('calendar_view') || !allowedTo('profile_view_any'))
 		return;
 
 	$eventOptions = array(
@@ -1553,7 +1576,7 @@ function ssi_todaysCalendar($output_method = 'echo')
 		return;
 
 	$eventOptions = array(
-		'include_birthdays' => true,
+		'include_birthdays' => allowedTo('profile_view_any'),
 		'include_holidays' => true,
 		'include_events' => true,
 		'num_days_shown' => empty($modSettings['cal_days_for_index']) || $modSettings['cal_days_for_index'] < 1 ? 1 : $modSettings['cal_days_for_index'],

+ 4 - 0
Sources/ManagePosts.php

@@ -266,12 +266,16 @@ function ModifyBBCSettings($return_config = false)
 	$config_vars = array(
 			// Main tweaks
 			array('check', 'enableBBC'),
+			array('check', 'enableBBC', 0, 'onchange' => 'toggleBBCDisabled(\'disabledBBC\', !this.checked);'),
 			array('check', 'enablePostHTML'),
 			array('check', 'autoLinkUrls'),
 		'',
 			array('bbc', 'disabledBBC'),
 	);
 
+	$context['settings_post_javascript'] = '
+		toggleBBCDisabled(\'disabledBBC\', ' . (empty($modSettings['enableBBC']) ? 'true' : 'false') . ');';
+
 	call_integration_hook('integrate_modify_bbc_settings', array(&$config_vars));
 
 	if ($return_config)

+ 2 - 2
Sources/Profile.php

@@ -459,12 +459,12 @@ function ModifyProfile($post_errors = array())
 	unset($profile_areas);
 
 	// Now the context is setup have we got any security checks to carry out additional to that above?
+	if (isset($security_checks['validateToken']))
+		validateToken($token_name, $token_type);
 	if (isset($security_checks['session']))
 		checkSession($security_checks['session']);
 	if (isset($security_checks['validate']))
 		validateSession();
-	if (isset($security_checks['validateToken']))
-		validateToken($token_name, $token_type);
 	if (isset($security_checks['permission']))
 		isAllowedTo($security_checks['permission']);
 

+ 4 - 16
Sources/Register.php

@@ -836,28 +836,16 @@ function RegisterCheckUsername()
 	// This is XML!
 	loadTemplate('Xml');
 	$context['sub_template'] = 'check_username';
-	$context['checked_username'] = isset($_GET['username']) ? $_GET['username'] : '';
+	$context['checked_username'] = isset($_GET['username']) ? un_htmlspecialchars($_GET['username']) : '';
 	$context['valid_username'] = true;
 
 	// Clean it up like mother would.
 	$context['checked_username'] = preg_replace('~[\t\n\r\x0B\0' . ($context['utf8'] ? '\x{A0}' : '\xA0') . ']+~' . ($context['utf8'] ? 'u' : ''), ' ', $context['checked_username']);
-	if ($smcFunc['strlen']($context['checked_username']) > 25)
-		$context['checked_username'] = $smcFunc['htmltrim']($smcFunc['substr']($context['checked_username'], 0, 25));
 
-	// Only these characters are permitted.
-	if (preg_match('~[<>&"\'=\\\]~', preg_replace('~&#(?:\\d{1,7}|x[0-9a-fA-F]{1,6});~', '', $context['checked_username'])) != 0 || $context['checked_username'] == '_' || $context['checked_username'] == '|' || strpos($context['checked_username'], '[code') !== false || strpos($context['checked_username'], '[/code') !== false)
-		$context['valid_username'] = false;
+	require_once($sourcedir . '/Subs-Auth.php');
+	$errors = validateUsername(0, $context['checked_username'], true);
 
-	if (stristr($context['checked_username'], $txt['guest_title']) !== false)
-		$context['valid_username'] = false;
-
-	if (trim($context['checked_username']) == '')
-		$context['valid_username'] = false;
-	else
-	{
-		require_once($sourcedir . '/Subs-Members.php');
-		$context['valid_username'] &= isReservedName($context['checked_username'], 0, false, false) ? 0 : 1;
-	}
+	$context['valid_username'] = empty($errors);
 }
 
 ?>

+ 40 - 20
Sources/RemoveTopic.php

@@ -1,6 +1,9 @@
 <?php
 
 /**
+ * The contents of this file handle the deletion of topics, posts, and related
+ * paraphernalia.
+ * 
  * Simple Machines Forum (SMF)
  *
  * @package SMF
@@ -17,23 +20,12 @@ if (!defined('SMF'))
 /*	The contents of this file handle the deletion of topics, posts, and related
 	paraphernalia.  It has the following functions:
 
-	void RemoveTopic2()
-		// !!!
-
-	void DeleteMessage()
-		// !!!
-
-	void RemoveOldTopics2()
-		// !!!
-
-	void removeTopics(array topics, bool decreasePostCount = true, bool ignoreRecycling = false)
-		// !!!
-
-	bool removeMessage(int id_msg, bool decreasePostCount = true)
-		// !!!
 */
 
-// Completely remove an entire topic.
+/**
+ * Completely remove an entire topic.
+ * Redirects to the board when completed.
+ */
 function RemoveTopic2()
 {
 	global $user_info, $topic, $board, $sourcedir, $smcFunc, $context, $modSettings;
@@ -84,7 +76,10 @@ function RemoveTopic2()
 	redirectexit('board=' . $board . '.0');
 }
 
-// Remove just a single post.
+/**
+ * Remove just a single post.
+ * On completion redirect to the topic or to the board.
+ */
 function DeleteMessage()
 {
 	global $user_info, $topic, $board, $modSettings, $smcFunc;
@@ -151,7 +146,10 @@ function DeleteMessage()
 		redirectexit('topic=' . $topic . '.' . $_REQUEST['start']);
 }
 
-// So long as you are sure... all old posts will be gone.
+/**
+ * So long as you are sure... all old posts will be gone.
+ * Used in ManageMaintenance.php to prune old topics.
+ */
 function RemoveOldTopics2()
 {
 	global $modSettings, $smcFunc;
@@ -221,7 +219,13 @@ function RemoveOldTopics2()
 	redirectexit('action=admin;area=maintain;sa=topics;done=purgeold');
 }
 
-// Removes the passed id_topic's. (permissions are NOT checked here!)
+/**
+ * Removes the passed id_topic's. (permissions are NOT checked here!).
+ *
+ * @param array/int $topics The topics to remove (can be an id or an array of ids).
+ * @param bool $decreasePostCount if true users' post count will be reduced
+ * @param bool $ignoreRecycling if true topics are not moved to the recycle board (if it exists).
+ */
 function removeTopics($topics, $decreasePostCount = true, $ignoreRecycling = false)
 {
 	global $sourcedir, $modSettings, $smcFunc;
@@ -551,7 +555,15 @@ function removeTopics($topics, $decreasePostCount = true, $ignoreRecycling = fal
 	updateLastMessages($updates);
 }
 
-// Remove a specific message (including permission checks).
+/**
+ * Remove a specific message (including permission checks).
+ * - normally, local and global should be the localCookies and globalCookies settings, respectively.
+ * - uses boardurl to determine these two things.
+ *
+ * @param int $message The message id
+ * @param bool $decreasePostCount if true users' post count will be reduced
+ * @return array an array to set the cookie on with domain and path in it, in that order
+ */
 function removeMessage($message, $decreasePostCount = true)
 {
 	global $board, $sourcedir, $modSettings, $user_info, $smcFunc, $context;
@@ -984,6 +996,9 @@ function removeMessage($message, $decreasePostCount = true)
 	return false;
 }
 
+/**
+ * Move back a topic from the recycle board to its original board.
+ */
 function RestoreTopic()
 {
 	global $context, $smcFunc, $modSettings, $sourcedir;
@@ -1215,7 +1230,9 @@ function RestoreTopic()
 	redirectexit();
 }
 
-// Take a load of messages from one place and stick them in a topic.
+/**
+ * Take a load of messages from one place and stick them in a topic.
+ */
 function mergePosts($msgs = array(), $from_topic, $target_topic)
 {
 	global $context, $smcFunc, $modSettings, $sourcedir;
@@ -1468,6 +1485,9 @@ function mergePosts($msgs = array(), $from_topic, $target_topic)
 	updateLastMessages(array($from_board, $target_board));
 }
 
+/**
+ * Try to determine if the topic has already been deleted by another user.
+ */
 function removeDeleteConcurrence()
 {
 	global $modSettings, $board, $topic, $smcFunc, $scripturl, $context;

+ 27 - 9
Sources/Subs-Auth.php

@@ -604,26 +604,44 @@ function resetPassword($memID, $username = null)
  * @param string $username
  * @return string Returns null if fine
  */
-function validateUsername($memID, $username)
+function validateUsername($memID, $username, $return_error = false, $check_reserved_name = true)
 {
-	global $sourcedir, $txt;
+	global $sourcedir, $txt, $smcFunc, $user_info;
+
+	$errors = array();
+
+	// Don't use too long a name.
+	if ($smcFunc['strlen']($username) > 25)
+		$errors[] = array('lang', 'error_long_name');
 
 	// No name?!  How can you register with no name?
 	if ($username == '')
-		fatal_lang_error('need_username', false);
+		$errors[] = array('lang', 'need_username');
 
 	// Only these characters are permitted.
 	if (in_array($username, array('_', '|')) || preg_match('~[<>&"\'=\\\\]~', preg_replace('~&#(?:\\d{1,7}|x[0-9a-fA-F]{1,6});~', '', $username)) != 0 || strpos($username, '[code') !== false || strpos($username, '[/code') !== false)
-		fatal_lang_error('error_invalid_characters_username', false);
+		$errors[] = array('lang', 'error_invalid_characters_username');
 
 	if (stristr($username, $txt['guest_title']) !== false)
-		fatal_lang_error('username_reserved', true, array($txt['guest_title']));
+		$errors[] = array('lang', 'username_reserved', 'general', array($txt['guest_title']));
+
+	if ($check_reserved_name)
+	{
+		require_once($sourcedir . '/Subs-Members.php');
+		if (isReservedName($username, $memID, false))
+			$errors[] = array('done', '(' . htmlspecialchars($username) . ') ' . $txt['name_in_use']);
+	}
+
+	if ($return_error)
+		return $errors;
+	elseif (empty($errors))
+		return null;
 
-	require_once($sourcedir . '/Subs-Members.php');
-	if (isReservedName($username, $memID, false))
-		fatal_error('(' . htmlspecialchars($username) . ') ' . $txt['name_in_use'], false);
+	loadLanguage('Errors');
+	$error = $errors[0];
 
-	return null;
+	$message = $error[0] == 'lang' ? (empty($error[3]) ? $txt[$error[1]] : vsprintf($txt[$error[1]], $error[3])) : $error[1];
+	fatal_error($message, empty($error[2]) || $user_info['is_admin'] ? false : $error[2]);
 }
 
 /**

+ 19 - 45
Sources/Subs-Boards.php

@@ -17,50 +17,6 @@
 if (!defined('SMF'))
 	die('Hacking attempt...');
 
-/*
-	void modifyBoard(int board_id, array boardOptions)
-		- general function to modify the settings and position of a board.
-		- used by ManageBoards.php to change the settings of a board.
-
-	int createBoard(array boardOptions)
-		- general function to create a new board and set its position.
-		- allows (almost) the same options as the modifyBoard() function.
-		- with the option inherit_permissions set, the parent board permissions
-		  will be inherited.
-		- returns the ID of the newly created board.
-
-	void deleteBoards(array boards_to_remove, moveChildrenTo = null)
-		- general function to delete one or more boards.
-		- allows to move the children of the board before deleting it
-		- if moveChildrenTo is set to null, the child boards will be deleted.
-		- deletes all topics that are on the given boards.
-		- deletes all information that's associated with the given boards.
-		- updates the statistics to reflect the new situation.
-
-	void reorderBoards()
-		- updates the database to put all boards in the right order.
-		- sorts the records of the boards table.
-		- used by modifyBoard(), deleteBoards(), modifyCategory(), and
-		  deleteCategories() functions.
-
-	void fixChildren(int parent, int newLevel, int newParent)
-		- recursively updates the children of parent's child_level and
-		  id_parent to newLevel and newParent.
-		- used when a board is deleted or moved, to affect its children.
-
-	bool isChildOf(int child, int parent)
-		- determines if child is a child of parent.
-		- recurses down the tree until there are no more parents.
-		- returns true if child is a child of parent.
-
-	void recursiveBoards()
-		- function used by getBoardTree to recursively get a list of boards.
-
-	bool isChildOf(int child, int parent)
-		- determine if a certain board id is a child of another board.
-		- the parent might be several levels higher than the child.
-*/
-
 /**
  * Mark a board or multiple boards read.
  *
@@ -469,6 +425,8 @@ function getMsgMemberID($messageID)
 
 /**
  * Modify the settings and position of a board.
+ * Used by ManageBoards.php to change the settings of a board.
+ *
  * @param int $board_id
  * @param array &$boardOptions
  */
@@ -752,6 +710,10 @@ function modifyBoard($board_id, &$boardOptions)
 
 /**
  * Create a new board and set its properties and position.
+ * Allows (almost) the same options as the modifyBoard() function.
+ * With the option inherit_permissions set, the parent board permissions
+ * will be inherited.
+ * 
  * @param array $boardOptions
  * @return int The new board id
  */
@@ -845,6 +807,13 @@ function createBoard($boardOptions)
 
 /**
  * Remove one or more boards.
+ * Allows to move the children of the board before deleting it
+ * if moveChildrenTo is set to null, the child boards will be deleted.
+ * Deletes:
+ *   - all topics that are on the given boards;
+ *   - all information that's associated with the given boards;
+ * updates the statistics to reflect the new situation.
+ *
  * @param array $boards_to_remove
  * @param array $moveChildrenTo = null
  */
@@ -982,7 +951,8 @@ function deleteBoards($boards_to_remove, $moveChildrenTo = null)
 }
 
 /**
- * Put all boards in the right order.
+ * Put all boards in the right order and sorts the records of the boards table.
+ * Used by modifyBoard(), deleteBoards(), modifyCategory(), and deleteCategories() functions
  */
 function reorderBoards()
 {
@@ -1019,6 +989,8 @@ function reorderBoards()
 
 /**
  * Fixes the children of a board by setting their child_levels to new values.
+ * Used when a board is deleted or moved, to affect its children.
+ *
  * @param int $parent
  * @param int $newLevel
  * @param int $newParent
@@ -1179,6 +1151,8 @@ function getBoardTree()
 
 /**
  * Recursively get a list of boards.
+ * Used by getBoardTree 
+ *
  * @param array &$_boardList
  * @param array &$_tree
  */

+ 3 - 21
Sources/Subs-Members.php

@@ -469,34 +469,16 @@ function registerMember(&$regOptions, $return_errors = false)
 			$regOptions['auth_method'] = 'password';
 	}
 
-	// No name?!  How can you register with no name?
-	if (empty($regOptions['username']))
-		$reg_errors[] = array('lang', 'need_username');
-
 	// Spaces and other odd characters are evil...
 	$regOptions['username'] = preg_replace('~[\t\n\r\x0B\0' . ($context['utf8'] ? '\x{A0}' : '\xA0') . ']+~' . ($context['utf8'] ? 'u' : ''), ' ', $regOptions['username']);
 
-	// Don't use too long a name.
-	if ($smcFunc['strlen']($regOptions['username']) > 25)
-		$reg_errors[] = array('lang', 'error_long_name');
-
-	// Only these characters are permitted.
-	if (preg_match('~[<>&"\'=\\\\]~', preg_replace('~&#(?:\\d{1,7}|x[0-9a-fA-F]{1,6});~', '', $regOptions['username'])) != 0 || $regOptions['username'] == '_' || $regOptions['username'] == '|' || strpos($regOptions['username'], '[code') !== false || strpos($regOptions['username'], '[/code') !== false)
-		$reg_errors[] = array('lang', 'error_invalid_characters_username');
-
-	if ($smcFunc['strtolower']($regOptions['username']) === $smcFunc['strtolower']($txt['guest_title']))
-		$reg_errors[] = array('lang', 'username_reserved', 'general', array($txt['guest_title']));
-
 	// @todo Separate the sprintf?
 	if (empty($regOptions['email']) || preg_match('~^[0-9A-Za-z=_+\-/][0-9A-Za-z=_\'+\-/\.]*@[\w\-]+(\.[\w\-]+)*(\.[\w]{2,6})$~', $regOptions['email']) === 0 || strlen($regOptions['email']) > 255)
 		$reg_errors[] = array('done', sprintf($txt['valid_email_needed'], $smcFunc['htmlspecialchars']($regOptions['username'])));
 
-	if (!empty($regOptions['check_reserved_name']) && isReservedName($regOptions['username'], 0, false))
-	{
-		if ($regOptions['password'] == 'chocolate cake')
-			$reg_errors[] = array('done', 'Sorry, I don\'t take bribes... you\'ll need to come up with a different name.');
-		$reg_errors[] = array('done', '(' . htmlspecialchars($regOptions['username']) . ') ' . $txt['name_in_use']);
-	}
+	$username_validation_errors = validateUsername(0, $regOptions['username'], true, !empty($regOptions['check_reserved_name']));
+	if (!empty($username_validation_errors))
+		$reg_errors = array_merge($reg_errors, $username_validation_errors);
 
 	// Generate a validation code if it's supposed to be emailed.
 	$validation_code = '';

+ 4 - 4
Sources/Subs-MembersOnline.php

@@ -120,7 +120,7 @@ function getMembersOnlineStats($membersOnlineOptions)
 		}
 
 		// A lot of useful information for each member.
-		$membersOnlineStats['users_online'][$row[$membersOnlineOptions['sort']] . $row['member_name']] = array(
+		$membersOnlineStats['users_online'][$row[$membersOnlineOptions['sort']] . '_' . $row['member_name']] = array(
 			'id' => $row['id_member'],
 			'username' => $row['member_name'],
 			'name' => $row['real_name'],
@@ -133,7 +133,7 @@ function getMembersOnlineStats($membersOnlineOptions)
 		);
 
 		// This is the compact version, simply implode it to show.
-		$membersOnlineStats['list_users_online'][$row[$membersOnlineOptions['sort']] . $row['member_name']] = empty($row['show_online']) ? '<em>' . $link . '</em>' : $link;
+		$membersOnlineStats['list_users_online'][$row[$membersOnlineOptions['sort']] . '_' . $row['member_name']] = empty($row['show_online']) ? '<em>' . $link . '</em>' : $link;
 
 		// Store all distinct (primary) membergroups that are shown.
 		if (!isset($membersOnlineStats['online_groups'][$row['id_group']]))
@@ -152,7 +152,7 @@ function getMembersOnlineStats($membersOnlineOptions)
 		foreach ($spider_finds as $id => $count)
 		{
 			$link = $spiders[$id] . ($count > 1 ? ' (' . $count . ')' : '');
-			$membersOnlineStats['users_online'][$sort . $spiders[$id]] = array(
+			$membersOnlineStats['users_online'][$sort . '_' . $spiders[$id]] = array(
 				'id' => 0,
 				'username' => $spiders[$id],
 				'name' => $link,
@@ -163,7 +163,7 @@ function getMembersOnlineStats($membersOnlineOptions)
 				'hidden' => false,
 				'is_last' => false,
 			);
-			$membersOnlineStats['list_users_online'][$sort . $spiders[$id]] = $link;
+			$membersOnlineStats['list_users_online'][$sort . '_' . $spiders[$id]] = $link;
 		}
 	}
 

+ 1 - 1
Themes/default/Admin.template.php

@@ -880,7 +880,7 @@ function template_show_settings()
 										</li>';
 					}
 					echo '			</ul>
-								<input type="checkbox" id="select_all" onclick="invertAll(this, this.form, \'', $config_var['name'], '_enabledTags\');"', $context['bbc_sections'][$config_var['name']]['all_selected'] ? ' checked="checked"' : '', ' class="input_check" /> <label for="select_all"><em>', $txt['bbcTagsToUse_select_all'], '</em></label>
+								<input type="checkbox" id="bbc_', $config_var['name'], '_select_all" onclick="invertAll(this, this.form, \'', $config_var['name'], '_enabledTags\');"', $context['bbc_sections'][$config_var['name']]['all_selected'] ? ' checked="checked"' : '', ' class="input_check" /> <label for="select_all"><em>', $txt['bbcTagsToUse_select_all'], '</em></label>
 							</fieldset>';
 				}
 				// A simple message?

+ 4 - 3
Themes/default/scripts/admin.js

@@ -339,12 +339,13 @@ function addNewWord()
 
 function toggleBBCDisabled(section, disable)
 {
-	for (var i = 0; i < document.forms.bbcForm.length; i++)
+	elems = document.getElementById(section).getElementsByTagName('*');
+	for (var i = 0; i < elems.length; i++)
 	{
-		if (typeof(document.forms.bbcForm[i].name) == "undefined" || (document.forms.bbcForm[i].name.substr(0, 11) != "enabledTags") || (document.forms.bbcForm[i].name.indexOf(section) != 11))
+		if (typeof(elems[i].name) == "undefined" || (elems[i].name.substr((section.length + 1), (elems[i].name.length - 2 - (section.length + 1))) != "enabledTags") || (elems[i].name.indexOf(section) != 0))
 			continue;
 
-		document.forms.bbcForm[i].disabled = disable;
+		elems[i].disabled = disable;
 	}
 	document.getElementById("bbc_" + section + "_select_all").disabled = disable;
 }

+ 5 - 5
other/install.php

@@ -76,6 +76,7 @@ $databases = array(
 		'always_has_db' => true,
 		'utf8_default' => true,
 		'utf8_required' => true,
+		'utf8_support' => true,
 		'validate_prefix' => create_function('&$value', '
 			global $incontext, $txt;
 
@@ -944,9 +945,9 @@ function ForumSettings()
 		require(dirname(__FILE__) . '/Settings.php');
 
 		// UTF-8 requires a setting to override the language charset.
-		if (isset($_POST['utf8']) && !empty($databases[$db_type]['utf8_support']))
+		if ((!empty($databases[$db_type]['utf8_support']) && !empty($databases[$db_type]['utf8_required'])) || (empty($databases[$db_type]['utf8_required']) && !empty($databases[$db_type]['utf8_support']) && isset($_POST['utf8'])))
 		{
-			if (version_compare($databases[$db_type]['utf8_version'], preg_replace('~\-.+?$~', '', eval($databases[$db_type]['utf8_version_check'])), '>'))
+			if (!empty($databases[$db_type]['utf8_version_check']) && version_compare($databases[$db_type]['utf8_version'], preg_replace('~\-.+?$~', '', eval($databases[$db_type]['utf8_version_check'])), '>'))
 			{
 				$incontext['error'] = sprintf($txt['error_utf8_version'], $databases[$db_type]['utf8_version']);
 				return false;
@@ -1033,8 +1034,7 @@ function DatabasePopulation()
 	$replaces['{$default_reserved_names}'] = strtr($replaces['{$default_reserved_names}'], array('\\\\n' => '\\n'));
 
 	// If the UTF-8 setting was enabled, add it to the table definitions.
-	// @todo Very MySQL specific still
-	if ($db_type == 'mysql' && isset($_POST['utf8']) && !empty($databases[$db_type]['utf8_support']))
+	if (empty($databases[$db_type]['utf8_required']) && isset($_POST['utf8']) && !empty($databases[$db_type]['utf8_support']))
 		$replaces[') ENGINE=MyISAM;'] = ') ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;';
 
 	// Read in the SQL.  Turn this on and that off... internationalize... etc.
@@ -1110,7 +1110,7 @@ function DatabasePopulation()
 	}
 
 	// Make sure UTF will be used globally.
-	if (isset($_POST['utf8']) && !empty($databases[$db_type]['utf8_support']))
+	if ((!empty($databases[$db_type]['utf8_support']) && !empty($databases[$db_type]['utf8_required'])) || (empty($databases[$db_type]['utf8_required']) && !empty($databases[$db_type]['utf8_support']) && isset($_POST['utf8'])))
 		$smcFunc['db_insert']('replace',
 			$db_prefix . 'settings',
 			array(

+ 1 - 1
other/install_2-1_postgresql.sql

@@ -2132,7 +2132,7 @@ INSERT INTO {$db_prefix}scheduled_tasks	(id_task, next_time, time_offset, time_r
 INSERT INTO {$db_prefix}scheduled_tasks	(id_task, next_time, time_offset, time_regularity, time_unit, disabled, task) VALUES (10, 0, 120, 1, 'd', 1, 'paid_subscriptions');
 INSERT INTO {$db_prefix}scheduled_tasks	(id_task, next_time, time_offset, time_regularity, time_unit, disabled, task) VALUES (11, 0, 120, 1, 'd', 1, 'remove_temp_attachments');
 INSERT INTO {$db_prefix}scheduled_tasks	(id_task, next_time, time_offset, time_regularity, time_unit, disabled, task) VALUES (12, 0, 180, 1, 'd', 1, 'remove_topic_redirect');
-INSERT INTO {$db_prefix}scheduled_tasks	(id_task, next_time, time_offset, time_regularity, time_unit, disabled, task) VALUES (12, 0, 240, 1, 'd', 1, 'remove_old_drafts');
+INSERT INTO {$db_prefix}scheduled_tasks	(id_task, next_time, time_offset, time_regularity, time_unit, disabled, task) VALUES (13, 0, 240, 1, 'd', 1, 'remove_old_drafts');
 
 # --------------------------------------------------------
 

+ 1 - 1
other/install_2-1_sqlite.sql

@@ -1783,7 +1783,7 @@ INSERT INTO {$db_prefix}scheduled_tasks	(id_task, next_time, time_offset, time_r
 INSERT INTO {$db_prefix}scheduled_tasks	(id_task, next_time, time_offset, time_regularity, time_unit, disabled, task) VALUES (10, 0, 120, 1, 'd', 1, 'paid_subscriptions');
 INSERT INTO {$db_prefix}scheduled_tasks	(id_task, next_time, time_offset, time_regularity, time_unit, disabled, task) VALUES (11, 0, 120, 1, 'd', 1, 'remove_temp_attachments');
 INSERT INTO {$db_prefix}scheduled_tasks	(id_task, next_time, time_offset, time_regularity, time_unit, disabled, task) VALUES (12, 0, 180, 1, 'd', 1, 'remove_topic_redirect');
-INSERT INTO {$db_prefix}scheduled_tasks	(id_task, next_time, time_offset, time_regularity, time_unit, disabled, task) VALUES (12, 0, 240, 1, 'd', 1, 'remove_old_drafts');
+INSERT INTO {$db_prefix}scheduled_tasks	(id_task, next_time, time_offset, time_regularity, time_unit, disabled, task) VALUES (13, 0, 240, 1, 'd', 1, 'remove_old_drafts');
 COMMIT;
 
 # --------------------------------------------------------

+ 14 - 0
other/upgrade_2-1_postgresql.sql

@@ -30,6 +30,20 @@ if (!isset($modSettings['package_make_full_backups']) && isset($modSettings['pac
 ---}
 ---#
 
+---# Adding back proper support for UTF8
+---{
+global $sourcedir;
+require_once($sourcedir . '/Subs-Admin.php');
+updateSettingsFile(array('db_character_set' => 'utf8'));
+
+upgrade_query("
+	INSERT INTO {$db_prefix}settings
+		(variable, value)
+	VALUES
+		('global_character_set', 'UTF-8')");
+---}
+---#
+
 /******************************************************************************/
 --- Updating legacy attachments...
 /******************************************************************************/

+ 14 - 0
other/upgrade_2-1_sqlite.sql

@@ -28,6 +28,20 @@ if (!isset($modSettings['package_make_full_backups']) && isset($modSettings['pac
 ---}
 ---#
 
+---# Adding back proper support for UTF8
+---{
+global $sourcedir;
+require_once($sourcedir . '/Subs-Admin.php');
+updateSettingsFile(array('db_character_set' => 'utf8'));
+
+upgrade_query("
+	INSERT INTO {$db_prefix}settings
+		(variable, value)
+	VALUES
+		('global_character_set', 'UTF-8')");
+---}
+---#
+
 /******************************************************************************/
 --- Updating legacy attachments...
 /******************************************************************************/

+ 3 - 0
subscriptions.php

@@ -29,7 +29,10 @@ loadLanguage('ManagePaid');
 
 // If there's literally nothing coming in, let's take flight!
 if (empty($_POST))
+{
+	header('Content-Type: text/html; charset=' . (empty($modSettings['global_character_set']) ? (empty($txt['lang_character_set']) ? 'ISO-8859-1' : $txt['lang_character_set']) : $modSettings['global_character_set']));
 	die($txt['paid_no_data']);
+}
 
 // I assume we're even active?
 if (empty($modSettings['paid_enabled']))