Browse Source

Added the .sql upgrade scripts to 1.0, 1.1 and 2.0

Signed-off-by: emanuele <[email protected]>
emanuele 11 years ago
parent
commit
af4da4de89
5 changed files with 10181 additions and 0 deletions
  1. 2017 0
      other/upgrade_1-0.sql
  2. 2655 0
      other/upgrade_1-1.sql
  3. 3134 0
      other/upgrade_2-0_mysql.sql
  4. 1380 0
      other/upgrade_2-0_postgresql.sql
  5. 995 0
      other/upgrade_2-0_sqlite.sql

+ 2017 - 0
other/upgrade_1-0.sql

@@ -0,0 +1,2017 @@
+/* ATTENTION: You don't need to run or use this file!  The upgrade.php script does everything for you! */
+
+/******************************************************************************/
+--- Creating new tables and inserting default data...
+/******************************************************************************/
+
+---# Creating "themes"...
+CREATE TABLE IF NOT EXISTS {$db_prefix}themes (
+	ID_MEMBER mediumint(8) NOT NULL default '0',
+	ID_THEME tinyint(4) unsigned NOT NULL default '1',
+	variable tinytext NOT NULL default '',
+	value text NOT NULL default '',
+	PRIMARY KEY (ID_MEMBER, ID_THEME, variable(30))
+) ENGINE=MyISAM;
+
+ALTER TABLE {$db_prefix}themes
+CHANGE COLUMN ID_MEMBER ID_MEMBER mediumint(8) NOT NULL default '0';
+
+ALTER TABLE {$db_prefix}themes
+CHANGE COLUMN value value text NOT NULL default '';
+
+INSERT IGNORE INTO {$db_prefix}themes
+	(ID_MEMBER, ID_THEME, variable, value)
+VALUES (0, 1, 'name', 'SMF Default Theme'),
+	(0, 1, 'theme_url', '{$boardurl}/Themes/default'),
+	(0, 1, 'images_url', '{$boardurl}/Themes/default/images'),
+	(0, 1, 'theme_dir', '{$sboarddir}/Themes/default'),
+	(0, 1, 'allow_no_censored', '0'),
+	(0, 1, 'additional_options_collapsable', '1'),
+	(0, 2, 'name', 'Classic YaBB SE Theme'),
+	(0, 2, 'theme_url', '{$boardurl}/Themes/classic'),
+	(0, 2, 'images_url', '{$boardurl}/Themes/classic/images'),
+	(0, 2, 'theme_dir', '{$sboarddir}/Themes/classic');
+---#
+
+---# Creating "collapsed_categories"...
+CREATE TABLE IF NOT EXISTS {$db_prefix}collapsed_categories (
+	ID_CAT tinyint(4) unsigned NOT NULL default '0',
+	ID_MEMBER mediumint(8) unsigned NOT NULL default '0',
+	PRIMARY KEY (ID_CAT, ID_MEMBER)
+) ENGINE=MyISAM;
+---#
+
+---# Creating and verifying "permissions"...
+CREATE TABLE IF NOT EXISTS {$db_prefix}permissions (
+	ID_GROUP smallint(6) NOT NULL default '0',
+	permission varchar(30) NOT NULL default '',
+	addDeny tinyint(4) NOT NULL default '1',
+	PRIMARY KEY (ID_GROUP, permission)
+) ENGINE=MyISAM;
+
+ALTER TABLE {$db_prefix}permissions
+ADD addDeny tinyint(4) NOT NULL default '1';
+ALTER TABLE {$db_prefix}permissions
+CHANGE COLUMN permission permission varchar(30) NOT NULL default '';
+
+UPDATE IGNORE {$db_prefix}permissions
+SET
+	permission = REPLACE(permission, 'profile_own_identity', 'profile_identity_own'),
+	permission = REPLACE(permission, 'profile_any_identity', 'profile_identity_any'),
+	permission = REPLACE(permission, 'profile_own_extra', 'profile_extra_own'),
+	permission = REPLACE(permission, 'profile_any_extra', 'profile_extra_any'),
+	permission = REPLACE(permission, 'profile_own_title', 'profile_title_own'),
+	permission = REPLACE(permission, 'profile_any_title', 'profile_title_any'),
+	permission = REPLACE(permission, 'im_read', 'pm_read'),
+	permission = REPLACE(permission, 'im_send', 'pm_send');
+---#
+
+---# Inserting data into "permissions"...
+INSERT INTO {$db_prefix}permissions
+	(ID_GROUP, permission)
+VALUES (-1, 'search_posts'), (-1, 'calendar_view'), (-1, 'view_stats'), (-1, 'profile_view_any'),
+	(2, 'calendar_post'), (2, 'calendar_edit_any'), (2, 'calendar_edit_own');
+---#
+
+---# Creating and verifying "board_permissions"...
+CREATE TABLE IF NOT EXISTS {$db_prefix}board_permissions (
+	ID_GROUP smallint(6) NOT NULL default '0',
+	ID_BOARD smallint(5) unsigned NOT NULL default '0',
+	permission varchar(30) NOT NULL default '',
+	addDeny tinyint(4) NOT NULL default '1',
+	PRIMARY KEY (ID_GROUP, ID_BOARD, permission)
+) ENGINE=MyISAM;
+
+ALTER TABLE {$db_prefix}board_permissions
+ADD addDeny tinyint(4) NOT NULL default '1';
+ALTER TABLE {$db_prefix}board_permissions
+CHANGE COLUMN permission permission varchar(30) NOT NULL default '';
+---#
+
+---# Inserting data into "board_permissions"...
+INSERT INTO {$db_prefix}board_permissions
+	(ID_GROUP, ID_BOARD, permission)
+VALUES (-1, 0, 'poll_view'), (3, 0, 'make_sticky'), (3, 0, 'lock_any'),
+	(3, 0, 'remove_any'), (3, 0, 'move_any'), (3, 0, 'merge_any'), (3, 0, 'split_any'),
+	(3, 0, 'delete_any'), (3, 0, 'modify_any'), (2, 0, 'make_sticky'), (2, 0, 'lock_any'),
+	(2, 0, 'remove_any'), (2, 0, 'move_any'), (2, 0, 'merge_any'), (2, 0, 'split_any'),
+	(2, 0, 'delete_any'), (2, 0, 'modify_any'), (2, 0, 'poll_lock_any'), (2, 0, 'poll_lock_any'),
+	(2, 0, 'poll_add_any'), (2, 0, 'poll_remove_any'), (2, 0, 'poll_remove_any');
+INSERT IGNORE INTO {$db_prefix}board_permissions
+	(ID_GROUP, ID_BOARD, permission)
+VALUES (3, 0, 'moderate_board'), (2, 0, 'moderate_board');
+---#
+
+---# Creating "moderators"...
+CREATE TABLE IF NOT EXISTS {$db_prefix}moderators (
+	ID_BOARD smallint(5) unsigned NOT NULL default '0',
+	ID_MEMBER mediumint(8) unsigned NOT NULL default '0',
+	PRIMARY KEY (ID_BOARD, ID_MEMBER)
+) ENGINE=MyISAM;
+---#
+
+---# Creating "attachments"...
+CREATE TABLE IF NOT EXISTS {$db_prefix}attachments (
+	ID_ATTACH int(11) unsigned NOT NULL auto_increment,
+	ID_MSG int(10) unsigned NOT NULL default '0',
+	ID_MEMBER int(10) unsigned NOT NULL default '0',
+	filename tinytext NOT NULL default '',
+	size int(10) unsigned NOT NULL default '0',
+	downloads mediumint(8) unsigned NOT NULL default '0',
+	PRIMARY KEY (ID_ATTACH),
+	UNIQUE ID_MEMBER (ID_MEMBER, ID_ATTACH),
+	KEY ID_MSG (ID_MSG)
+) ENGINE=MyISAM;
+---#
+
+---# Creating "log_notify"...
+CREATE TABLE IF NOT EXISTS {$db_prefix}log_notify (
+	ID_MEMBER mediumint(8) unsigned NOT NULL default '0',
+	ID_TOPIC mediumint(8) unsigned NOT NULL default '0',
+	ID_BOARD smallint(5) unsigned NOT NULL default '0',
+	sent tinyint(1) unsigned NOT NULL default '0',
+	PRIMARY KEY (ID_MEMBER, ID_TOPIC, ID_BOARD)
+) ENGINE=MyISAM;
+---#
+
+---# Creating "log_polls"...
+CREATE TABLE IF NOT EXISTS {$db_prefix}log_polls (
+	ID_POLL mediumint(8) unsigned NOT NULL default '0',
+	ID_MEMBER mediumint(8) unsigned NOT NULL default '0',
+	ID_CHOICE tinyint(4) unsigned NOT NULL default '0',
+	PRIMARY KEY (ID_POLL, ID_MEMBER, ID_CHOICE)
+) ENGINE=MyISAM;
+---#
+
+---# Creating "log_actions"...
+CREATE TABLE IF NOT EXISTS {$db_prefix}log_actions (
+	ID_ACTION int(10) unsigned NOT NULL auto_increment,
+	logTime int(10) unsigned NOT NULL default '0',
+	ID_MEMBER mediumint(8) unsigned NOT NULL default '0',
+	IP tinytext NOT NULL default '',
+	action varchar(30) NOT NULL default '',
+	extra text NOT NULL default '',
+	PRIMARY KEY (ID_ACTION),
+	KEY logTime (logTime),
+	KEY ID_MEMBER (ID_MEMBER)
+) ENGINE=MyISAM;
+---#
+
+---# Creating "poll_choices"...
+CREATE TABLE IF NOT EXISTS {$db_prefix}poll_choices (
+	ID_POLL mediumint(8) unsigned NOT NULL default '0',
+	ID_CHOICE tinyint(4) unsigned NOT NULL default '0',
+	label tinytext NOT NULL default '',
+	votes smallint(5) unsigned NOT NULL default '0',
+	PRIMARY KEY (ID_POLL, ID_CHOICE)
+) ENGINE=MyISAM;
+---#
+
+---# Creating "smileys"...
+CREATE TABLE IF NOT EXISTS {$db_prefix}smileys (
+	id_smiley smallint(5) unsigned NOT NULL auto_increment,
+	code varchar(30) NOT NULL default '',
+	filename varchar(48) NOT NULL default '',
+	description varchar(80) NOT NULL default '',
+	smileyRow tinyint(4) unsigned NOT NULL default '0',
+	smileyOrder tinyint(4) unsigned NOT NULL default '0',
+	hidden tinyint(4) unsigned NOT NULL default '0',
+	PRIMARY KEY (id_smiley),
+	KEY smileyOrder (smileyOrder)
+) ENGINE=MyISAM;
+---#
+
+---# Loading default smileys...
+INSERT IGNORE INTO {$db_prefix}smileys
+	(id_smiley, code, filename, description, smileyOrder, hidden)
+VALUES (1, ':)', 'smiley.gif', 'Smiley', 0, 0),
+	(2, ';)', 'wink.gif', 'Wink', 1, 0),
+	(3, ':D', 'cheesy.gif', 'Cheesy', 2, 0),
+	(4, ';D', 'grin.gif', 'Grin', 3, 0),
+	(5, '>:(', 'angry.gif', 'Angry', 4, 0),
+	(6, ':(', 'sad.gif', 'Sad', 5, 0),
+	(7, ':o', 'shocked.gif', 'Shocked', 6, 0),
+	(8, '8)', 'cool.gif', 'Cool', 7, 0),
+	(9, '???', 'huh.gif', 'Huh', 8, 0),
+	(10, '::)', 'rolleyes.gif', 'Roll Eyes', 9, 0),
+	(11, ':P', 'tongue.gif', 'Tongue', 10, 0),
+	(12, ':-[', 'embarassed.gif', 'Embarrassed', 11, 0),
+	(13, ':-X', 'lipsrsealed.gif', 'Lips Sealed', 12, 0),
+	(14, ':-\\', 'undecided.gif', 'Undecided', 13, 0),
+	(15, ':-*', 'kiss.gif', 'Kiss', 14, 0),
+	(16, ':\'(', 'cry.gif', 'Cry', 15, 0),
+	(17, '>:D', 'evil.gif', 'Evil', 16, 1),
+	(18, '^-^', 'azn.gif', 'Azn', 17, 1),
+	(19, 'O0', 'afro.gif', 'Afro', 18, 1);
+---#
+
+---# Dropping "log_search" and recreating it...
+DROP TABLE IF EXISTS {$db_prefix}log_search;
+CREATE TABLE {$db_prefix}log_search (
+	ID_SEARCH tinyint(3) unsigned NOT NULL default '0',
+	ID_TOPIC mediumint(8) unsigned NOT NULL default '0',
+	ID_MSG int(10) unsigned NOT NULL default '0',
+	relevance smallint(5) unsigned NOT NULL default '0',
+	num_matches smallint(5) unsigned NOT NULL default '0',
+	PRIMARY KEY (ID_SEARCH, ID_TOPIC)
+) ENGINE=MyISAM;
+---#
+
+---# Dropping "sessions" and recreating it...
+DROP TABLE IF EXISTS {$db_prefix}sessions;
+CREATE TABLE {$db_prefix}sessions (
+	session_id char(32) NOT NULL,
+	last_update int(10) unsigned NOT NULL,
+	data text NOT NULL,
+	PRIMARY KEY (session_id)
+) ENGINE=MyISAM;
+---#
+
+---# Verifying "settings"...
+ALTER IGNORE TABLE {$db_prefix}settings
+DROP PRIMARY KEY,
+ADD PRIMARY KEY (variable(30));
+---#
+
+/******************************************************************************/
+--- Converting activity logs...
+/******************************************************************************/
+
+---# Converting "log_online"...
+DROP TABLE IF EXISTS {$db_prefix}log_online;
+CREATE TABLE {$db_prefix}log_online (
+	session char(32) NOT NULL default '                                ',
+	logTime timestamp,
+	ID_MEMBER mediumint(8) unsigned NOT NULL default '0',
+	ip int(11) unsigned NOT NULL default '0',
+	url text NOT NULL default '',
+	PRIMARY KEY (session),
+	KEY online (logTime, ID_MEMBER),
+	KEY ID_MEMBER (ID_MEMBER)
+) ENGINE=MyISAM;
+---#
+
+---# Converting "log_floodcontrol"...
+DROP TABLE IF EXISTS {$db_prefix}log_floodcontrol;
+CREATE TABLE {$db_prefix}log_floodcontrol (
+	ip tinytext NOT NULL default '',
+	logTime int(10) unsigned NOT NULL default '0',
+	PRIMARY KEY (ip(16)),
+	KEY logTime (logTime)
+) ENGINE=MyISAM;
+---#
+
+---# Converting "log_karma"...
+DROP TABLE IF EXISTS {$db_prefix}log_karma;
+CREATE TABLE {$db_prefix}log_karma (
+	ID_TARGET mediumint(8) unsigned NOT NULL default '0',
+	ID_EXECUTOR mediumint(8) unsigned NOT NULL default '0',
+	logTime int(10) unsigned NOT NULL default '0',
+	action tinyint(4) NOT NULL default '0',
+	PRIMARY KEY (ID_TARGET, ID_EXECUTOR),
+	KEY logTime (logTime)
+) ENGINE=MyISAM;
+---#
+
+---# Retiring "log_clicks"...
+DROP TABLE IF EXISTS {$db_prefix}log_clicks;
+---#
+
+---# Converting "log_notify"...
+INSERT INTO {$db_prefix}log_notify
+SELECT ID_MEMBER, ID_TOPIC, 0, notificationSent
+FROM {$db_prefix}log_topics
+WHERE notificationSent != 0;
+
+ALTER TABLE {$db_prefix}log_topics
+DROP notificationSent;
+---#
+
+---# Converting "log_errors"...
+ALTER TABLE {$db_prefix}log_errors
+CHANGE COLUMN ID_ERROR ID_ERROR mediumint(8) unsigned NOT NULL auto_increment,
+ADD session char(32) NOT NULL default '                                ';
+---#
+
+---# Converting "log_boards"...
+---{
+$request = upgrade_query("
+	SELECT lmr.ID_BOARD, lmr.ID_MEMBER, lmr.logTime
+	FROM {$db_prefix}log_mark_read AS lmr
+		LEFT JOIN {$db_prefix}log_boards AS lb ON (lb.ID_BOARD = lmr.ID_BOARD AND lb.ID_MEMBER = lmr.ID_MEMBER)
+	WHERE lb.logTime < lmr.logTime");
+$replaceRows = '';
+while ($row = mysql_fetch_assoc($request))
+	$replaceRows .= "($row[ID_BOARD], $row[ID_MEMBER], $row[logTime]),";
+mysql_free_result($request);
+if (!empty($replaceRows))
+{
+	$replaceRows = substr($replaceRows, 0, -1);
+
+	upgrade_query("
+		REPLACE INTO {$db_prefix}log_boards
+			(ID_BOARD, ID_MEMBER, logTime)
+		VALUES $replaceRows");
+}
+---}
+---#
+
+---# Converting "log_activity"...
+ALTER TABLE {$db_prefix}log_activity
+ADD date date NOT NULL default '0001-01-01';
+
+ALTER TABLE {$db_prefix}log_activity
+DROP PRIMARY KEY;
+
+UPDATE IGNORE {$db_prefix}log_activity
+SET date = year * 10000 + month * 100 + day;
+
+ALTER TABLE {$db_prefix}log_activity
+DROP day,
+DROP month,
+DROP year;
+
+ALTER TABLE {$db_prefix}log_activity
+ADD INDEX hits (hits);
+ALTER TABLE {$db_prefix}log_activity
+ADD PRIMARY KEY (date);
+
+ALTER TABLE {$db_prefix}log_activity
+CHANGE COLUMN hits hits mediumint(8) unsigned NOT NULL default '0',
+CHANGE COLUMN topics topics smallint(5) unsigned NOT NULL default '0',
+CHANGE COLUMN posts posts smallint(5) unsigned NOT NULL default '0',
+CHANGE COLUMN registers registers smallint(5) unsigned NOT NULL default '0',
+CHANGE COLUMN most_on most_on smallint(5) unsigned NOT NULL default '0';
+---#
+
+/******************************************************************************/
+--- Converting Boards and Categories...
+/******************************************************************************/
+
+---# Adding new columns to "boards"...
+ALTER TABLE {$db_prefix}boards
+CHANGE COLUMN count countPosts tinyint(4) NOT NULL default '0',
+ADD lastUpdated int(11) unsigned NOT NULL default '0',
+ADD ID_PARENT smallint(5) unsigned NOT NULL default '0',
+ADD ID_LAST_MSG int(10) unsigned NOT NULL default '0',
+ADD childLevel tinyint(4) unsigned NOT NULL default '0';
+---#
+
+---# Updating the structure of "boards"...
+ALTER TABLE {$db_prefix}boards
+CHANGE COLUMN boardOrder boardOrder smallint(5) NOT NULL default '0';
+
+ALTER TABLE {$db_prefix}boards
+DROP isAnnouncement;
+ALTER TABLE {$db_prefix}boards
+ADD ID_THEME tinyint(4) unsigned NOT NULL default '0';
+ALTER TABLE {$db_prefix}boards
+ADD use_local_permissions tinyint(4) unsigned NOT NULL default '0';
+ALTER TABLE {$db_prefix}boards
+ADD override_theme tinyint(4) unsigned NOT NULL default '0';
+---#
+
+---# Reindexing "boards" (part 1)...
+ALTER TABLE {$db_prefix}boards
+DROP INDEX ID_CAT,
+DROP ID_LAST_TOPIC;
+ALTER TABLE {$db_prefix}boards
+DROP INDEX memberGroups;
+---#
+
+---# Reindexing "boards" (part 2)...
+ALTER TABLE {$db_prefix}boards
+ADD INDEX lastUpdated (lastUpdated),
+ADD INDEX memberGroups (memberGroups(48)),
+ADD UNIQUE INDEX categories (ID_CAT, ID_BOARD);
+---#
+
+---# Updating the column sizes on "boards"...
+ALTER TABLE {$db_prefix}boards
+DROP PRIMARY KEY,
+CHANGE COLUMN ID_CAT ID_CAT tinyint(4) unsigned NOT NULL default '0',
+CHANGE COLUMN numTopics numTopics mediumint(8) unsigned NOT NULL default '0',
+CHANGE COLUMN numPosts numPosts mediumint(8) unsigned NOT NULL default '0',
+CHANGE COLUMN description description text NOT NULL default '',
+CHANGE COLUMN ID_BOARD ID_BOARD smallint(5) unsigned NOT NULL auto_increment PRIMARY KEY;
+---#
+
+---# Updating access permissions...
+---{
+$member_groups = getMemberGroups();
+
+$result = upgrade_query("
+	ALTER TABLE {$db_prefix}boards
+	ADD memberGroups varchar(128) NOT NULL default '-1,0'");
+if ($result !== false)
+{
+	$result = upgrade_query("
+		SELECT TRIM(memberGroups) AS memberGroups, ID_CAT
+		FROM {$db_prefix}categories");
+	while ($row = mysql_fetch_assoc($result))
+	{
+		if (trim($row['memberGroups']) == '')
+			$groups = '-1,0,2';
+		else
+		{
+			$memberGroups = array_unique(explode(',', $row['memberGroups']));
+			$groups = array(2);
+			foreach ($memberGroups as $k => $check)
+			{
+				$memberGroups[$k] = trim($memberGroups[$k]);
+				if ($memberGroups[$k] == '' || !isset($member_groups[$memberGroups[$k]]) || $member_groups[$memberGroups[$k]] == 8)
+					continue;
+
+				$groups[] = $member_groups[$memberGroups[$k]];
+			}
+
+			$groups = implode(',', array_unique($groups));
+		}
+
+		upgrade_query("
+			UPDATE {$db_prefix}boards
+			SET memberGroups = '$groups', lastUpdated = " . time() . "
+			WHERE ID_CAT = $row[ID_CAT]");
+	}
+}
+---}
+
+ALTER TABLE {$db_prefix}categories
+DROP memberGroups;
+
+ALTER TABLE {$db_prefix}boards
+CHANGE COLUMN memberGroups memberGroups varchar(128) NOT NULL default '-1,0';
+---#
+
+---# Converting "categories"...
+ALTER TABLE {$db_prefix}categories
+DROP PRIMARY KEY,
+ADD canCollapse tinyint(1) NOT NULL default '1',
+CHANGE COLUMN ID_CAT ID_CAT tinyint(4) unsigned NOT NULL auto_increment PRIMARY KEY;
+---#
+
+---# Converting announcement permissions...
+---{
+$request = upgrade_query("
+	SHOW COLUMNS
+	FROM {$db_prefix}boards
+	LIKE 'notifyAnnouncements'");
+if (mysql_num_rows($request) > 0)
+{
+	$conversions = array(
+		'moderate_forum' => array('manage_membergroups', 'manage_bans'),
+		'admin_forum' => array('manage_permissions'),
+		'edit_forum' => array('manage_boards', 'manage_smileys', 'manage_attachments'),
+	);
+	foreach ($conversions as $original_permission => $new_permissions)
+	{
+		$setString = '';
+		$result = upgrade_query("
+			SELECT ID_GROUP, addDeny
+			FROM {$db_prefix}permissions
+			WHERE permission = '$original_permission'");
+		while ($row = mysql_fetch_assoc($result))
+			$setString .= "
+				('" . implode("', $row[ID_GROUP], $row[addDeny]),
+				('", $new_permissions) . "', $row[ID_GROUP], $row[addDeny]),";
+		mysql_free_result($result);
+
+		if ($setString != '')
+			upgrade_query("
+				INSERT IGNORE INTO {$db_prefix}permissions
+					(permission, ID_GROUP, addDeny)
+				VALUES" . substr($setString, 0, -1));
+	}
+}
+mysql_free_result($request);
+---}
+
+DELETE FROM {$db_prefix}permissions
+WHERE permission = 'edit_forum';
+
+ALTER TABLE {$db_prefix}boards
+DROP COLUMN notifyAnnouncements;
+---#
+
+---# Converting board statistics...
+---{
+$result = upgrade_query("
+	SELECT MAX(m.ID_MSG) AS ID_LAST_MSG, t.ID_BOARD
+	FROM ({$db_prefix}messages AS m, {$db_prefix}topics AS t)
+	WHERE m.ID_MSG = t.ID_LAST_MSG
+	GROUP BY t.ID_BOARD");
+$last_msgs = array();
+while ($row = mysql_fetch_assoc($result))
+	$last_msgs[] = $row['ID_LAST_MSG'];
+mysql_free_result($result);
+
+if (!empty($last_msgs))
+{
+	$result = upgrade_query("
+		SELECT m.ID_MSG, m.posterTime, t.ID_BOARD
+		FROM ({$db_prefix}messages AS m, {$db_prefix}topics AS t)
+		WHERE t.ID_TOPIC = m.ID_TOPIC
+			AND m.ID_MSG IN (" . implode(',', $last_msgs) . ")
+		LIMIT " . count($last_msgs));
+	while ($row = mysql_fetch_assoc($result))
+	{
+		upgrade_query("
+			UPDATE {$db_prefix}boards
+			SET ID_LAST_MSG = $row[ID_MSG], lastUpdated = " . (int) $row['posterTime'] . "
+			WHERE ID_BOARD = $row[ID_BOARD]
+			LIMIT 1");
+	}
+	mysql_free_result($result);
+}
+---}
+---#
+
+---# Converting "moderators"...
+---{
+$request = upgrade_query("
+	SHOW COLUMNS
+	FROM {$db_prefix}boards
+	LIKE 'moderators'");
+$do_moderators = mysql_num_rows($request) > 0;
+mysql_free_result($request);
+
+if ($do_moderators)
+{
+	$result = upgrade_query("
+		SELECT TRIM(moderators) AS moderators, ID_BOARD
+		FROM {$db_prefix}boards
+		WHERE TRIM(moderators) != ''");
+	while ($row = mysql_fetch_assoc($result))
+	{
+		$moderators = array_unique(explode(',', $row['moderators']));
+		foreach ($moderators as $k => $dummy)
+		{
+			$moderators[$k] = addslashes(trim($moderators[$k]));
+			if ($moderators[$k] == '')
+				unset($moderators[$k]);
+		}
+
+		if (!empty($moderators))
+		{
+			upgrade_query("
+				INSERT IGNORE INTO {$db_prefix}moderators
+					(ID_BOARD, ID_MEMBER)
+				SELECT $row[ID_BOARD], ID_MEMBER
+				FROM {$db_prefix}members
+				WHERE memberName IN ('" . implode("', '", $moderators) . "')
+				LIMIT " . count($moderators));
+		}
+	}
+}
+---}
+
+ALTER TABLE {$db_prefix}boards
+DROP moderators;
+---#
+
+---# Updating board order...
+---{
+$request = upgrade_query("
+	SELECT c.ID_CAT, c.catOrder, b.ID_BOARD, b.boardOrder
+	FROM {$db_prefix}categories AS c
+		LEFT JOIN {$db_prefix}boards AS b ON (b.ID_CAT = c.ID_CAT)
+	ORDER BY c.catOrder, b.childLevel, b.boardOrder, b.ID_BOARD");
+$catOrder = -1;
+$boardOrder = -1;
+$curCat = -1;
+while ($row = mysql_fetch_assoc($request))
+{
+	if ($curCat != $row['ID_CAT'])
+	{
+		$curCat = $row['ID_CAT'];
+		if (++$catOrder != $row['catOrder'])
+			upgrade_query("
+				UPDATE {$db_prefix}categories
+				SET catOrder = $catOrder
+				WHERE ID_CAT = $row[ID_CAT]
+				LIMIT 1");
+	}
+	if (!empty($row['ID_BOARD']) && ++$boardOrder != $row['boardOrder'])
+		upgrade_query("
+			UPDATE {$db_prefix}boards
+			SET boardOrder = $boardOrder
+			WHERE ID_BOARD = $row[ID_BOARD]
+			LIMIT 1");
+}
+mysql_free_result($request);
+---}
+---#
+
+---# Fixing possible issues with board access (part 1)...
+---{
+if (empty($modSettings['smfVersion']) || (substr($modSettings['smfVersion'], 0, 9) == '1.0 Beta ' && $modSettings['smfVersion'][9] <= 5))
+{
+	$all_groups = array();
+	$result = upgrade_query("
+		SELECT ID_GROUP
+		FROM {$db_prefix}membergroups");
+	while ($row = mysql_fetch_assoc($result))
+		$all_groups[] = $row['ID_GROUP'];
+	mysql_free_result($result);
+
+	$result = upgrade_query("
+		SELECT ID_BOARD, memberGroups
+		FROM {$db_prefix}boards
+		WHERE FIND_IN_SET(0, memberGroups)");
+	while ($row = mysql_fetch_assoc($result))
+	{
+		upgrade_query("
+			UPDATE {$db_prefix}boards
+			SET memberGroups = '" . implode(',', array_unique(array_merge(explode(',', $row['memberGroups']), $all_groups))) . "'
+			WHERE ID_BOARD = $row[ID_BOARD]
+			LIMIT 1");
+	}
+	mysql_free_result($result);
+}
+---}
+---#
+
+---# Fixing possible issues with board access. (part 2)..
+UPDATE {$db_prefix}boards
+SET memberGroups = SUBSTRING(memberGroups, 2)
+WHERE SUBSTRING(memberGroups, 1, 1) = ',';
+
+UPDATE {$db_prefix}boards
+SET memberGroups = SUBSTRING(memberGroups, 1, LENGTH(memberGroups) - 1)
+WHERE SUBSTRING(memberGroups, LENGTH(memberGroups)) = ',';
+
+UPDATE {$db_prefix}boards
+SET memberGroups = REPLACE(',,', ',', REPLACE(',,', ',', memberGroups))
+WHERE LOCATE(',,', memberGroups);
+---#
+
+/******************************************************************************/
+--- Converting attachments, topics, and messages...
+/******************************************************************************/
+
+---# Converting "attachments"...
+INSERT INTO {$db_prefix}attachments
+	(ID_MSG, filename, size)
+SELECT ID_MSG, SUBSTRING(attachmentFilename, 1, 255), attachmentSize
+FROM {$db_prefix}messages
+WHERE attachmentFilename IS NOT NULL
+	AND attachmentFilename != '';
+
+ALTER TABLE {$db_prefix}messages
+DROP attachmentSize,
+DROP attachmentFilename;
+---#
+
+---# Updating "attachments"...
+ALTER TABLE {$db_prefix}attachments
+DROP INDEX ID_MEMBER,
+ADD UNIQUE ID_MEMBER (ID_MEMBER, ID_ATTACH);
+
+ALTER TABLE {$db_prefix}attachments
+CHANGE COLUMN size size int(10) unsigned NOT NULL default '0';
+---#
+
+---# Updating columns on "messages" (part 1)...
+ALTER TABLE {$db_prefix}messages
+DROP PRIMARY KEY,
+CHANGE COLUMN ID_MSG ID_MSG int(10) unsigned NOT NULL auto_increment PRIMARY KEY;
+---#
+
+---# Updating columns on "messages" (part 2)...
+ALTER TABLE {$db_prefix}messages
+CHANGE COLUMN ID_TOPIC ID_TOPIC mediumint(8) unsigned NOT NULL default '0';
+ALTER TABLE {$db_prefix}messages
+CHANGE COLUMN smiliesEnabled smileysEnabled tinyint(4) NOT NULL default '1';
+---#
+
+---# Updating columns on "messages" (part 3)...
+ALTER TABLE {$db_prefix}messages
+CHANGE COLUMN posterTime posterTime int(10) unsigned NOT NULL default '0',
+CHANGE COLUMN modifiedTime modifiedTime int(10) unsigned NOT NULL default '0';
+
+ALTER TABLE {$db_prefix}messages
+ADD INDEX participation (ID_MEMBER, ID_TOPIC);
+ALTER TABLE {$db_prefix}messages
+ADD INDEX ipIndex (posterIP(15), ID_TOPIC);
+---#
+
+---# Updating columns on "messages" (part 4)...
+ALTER TABLE {$db_prefix}messages
+CHANGE COLUMN ID_MEMBER ID_MEMBER mediumint(8) unsigned NOT NULL default '0',
+CHANGE COLUMN icon icon varchar(16) NOT NULL default 'xx';
+
+ALTER TABLE {$db_prefix}messages
+ADD INDEX ID_MEMBER (ID_MEMBER);
+ALTER TABLE {$db_prefix}messages
+ADD UNIQUE INDEX topic (ID_TOPIC, ID_MSG);
+---#
+
+---# Updating columns on "messages" (part 5)...
+ALTER TABLE {$db_prefix}messages
+ADD COLUMN ID_BOARD smallint(5) unsigned NOT NULL default '0';
+---#
+
+---# Updating data in "messages"...
+---{
+while (true)
+{
+	nextSubstep($substep);
+
+	$request = upgrade_query("
+		SELECT DISTINCT t.ID_BOARD, t.ID_TOPIC
+		FROM ({$db_prefix}messages AS m, {$db_prefix}topics AS t)
+		WHERE t.ID_TOPIC = m.ID_TOPIC
+			AND m.ID_BOARD = 0
+		LIMIT 1400");
+	$boards = array();
+	while ($row = mysql_fetch_assoc($request))
+		$boards[$row['ID_BOARD']][] = $row['ID_TOPIC'];
+
+	foreach ($boards as $board => $topics)
+		upgrade_query("
+			UPDATE {$db_prefix}messages
+			SET ID_BOARD = $board
+			WHERE ID_TOPIC IN (" . implode(', ', $topics) . ')');
+
+	if (mysql_num_rows($request) < 1400)
+		break;
+
+	mysql_free_result($request);
+}
+---}
+---#
+
+---# Cleaning up "messages"...
+ALTER TABLE {$db_prefix}messages
+ADD INDEX ID_BOARD (ID_BOARD);
+
+ALTER TABLE {$db_prefix}messages
+DROP INDEX posterTime_2;
+ALTER TABLE {$db_prefix}messages
+DROP INDEX posterTime_3;
+
+ALTER TABLE {$db_prefix}messages
+DROP INDEX ID_MEMBER_2;
+ALTER TABLE {$db_prefix}messages
+DROP INDEX ID_MEMBER_3;
+---#
+
+---# Updating indexes on "topics" (part 1)...
+ALTER TABLE {$db_prefix}topics
+DROP INDEX ID_FIRST_MSG;
+
+ALTER TABLE {$db_prefix}topics
+DROP INDEX ID_LAST_MSG;
+
+ALTER TABLE {$db_prefix}topics
+ADD INDEX isSticky (isSticky);
+---#
+
+---# Updating indexes on "topics" (part 2)...
+ALTER IGNORE TABLE {$db_prefix}topics
+ADD UNIQUE INDEX lastMessage (ID_LAST_MSG, ID_BOARD),
+ADD UNIQUE INDEX firstMessage (ID_FIRST_MSG, ID_BOARD),
+ADD UNIQUE INDEX poll (ID_POLL, ID_TOPIC);
+---#
+
+---# Updating columns on "topics" (part 1)...
+ALTER TABLE {$db_prefix}topics
+DROP PRIMARY KEY,
+CHANGE COLUMN ID_TOPIC ID_TOPIC mediumint(8) unsigned NOT NULL auto_increment PRIMARY KEY,
+CHANGE COLUMN ID_BOARD ID_BOARD smallint(5) unsigned NOT NULL default '0';
+---#
+
+---# Updating columns on "topics" (part 2)...
+ALTER TABLE {$db_prefix}topics
+CHANGE COLUMN ID_MEMBER_STARTED ID_MEMBER_STARTED mediumint(8) unsigned NOT NULL default '0',
+CHANGE COLUMN ID_MEMBER_UPDATED ID_MEMBER_UPDATED mediumint(8) unsigned NOT NULL default '0';
+---#
+
+---# Updating columns on "topics" (part 3)...
+ALTER TABLE {$db_prefix}topics
+CHANGE COLUMN ID_FIRST_MSG ID_FIRST_MSG int(10) unsigned NOT NULL default '0',
+CHANGE COLUMN ID_LAST_MSG ID_LAST_MSG int(10) unsigned NOT NULL default '0';
+---#
+
+---# Updating columns on "topics" (part 4)...
+ALTER TABLE {$db_prefix}topics
+CHANGE COLUMN ID_POLL ID_POLL mediumint(8) unsigned NOT NULL default '0';
+---#
+
+/******************************************************************************/
+--- Converting members and personal messages...
+/******************************************************************************/
+
+---# Updating data in "members" (part 1)...
+UPDATE IGNORE {$db_prefix}members
+SET im_ignore_list = '*'
+WHERE im_ignore_list RLIKE '([\n,]|^)[*]([\n,]|$)';
+---#
+
+---# Updating data in "members" (part 2)...
+---{
+$request = upgrade_query("
+	SHOW COLUMNS
+	FROM {$db_prefix}members
+	LIKE 'im_ignore_list'");
+$do_it = mysql_num_rows($request) != 0;
+mysql_free_result($request);
+
+while ($do_it)
+{
+	nextSubstep($substep);
+
+	$request = upgrade_query("
+		SELECT ID_MEMBER, im_ignore_list
+		FROM {$db_prefix}members
+		WHERE im_ignore_list RLIKE '[a-z]'
+		LIMIT 512");
+	while ($row = mysql_fetch_assoc($request))
+	{
+		$request2 = upgrade_query("
+			SELECT ID_MEMBER
+			FROM {$db_prefix}members
+			WHERE FIND_IN_SET(memberName, '" . addslashes($row['im_ignore_list']) . "')");
+		$im_ignore_list = '';
+		while ($row2 = mysql_fetch_assoc($request2))
+			$im_ignore_list .= ',' . $row2['ID_MEMBER'];
+		mysql_free_result($request2);
+
+		upgrade_query("
+			UPDATE {$db_prefix}members
+			SET im_ignore_list = '" . substr($im_ignore_list, 1) . "'
+			WHERE ID_MEMBER = $row[ID_MEMBER]
+			LIMIT 1");
+	}
+	if (mysql_num_rows($request) < 512)
+		break;
+	mysql_free_result($request);
+}
+---}
+---#
+
+---# Updating data in "members" (part 3)...
+UPDATE {$db_prefix}members
+SET realName = memberName
+WHERE IFNULL(realName, '') = '';
+---#
+
+---# Updating data in "members" (part 4)...
+UPDATE {$db_prefix}members
+SET lngfile = REPLACE(lngfile, '.lng', '')
+WHERE lngfile LIKE '%.lng';
+---#
+
+---# Cleaning up "members"...
+ALTER TABLE {$db_prefix}members
+DROP INDEX memberID;
+ALTER TABLE {$db_prefix}members
+DROP INDEX memberID_2;
+---#
+
+---# Adding new columns to "members"...
+ALTER TABLE {$db_prefix}members
+DROP PRIMARY KEY,
+CHANGE COLUMN ID_MEMBER ID_MEMBER mediumint(8) unsigned NOT NULL auto_increment PRIMARY KEY,
+ADD instantMessages smallint(5) NOT NULL default 0,
+ADD unreadMessages smallint(5) NOT NULL default 0,
+ADD ID_THEME tinyint(4) unsigned NOT NULL default 0,
+ADD ID_GROUP smallint(5) unsigned NOT NULL default 0,
+ADD is_activated tinyint(3) unsigned NOT NULL default '1',
+ADD validation_code varchar(10) NOT NULL default '',
+ADD ID_MSG_LAST_VISIT int(10) unsigned NOT NULL default '0',
+ADD additionalGroups tinytext NOT NULL default '';
+---#
+
+---# Updating columns on "members"...
+ALTER TABLE {$db_prefix}members
+CHANGE COLUMN ID_THEME ID_THEME tinyint(4) unsigned NOT NULL default 0;
+ALTER TABLE {$db_prefix}members
+ADD showOnline tinyint(4) NOT NULL default '1';
+ALTER TABLE {$db_prefix}members
+ADD smileySet varchar(48) NOT NULL default '';
+ALTER TABLE {$db_prefix}members
+ADD totalTimeLoggedIn int(10) unsigned NOT NULL default '0';
+ALTER TABLE {$db_prefix}members
+ADD passwordSalt varchar(5) NOT NULL default '';
+---#
+
+---# Updating data in "members" (part 5)...
+UPDATE {$db_prefix}members
+SET gender = CASE gender
+	WHEN '0' THEN 0
+	WHEN 'Male' THEN 1
+	WHEN 'Female' THEN 2
+	ELSE 0 END, secretAnswer = IF(secretAnswer = '', '', MD5(secretAnswer))
+WHERE gender NOT IN ('0', '1', '2');
+---#
+
+---# Updating data in "members" (part 6)...
+---{
+$member_groups = getMemberGroups();
+
+foreach ($member_groups as $name => $id)
+{
+	upgrade_query("
+		UPDATE IGNORE {$db_prefix}members
+		SET ID_GROUP = $id
+		WHERE memberGroup = '" . addslashes($name) . "'");
+
+	nextSubstep($substep);
+}
+---}
+UPDATE IGNORE {$db_prefix}members
+SET ID_GROUP = 1
+WHERE memberGroup = 'Administrator';
+UPDATE IGNORE {$db_prefix}members
+SET ID_GROUP = 2
+WHERE memberGroup = 'Global Moderator';
+
+ALTER TABLE {$db_prefix}members
+DROP memberGroup;
+---#
+
+---# Changing column sizes on "members" (part 1)...
+ALTER TABLE {$db_prefix}members
+CHANGE COLUMN timeOffset timeOffset float NOT NULL default '0',
+CHANGE COLUMN posts posts mediumint(8) unsigned NOT NULL default '0',
+CHANGE COLUMN timeFormat timeFormat varchar(80) NOT NULL default '',
+CHANGE COLUMN lastLogin lastLogin int(11) NOT NULL default '0',
+CHANGE COLUMN karmaBad karmaBad smallint(5) unsigned NOT NULL default '0',
+CHANGE COLUMN karmaGood karmaGood smallint(5) unsigned NOT NULL default '0',
+CHANGE COLUMN gender gender tinyint(4) unsigned NOT NULL default '0',
+CHANGE COLUMN hideEmail hideEmail tinyint(4) NOT NULL default '0';
+---#
+
+---# Changing column sizes on "members" (part 2)...
+ALTER TABLE {$db_prefix}members
+DROP INDEX realName;
+
+ALTER TABLE {$db_prefix}members
+CHANGE COLUMN AIM AIM varchar(16) NOT NULL default '',
+CHANGE COLUMN YIM YIM varchar(32) NOT NULL default '',
+CHANGE COLUMN ICQ ICQ tinytext NOT NULL default '',
+CHANGE COLUMN realName realName tinytext NOT NULL default '',
+CHANGE COLUMN emailAddress emailAddress tinytext NOT NULL default '',
+CHANGE COLUMN dateRegistered dateRegistered int(10) unsigned NOT NULL default '0',
+CHANGE COLUMN passwd passwd varchar(64) NOT NULL default '',
+CHANGE COLUMN personalText personalText tinytext NOT NULL default '',
+CHANGE COLUMN websiteTitle websiteTitle tinytext NOT NULL default '';
+---#
+
+---# Changing column sizes on "members" (part 3)...
+ALTER TABLE {$db_prefix}members
+DROP INDEX lngfile;
+
+ALTER TABLE {$db_prefix}members
+CHANGE COLUMN websiteUrl websiteUrl tinytext NOT NULL default '',
+CHANGE COLUMN location location tinytext NOT NULL default '',
+CHANGE COLUMN avatar avatar tinytext NOT NULL default '',
+CHANGE COLUMN im_ignore_list im_ignore_list tinytext NOT NULL default '',
+CHANGE COLUMN usertitle usertitle tinytext NOT NULL default '',
+CHANGE COLUMN lngfile lngfile tinytext NOT NULL default '',
+CHANGE COLUMN MSN MSN tinytext NOT NULL default '',
+CHANGE COLUMN memberIP memberIP tinytext NOT NULL default '',
+ADD INDEX lngfile (lngfile(24));
+---#
+
+---# Updating keys on "members"...
+ALTER TABLE {$db_prefix}members
+ADD INDEX ID_GROUP (ID_GROUP),
+ADD INDEX birthdate (birthdate),
+ADD INDEX lngfile (lngfile(30));
+---#
+
+---# Converting member statistics...
+REPLACE INTO {$db_prefix}settings
+	(variable, value)
+SELECT 'latestMember', ID_MEMBER
+FROM {$db_prefix}members
+ORDER BY ID_MEMBER DESC
+LIMIT 1;
+
+REPLACE INTO {$db_prefix}settings
+	(variable, value)
+SELECT 'latestRealName', IFNULL(realName, memberName)
+FROM {$db_prefix}members
+ORDER BY ID_MEMBER DESC
+LIMIT 1;
+
+REPLACE INTO {$db_prefix}settings
+	(variable, value)
+SELECT 'maxMsgID', ID_MSG
+FROM {$db_prefix}messages
+ORDER BY ID_MSG DESC
+LIMIT 1;
+---#
+
+---# Adding new columns to "instant_messages"...
+ALTER IGNORE TABLE {$db_prefix}instant_messages
+ADD COLUMN deletedBySender tinyint(3) unsigned NOT NULL default '0' AFTER ID_MEMBER_FROM;
+---#
+
+---# Changing column sizes on "instant_messages" (part 1)...
+ALTER TABLE {$db_prefix}instant_messages
+CHANGE COLUMN ID_MEMBER_FROM ID_MEMBER_FROM mediumint(8) unsigned NOT NULL default 0,
+CHANGE COLUMN msgtime msgtime int(10) unsigned NOT NULL default '0',
+CHANGE COLUMN subject subject tinytext NOT NULL;
+ALTER TABLE {$db_prefix}instant_messages
+DROP INDEX fromName,
+DROP INDEX ID_MEMBER_FROM;
+---#
+
+---# Changing column sizes on "instant_messages" (part 2)...
+ALTER TABLE {$db_prefix}instant_messages
+DROP PRIMARY KEY,
+CHANGE COLUMN ID_IM ID_PM int(10) unsigned NOT NULL auto_increment PRIMARY KEY;
+ALTER TABLE {$db_prefix}instant_messages
+ADD INDEX msgtime (msgtime);
+---#
+
+---# Cleaning up "instant_messages"...
+ALTER TABLE {$db_prefix}instant_messages
+DROP INDEX ID_MEMBER_FROM_2;
+ALTER TABLE {$db_prefix}instant_messages
+DROP INDEX ID_MEMBER_FROM_3;
+ALTER TABLE {$db_prefix}instant_messages
+DROP INDEX ID_MEMBER_FROM_4;
+ALTER TABLE {$db_prefix}instant_messages
+DROP INDEX ID_MEMBER_FROM_5;
+ALTER TABLE {$db_prefix}instant_messages
+DROP INDEX ID_MEMBER_TO_2;
+ALTER TABLE {$db_prefix}instant_messages
+DROP INDEX ID_MEMBER_TO_3;
+ALTER TABLE {$db_prefix}instant_messages
+DROP INDEX ID_MEMBER_TO_4;
+ALTER TABLE {$db_prefix}instant_messages
+DROP INDEX ID_MEMBER_TO_5;
+ALTER TABLE {$db_prefix}instant_messages
+DROP INDEX deletedBy_2;
+ALTER TABLE {$db_prefix}instant_messages
+DROP INDEX deletedBy_3;
+ALTER TABLE {$db_prefix}instant_messages
+DROP INDEX deletedBy_4;
+ALTER TABLE {$db_prefix}instant_messages
+DROP INDEX deletedBy_5;
+---#
+
+---# Creating "im_recipients"...
+CREATE TABLE IF NOT EXISTS {$db_prefix}im_recipients (
+	ID_PM int(10) unsigned NOT NULL default '0',
+	ID_MEMBER mediumint(8) unsigned NOT NULL default '0',
+	bcc tinyint(3) unsigned NOT NULL default '0',
+	is_read tinyint(3) unsigned NOT NULL default '0',
+	deleted tinyint(3) unsigned NOT NULL default '0',
+	PRIMARY KEY (ID_PM, ID_MEMBER),
+	KEY ID_MEMBER (ID_MEMBER, deleted)
+) ENGINE=MyISAM;
+---#
+
+---# Updating "im_recipients"...
+ALTER TABLE {$db_prefix}im_recipients
+DROP PRIMARY KEY,
+CHANGE COLUMN ID_IM ID_PM int(10) unsigned NOT NULL default '0',
+ADD PRIMARY KEY (ID_PM, ID_MEMBER);
+---#
+
+---# Updating data in "instant_messages" (part 1)...
+---{
+$request = mysql_query("
+	SHOW COLUMNS
+	FROM {$db_prefix}instant_messages
+	LIKE 'readBy'");
+$do_it = $request !== false;
+
+if ($do_it)
+{
+	$adv_im = mysql_num_rows($request) == 0;
+	mysql_free_result($request);
+
+	mysql_query("
+		INSERT IGNORE INTO {$db_prefix}im_recipients
+			(ID_PM, ID_MEMBER, bcc, is_read, deleted)
+		SELECT ID_PM, ID_MEMBER_TO, 0, IF(" . (!$adv_im ? 'readBy' : 'alerted') . " != 0, 1, 0), IF(deletedBy = '1', 1, 0)
+		FROM {$db_prefix}instant_messages");
+}
+---}
+
+UPDATE IGNORE {$db_prefix}instant_messages
+SET deletedBySender = 1
+WHERE deletedBy = 0;
+---#
+
+---# Updating data in "instant_messages" (part 2)...
+ALTER TABLE {$db_prefix}instant_messages
+DROP INDEX ID_MEMBER_TO;
+ALTER TABLE {$db_prefix}instant_messages
+DROP INDEX deletedBy;
+ALTER TABLE {$db_prefix}instant_messages
+DROP INDEX readBy;
+
+ALTER TABLE {$db_prefix}instant_messages
+DROP COLUMN ID_MEMBER_TO,
+DROP COLUMN deletedBy,
+DROP COLUMN toName,
+DROP COLUMN readBy;
+
+ALTER TABLE {$db_prefix}instant_messages
+ADD INDEX ID_MEMBER (ID_MEMBER_FROM, deletedBySender);
+---#
+
+---# Recounting personal message totals...
+---{
+$request = mysql_query("
+	SHOW CREATE TABLE {$db_prefix}instant_messages");
+$do_it = $request !== false;
+@mysql_free_result($request);
+
+$request = upgrade_query("
+	SELECT COUNT(*)
+	FROM {$db_prefix}members");
+list ($totalMembers) = mysql_fetch_row($request);
+mysql_free_result($request);
+
+$_GET['m'] = (int) @$_GET['m'];
+
+while ($_GET['m'] < $totalMembers && $do_it)
+{
+	nextSubstep($substep);
+
+	$mrequest = upgrade_query("
+		SELECT mem.ID_MEMBER, COUNT(pmr.ID_PM) AS instantMessages_real, mem.instantMessages
+		FROM {$db_prefix}members AS mem
+			LEFT JOIN {$db_prefix}im_recipients AS pmr ON (pmr.ID_MEMBER = mem.ID_MEMBER AND pmr.deleted = 0)
+		WHERE mem.ID_MEMBER > $_GET[m]
+			AND mem.ID_MEMBER <= $_GET[m] + 512
+		GROUP BY mem.ID_MEMBER
+		HAVING instantMessages_real != instantMessages
+		LIMIT 512");
+	while ($row = mysql_fetch_assoc($mrequest))
+	{
+		upgrade_query("
+			UPDATE {$db_prefix}members
+			SET instantMessages = $row[instantMessages_real]
+			WHERE ID_MEMBER = $row[ID_MEMBER]
+			LIMIT 1");
+	}
+
+	$_GET['m'] += 512;
+}
+unset($_GET['m']);
+---}
+---{
+$request = mysql_query("
+	SHOW CREATE TABLE {$db_prefix}instant_messages");
+$do_it = $request !== false;
+@mysql_free_result($request);
+
+$request = upgrade_query("
+	SELECT COUNT(*)
+	FROM {$db_prefix}members");
+list ($totalMembers) = mysql_fetch_row($request);
+mysql_free_result($request);
+
+$_GET['m'] = (int) @$_GET['m'];
+
+while ($_GET['m'] < $totalMembers && $do_it)
+{
+	nextSubstep($substep);
+
+	$mrequest = upgrade_query("
+		SELECT mem.ID_MEMBER, COUNT(pmr.ID_PM) AS unreadMessages_real, mem.unreadMessages
+		FROM {$db_prefix}members AS mem
+			LEFT JOIN {$db_prefix}im_recipients AS pmr ON (pmr.ID_MEMBER = mem.ID_MEMBER AND pmr.deleted = 0 AND pmr.is_read = 0)
+		WHERE mem.ID_MEMBER > $_GET[m]
+			AND mem.ID_MEMBER <= $_GET[m] + 512
+		GROUP BY mem.ID_MEMBER
+		HAVING unreadMessages_real != unreadMessages
+		LIMIT 512");
+	while ($row = mysql_fetch_assoc($mrequest))
+	{
+		upgrade_query("
+			UPDATE {$db_prefix}members
+			SET unreadMessages = $row[unreadMessages_real]
+			WHERE ID_MEMBER = $row[ID_MEMBER]
+			LIMIT 1");
+	}
+
+	$_GET['m'] += 512;
+}
+unset($_GET['m']);
+---}
+---#
+
+---# Converting "membergroups"...
+---{
+global $JrPostNum, $FullPostNum, $SrPostNum, $GodPostNum;
+
+$result = mysql_query("
+	SELECT minPosts
+	FROM {$db_prefix}membergroups
+	LIMIT 1");
+if ($result === false)
+{
+	upgrade_query("
+		RENAME TABLE {$db_prefix}membergroups TO {$db_prefix}old_membergroups");
+
+	upgrade_query("
+		CREATE TABLE {$db_prefix}membergroups (
+			ID_GROUP smallint(5) unsigned NOT NULL auto_increment,
+			groupName varchar(80) NOT NULL default '',
+			onlineColor varchar(20) NOT NULL default '',
+			minPosts mediumint(9) NOT NULL default '-1',
+			maxMessages smallint(5) unsigned NOT NULL default '0',
+			stars tinytext NOT NULL default '',
+			PRIMARY KEY (ID_GROUP),
+			KEY minPosts (minPosts)
+		) ENGINE=MyISAM");
+
+	upgrade_query("
+		INSERT INTO {$db_prefix}membergroups
+			(ID_GROUP, groupName, onlineColor, minPosts, stars)
+		SELECT ID_GROUP, membergroup, '#FF0000', -1, '5#staradmin.gif'
+		FROM {$db_prefix}old_membergroups
+		WHERE ID_GROUP = 1");
+
+	upgrade_query("
+		INSERT INTO {$db_prefix}membergroups
+			(ID_GROUP, groupName, onlineColor, minPosts, stars)
+		SELECT 2, membergroup, '#0000FF', -1, '5#stargmod.gif'
+		FROM {$db_prefix}old_membergroups
+		WHERE ID_GROUP = 8");
+
+	upgrade_query("
+		INSERT INTO {$db_prefix}membergroups
+			(ID_GROUP, groupName, onlineColor, minPosts, stars)
+		SELECT 3, membergroup, '', -1, '5#starmod.gif'
+		FROM {$db_prefix}old_membergroups
+		WHERE ID_GROUP = 2");
+
+	upgrade_query("
+		INSERT INTO {$db_prefix}membergroups
+			(ID_GROUP, groupName, onlineColor, minPosts, stars)
+		SELECT
+			ID_GROUP + 1, membergroup, '', CASE ID_GROUP
+				WHEN 3 THEN 0
+				WHEN 4 THEN '$JrPostNum'
+				WHEN 5 THEN '$FullPostNum'
+				WHEN 6 THEN '$SrPostNum'
+				WHEN 7 THEN '$GodPostNum'
+			END, CONCAT(ID_GROUP - 2, '#star.gif')
+		FROM {$db_prefix}old_membergroups
+		WHERE ID_GROUP IN (3, 4, 5, 6, 7)");
+
+	upgrade_query("
+		INSERT INTO {$db_prefix}membergroups
+			(ID_GROUP, groupName, onlineColor, minPosts, stars)
+		SELECT ID_GROUP, membergroup, '', -1, ''
+		FROM {$db_prefix}old_membergroups
+		WHERE ID_GROUP > 8");
+
+	upgrade_query("
+		DROP TABLE IF EXISTS {$db_prefix}old_membergroups");
+
+	$permissions = array(
+		'view_mlist',
+		'search_posts',
+		'profile_view_own',
+		'profile_view_any',
+		'pm_read',
+		'pm_send',
+		'calendar_view',
+		'view_stats',
+		'who_view',
+		'profile_identity_own',
+		'profile_extra_own',
+		'profile_remote_avatar',
+		'profile_remove_own',
+	);
+
+	foreach ($permissions as $perm)
+		upgrade_query("
+			INSERT INTO {$db_prefix}permissions
+				(ID_GROUP, permission)
+			SELECT IF(ID_GROUP = 1, 0, ID_GROUP), '$perm'
+			FROM {$db_prefix}membergroups
+			WHERE ID_GROUP != 3
+				AND minPosts = -1");
+
+	$board_permissions = array(
+		'remove_own',
+		'lock_own',
+		'mark_any_notify',
+		'mark_notify',
+		'modify_own',
+		'poll_add_own',
+		'poll_edit_own',
+		'poll_lock_own',
+		'poll_post',
+		'poll_view',
+		'poll_vote',
+		'post_attachment',
+		'post_new',
+		'post_reply_any',
+		'post_reply_own',
+		'delete_own',
+		'report_any',
+		'send_topic',
+		'view_attachments',
+	);
+
+	foreach ($board_permissions as $perm)
+		upgrade_query("
+			INSERT INTO {$db_prefix}board_permissions
+				(ID_GROUP, permission)
+			SELECT IF(ID_GROUP = 1, 0, ID_GROUP), '$perm'
+			FROM {$db_prefix}membergroups
+			WHERE minPosts = -1");
+}
+---}
+---#
+
+---# Converting "reserved_names"...
+---{
+$request = mysql_query("
+	SELECT setting, value
+	FROM {$db_prefix}reserved_names");
+if ($request !== false)
+{
+	$words = array();
+	$match_settings = array();
+	while ($row = mysql_fetch_assoc($request))
+	{
+		if (substr($row['setting'], 0, 5) == 'match')
+			$match_settings[$row['setting']] = $row['value'];
+		else
+			$words[] = $row['value'];
+	}
+	mysql_free_result($request);
+
+	upgrade_query("
+		INSERT IGNORE INTO {$db_prefix}settings
+		VALUES ('reserveWord', '" . (int) @$match_settings['matchword'] . "'),
+			('reserveCase', '" . (int) @$match_settings['matchcase'] . "'),
+			('reserveUser', '" . (int) @$match_settings['matchuser'] . "'),
+			('reserveName', '" . (int) @$match_settings['matchname'] . "'),
+			('reserveNames', '" . implode("\n", $words) . "')");
+
+	upgrade_query("
+		DROP TABLE {$db_prefix}reserved_names");
+}
+---}
+---#
+
+---# Converting member's groups...
+ALTER TABLE {$db_prefix}members
+ADD COLUMN ID_POST_GROUP smallint(5) unsigned NOT NULL default '0',
+ADD INDEX ID_POST_GROUP (ID_POST_GROUP);
+
+---{
+$request = upgrade_query("
+	SELECT ID_GROUP, minPosts
+	FROM {$db_prefix}membergroups
+	WHERE minPosts != -1
+	ORDER BY minPosts DESC");
+$post_groups = array();
+while ($row = mysql_fetch_assoc($request))
+	$post_groups[$row['minPosts']] = $row['ID_GROUP'];
+mysql_free_result($request);
+
+$request = upgrade_query("
+	SELECT ID_MEMBER, posts
+	FROM {$db_prefix}members");
+$mg_updates = array();
+while ($row = mysql_fetch_assoc($request))
+{
+	$group = 4;
+	foreach ($post_groups as $min_posts => $group_id)
+		if ($row['posts'] > $min_posts)
+		{
+			$group = $group_id;
+			break;
+		}
+
+	$mg_updates[$group][] = $row['ID_MEMBER'];
+}
+mysql_free_result($request);
+
+foreach ($mg_updates as $group_to => $update_members)
+	upgrade_query("
+		UPDATE {$db_prefix}members
+		SET ID_POST_GROUP = $group_to
+		WHERE ID_MEMBER IN (" . implode(', ', $update_members) . ")
+		LIMIT " . count($update_members));
+---}
+---#
+
+/******************************************************************************/
+--- Converting the calendar, notifications, and miscellaneous...
+/******************************************************************************/
+
+---# Converting censored words...
+---{
+if (!isset($modSettings['censor_vulgar']) || !isset($modSettings['censor_proper']))
+{
+	$request = upgrade_query("
+		SELECT vulgar, proper
+		FROM {$db_prefix}censor");
+	$censor_vulgar = array();
+	$censor_proper = array();
+	while ($row = mysql_fetch_row($request))
+	{
+		$censor_vulgar[] = trim($row[0]);
+		$censor_proper[] = trim($row[1]);
+	}
+	mysql_free_result($request);
+
+	$modSettings['censor_vulgar'] = addslashes(implode("\n", $censor_vulgar));
+	$modSettings['censor_proper'] = addslashes(implode("\n", $censor_proper));
+
+	upgrade_query("
+		INSERT IGNORE INTO {$db_prefix}settings
+			(variable, value)
+		VALUES
+			('censor_vulgar', '$modSettings[censor_vulgar]'),
+			('censor_proper', '$modSettings[censor_proper]')");
+
+	upgrade_query("
+		DROP TABLE IF EXISTS {$db_prefix}censor");
+}
+---}
+---#
+
+---# Converting topic notifications...
+---{
+$result = mysql_query("
+	SELECT COUNT(*)
+	FROM {$db_prefix}topics
+	WHERE notifies != ''");
+if ($result !== false)
+{
+	list ($numNotifies) = mysql_fetch_row($result);
+	mysql_free_result($result);
+
+	$_GET['t'] = (int) @$_GET['t'];
+
+	while ($_GET['t'] < $numNotifies)
+	{
+		nextSubstep($substep);
+
+		upgrade_query("
+			INSERT IGNORE INTO {$db_prefix}log_notify
+				(ID_MEMBER, ID_TOPIC)
+			SELECT mem.ID_MEMBER, t.ID_TOPIC
+			FROM ({$db_prefix}topics AS t, {$db_prefix}members AS mem)
+			WHERE FIND_IN_SET(mem.ID_MEMBER, t.notifies)
+				AND t.notifies != ''
+			LIMIT $_GET[t], 512");
+
+		$_GET['t'] += 512;
+	}
+	unset($_GET['t']);
+}
+---}
+
+ALTER TABLE {$db_prefix}topics
+DROP notifies;
+---#
+
+---# Converting "banned"...
+---{
+$request = mysql_query("
+	SELECT type, value
+	FROM {$db_prefix}banned
+	WHERE type = 'ip'");
+if ($request !== false)
+{
+	$insertEntries = array();
+	while ($row = mysql_fetch_assoc($request))
+	{
+		if (preg_match('~^\d{1,3}\.(\d{1,3}|\*)\.(\d{1,3}|\*)\.(\d{1,3}|\*)$~', $row['value']) == 0)
+			continue;
+
+		$ip_parts = ip2range($row['value']);
+		$insertEntries[] = "('ip_ban', {$ip_parts[0]['low']}, {$ip_parts[0]['high']}, {$ip_parts[1]['low']}, {$ip_parts[1]['high']}, {$ip_parts[2]['low']}, {$ip_parts[2]['high']}, {$ip_parts[3]['low']}, {$ip_parts[3]['high']}, '', '', 0, " . time() . ", NULL, 'full_ban', '', 'Imported from YaBB SE')";
+	}
+	mysql_free_result($request);
+
+	upgrade_query("
+		CREATE TABLE IF NOT EXISTS {$db_prefix}banned2 (
+			id_ban mediumint(8) unsigned NOT NULL auto_increment,
+			ban_type varchar(30) NOT NULL default '',
+			ip_low1 tinyint(3) unsigned NOT NULL default '0',
+			ip_high1 tinyint(3) unsigned NOT NULL default '0',
+			ip_low2 tinyint(3) unsigned NOT NULL default '0',
+			ip_high2 tinyint(3) unsigned NOT NULL default '0',
+			ip_low3 tinyint(3) unsigned NOT NULL default '0',
+			ip_high3 tinyint(3) unsigned NOT NULL default '0',
+			ip_low4 tinyint(3) unsigned NOT NULL default '0',
+			ip_high4 tinyint(3) unsigned NOT NULL default '0',
+			hostname tinytext NOT NULL default '',
+			email_address tinytext NOT NULL default '',
+			ID_MEMBER mediumint(8) unsigned NOT NULL default '0',
+			ban_time int(10) unsigned NOT NULL default '0',
+			expire_time int(10) unsigned,
+			restriction_type varchar(30) NOT NULL default '',
+			reason tinytext NOT NULL default '',
+			notes text NOT NULL default '',
+			PRIMARY KEY (id_ban)
+		) ENGINE=MyISAM");
+
+	upgrade_query("
+		INSERT INTO {$db_prefix}banned2
+			(ban_type, ip_low1, ip_high1, ip_low2, ip_high2, ip_low3, ip_high3, ip_low4, ip_high4, hostname, email_address, ID_MEMBER, ban_time, expire_time, restriction_type, reason, notes)
+		SELECT 'email_ban', 0, 0, 0, 0, 0, 0, 0, 0, '', value, 0, " . time() . ", NULL, 'full_ban', '', 'Imported from YaBB SE'
+		FROM {$db_prefix}banned
+		WHERE type = 'email'");
+
+	upgrade_query("
+		INSERT INTO {$db_prefix}banned2
+			(ban_type, ip_low1, ip_high1, ip_low2, ip_high2, ip_low3, ip_high3, ip_low4, ip_high4, hostname, email_address, ID_MEMBER, ban_time, expire_time, restriction_type, reason, notes)
+		SELECT 'user_ban', 0, 0, 0, 0, 0, 0, 0, 0, '', '', mem.ID_MEMBER, " . time() . ", NULL, 'full_ban', '', 'Imported from YaBB SE'
+		FROM ({$db_prefix}banned AS ban, {$db_prefix}members AS mem)
+		WHERE ban.type = 'username'
+			AND mem.memberName = ban.value");
+
+	upgrade_query("
+		DROP TABLE {$db_prefix}banned");
+	upgrade_query("
+		RENAME TABLE {$db_prefix}banned2 TO {$db_prefix}banned");
+
+	if (!empty($insertEntries))
+	{
+		upgrade_query("
+			INSERT INTO {$db_prefix}banned
+				(ban_type, ip_low1, ip_high1, ip_low2, ip_high2, ip_low3, ip_high3, ip_low4, ip_high4, hostname, email_address, ID_MEMBER, ban_time, expire_time, restriction_type, reason, notes)
+			VALUES " . implode(',', $insertEntries));
+	}
+}
+---}
+---#
+
+---# Updating "log_banned"...
+ALTER TABLE {$db_prefix}log_banned
+CHANGE COLUMN logTime logTime int(10) unsigned NOT NULL default '0';
+ALTER TABLE {$db_prefix}log_banned
+ADD COLUMN id_ban_log mediumint(8) unsigned NOT NULL auto_increment PRIMARY KEY FIRST,
+ADD COLUMN ID_MEMBER mediumint(8) unsigned NOT NULL default '0' AFTER id_ban_log,
+ADD INDEX logTime (logTime);
+---#
+
+---# Updating columns on "calendar"...
+ALTER TABLE {$db_prefix}calendar
+DROP PRIMARY KEY,
+CHANGE COLUMN id ID_EVENT smallint(5) unsigned NOT NULL auto_increment PRIMARY KEY,
+CHANGE COLUMN id_board ID_BOARD smallint(5) unsigned NOT NULL default '0',
+CHANGE COLUMN id_topic ID_TOPIC mediumint(8) unsigned NOT NULL default '0',
+CHANGE COLUMN id_member ID_MEMBER mediumint(8) unsigned NOT NULL default '0';
+ALTER TABLE {$db_prefix}calendar
+CHANGE COLUMN title title varchar(48) NOT NULL default '';
+
+ALTER TABLE {$db_prefix}calendar
+ADD eventDate date NOT NULL default '0000-00-00';
+---#
+
+---# Updating indexes on "calendar"...
+ALTER TABLE {$db_prefix}calendar
+DROP INDEX idx_year_month;
+ALTER TABLE {$db_prefix}calendar
+DROP INDEX year;
+---#
+
+---# Updating data in "calendar"...
+UPDATE IGNORE {$db_prefix}calendar
+SET eventDate = CONCAT(year, '-', month + 1, '-', day);
+
+ALTER TABLE {$db_prefix}calendar
+DROP year,
+DROP month,
+DROP day,
+ADD INDEX eventDate (eventDate);
+---#
+
+---# Updating structure on "calendar_holidays"...
+CREATE TABLE IF NOT EXISTS {$db_prefix}calendar_holidays (
+	ID_HOLIDAY smallint(5) unsigned NOT NULL auto_increment,
+	eventDate date NOT NULL default '0000-00-00',
+	title varchar(30) NOT NULL default '',
+	PRIMARY KEY (ID_HOLIDAY),
+	KEY eventDate (eventDate)
+) ENGINE=MyISAM;
+---#
+
+---# Updating data in "calendar_holidays"...
+---{
+$result = upgrade_query("
+	SELECT COUNT(*)
+	FROM {$db_prefix}calendar_holidays");
+list ($size) = mysql_fetch_row($result);
+mysql_free_result($result);
+
+if (empty($size))
+{
+	upgrade_query("
+		INSERT INTO {$db_prefix}calendar_holidays
+			(eventDate, title)
+		SELECT IF(year IS NULL, CONCAT('0000-', month, '-', day), CONCAT(year, '-', month, '-', day)), title
+		FROM {$db_prefix}calendar_holiday");
+
+	upgrade_query("
+		INSERT INTO {$db_prefix}calendar_holidays
+			(eventDate, title)
+		VALUES ('0000-06-06', 'D-Day')");
+}
+---}
+
+UPDATE {$db_prefix}calendar_holidays
+SET title = 'New Year\'s'
+WHERE title = 'New Years';
+---#
+
+/******************************************************************************/
+--- Converting polls and choices...
+/******************************************************************************/
+
+---# Converting data to "poll_choices"...
+INSERT INTO {$db_prefix}poll_choices
+	(ID_POLL, ID_CHOICE, label, votes)
+SELECT ID_POLL, 0, option1, votes1
+FROM {$db_prefix}polls;
+
+INSERT INTO {$db_prefix}poll_choices
+	(ID_POLL, ID_CHOICE, label, votes)
+SELECT ID_POLL, 1, option2, votes2
+FROM {$db_prefix}polls;
+
+INSERT INTO {$db_prefix}poll_choices
+	(ID_POLL, ID_CHOICE, label, votes)
+SELECT ID_POLL, 2, option3, votes3
+FROM {$db_prefix}polls;
+
+INSERT INTO {$db_prefix}poll_choices
+	(ID_POLL, ID_CHOICE, label, votes)
+SELECT ID_POLL, 3, option4, votes4
+FROM {$db_prefix}polls;
+
+INSERT INTO {$db_prefix}poll_choices
+	(ID_POLL, ID_CHOICE, label, votes)
+SELECT ID_POLL, 4, option5, votes5
+FROM {$db_prefix}polls;
+
+INSERT INTO {$db_prefix}poll_choices
+	(ID_POLL, ID_CHOICE, label, votes)
+SELECT ID_POLL, 5, option6, votes6
+FROM {$db_prefix}polls;
+
+INSERT INTO {$db_prefix}poll_choices
+	(ID_POLL, ID_CHOICE, label, votes)
+SELECT ID_POLL, 6, option7, votes7
+FROM {$db_prefix}polls;
+
+INSERT INTO {$db_prefix}poll_choices
+	(ID_POLL, ID_CHOICE, label, votes)
+SELECT ID_POLL, 7, option8, votes8
+FROM {$db_prefix}polls;
+---#
+
+---# Converting data to "log_polls"...
+---{
+$query = mysql_query("
+	SELECT ID_POLL, votedMemberIDs
+	FROM {$db_prefix}polls");
+if ($query !== false)
+{
+	$setStringLog = '';
+	while ($row = mysql_fetch_assoc($query))
+	{
+		$members = explode(',', $row['votedMemberIDs']);
+		foreach ($members as $member)
+			if (is_numeric($member) && !empty($member))
+				$setStringLog .= "
+				($row[ID_POLL], $member, 0),";
+	}
+
+	if (!empty($setStringLog))
+	{
+		upgrade_query("
+			INSERT IGNORE INTO {$db_prefix}log_polls
+				(ID_POLL, ID_MEMBER, ID_CHOICE)
+			VALUES " . substr($setStringLog, 0, -1));
+	}
+}
+---}
+---#
+
+---# Updating "polls"...
+ALTER TABLE {$db_prefix}polls
+DROP option1, DROP option2, DROP option3, DROP option4, DROP option5, DROP option6, DROP option7, DROP option8,
+DROP votes1, DROP votes2, DROP votes3, DROP votes4, DROP votes5, DROP votes6, DROP votes7, DROP votes8,
+DROP votedMemberIDs,
+DROP PRIMARY KEY,
+CHANGE COLUMN ID_POLL ID_POLL mediumint(8) unsigned NOT NULL auto_increment PRIMARY KEY,
+CHANGE COLUMN votingLocked votingLocked tinyint(1) NOT NULL default '0',
+CHANGE COLUMN question question tinytext NOT NULL default '',
+ADD maxVotes tinyint(4) unsigned NOT NULL default '1',
+ADD expireTime int(10) unsigned NOT NULL default '0',
+ADD hideResults tinyint(4) unsigned NOT NULL default '0';
+
+ALTER TABLE {$db_prefix}polls
+ADD ID_MEMBER mediumint(8) unsigned NOT NULL default '0',
+ADD posterName tinytext NOT NULL default '';
+ALTER TABLE {$db_prefix}polls
+ADD changeVote tinyint(4) unsigned NOT NULL default '0';
+---#
+
+---# Updating data in "polls"...
+---{
+$result = upgrade_query("
+	SELECT p.ID_POLL, t.ID_MEMBER_STARTED
+	FROM ({$db_prefix}topics AS t, {$db_prefix}messages AS m, {$db_prefix}polls AS p)
+	WHERE m.ID_MSG = t.ID_FIRST_MSG
+		AND p.ID_POLL = t.ID_POLL
+		AND p.ID_MEMBER = 0
+		AND t.ID_MEMBER_STARTED != 0");
+while ($row = mysql_fetch_assoc($result))
+{
+	upgrade_query("
+		UPDATE {$db_prefix}polls
+		SET ID_MEMBER = $row[ID_MEMBER_STARTED]
+		WHERE ID_POLL = $row[ID_POLL]
+		LIMIT 1");
+}
+mysql_free_result($result);
+---}
+---#
+
+/******************************************************************************/
+--- Converting settings...
+/******************************************************************************/
+
+---# Updating news...
+---{
+if (!isset($modSettings['smfVersion']))
+{
+	upgrade_query("
+		REPLACE INTO {$db_prefix}settings
+			(variable, value)
+		VALUES
+			('news', SUBSTRING('" . htmlspecialchars(stripslashes($modSettings['news']), ENT_QUOTES) . "', 1, 65534))");
+}
+---}
+---#
+
+---# Updating "themes"...
+---{
+convertSettingsToTheme();
+
+$insertRows = '';
+$request = upgrade_query("
+	SELECT ID_THEME, IF(value = '2', 5, value) AS value
+	FROM {$db_prefix}themes
+	WHERE variable = 'display_recent_bar'");
+while ($row = mysql_fetch_assoc($request))
+	$insertRows .= "($row[ID_THEME], 'number_recent_posts', '$row[value]'),";
+mysql_free_result($request);
+if (!empty($insertRows))
+{
+	$insertRows = substr($insertRows, 0, -1);
+	upgrade_query("
+		INSERT IGNORE INTO {$db_prefix}themes
+			(ID_THEME, variable, value)
+		VALUES $insertRows");
+}
+---}
+---#
+
+---# Updating "settings"...
+ALTER TABLE {$db_prefix}settings
+DROP INDEX variable;
+
+UPDATE IGNORE {$db_prefix}settings
+SET variable = 'guest_hideContacts'
+WHERE variable = 'guest_hideEmail'
+LIMIT 1;
+---#
+
+---# Adding new settings (part 1)...
+INSERT IGNORE INTO {$db_prefix}settings
+	(variable, value)
+VALUES
+	('news', ''),
+	('compactTopicPagesContiguous', '5'),
+	('compactTopicPagesEnable', '1'),
+	('enableStickyTopics', '1'),
+	('todayMod', '1'),
+	('karmaMode', '0'),
+	('karmaTimeRestrictAdmins', '1'),
+	('enablePreviousNext', '1'),
+	('pollMode', '1'),
+	('enableVBStyleLogin', '1'),
+	('enableCompressedOutput', '1'),
+	('karmaWaitTime', '1'),
+	('karmaMinPosts', '0'),
+	('karmaLabel', 'Karma:'),
+	('karmaSmiteLabel', '[smite]'),
+	('karmaApplaudLabel', '[applaud]'),
+	('attachmentSizeLimit', '128'),
+	('attachmentPostLimit', '192'),
+	('attachmentNumPerPostLimit', '4'),
+	('attachmentDirSizeLimit', '10240'),
+	('attachmentUploadDir', '{$sboarddir}/attachments'),
+	('attachmentExtensions', 'txt,doc,pdf,jpg,gif,mpg,png'),
+	('attachmentCheckExtensions', '1'),
+	('attachmentShowImages', '1'),
+	('attachmentEnable', '1'),
+	('attachmentEncryptFilenames', '1'),
+	('censorIgnoreCase', '1'),
+	('mostOnline', '1');
+INSERT IGNORE INTO {$db_prefix}settings
+	(variable, value)
+VALUES
+	('mostOnlineToday', '1'),
+	('mostDate', UNIX_TIMESTAMP()),
+	('trackStats', '1'),
+	('userLanguage', '1'),
+	('titlesEnable', '1'),
+	('topicSummaryPosts', '15'),
+	('enableErrorLogging', '1'),
+	('onlineEnable', '0'),
+	('cal_holidaycolor', '000080'),
+	('cal_bdaycolor', '920AC4'),
+	('cal_eventcolor', '078907'),
+	('cal_enabled', '0'),
+	('cal_maxyear', '2010'),
+	('cal_minyear', '2002'),
+	('cal_daysaslink', '0'),
+	('cal_defaultboard', ''),
+	('cal_showeventsonindex', '0'),
+	('cal_showbdaysonindex', '0'),
+	('cal_showholidaysonindex', '0'),
+	('cal_showweeknum', '0'),
+	('cal_maxspan', '7'),
+	('smtp_host', ''),
+	('smtp_username', ''),
+	('smtp_password', ''),
+	('mail_type', '0'),
+	('timeLoadPageEnable', '0'),
+	('totalTopics', '1'),
+	('totalMessages', '1'),
+	('simpleSearch', '0'),
+	('censor_vulgar', ''),
+	('censor_proper', ''),
+	('mostOnlineToday', '1'),
+	('enablePostHTML', '0'),
+	('theme_allow', '1'),
+	('theme_default', '1'),
+	('theme_guests', '1'),
+	('enableEmbeddedFlash', '0'),
+	('xmlnews_enable', '1'),
+	('xmlnews_maxlen', '255'),
+	('hotTopicPosts', '15'),
+	('hotTopicVeryPosts', '25'),
+	('allow_editDisplayName', '1'),
+	('number_format', '1234.00'),
+	('attachmentEncryptFilenames', '1'),
+	('autoLinkUrls', '1');
+INSERT IGNORE INTO {$db_prefix}settings
+	(variable, value)
+VALUES
+	('avatar_allow_server_stored', '1'),
+	('avatar_check_size', '0'),
+	('avatar_action_too_large', 'option_user_resize'),
+	('avatar_resize_upload', '1'),
+	('avatar_download_png', '1'),
+	('failed_login_threshold', '3'),
+	('edit_wait_time', '90'),
+	('autoFixDatabase', '1'),
+	('autoOptDatabase', '7'),
+	('autoOptMaxOnline', '0'),
+	('autoOptLastOpt', '0'),
+	('enableParticipation', '1'),
+	('recycle_enable', '0'),
+	('recycle_board', '0'),
+	('banLastUpdated', '0'),
+	('enableAllMessages', '0'),
+	('fixLongWords', '0'),
+	('knownThemes', '1,2'),
+	('who_enabled', '1'),
+	('lastActive', '15'),
+	('allow_hideOnline', '1'),
+	('guest_hideContacts', '0');
+---#
+
+---# Adding new settings (part 2)...
+---{
+upgrade_query("
+	INSERT IGNORE INTO {$db_prefix}settings
+		(variable, value)
+	VALUES
+		('registration_method', '" . (!empty($modSettings['registration_disabled']) ? 3 : (!empty($modSettings['approve_registration']) ? 2 : (!empty($GLOBALS['emailpassword']) || !empty($modSettings['send_validation']) ? 1 : 0))) . "'),
+		('send_validation_onChange', '" . @$GLOBALS['emailnewpass'] . "'),
+		('send_welcomeEmail', '" . @$GLOBALS['emailwelcome'] . "'),
+		('allow_hideEmail', '" . @$GLOBALS['allow_hide_email'] . "'),
+		('allow_guestAccess', '" . @$GLOBALS['guestaccess'] . "'),
+		('time_format', '" . (!empty($GLOBALS['timeformatstring']) ? $GLOBALS['timeformatstring'] : '%B %d, %Y, %I:%M:%S %p') . "'),
+		('enableBBC', '" . (!isset($GLOBALS['enable_ubbc']) ? 1 : $GLOBALS['enable_ubbc']) . "'),
+		('max_messageLength', '" . (empty($GLOBALS['MaxMessLen']) ? 10000 : $GLOBALS['MaxMessLen']) . "'),
+		('max_signatureLength', '" . @$GLOBALS['MaxSigLen'] . "'),
+		('spamWaitTime', '" . @$GLOBALS['timeout'] . "'),
+		('avatar_directory', '" . (isset($GLOBALS['facesdir']) ? fixRelativePath($GLOBALS['facesdir']) : fixRelativePath('./avatars')) . "'),
+		('avatar_url', '" . @$GLOBALS['facesurl'] . "'),
+		('avatar_max_height_external', '" . @$GLOBALS['userpic_height'] . "'),
+		('avatar_max_width_external', '" . @$GLOBALS['userpic_width'] . "'),
+		('avatar_max_height_upload', '" . @$GLOBALS['userpic_height'] . "'),
+		('avatar_max_width_upload', '" . @$GLOBALS['userpic_width'] . "'),
+		('defaultMaxMessages', '" . (empty($GLOBALS['maxmessagedisplay']) ? 15 : $GLOBALS['maxmessagedisplay']) . "'),
+		('defaultMaxTopics', '" . (empty($GLOBALS['maxdisplay']) ? 20 : $GLOBALS['maxdisplay']) . "'),
+		('defaultMaxMembers', '" . (empty($GLOBALS['MembersPerPage']) ? 20 : $GLOBALS['MembersPerPage']) . "'),
+		('time_offset', '" . @$GLOBALS['timeoffset'] . "'),
+		('cookieTime', '" . (empty($GLOBALS['Cookie_Length']) ? 60 : $GLOBALS['Cookie_Length']) . "'),
+		('requireAgreement', '" . @$GLOBALS['RegAgree'] . "')");
+---}
+
+INSERT IGNORE INTO {$db_prefix}settings
+	(variable, value)
+VALUES
+	('smileys_dir', '{$sboarddir}/Smileys'),
+	('smileys_url', '{$boardurl}/Smileys'),
+	('smiley_sets_known', 'default,classic'),
+	('smiley_sets_names', 'Default\nClassic'),
+	('smiley_sets_default', 'default'),
+	('censorIgnoreCase', '1'),
+	('cal_days_for_index', '7'),
+	('unapprovedMembers', '0'),
+	('default_personalText', ''),
+	('attachmentPostLimit', '192'),
+	('attachmentNumPerPostLimit', '4'),
+	('package_make_backups', '1'),
+	('databaseSession_loose', '1'),
+	('databaseSession_lifetime', '2880'),
+	('smtp_port', '25'),
+	('search_cache_size', '50'),
+	('search_results_per_page', '30'),
+	('search_weight_frequency', '30'),
+	('search_weight_age', '25'),
+	('search_weight_length', '20'),
+	('search_weight_subject', '15'),
+	('search_weight_first_message', '10');
+
+DELETE FROM {$db_prefix}settings
+WHERE variable = 'agreement'
+LIMIT 1;
+---#
+
+---# Converting settings to options...
+---{
+convertSettingsToOptions();
+---}
+---#
+
+---# Updating statistics...
+REPLACE INTO {$db_prefix}settings
+	(variable, value)
+SELECT 'latestMember', ID_MEMBER
+FROM {$db_prefix}members
+ORDER BY ID_MEMBER DESC
+LIMIT 1;
+
+REPLACE INTO {$db_prefix}settings
+	(variable, value)
+SELECT 'latestRealName', IFNULL(realName, memberName)
+FROM {$db_prefix}members
+ORDER BY ID_MEMBER DESC
+LIMIT 1;
+
+REPLACE INTO {$db_prefix}settings
+	(variable, value)
+SELECT 'maxMsgID', ID_MSG
+FROM {$db_prefix}messages
+ORDER BY ID_MSG DESC
+LIMIT 1;
+
+REPLACE INTO {$db_prefix}settings
+	(variable, value)
+SELECT 'totalMembers', COUNT(*)
+FROM {$db_prefix}members;
+
+REPLACE INTO {$db_prefix}settings
+	(variable, value)
+SELECT 'unapprovedMembers', COUNT(*)
+FROM {$db_prefix}members
+WHERE is_activated = 0
+	AND validation_code = '';
+
+REPLACE INTO {$db_prefix}settings
+	(variable, value)
+SELECT 'totalMessages', COUNT(*)
+FROM {$db_prefix}messages;
+
+REPLACE INTO {$db_prefix}settings
+	(variable, value)
+SELECT 'totalTopics', COUNT(*)
+FROM {$db_prefix}topics;
+
+REPLACE INTO {$db_prefix}settings
+	(variable, value)
+VALUES ('cal_today_updated', '00000000');
+---#

+ 2655 - 0
other/upgrade_1-1.sql

@@ -0,0 +1,2655 @@
+/* ATTENTION: You don't need to run or use this file!  The upgrade.php script does everything for you! */
+
+/******************************************************************************/
+--- Updating and creating indexes...
+/******************************************************************************/
+
+---# Updating indexes on "messages"...
+---{
+$request = upgrade_query("
+	SHOW KEYS
+	FROM {$db_prefix}messages");
+$found = false;
+while ($row = mysql_fetch_assoc($request))
+	$found |= $row['Key_name'] == 'ID_BOARD' && $row['Column_name'] == 'ID_MSG';
+mysql_free_result($request);
+
+if (!$found)
+	upgrade_query("
+		ALTER TABLE {$db_prefix}messages
+		DROP INDEX ID_BOARD");
+---}
+---#
+
+---# Updating table indexes...
+---{
+$_GET['mess_ind'] = isset($_GET['mess_ind']) ? (int) $_GET['mess_ind'] : 0;
+$step_progress['name'] = 'Updating table indexes';
+$step_progress['current'] = $_GET['mess_ind'];
+$custom_warning = 'On a very large board these indexes may take a few minutes to create.';
+
+$index_changes = array(
+	array(
+		'table' => 'log_errors',
+		'type' => 'index',
+		'method' => 'add',
+		'name' => 'ID_MEMBER',
+		'target_columns' => array('ID_MEMBER'),
+		'text' => 'ADD INDEX ID_MEMBER (ID_MEMBER)',
+	),
+	array(
+		'table' => 'log_errors',
+		'type' => 'index',
+		'method' => 'add',
+		'name' => 'IP',
+		'target_columns' => array('IP'),
+		'text' => 'ADD INDEX IP (IP(15))',
+	),
+	array(
+		'table' => 'log_online',
+		'type' => 'index',
+		'method' => 'add',
+		'name' => 'logTime',
+		'target_columns' => array('logTime'),
+		'text' => 'ADD INDEX logTime (logTime)',
+	),
+	array(
+		'table' => 'log_online',
+		'type' => 'index',
+		'method' => 'remove',
+		'name' => 'online',
+		'target_columns' => array('online'),
+		'text' => 'DROP INDEX online',
+	),
+	array(
+		'table' => 'smileys',
+		'type' => 'index',
+		'method' => 'remove',
+		'name' => 'smileyOrder',
+		'target_columns' => array('smileyOrder'),
+		'text' => 'DROP INDEX smileyOrder',
+	),
+	array(
+		'table' => 'boards',
+		'type' => 'index',
+		'method' => 'add',
+		'name' => 'ID_PARENT',
+		'target_columns' => array('ID_PARENT'),
+		'text' => 'ADD INDEX ID_PARENT (ID_PARENT)',
+	),
+	array(
+		'table' => 'boards',
+		'type' => 'index',
+		'method' => 'remove',
+		'name' => 'children',
+		'target_columns' => array('children'),
+		'text' => 'DROP INDEX children',
+	),
+	array(
+		'table' => 'boards',
+		'type' => 'index',
+		'method' => 'remove',
+		'name' => 'boardOrder',
+		'target_columns' => array('boardOrder'),
+		'text' => 'DROP INDEX boardOrder',
+	),
+	array(
+		'table' => 'categories',
+		'type' => 'index',
+		'method' => 'remove',
+		'name' => 'catOrder',
+		'target_columns' => array('catOrder'),
+		'text' => 'DROP INDEX catOrder',
+	),
+	array(
+		'table' => 'messages',
+		'type' => 'index',
+		'method' => 'add',
+		'name' => 'ID_TOPIC',
+		'target_columns' => array('ID_TOPIC'),
+		'text' => 'ADD INDEX ID_TOPIC (ID_TOPIC)',
+	),
+	array(
+		'table' => 'messages',
+		'type' => 'index',
+		'method' => 'remove',
+		'name' => 'ID_MEMBER',
+		'target_columns' => array('ID_MEMBER'),
+		'text' => 'DROP INDEX ID_MEMBER',
+	),
+	array(
+		'table' => 'messages',
+		'type' => 'index',
+		'method' => 'add',
+		'name' => 'ID_BOARD',
+		'target_columns' => array('ID_BOARD', 'ID_MSG'),
+		'text' => 'ADD UNIQUE ID_BOARD (ID_BOARD, ID_MSG)',
+	),
+	array(
+		'table' => 'messages',
+		'type' => 'index',
+		'method' => 'add',
+		'name' => 'ID_MEMBER',
+		'target_columns' => array('ID_MEMBER', 'ID_MSG'),
+		'text' => 'ADD UNIQUE ID_MEMBER (ID_MEMBER, ID_MSG)',
+	),
+	array(
+		'table' => 'messages',
+		'type' => 'index',
+		'method' => 'add',
+		'name' => 'showPosts',
+		'target_columns' => array('ID_MEMBER', 'ID_BOARD'),
+		'text' => 'ADD INDEX showPosts (ID_MEMBER, ID_BOARD)',
+	),
+);
+
+$step_progress['total'] = count($index_changes);
+
+// Now we loop through the changes and work out where the hell we are.
+foreach ($index_changes as $ind => $change)
+{
+	// Already done it?
+	if ($_GET['mess_ind'] > $ind)
+		continue;
+
+	// Make the index, with all the protection and all.
+	protected_alter($change, $substep);
+
+	// Store this for the next table.
+	$_GET['mess_ind']++;
+	$step_progress['current'] = $_GET['mess_ind'];
+}
+
+// Clean up.
+unset($_GET['mess_ind']);
+---}
+---#
+
+---# Reordering boards and categories...
+ALTER TABLE {$db_prefix}categories
+ORDER BY catOrder;
+
+ALTER TABLE {$db_prefix}boards
+ORDER BY boardOrder;
+---#
+
+---# Updating indexes and data on "smileys"...
+ALTER TABLE {$db_prefix}smileys
+CHANGE COLUMN smileyOrder smileyOrder smallint(5) unsigned NOT NULL default '0';
+
+UPDATE {$db_prefix}smileys
+SET filename = 'embarrassed.gif'
+WHERE filename = 'embarassed.gif';
+---#
+
+---# Updating indexes on "log_boards"...
+ALTER TABLE {$db_prefix}log_boards
+DROP PRIMARY KEY,
+ADD PRIMARY KEY (ID_MEMBER, ID_BOARD);
+---#
+
+---# Updating indexes on "log_mark_read"...
+ALTER TABLE {$db_prefix}log_mark_read
+DROP PRIMARY KEY,
+ADD PRIMARY KEY (ID_MEMBER, ID_BOARD);
+---#
+
+---# Updating indexes on "themes"...
+ALTER TABLE {$db_prefix}themes
+DROP PRIMARY KEY,
+ADD PRIMARY KEY (ID_THEME, ID_MEMBER, variable(30)),
+ADD INDEX ID_MEMBER (ID_MEMBER);
+---#
+
+/******************************************************************************/
+--- Reorganizing configuration settings...
+/******************************************************************************/
+
+---# Updating data in "settings"...
+REPLACE INTO {$db_prefix}settings
+	(variable, value)
+SELECT 'totalMembers', COUNT(*)
+FROM {$db_prefix}members;
+
+UPDATE {$db_prefix}settings
+SET variable = 'notify_new_registration'
+WHERE variable = 'notify_on_new_registration'
+LIMIT 1;
+
+UPDATE IGNORE {$db_prefix}settings
+SET variable = 'max_image_width'
+WHERE variable = 'maxwidth'
+LIMIT 1;
+
+UPDATE IGNORE {$db_prefix}settings
+SET variable = 'max_image_height'
+WHERE variable = 'maxheight'
+LIMIT 1;
+
+UPDATE {$db_prefix}settings
+SET value = IF(value = 'sendmail' OR value = '0', '0', '1')
+WHERE variable = 'mail_type'
+LIMIT 1;
+
+UPDATE IGNORE {$db_prefix}settings
+SET variable = 'search_method'
+WHERE variable = 'search_match_complete_words'
+LIMIT 1;
+
+UPDATE IGNORE {$db_prefix}settings
+SET variable = 'allow_disableAnnounce'
+WHERE variable = 'notifyAnncmnts_UserDisable'
+LIMIT 1;
+---#
+
+---# Adding new settings...
+INSERT IGNORE INTO {$db_prefix}settings
+	(variable, value)
+VALUES ('edit_disable_time', '0'),
+	('oldTopicDays', '120'),
+	('cal_showeventsoncalendar', '1'),
+	('cal_showbdaysoncalendar', '1'),
+	('cal_showholidaysoncalendar', '1'),
+	('allow_disableAnnounce', '1'),
+	('attachmentThumbnails', '1'),
+	('attachmentThumbWidth', '150'),
+	('attachmentThumbHeight', '150'),
+	('max_pm_recipients', '10');
+
+---{
+if (@$modSettings['smfVersion'] < '1.1')
+{
+	// Hopefully 90 days is enough?
+	upgrade_query("
+		INSERT INTO {$db_prefix}settings
+			(variable, value)
+		VALUES ('disableHashTime', " . (time() + 7776000) . ")");
+}
+
+if (isset($modSettings['smfVersion']) && $modSettings['smfVersion'] <= '1.1 Beta 4')
+{
+	// Enable the buddy list for those used to it.
+	upgrade_query("
+		INSERT INTO {$db_prefix}settings
+			(variable, value)
+		VALUES ('enable_buddylist', '1')");
+}
+---}
+---#
+
+---# Adding PM spam protection settings.
+---{
+if (empty($modSettings['pm_spam_settings']))
+{
+	if (isset($modSettings['max_pm_recipients']))
+		$modSettings['pm_spam_settings'] = (int) $modSettings['max_pm_recipients'] . ',5,20';
+	else
+		$modSettings['pm_spam_settings'] = '10,5,20';
+
+	upgrade_query("
+		INSERT IGNORE INTO {$db_prefix}settings
+			(variable, value)
+		VALUES
+			('pm_spam_settings', '$modSettings[pm_spam_settings]')");
+}
+upgrade_query("
+	DELETE FROM {$db_prefix}settings
+	WHERE variable = 'max_pm_recipients'");
+---}
+---#
+
+---# Cleaning old values from "settings"...
+DELETE FROM {$db_prefix}settings
+WHERE variable IN ('modlog_enabled', 'localCookies', 'globalCookies', 'send_welcomeEmail', 'search_method', 'notify_new_registration', 'removeNestedQuotes', 'smiley_enable', 'smiley_sets_enable')
+	AND value = '0';
+
+DELETE FROM {$db_prefix}settings
+WHERE variable IN ('allow_guestAccess', 'userLanguage', 'allow_editDisplayName', 'allow_hideOnline', 'allow_hideEmail', 'guest_hideContacts', 'titlesEnable', 'search_match_complete_words')
+	AND value = '0';
+
+DELETE FROM {$db_prefix}settings
+WHERE variable IN ('cal_allowspan', 'hitStats', 'queryless_urls', 'disableHostnameLookup', 'messageIcons_enable', 'disallow_sendBody', 'censorWholeWord')
+	AND value = '0';
+
+DELETE FROM {$db_prefix}settings
+WHERE variable IN (
+	'totalMessag',
+	'redirectMetaRefresh',
+	'memberCount',
+	'cal_today_u',
+	'approve_registration',
+	'registration_disabled',
+	'requireRegistrationVerification',
+	'returnToPost',
+	'send_validation',
+	'search_max_cached_results',
+	'disableTemporaryTables',
+	'search_cache_size',
+	'enableReportToMod'
+);
+---#
+
+---# Encoding SMTP password...
+---{
+// Can't do this more than once, we just can't...
+if ((!isset($modSettings['smfVersion']) || $modSettings['smfVersion'] <= '1.1 RC1') && empty($modSettings['dont_repeat_smtp']))
+{
+	if (!empty($modSettings['smtp_password']))
+	{
+		upgrade_query("
+			UPDATE {$db_prefix}settings
+			SET value = '" . base64_encode($modSettings['smtp_password']) . "'
+			WHERE variable = 'smtp_password'");
+	}
+	// Don't let this run twice!
+	upgrade_query("
+		REPLACE INTO {$db_prefix}settings
+			(variable, value)
+		VALUES
+			('dont_repeat_smtp', '1')");
+}
+
+---}
+---#
+
+---# Adjusting timezone settings...
+---{
+	if (!isset($modSettings['default_timezone']) && function_exists('date_default_timezone_set'))
+	{
+		$server_offset = mktime(0, 0, 0, 1, 1, 1970);
+		$timezone_id = 'Etc/GMT' . ($server_offset > 0 ? '+' : '') . ($server_offset / 3600);
+		if (date_default_timezone_set($timezone_id))
+			upgrade_query("
+				REPLACE INTO {$db_prefix}settings
+					(variable, value)
+				VALUES
+					('default_timezone', '$timezone_id')");
+	}
+---}
+---#
+
+/******************************************************************************/
+--- Installing new default theme...
+/******************************************************************************/
+
+---# Installing theme settings...
+---{
+// This is Grudge's secret "I'm not a developer" theme install code - keep this quiet ;)
+
+// Firstly, I'm going out of my way to not do this twice!
+if ((!isset($modSettings['smfVersion']) || $modSettings['smfVersion'] <= '1.1 RC1') && empty($modSettings['dont_repeat_theme']))
+{
+	// Check it's not already here, just incase.
+	$theme_request = upgrade_query("
+		SELECT ID_THEME
+		FROM {$db_prefix}themes
+		WHERE variable = 'theme_dir'
+			AND value LIKE '%babylon'");
+	// Only do the upgrade if it doesn't find the theme already.
+	if (mysql_num_rows($theme_request) == 0)
+	{
+		// Try to get some settings from the current default theme.
+		$request = upgrade_query("
+			SELECT t1.value AS theme_dir, t2.value AS theme_url, t3.value AS images_url
+			FROM ({$db_prefix}themes AS t1, {$db_prefix}themes AS t2, {$db_prefix}themes AS t3)
+			WHERE t1.ID_THEME = 1
+				AND t1.ID_MEMBER = 0
+				AND t1.variable = 'theme_dir'
+				AND t2.ID_THEME = 1
+				AND t2.ID_MEMBER = 0
+				AND t2.variable = 'theme_url'
+				AND t3.ID_THEME = 1
+				AND t3.ID_MEMBER = 0
+				AND t3.variable = 'images_url'
+			LIMIT 1");
+		if (mysql_num_rows($request) != 0)
+		{
+			$core = mysql_fetch_assoc($request);
+
+			if (substr_count($core['theme_dir'], 'default') === 1)
+				$babylon['theme_dir'] = strtr($core['theme_dir'], array('default' => 'babylon'));
+			if (substr_count($core['theme_url'], 'default') === 1)
+				$babylon['theme_url'] = strtr($core['theme_url'], array('default' => 'babylon'));
+			if (substr_count($core['images_url'], 'default') === 1)
+				$babylon['images_url'] = strtr($core['images_url'], array('default' => 'babylon'));
+		}
+		mysql_free_result($request);
+
+		if (!isset($babylon['theme_dir']))
+			$babylon['theme_dir'] = addslashes($GLOBALS['boarddir']) . '/Themes/babylon';
+		if (!isset($babylon['theme_url']))
+			$babylon['theme_url'] = $GLOBALS['boardurl'] . '/Themes/babylon';
+		if (!isset($babylon['images_url']))
+			$babylon['images_url'] = $GLOBALS['boardurl'] . '/Themes/babylon/images';
+
+		// Get an available ID_THEME first...
+		$request = upgrade_query("
+			SELECT MAX(ID_THEME) + 1
+			FROM {$db_prefix}themes");
+		list ($ID_OLD_THEME) = mysql_fetch_row($request);
+		mysql_free_result($request);
+
+		// Insert the babylon theme into the tables.
+		upgrade_query("
+			INSERT INTO {$db_prefix}themes
+				(ID_MEMBER, ID_THEME, variable, value)
+			VALUES
+				(0, $ID_OLD_THEME, 'name', 'Babylon Theme'),
+				(0, $ID_OLD_THEME, 'theme_url', '$babylon[theme_url]'),
+				(0, $ID_OLD_THEME, 'images_url', '$babylon[images_url]'),
+				(0, $ID_OLD_THEME, 'theme_dir', '$babylon[theme_dir]')");
+
+		$newSettings = array();
+		// Now that we have the old theme details - switch anyone who used the default to it (Make sense?!)
+		if (!empty($modSettings['theme_default']) && $modSettings['theme_default'] == 1)
+			$newSettings[] = "('theme_default', $ID_OLD_THEME)";
+		// Did guests use to use the default?
+		if (!empty($modSettings['theme_guests']) && $modSettings['theme_guests'] == 1)
+			$newSettings[] = "('theme_guests', $ID_OLD_THEME)";
+
+		// If known themes aren't set, let's just pick all themes available.
+		if (empty($modSettings['knownThemes']))
+		{
+			$request = upgrade_query("
+				SELECT DISTINCT ID_THEME
+				FROM {$db_prefix}themes");
+			$themes = array();
+			while ($row = mysql_fetch_assoc($request))
+				$themes[] = $row['ID_THEME'];
+			$modSettings['knownThemes'] = implode(',', $themes);
+			upgrade_query("
+				UPDATE {$db_prefix}settings
+				SET value = '$modSettings[knownThemes]'
+				WHERE variable = 'knownThemes'");
+		}
+
+		// Known themes.
+		$allThemes = explode(',', $modSettings['knownThemes']);
+		$allThemes[] = $ID_OLD_THEME;
+		$newSettings[] = "('knownThemes', '" . implode(',', $allThemes) . "')";
+
+		upgrade_query("
+			REPLACE INTO {$db_prefix}settings
+				(variable, value)
+			VALUES
+				" . implode(', ', $newSettings));
+
+		// What about members?
+		upgrade_query("
+			UPDATE {$db_prefix}members
+			SET ID_THEME = $ID_OLD_THEME
+			WHERE ID_THEME = 1");
+
+		// Boards?
+		upgrade_query("
+			UPDATE {$db_prefix}boards
+			SET ID_THEME = $ID_OLD_THEME
+			WHERE ID_THEME = 1");
+
+		// The other themes used to use babylon as their base theme.
+		if (isset($babylon['theme_dir']) && isset($babylon['theme_url']))
+		{
+			$babylonBasedThemes = array_diff($allThemes, array(1));
+
+			// Exclude the themes that already have a base_theme_dir.
+			$request = upgrade_query("
+				SELECT DISTINCT ID_THEME
+				FROM {$db_prefix}themes
+				WHERE variable = 'base_theme_dir'");
+			while ($row = mysql_fetch_assoc($request))
+				$babylonBasedThemes = array_diff($babylonBasedThemes, array($row['ID_THEME']));
+			mysql_free_result($request);
+
+			// Only base themes if there are templates that need a fall-back.
+			$insertRows = array();
+			$request = upgrade_query("
+				SELECT ID_THEME, value AS theme_dir
+				FROM {$db_prefix}themes
+				WHERE ID_THEME IN (" . implode(', ', $babylonBasedThemes) . ")
+					AND ID_MEMBER = 0
+					AND variable = 'theme_dir'");
+			while ($row = mysql_fetch_assoc($request))
+			{
+				if (!file_exists($row['theme_dir'] . '/BoardIndex.template.php') || !file_exists($row['theme_dir'] . '/Display.template.php') || !file_exists($row['theme_dir'] . '/index.template.php') || !file_exists($row['theme_dir'] . '/MessageIndex.template.php') || !file_exists($row['theme_dir'] . '/Settings.template.php'))
+				{
+					$insertRows[] = "(0, $row[ID_THEME], 'base_theme_dir', '" . addslashes($babylon['theme_dir']) . "')";
+					$insertRows[] = "(0, $row[ID_THEME], 'base_theme_url', '" . addslashes($babylon['theme_url']) . "')";
+				}
+			}
+			mysql_free_result($request);
+
+			if (!empty($insertRows))
+				upgrade_query("
+					INSERT IGNORE INTO {$db_prefix}themes
+						(ID_MEMBER, ID_THEME, variable, value)
+					VALUES
+						" . implode(',
+						', $insertRows));
+		}
+	}
+	mysql_free_result($theme_request);
+
+	// This ain't running twice either - not with the risk of log_tables timing us all out!
+	upgrade_query("
+		REPLACE INTO {$db_prefix}settings
+			(variable, value)
+		VALUES
+			('dont_repeat_theme', '1')");
+}
+
+---}
+---#
+
+/******************************************************************************/
+--- Adding and updating member data...
+/******************************************************************************/
+
+---# Renaming personal message tables...
+RENAME TABLE {$db_prefix}instant_messages
+TO {$db_prefix}personal_messages;
+
+RENAME TABLE {$db_prefix}im_recipients
+TO {$db_prefix}pm_recipients;
+---#
+
+---# Updating indexes on "pm_recipients"...
+ALTER TABLE {$db_prefix}pm_recipients
+DROP INDEX ID_MEMBER,
+ADD UNIQUE ID_MEMBER (ID_MEMBER, deleted, ID_PM);
+---#
+
+---# Updating columns on "pm_recipients"...
+ALTER TABLE {$db_prefix}pm_recipients
+ADD COLUMN labels varchar(60) NOT NULL default '-1';
+
+ALTER TABLE {$db_prefix}pm_recipients
+CHANGE COLUMN labels labels varchar(60) NOT NULL default '-1';
+
+UPDATE {$db_prefix}pm_recipients
+SET labels = '-1'
+WHERE labels NOT RLIKE '[0-9,\-]' OR labels = '';
+---#
+
+---# Updating columns on "members"...
+ALTER TABLE {$db_prefix}members
+ADD COLUMN messageLabels text NOT NULL,
+ADD COLUMN buddy_list tinytext NOT NULL,
+ADD COLUMN notifySendBody tinyint(4) NOT NULL default '0',
+ADD COLUMN notifyTypes tinyint(4) NOT NULL default '2',
+CHANGE COLUMN im_ignore_list pm_ignore_list tinytext NOT NULL,
+CHANGE COLUMN im_email_notify pm_email_notify tinyint(4) NOT NULL default '0';
+---#
+
+---# Updating columns on "members" - part 2...
+ALTER TABLE {$db_prefix}members
+CHANGE COLUMN secretAnswer secretAnswer varchar(64) NOT NULL default '';
+
+ALTER TABLE {$db_prefix}members
+ADD COLUMN memberIP2 tinytext NOT NULL;
+---#
+
+---# Updating member approval...
+---{
+// Although it *shouldn't* matter, best to do it just once to be sure.
+if (@$modSettings['smfVersion'] < '1.1')
+{
+	upgrade_query("
+		UPDATE {$db_prefix}members
+		SET is_activated = 3
+		WHERE validation_code = ''
+			AND is_activated = 0");
+}
+---}
+---#
+
+/******************************************************************************/
+--- Updating holidays and calendar...
+/******************************************************************************/
+
+---# Adding new holidays...
+---{
+$result = upgrade_query("
+	SELECT ID_HOLIDAY
+	FROM {$db_prefix}calendar_holidays
+	WHERE YEAR(eventDate) > 2010
+	LIMIT 1");
+$do_it = mysql_num_rows($result) == 0;
+mysql_free_result($result);
+
+if ($do_it)
+{
+	upgrade_query("
+		INSERT INTO {$db_prefix}calendar_holidays
+			(title, eventDate)
+		VALUES
+			('Mother\\'s Day', '2011-05-08'),
+			('Mother\\'s Day', '2012-05-13'),
+			('Mother\\'s Day', '2013-05-12'),
+			('Mother\\'s Day', '2014-05-11'),
+			('Mother\\'s Day', '2015-05-10'),
+			('Mother\\'s Day', '2016-05-08'),
+			('Mother\\'s Day', '2017-05-14'),
+			('Mother\\'s Day', '2018-05-13'),
+			('Mother\\'s Day', '2019-05-12'),
+			('Mother\\'s Day', '2020-05-10'),
+			('Father\\'s Day', '2011-06-19'),
+			('Father\\'s Day', '2012-06-17'),
+			('Father\\'s Day', '2013-06-16'),
+			('Father\\'s Day', '2014-06-15'),
+			('Father\\'s Day', '2015-06-21'),
+			('Father\\'s Day', '2016-06-19'),
+			('Father\\'s Day', '2017-06-18'),
+			('Father\\'s Day', '2018-06-17'),
+			('Father\\'s Day', '2019-06-16'),
+			('Father\\'s Day', '2020-06-21'),
+			('Summer Solstice', '2011-06-21'),
+			('Summer Solstice', '2012-06-20'),
+			('Summer Solstice', '2013-06-21'),
+			('Summer Solstice', '2014-06-21'),
+			('Summer Solstice', '2015-06-21'),
+			('Summer Solstice', '2016-06-20'),
+			('Summer Solstice', '2017-06-20'),
+			('Summer Solstice', '2018-06-21'),
+			('Summer Solstice', '2019-06-21'),
+			('Summer Solstice', '2020-06-20'),
+			('Vernal Equinox', '2011-03-20'),
+			('Vernal Equinox', '2012-03-20'),
+			('Vernal Equinox', '2013-03-20'),
+			('Vernal Equinox', '2014-03-20'),
+			('Vernal Equinox', '2015-03-20'),
+			('Vernal Equinox', '2016-03-19'),
+			('Vernal Equinox', '2017-03-20'),
+			('Vernal Equinox', '2018-03-20'),
+			('Vernal Equinox', '2019-03-20'),
+			('Vernal Equinox', '2020-03-19'),
+			('Winter Solstice', '2011-12-22'),
+			('Winter Solstice', '2012-12-21'),
+			('Winter Solstice', '2013-12-21'),
+			('Winter Solstice', '2014-12-21'),
+			('Winter Solstice', '2015-12-21'),
+			('Winter Solstice', '2016-12-21'),
+			('Winter Solstice', '2017-12-21'),
+			('Winter Solstice', '2018-12-21'),
+			('Winter Solstice', '2019-12-21'),
+			('Winter Solstice', '2020-12-21'),
+			('Autumnal Equinox', '2011-09-23'),
+			('Autumnal Equinox', '2012-09-22'),
+			('Autumnal Equinox', '2013-09-22'),
+			('Autumnal Equinox', '2014-09-22'),
+			('Autumnal Equinox', '2015-09-23'),
+			('Autumnal Equinox', '2016-09-22'),
+			('Autumnal Equinox', '2017-09-22'),
+			('Autumnal Equinox', '2018-09-22'),
+			('Autumnal Equinox', '2019-09-23'),
+			('Autumnal Equinox', '2020-09-22'),
+			('Thanksgiving', '2011-11-24'),
+			('Thanksgiving', '2012-11-22'),
+			('Thanksgiving', '2013-11-21'),
+			('Thanksgiving', '2014-11-20'),
+			('Thanksgiving', '2015-11-26'),
+			('Thanksgiving', '2016-11-24'),
+			('Thanksgiving', '2017-11-23'),
+			('Thanksgiving', '2018-11-22'),
+			('Thanksgiving', '2019-11-21'),
+			('Thanksgiving', '2020-11-26'),
+			('Memorial Day', '2011-05-30'),
+			('Memorial Day', '2012-05-28'),
+			('Memorial Day', '2013-05-27'),
+			('Memorial Day', '2014-05-26'),
+			('Memorial Day', '2015-05-25'),
+			('Memorial Day', '2016-05-30'),
+			('Memorial Day', '2017-05-29'),
+			('Memorial Day', '2018-05-28'),
+			('Memorial Day', '2019-05-27'),
+			('Memorial Day', '2020-05-25'),
+			('Labor Day', '2011-09-05'),
+			('Labor Day', '2012-09-03'),
+			('Labor Day', '2013-09-09'),
+			('Labor Day', '2014-09-08'),
+			('Labor Day', '2015-09-07'),
+			('Labor Day', '2016-09-05'),
+			('Labor Day', '2017-09-04'),
+			('Labor Day', '2018-09-03'),
+			('Labor Day', '2019-09-09'),
+			('Labor Day', '2020-09-07')");
+}
+---}
+---#
+
+---# Updating event start and end dates...
+ALTER TABLE {$db_prefix}calendar
+DROP INDEX eventDate;
+
+ALTER TABLE {$db_prefix}calendar
+CHANGE COLUMN eventDate startDate date NOT NULL default '0001-01-01';
+
+ALTER TABLE {$db_prefix}calendar
+CHANGE COLUMN startDate startDate date NOT NULL default '0001-01-01';
+
+UPDATE {$db_prefix}calendar
+SET startDate = '0001-01-01'
+WHERE startDate = '0000-00-00';
+
+ALTER TABLE {$db_prefix}calendar
+ADD COLUMN endDate date NOT NULL default '0001-01-01';
+
+ALTER TABLE {$db_prefix}calendar
+CHANGE COLUMN endDate endDate date NOT NULL default '0001-01-01';
+
+UPDATE {$db_prefix}calendar
+SET endDate = startDate
+WHERE endDate = '0001-01-01'
+	OR endDate = '0000-00-00';
+
+ALTER TABLE {$db_prefix}calendar
+ADD INDEX startDate (startDate),
+ADD INDEX endDate (endDate);
+
+ALTER TABLE {$db_prefix}calendar
+DROP INDEX ID_TOPIC;
+
+ALTER TABLE {$db_prefix}calendar
+ADD INDEX topic (ID_TOPIC, ID_MEMBER);
+
+ALTER TABLE {$db_prefix}calendar_holidays
+CHANGE COLUMN eventDate eventDate date NOT NULL default '0001-01-01';
+
+UPDATE {$db_prefix}calendar_holidays
+SET eventDate = '0001-01-01'
+WHERE eventDate = '0000-00-00';
+
+UPDATE {$db_prefix}calendar_holidays
+SET eventDate = CONCAT('0004-', MONTH(eventDate), '-', DAYOFMONTH(eventDate))
+WHERE YEAR(eventDate) = 0;
+---#
+
+---# Converting other date columns...
+ALTER TABLE {$db_prefix}log_activity
+CHANGE COLUMN startDate date date NOT NULL default '0001-01-01';
+
+ALTER TABLE {$db_prefix}log_activity
+CHANGE COLUMN date date date NOT NULL default '0001-01-01';
+
+UPDATE {$db_prefix}log_activity
+SET date = '0001-01-01'
+WHERE date = '0000-00-00';
+
+ALTER TABLE {$db_prefix}members
+CHANGE COLUMN birthdate birthdate date NOT NULL default '0001-01-01';
+
+UPDATE {$db_prefix}members
+SET birthdate = '0001-01-01'
+WHERE birthdate = '0000-00-00';
+
+UPDATE {$db_prefix}members
+SET birthdate = CONCAT('0004-', MONTH(birthdate), '-', DAYOFMONTH(birthdate))
+WHERE YEAR(birthdate) = 0;
+---#
+
+/******************************************************************************/
+--- Adding custom message icons...
+/******************************************************************************/
+
+---# Checking for an old table...
+---{
+$request = mysql_query("
+	SHOW COLUMNS
+	FROM {$db_prefix}message_icons");
+$test = false;
+while ($request && $row = mysql_fetch_row($request))
+	$test |= $row[0] == 'Name';
+if ($request)
+	mysql_free_result($request);
+
+if ($test)
+{
+	upgrade_query("
+		ALTER TABLE {$db_prefix}message_icons
+		DROP PRIMARY KEY,
+		CHANGE COLUMN id_icon id_icon smallint(5) unsigned NOT NULL auto_increment PRIMARY KEY,
+		CHANGE COLUMN Name filename varchar(80) NOT NULL default '',
+		CHANGE COLUMN Description title varchar(80) NOT NULL default '',
+		CHANGE COLUMN ID_BOARD ID_BOARD mediumint(8) unsigned NOT NULL default '0',
+		DROP INDEX id_icon,
+		ADD COLUMN iconOrder smallint(5) unsigned NOT NULL default '0'");
+}
+---}
+---#
+
+---# Creating "message_icons"...
+CREATE TABLE IF NOT EXISTS {$db_prefix}message_icons (
+	id_icon smallint(5) unsigned NOT NULL auto_increment,
+	title varchar(80) NOT NULL default '',
+	filename varchar(80) NOT NULL default '',
+	ID_BOARD mediumint(8) unsigned NOT NULL default 0,
+	iconOrder smallint(5) unsigned NOT NULL default 0,
+	PRIMARY KEY (id_icon),
+	KEY ID_BOARD (ID_BOARD)
+) ENGINE=MyISAM;
+---#
+
+---# Inserting "message_icons"...
+---{
+// We do not want to do this twice!
+if (@$modSettings['smfVersion'] < '1.1')
+{
+	upgrade_query("
+		INSERT INTO {$db_prefix}message_icons
+			(filename, title, iconOrder)
+		VALUES ('xx', 'Standard', '0'),
+			('thumbup', 'Thumb Up', '1'),
+			('thumbdown', 'Thumb Down', '2'),
+			('exclamation', 'Exclamation point', '3'),
+			('question', 'Question mark', '4'),
+			('lamp', 'Lamp', '5'),
+			('smiley', 'Smiley', '6'),
+			('angry', 'Angry', '7'),
+			('cheesy', 'Cheesy', '8'),
+			('grin', 'Grin', '9'),
+			('sad', 'Sad', '10'),
+			('wink', 'Wink', '11')");
+}
+---}
+---#
+
+/******************************************************************************/
+--- Adding package servers...
+/******************************************************************************/
+
+---# Creating "package_servers"...
+CREATE TABLE IF NOT EXISTS {$db_prefix}package_servers (
+	id_server smallint(5) unsigned NOT NULL auto_increment,
+	name tinytext NOT NULL,
+	url tinytext NOT NULL,
+	PRIMARY KEY (id_server)
+) ENGINE=MyISAM;
+---#
+
+---# Inserting "package_servers"...
+INSERT IGNORE INTO {$db_prefix}package_servers
+	(id_server, name, url)
+VALUES
+	(1, 'Simple Machines Third-party Mod Site', 'http://mods.simplemachines.org');
+---#
+
+/******************************************************************************/
+--- Cleaning up database...
+/******************************************************************************/
+
+---# Updating flood control log...
+ALTER IGNORE TABLE {$db_prefix}log_floodcontrol
+CHANGE COLUMN ip ip char(16) NOT NULL default '                ';
+
+ALTER TABLE {$db_prefix}log_floodcontrol
+DROP INDEX logTime;
+---#
+
+---# Updating ip address storage...
+ALTER IGNORE TABLE {$db_prefix}log_actions
+CHANGE COLUMN IP ip char(16) NOT NULL default '                ';
+
+ALTER IGNORE TABLE {$db_prefix}log_banned
+CHANGE COLUMN IP ip char(16) NOT NULL default '                ';
+
+ALTER IGNORE TABLE {$db_prefix}log_banned
+DROP COLUMN ban_ids;
+
+ALTER IGNORE TABLE {$db_prefix}log_errors
+DROP INDEX IP,
+CHANGE COLUMN IP ip char(16) NOT NULL default '                ',
+ADD INDEX ip (ip(16));
+---#
+
+---# Converting "log_online"...
+DROP TABLE IF EXISTS {$db_prefix}log_online;
+CREATE TABLE {$db_prefix}log_online (
+	session char(32) NOT NULL default '                                ',
+	logTime timestamp /*!40102 NOT NULL default CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP */,
+	ID_MEMBER mediumint(8) unsigned NOT NULL default '0',
+	ip int(10) unsigned NOT NULL default '0',
+	url text NOT NULL,
+	PRIMARY KEY (session),
+	KEY online (logTime, ID_MEMBER),
+	KEY ID_MEMBER (ID_MEMBER)
+) ENGINE=MyISAM;
+---#
+
+---# Updating poll column sizes...
+ALTER TABLE {$db_prefix}polls
+CHANGE COLUMN maxVotes maxVotes tinyint(3) unsigned NOT NULL default '1',
+CHANGE COLUMN hideResults hideResults tinyint(3) unsigned NOT NULL default '0',
+CHANGE COLUMN changeVote changeVote tinyint(3) unsigned NOT NULL default '0';
+
+ALTER TABLE {$db_prefix}poll_choices
+CHANGE COLUMN ID_CHOICE ID_CHOICE tinyint(3) unsigned NOT NULL default '0';
+
+ALTER TABLE {$db_prefix}log_polls
+CHANGE COLUMN ID_CHOICE ID_CHOICE tinyint(3) unsigned NOT NULL default '0';
+---#
+
+---# Updating attachments table...
+ALTER TABLE {$db_prefix}attachments
+DROP PRIMARY KEY,
+CHANGE COLUMN ID_ATTACH ID_ATTACH int(10) unsigned NOT NULL auto_increment PRIMARY KEY;
+---#
+
+---# Updating boards and topics...
+ALTER TABLE {$db_prefix}topics
+CHANGE COLUMN numReplies numReplies int(10) unsigned NOT NULL default 0,
+CHANGE COLUMN numViews numViews int(10) unsigned NOT NULL default 0;
+---#
+
+---# Updating members...
+ALTER TABLE {$db_prefix}members
+CHANGE COLUMN lastLogin lastLogin int(10) unsigned NOT NULL default 0;
+---#
+
+---# Recounting member pm totals (step 1)...
+---{
+$request = upgrade_query("
+	SELECT COUNT(*)
+	FROM {$db_prefix}members");
+list ($totalMembers) = mysql_fetch_row($request);
+mysql_free_result($request);
+
+$_GET['m'] = isset($_GET['m']) ? (int) $_GET['m'] : 0;
+
+while ($_GET['m'] < $totalMembers)
+{
+	nextSubstep($substep);
+
+	$mrequest = upgrade_query("
+		SELECT mem.ID_MEMBER, COUNT(pmr.ID_PM) AS instantMessages_real, mem.instantMessages
+		FROM {$db_prefix}members AS mem
+			LEFT JOIN {$db_prefix}pm_recipients AS pmr ON (pmr.ID_MEMBER = mem.ID_MEMBER AND pmr.deleted = 0)
+		WHERE mem.ID_MEMBER > $_GET[m]
+			AND mem.ID_MEMBER <= $_GET[m] + 128
+		GROUP BY mem.ID_MEMBER
+		HAVING instantMessages_real != instantMessages
+		LIMIT 256");
+	while ($row = mysql_fetch_assoc($mrequest))
+	{
+		upgrade_query("
+			UPDATE {$db_prefix}members
+			SET instantMessages = $row[instantMessages_real]
+			WHERE ID_MEMBER = $row[ID_MEMBER]
+			LIMIT 1");
+	}
+
+	$_GET['m'] += 128;
+}
+unset($_GET['m']);
+---}
+---#
+
+---# Recounting member pm totals (step 2)...
+---{
+$request = upgrade_query("
+	SELECT COUNT(*)
+	FROM {$db_prefix}members");
+list ($totalMembers) = mysql_fetch_row($request);
+mysql_free_result($request);
+
+$_GET['m'] = isset($_GET['m']) ? (int) $_GET['m'] : 0;
+
+while ($_GET['m'] < $totalMembers)
+{
+	nextSubstep($substep);
+
+	$mrequest = upgrade_query("
+		SELECT mem.ID_MEMBER, COUNT(pmr.ID_PM) AS unreadMessages_real, mem.unreadMessages
+		FROM {$db_prefix}members AS mem
+			LEFT JOIN {$db_prefix}pm_recipients AS pmr ON (pmr.ID_MEMBER = mem.ID_MEMBER AND pmr.deleted = 0 AND pmr.is_read = 0)
+		WHERE mem.ID_MEMBER > $_GET[m]
+			AND mem.ID_MEMBER <= $_GET[m] + 128
+		GROUP BY mem.ID_MEMBER
+		HAVING unreadMessages_real != unreadMessages
+		LIMIT 256");
+	while ($row = mysql_fetch_assoc($mrequest))
+	{
+		upgrade_query("
+			UPDATE {$db_prefix}members
+			SET unreadMessages = $row[unreadMessages_real]
+			WHERE ID_MEMBER = $row[ID_MEMBER]
+			LIMIT 1");
+	}
+
+	$_GET['m'] += 128;
+}
+unset($_GET['m']);
+---}
+---#
+
+/******************************************************************************/
+--- Converting avatar permissions...
+/******************************************************************************/
+
+---# Converting server stored setting...
+---{
+if (!empty($modSettings['avatar_allow_server_stored']))
+{
+	// Create permissions for existing membergroups.
+	upgrade_query("
+		INSERT INTO {$db_prefix}permissions
+			(ID_GROUP, permission)
+		SELECT IF(ID_GROUP = 1, 0, ID_GROUP), 'profile_server_avatar'
+		FROM {$db_prefix}membergroups
+		WHERE ID_GROUP != 3
+			AND minPosts = -1");
+}
+---}
+---#
+
+---# Converting avatar upload setting...
+---{
+// Do the same, but for uploading avatars.
+if (!empty($modSettings['avatar_allow_upload']))
+{
+	// Put in these permissions
+	upgrade_query("
+		INSERT INTO {$db_prefix}permissions
+			(ID_GROUP, permission)
+		SELECT IF(ID_GROUP = 1, 0, ID_GROUP), 'profile_upload_avatar'
+		FROM {$db_prefix}membergroups
+		WHERE ID_GROUP != 3
+			AND minPosts = -1");
+}
+---}
+---#
+
+/******************************************************************************/
+--- Adjusting uploadable avatars...
+/******************************************************************************/
+
+---# Updating attachments...
+ALTER TABLE {$db_prefix}attachments
+CHANGE COLUMN ID_MEMBER ID_MEMBER mediumint(8) unsigned NOT NULL default '0';
+---#
+
+---# Updating settings...
+DELETE FROM {$db_prefix}settings
+WHERE variable IN ('avatar_allow_external_url', 'avatar_check_size', 'avatar_allow_upload', 'avatar_allow_server_stored');
+---#
+
+/******************************************************************************/
+--- Updating thumbnails...
+/******************************************************************************/
+
+---# Registering thumbs...
+---{
+// Checkout the current structure of the attachment table.
+$request = mysql_query("
+	SHOW COLUMNS
+	FROM {$db_prefix}attachments");
+$has_customAvatarDir_column = false;
+$has_attachmentType_column = false;
+while ($row = mysql_fetch_assoc($request))
+{
+	$has_customAvatarDir_column |= $row['Field'] == 'customAvatarDir';
+	$has_attachmentType_column |= $row['Field'] == 'attachmentType';
+}
+mysql_free_result($request);
+
+// Post SMF 1.1 Beta 1.
+if ($has_customAvatarDir_column)
+	$request = upgrade_query("
+		ALTER TABLE {$db_prefix}attachments
+		CHANGE COLUMN customAvatarDir attachmentType tinyint(3) unsigned NOT NULL default '0'");
+// Pre SMF 1.1.
+elseif (!$has_attachmentType_column)
+	$request = upgrade_query("
+		ALTER TABLE {$db_prefix}attachments
+		ADD COLUMN attachmentType tinyint(3) unsigned NOT NULL default '0'");
+
+if (!$has_attachmentType_column)
+{
+	$request = upgrade_query("
+		ALTER TABLE {$db_prefix}attachments
+		ADD COLUMN id_thumb int(10) unsigned NOT NULL default '0' AFTER ID_ATTACH,
+		ADD COLUMN width mediumint(8) unsigned NOT NULL default '0',
+		ADD COLUMN height mediumint(8) unsigned NOT NULL default '0'");
+
+	// Get a list of attachments currently stored in the database.
+	$request = upgrade_query("
+		SELECT ID_ATTACH, ID_MSG, filename
+		FROM {$db_prefix}attachments");
+	$filenames = array();
+	$encrypted_filenames = array();
+	$ID_MSG = array();
+	while ($row = mysql_fetch_assoc($request))
+	{
+		$clean_name = strtr($row['filename'], 'ŠŽšžŸÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÑÒÓÔÕÖØÙÚÛÜÝàáâãäåçèéêëìíîïñòóôõöøùúûüýÿ', 'SZszYAAAAAACEEEEIIIINOOOOOOUUUUYaaaaaaceeeeiiiinoooooouuuuyy');
+		$clean_name = strtr($clean_name, array('Þ' => 'TH', 'þ' => 'th', 'Ð' => 'DH', 'ð' => 'dh', 'ß' => 'ss', 'Œ' => 'OE', 'œ' => 'oe', 'Æ' => 'AE', 'æ' => 'ae', 'µ' => 'u'));
+		$clean_name = preg_replace(array('/\s/', '/[^\w_\.\-]/'), array('_', ''), $clean_name);
+		$enc_name = $row['ID_ATTACH'] . '_' . strtr($clean_name, '.', '_') . md5($clean_name);
+		$clean_name = preg_replace('~\.[\.]+~', '.', $clean_name);
+
+		if (file_exists($modSettings['attachmentUploadDir'] . '/' . $enc_name))
+			$filename = $enc_name;
+		elseif (file_exists($modSettings['attachmentUploadDir'] . '/' . $clean_name))
+			$filename = $clean_name;
+		else
+			$filename = $row['filename'];
+
+		$filenames[$row['ID_ATTACH']] = $clean_name;
+		$encrypted_filenames[$row['ID_ATTACH']] = $filename;
+		$ID_MSG[$row['ID_ATTACH']] = $row['ID_MSG'];
+	}
+	mysql_free_result($request);
+
+	// Let's loop through the attachments
+	if (is_dir($modSettings['attachmentUploadDir']) && $dir = @opendir($modSettings['attachmentUploadDir']))
+	{
+		while ($file = readdir($dir))
+		{
+			if (substr($file, -6) == '_thumb')
+			{
+				// We found a thumbnail, now find the attachment it represents.
+				$attach_realFilename = substr($file, 0, -6);
+				if (in_array($attach_realFilename, $filenames))
+				{
+					$attach_id = array_search($attach_realFilename, $filenames);
+					$attach_filename = $attach_realFilename;
+				}
+				elseif (in_array($attach_realFilename, $encrypted_filenames))
+				{
+					$attach_id = array_search($attach_realFilename, $encrypted_filenames);
+					$attach_filename = $filenames[$attach_id];
+				}
+				else
+					continue;
+
+				// No need to register thumbs of non-existent attachments.
+				if (!file_exists($modSettings['attachmentUploadDir'] . '/' . $attach_realFilename) || strlen($attach_filename) > 249)
+					continue;
+
+				// Determine the dimensions of the thumb.
+				list ($thumb_width, $thumb_height) = @getimagesize($modSettings['attachmentUploadDir'] . '/' . $file);
+				$thumb_size = filesize($modSettings['attachmentUploadDir'] . '/' . $file);
+				$thumb_filename = $attach_filename . '_thumb';
+
+				// Insert the thumbnail in the attachment database.
+				upgrade_query("
+					INSERT INTO {$db_prefix}attachments
+						(ID_MSG, attachmentType, filename, size, width, height)
+					VALUES (" . $ID_MSG[$attach_id] . ", 3, '$thumb_filename', " . (int) $thumb_size . ', ' . (int) $thumb_width . ', ' . (int) $thumb_height . ')');
+				$thumb_attach_id = mysql_insert_id();
+
+				// Determine the dimensions of the original attachment.
+				$attach_width = $attach_height = 0;
+				list ($attach_width, $attach_height) = @getimagesize($modSettings['attachmentUploadDir'] . '/' . $attach_realFilename);
+
+				// Link the original attachment to its thumb.
+				upgrade_query("
+					UPDATE {$db_prefix}attachments
+					SET
+						id_thumb = $thumb_attach_id,
+						width = " . (int) $attach_width . ",
+						height = " . (int) $attach_height . "
+					WHERE ID_ATTACH = $attach_id
+					LIMIT 1");
+
+				// Since it's an attachment now, we might as well encrypt it.
+				if (!empty($modSettings['attachmentEncryptFilenames']))
+					@rename($modSettings['attachmentUploadDir'] . '/' . $file, $modSettings['attachmentUploadDir'] . '/' . $thumb_attach_id . '_' . strtr($thumb_filename, '.', '_') . md5($thumb_filename));
+			}
+		}
+		closedir($dir);
+	}
+}
+---}
+---#
+
+---# Adding image dimensions...
+---{
+// Now add dimension to the images that have no thumb (yet).
+$request = upgrade_query("
+	SELECT ID_ATTACH, filename, attachmentType
+	FROM {$db_prefix}attachments
+	WHERE id_thumb = 0
+		AND (RIGHT(filename, 4) IN ('.gif', '.jpg', '.png', '.bmp') OR RIGHT(filename, 5) = '.jpeg')
+		AND width = 0
+		AND height = 0");
+while ($row = mysql_fetch_assoc($request))
+{
+	if ($row['attachmentType'] == 1)
+		$filename = $modSettings['custom_avatar_dir'] . '/' . $row['filename'];
+	else
+	{
+		$clean_name = strtr($row['filename'], 'ŠŽšžŸÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÑÒÓÔÕÖØÙÚÛÜÝàáâãäåçèéêëìíîïñòóôõöøùúûüýÿ', 'SZszYAAAAAACEEEEIIIINOOOOOOUUUUYaaaaaaceeeeiiiinoooooouuuuyy');
+		$clean_name = strtr($clean_name, array('Þ' => 'TH', 'þ' => 'th', 'Ð' => 'DH', 'ð' => 'dh', 'ß' => 'ss', 'Œ' => 'OE', 'œ' => 'oe', 'Æ' => 'AE', 'æ' => 'ae', 'µ' => 'u'));
+		$clean_name = preg_replace(array('/\s/', '/[^\w_\.\-]/'), array('_', ''), $clean_name);
+		$enc_name = $row['ID_ATTACH'] . '_' . strtr($clean_name, '.', '_') . md5($clean_name);
+		$clean_name = preg_replace('~\.[\.]+~', '.', $clean_name);
+
+		if (file_exists($modSettings['attachmentUploadDir'] . '/' . $enc_name))
+			$filename = $modSettings['attachmentUploadDir'] . '/' . $enc_name;
+		elseif (file_exists($modSettings['attachmentUploadDir'] . '/' . $clean_name))
+			$filename = $modSettings['attachmentUploadDir'] . '/' . $clean_name;
+		else
+			$filename = $modSettings['attachmentUploadDir'] . '/' . $row['filename'];
+	}
+
+	$width = 0;
+	$height = 0;
+	list ($width, $height) = @getimagesize($filename);
+	if (!empty($width) && !empty($height))
+		upgrade_query("
+			UPDATE {$db_prefix}attachments
+			SET
+				width = $width,
+				height = $height
+			WHERE ID_ATTACH = $row[ID_ATTACH]
+			LIMIT 1");
+}
+mysql_free_result($request);
+---}
+---#
+
+/******************************************************************************/
+--- Updating ban system...
+/******************************************************************************/
+
+---# Splitting ban table...
+---{
+// Checkout the current structure of the attachment table.
+$request = mysql_query("
+	SHOW TABLES
+	LIKE '{$db_prefix}banned'");
+$upgradeBanTable = mysql_num_rows($request) == 1;
+mysql_free_result($request);
+
+if ($upgradeBanTable)
+{
+	upgrade_query("
+		RENAME TABLE {$db_prefix}banned
+		TO {$db_prefix}ban_groups");
+	upgrade_query("
+		ALTER TABLE {$db_prefix}ban_groups
+		CHANGE COLUMN id_ban id_ban_group mediumint(8) unsigned NOT NULL auto_increment");
+
+	upgrade_query("
+		CREATE TABLE IF NOT EXISTS {$db_prefix}ban_items (
+			id_ban mediumint(8) unsigned NOT NULL auto_increment,
+			id_ban_group smallint(5) unsigned NOT NULL default '0',
+			ip_low1 tinyint(3) unsigned NOT NULL default '0',
+			ip_high1 tinyint(3) unsigned NOT NULL default '0',
+			ip_low2 tinyint(3) unsigned NOT NULL default '0',
+			ip_high2 tinyint(3) unsigned NOT NULL default '0',
+			ip_low3 tinyint(3) unsigned NOT NULL default '0',
+			ip_high3 tinyint(3) unsigned NOT NULL default '0',
+			ip_low4 tinyint(3) unsigned NOT NULL default '0',
+			ip_high4 tinyint(3) unsigned NOT NULL default '0',
+			hostname tinytext NOT NULL,
+			email_address tinytext NOT NULL,
+			ID_MEMBER mediumint(8) unsigned NOT NULL default '0',
+			hits mediumint(8) unsigned NOT NULL default '0',
+			PRIMARY KEY (id_ban),
+			KEY id_ban_group (id_ban_group)
+		) ENGINE=MyISAM");
+
+	upgrade_query("
+		INSERT INTO {$db_prefix}ban_items
+			(id_ban_group, ip_low1, ip_high1, ip_low2, ip_high2, ip_low3, ip_high3, ip_low4, ip_high4, hostname, email_address, ID_MEMBER)
+		SELECT id_ban_group, ip_low1, ip_high1, ip_low2, ip_high2, ip_low3, ip_high3, ip_low4, ip_high4, hostname, email_address, ID_MEMBER
+		FROM {$db_prefix}ban_groups");
+
+	upgrade_query("
+		ALTER TABLE {$db_prefix}ban_groups
+		DROP COLUMN ban_type,
+		DROP COLUMN ip_low1,
+		DROP COLUMN ip_high1,
+		DROP COLUMN ip_low2,
+		DROP COLUMN ip_high2,
+		DROP COLUMN ip_low3,
+		DROP COLUMN ip_high3,
+		DROP COLUMN ip_low4,
+		DROP COLUMN ip_high4,
+		DROP COLUMN hostname,
+		DROP COLUMN email_address,
+		DROP COLUMN ID_MEMBER,
+		ADD COLUMN cannot_access tinyint(3) unsigned NOT NULL default '0' AFTER expire_time,
+		ADD COLUMN cannot_register tinyint(3) unsigned NOT NULL default '0' AFTER cannot_access,
+		ADD COLUMN cannot_post tinyint(3) unsigned NOT NULL default '0' AFTER cannot_register,
+		ADD COLUMN cannot_login tinyint(3) unsigned NOT NULL default '0' AFTER cannot_post");
+
+	// Generate names for existing bans.
+	upgrade_query("
+		ALTER TABLE {$db_prefix}ban_groups
+		ADD COLUMN name varchar(20) NOT NULL default '' AFTER id_ban_group");
+
+	$request = mysql_query("
+		SELECT id_ban_group, restriction_type
+		FROM {$db_prefix}ban_groups
+		ORDER BY ban_time ASC");
+	$ban_names = array(
+		'full_ban' => 1,
+		'cannot_register' => 1,
+		'cannot_post' => 1,
+	);
+	if ($request != false)
+	{
+		while ($row = mysql_fetch_assoc($request))
+			upgrade_query("
+				UPDATE {$db_prefix}ban_groups
+				SET name = '" . $row['restriction_type'] . '_' . str_pad($ban_names[$row['restriction_type']]++, 3, '0', STR_PAD_LEFT) . "'
+				WHERE id_ban_group = $row[id_ban_group]");
+		mysql_free_result($request);
+	}
+
+	// Move each restriction type to its own column.
+	mysql_query("
+		UPDATE {$db_prefix}ban_groups
+		SET
+			cannot_access = IF(restriction_type = 'full_ban', 1, 0),
+			cannot_register = IF(restriction_type = 'cannot_register', 1, 0),
+			cannot_post = IF(restriction_type = 'cannot_post', 1, 0)");
+	upgrade_query("
+		ALTER TABLE {$db_prefix}ban_groups
+		DROP COLUMN restriction_type");
+
+	// Make sure everybody's ban situation is re-evaluated.
+	upgrade_query("
+		UPDATE {$db_prefix}settings
+		SET value = '" . time() . "'
+		WHERE variable = 'banLastUpdated'");
+}
+---}
+---#
+
+---# Updating ban statistics...
+---{
+	$request = upgrade_query("
+		SELECT mem.ID_MEMBER, mem.is_activated + 10 AS new_value
+		FROM ({$db_prefix}ban_groups AS bg, {$db_prefix}ban_items AS bi, {$db_prefix}members AS mem)
+		WHERE bg.id_ban_group = bi.id_ban_group
+			AND bg.cannot_access = 1
+			AND (bg.expire_time IS NULL OR bg.expire_time > " . time() . ")
+			AND (mem.ID_MEMBER = bi.ID_MEMBER OR mem.emailAddress LIKE bi.email_address)
+			AND mem.is_activated < 10");
+	$updates = array();
+	while ($row = mysql_fetch_assoc($request))
+		$updates[$row['new_value']][] = $row['ID_MEMBER'];
+	mysql_free_result($request);
+
+	// Find members that are wrongfully marked as banned.
+	$request = upgrade_query("
+		SELECT mem.ID_MEMBER, mem.is_activated - 10 AS new_value
+		FROM {$db_prefix}members AS mem
+			LEFT JOIN {$db_prefix}ban_items AS bi ON (bi.ID_MEMBER = mem.ID_MEMBER OR mem.emailAddress LIKE bi.email_address)
+			LEFT JOIN {$db_prefix}ban_groups AS bg ON (bg.id_ban_group = bi.id_ban_group AND bg.cannot_access = 1 AND (bg.expire_time IS NULL OR bg.expire_time > " . time() . "))
+		WHERE (bi.id_ban IS NULL OR bg.id_ban_group IS NULL)
+			AND mem.is_activated >= 10");
+	while ($row = mysql_fetch_assoc($request))
+		$updates[$row['new_value']][] = $row['ID_MEMBER'];
+	mysql_free_result($request);
+
+	if (!empty($updates))
+		foreach ($updates as $newStatus => $members)
+			upgrade_query("
+				UPDATE {$db_prefix}members
+				SET is_activated = $newStatus
+				WHERE ID_MEMBER IN (" . implode(', ', $members) . ")
+				LIMIT " . count($members));
+---}
+---#
+
+/******************************************************************************/
+--- Updating permissions...
+/******************************************************************************/
+
+---# Deleting some very old permissions...
+DELETE FROM {$db_prefix}board_permissions
+WHERE permission IN ('view_threads', 'poll_delete_own', 'poll_delete_any', 'profile_edit_own', 'profile_edit_any');
+---#
+
+---# Renaming permissions...
+---{
+// We *cannot* do this twice!
+if (@$modSettings['smfVersion'] < '1.1')
+{
+	upgrade_query("
+		UPDATE {$db_prefix}board_permissions
+		SET
+			permission = REPLACE(permission, 'remove_replies', 'delete_replies'),
+			permission = REPLACE(permission, 'remove_own', 'delete2_own'),
+			permission = REPLACE(permission, 'remove_any', 'delete2_any')");
+	upgrade_query("
+		UPDATE {$db_prefix}board_permissions
+		SET
+			permission = REPLACE(permission, 'delete_own', 'remove_own'),
+			permission = REPLACE(permission, 'delete_any', 'remove_any')");
+	upgrade_query("
+		UPDATE {$db_prefix}board_permissions
+		SET
+			permission = REPLACE(permission, 'delete2_own', 'delete_own'),
+			permission = REPLACE(permission, 'delete2_any', 'delete_any')");
+}
+---}
+---#
+
+---# Upgrading "deny"-permissions...
+---{
+if (!isset($modSettings['permission_enable_deny']))
+{
+	// Only disable if no deny permissions are used.
+	$request = upgrade_query("
+		SELECT permission
+		FROM {$db_prefix}permissions
+		WHERE addDeny = 0
+		LIMIT 1");
+	$disable_deny_permissions = mysql_num_rows($request) == 0;
+	mysql_free_result($request);
+
+	// Still wanna disable deny permissions? Check board permissions.
+	if ($disable_deny_permissions)
+	{
+		$request = upgrade_query("
+			SELECT permission
+			FROM {$db_prefix}board_permissions
+			WHERE addDeny = 0
+			LIMIT 1");
+		$disable_deny_permissions &= mysql_num_rows($request) == 0;
+		mysql_free_result($request);
+	}
+
+	$request = upgrade_query("
+		INSERT INTO {$db_prefix}settings
+			(variable, value)
+		VALUES ('permission_enable_deny', '" . ($disable_deny_permissions ? '0' : '1') . "')");
+}
+---}
+---#
+
+---# Upgrading post based group permissions...
+---{
+if (!isset($modSettings['permission_enable_postgroups']))
+{
+	// Only disable if no post group permissions are used.
+	$disable_postgroup_permissions = true;
+	$request = upgrade_query("
+		SELECT p.permission
+		FROM ({$db_prefix}permissions AS p, {$db_prefix}membergroups AS mg)
+		WHERE mg.ID_GROUP = p.ID_GROUP
+			AND mg.minPosts != -1
+		LIMIT 1");
+	$disable_postgroup_permissions &= mysql_num_rows($request) == 0;
+	mysql_free_result($request);
+
+	// Still wanna disable postgroup permissions? Check board permissions.
+	if ($disable_postgroup_permissions)
+	{
+		$request = upgrade_query("
+			SELECT bp.permission
+			FROM ({$db_prefix}board_permissions AS bp, {$db_prefix}membergroups AS mg)
+			WHERE mg.ID_GROUP = bp.ID_GROUP
+				AND mg.minPosts != -1
+			LIMIT 1");
+		$disable_postgroup_permissions &= mysql_num_rows($request) == 0;
+		mysql_free_result($request);
+	}
+
+	$request = upgrade_query("
+		INSERT INTO {$db_prefix}settings
+			(variable, value)
+		VALUES ('permission_enable_postgroups', '" . ($disable_postgroup_permissions ? '0' : '1') . "')");
+}
+---}
+---#
+
+---# Upgrading by-board permissions...
+ALTER TABLE {$db_prefix}boards
+CHANGE COLUMN use_local_permissions permission_mode tinyint(4) unsigned NOT NULL default '0';
+
+---{
+if (!isset($modSettings['permission_enable_by_board']))
+{
+	// Enable by-board permissions if there's >= 1 local permission board.
+	$request = upgrade_query("
+		SELECT ID_BOARD
+		FROM {$db_prefix}boards
+		WHERE permission_mode = 1
+		LIMIT 1");
+	$enable_by_board = mysql_num_rows($request) == 1 ? '1' : '0';
+	mysql_free_result($request);
+
+	$request = upgrade_query("
+		INSERT INTO {$db_prefix}settings
+			(variable, value)
+		VALUES ('permission_enable_by_board', '$enable_by_board')");
+}
+---}
+---#
+
+---# Removing all guest deny permissions...
+DELETE FROM {$db_prefix}permissions
+WHERE ID_GROUP = -1
+	AND addDeny = 0;
+
+DELETE FROM {$db_prefix}board_permissions
+WHERE ID_GROUP = -1
+	AND addDeny = 0;
+---#
+
+---# Removing guest admin permissions (if any)...
+DELETE FROM {$db_prefix}permissions
+WHERE ID_GROUP = -1
+	AND permission IN ('admin_forum', 'manage_boards', 'manage_attachments', 'manage_smileys', 'edit_news', 'moderate_forum', 'manage_membergroups', 'manage_permissions', 'manage_bans', 'send_mail');
+
+DELETE FROM {$db_prefix}board_permissions
+WHERE ID_GROUP = -1
+	AND permission IN ('admin_forum', 'manage_boards', 'manage_attachments', 'manage_smileys', 'edit_news', 'moderate_forum', 'manage_membergroups', 'manage_permissions', 'manage_bans', 'send_mail');
+---#
+
+/******************************************************************************/
+--- Updating search cache...
+/******************************************************************************/
+
+---# Creating search cache tables...
+DROP TABLE IF EXISTS {$db_prefix}log_search_fulltext;
+DROP TABLE IF EXISTS {$db_prefix}log_search_messages;
+DROP TABLE IF EXISTS {$db_prefix}log_search_topics;
+DROP TABLE IF EXISTS {$db_prefix}log_search;
+
+CREATE TABLE IF NOT EXISTS {$db_prefix}log_search_messages (
+  id_search tinyint(3) unsigned NOT NULL default '0',
+  ID_MSG int(10) NOT NULL default '0',
+  PRIMARY KEY (id_search, ID_MSG)
+) ENGINE=MyISAM;
+
+CREATE TABLE IF NOT EXISTS {$db_prefix}log_search_topics (
+  id_search tinyint(3) unsigned NOT NULL default '0',
+  ID_TOPIC mediumint(9) NOT NULL default '0',
+  PRIMARY KEY (id_search, ID_TOPIC)
+) ENGINE=MyISAM;
+
+CREATE TABLE IF NOT EXISTS {$db_prefix}log_search_results (
+  id_search tinyint(3) unsigned NOT NULL default '0',
+  ID_TOPIC mediumint(8) unsigned NOT NULL default '0',
+  ID_MSG int(10) unsigned NOT NULL default '0',
+  relevance smallint(5) unsigned NOT NULL default '0',
+  num_matches smallint(5) unsigned NOT NULL default '0',
+  PRIMARY KEY (id_search, ID_TOPIC),
+  KEY relevance (relevance)
+) ENGINE=MyISAM;
+
+CREATE TABLE IF NOT EXISTS {$db_prefix}log_search_subjects (
+  word varchar(20) NOT NULL default '',
+  ID_TOPIC mediumint(8) unsigned NOT NULL default '0',
+  PRIMARY KEY (word, ID_TOPIC),
+  KEY ID_TOPIC (ID_TOPIC)
+) ENGINE=MyISAM;
+---#
+
+---# Rebuilding fulltext index...
+---{
+$request = upgrade_query("
+	SHOW KEYS
+	FROM {$db_prefix}messages");
+$found = false;
+while ($row = mysql_fetch_assoc($request))
+	$found |= $row['Key_name'] == 'subject' && $row['Column_name'] == 'subject';
+mysql_free_result($request);
+if ($found)
+{
+	$request = upgrade_query("
+		ALTER TABLE {$db_prefix}messages
+		DROP INDEX subject,
+		DROP INDEX body,
+		ADD FULLTEXT body (body)");
+}
+---}
+---#
+
+---# Indexing topic subjects...
+---{
+$request = upgrade_query("
+	SELECT COUNT(*)
+	FROM {$db_prefix}log_search_subjects");
+list ($numIndexedWords) = mysql_fetch_row($request);
+mysql_free_result($request);
+if ($numIndexedWords == 0 || isset($_GET['lt']))
+{
+	$request = upgrade_query("
+		SELECT COUNT(*)
+		FROM {$db_prefix}topics");
+	list ($maxTopics) = mysql_fetch_row($request);
+	mysql_free_result($request);
+
+	$_GET['lt'] = isset($_GET['lt']) ? (int) $_GET['lt'] : 0;
+	$step_progress['name'] = 'Indexing Topic Subjects';
+	$step_progress['current'] = $_GET['lt'];
+	$step_progress['total'] = $maxTopics;
+
+	while ($_GET['lt'] <= $maxTopics)
+	{
+		$request = upgrade_query("
+			SELECT t.ID_TOPIC, m.subject
+			FROM ({$db_prefix}topics AS t, {$db_prefix}messages AS m)
+			WHERE m.ID_MSG = t.ID_FIRST_MSG
+			LIMIT $_GET[lt], 250");
+		$inserts = array();
+		while ($row = mysql_fetch_assoc($request))
+		{
+			foreach (text2words($row['subject']) as $word)
+				$inserts[] = "'" . mysql_real_escape_string($word) . "', $row[ID_TOPIC]";
+		}
+		mysql_free_result($request);
+
+		if (!empty($inserts))
+			upgrade_query("
+				INSERT INTO {$db_prefix}log_search_subjects
+					(word, ID_TOPIC)
+				VALUES (" . implode('),
+					(', array_unique($inserts)) . ")");
+
+		$_GET['lt'] += 250;
+		$step_progress['current'] = $_GET['lt'];
+		nextSubstep($substep);
+	}
+	unset($_GET['lt']);
+}
+---}
+---#
+
+---# Converting settings...
+---{
+if (isset($modSettings['search_method']))
+{
+	if (!empty($modSettings['search_method']))
+		$request = upgrade_query("
+			INSERT INTO {$db_prefix}settings
+				(variable, value)
+			VALUES
+				('search_match_words', '1')");
+
+	if ($modSettings['search_method'] > 1)
+		$request = upgrade_query("
+			INSERT INTO {$db_prefix}settings
+				(variable, value)
+			VALUES
+				('search_index', 'fulltext')");
+
+	if ($modSettings['search_method'] == 3)
+		$request = upgrade_query("
+			INSERT INTO {$db_prefix}settings
+				(variable, value)
+			VALUES
+				('search_force_index', '1')");
+
+	$request = upgrade_query("
+		DELETE FROM {$db_prefix}settings
+		WHERE variable = 'search_method'");
+}
+---}
+---#
+
+/******************************************************************************/
+--- Upgrading log system...
+/******************************************************************************/
+
+---# Creating log table indexes (this might take some time!)...
+---{
+$request = upgrade_query("
+	SHOW COLUMNS
+	FROM {$db_prefix}log_topics");
+$upgradeLogTable = false;
+while ($request && $row = mysql_fetch_row($request))
+	$upgradeLogTable |= $row[0] == 'logTime';
+if ($request !== false)
+	mysql_free_result($request);
+
+if ($upgradeLogTable)
+{
+	$_GET['preprep_lt'] = isset($_GET['preprep_lt']) ? (int) $_GET['preprep_lt'] : 0;
+	$step_progress['name'] = 'Creating index\'s for log table';
+	$step_progress['current'] = $_GET['preprep_lt'];
+	$custom_warning = 'On a very large board these index\'s may take a few minutes to create.';
+
+	$log_additions = array(
+		array(
+			'table' => 'log_boards',
+			'type' => 'index',
+			'method' => 'add',
+			'name' => 'logTime',
+			'target_columns' => array('logTime'),
+			'text' => 'ADD INDEX logTime (logTime)',
+		),
+		array(
+			'table' => 'log_mark_read',
+			'type' => 'index',
+			'method' => 'add',
+			'name' => 'logTime',
+			'target_columns' => array('logTime'),
+			'text' => 'ADD INDEX logTime (logTime)',
+		),
+		array(
+			'table' => 'messages',
+			'type' => 'index',
+			'method' => 'add',
+			'name' => 'modifiedTime',
+			'target_columns' => array('modifiedTime'),
+			'text' => 'ADD INDEX modifiedTime (modifiedTime)',
+		),
+	);
+
+	$step_progress['total'] = count($log_additions);
+
+	// Now we loop through the changes and work out where the hell we are.
+	foreach ($log_additions as $ind => $change)
+	{
+		// Already done it?
+		if ($_GET['preprep_lt'] > $ind)
+			continue;
+
+		// Make the index, with all the protection and all.
+		protected_alter($change, $substep);
+
+		// Store this for the next table.
+		$_GET['preprep_lt']++;
+		$step_progress['current'] = $_GET['preprep_lt'];
+	}
+
+	// Clean up.
+	unset($_GET['preprep_lt']);
+}
+---}
+---#
+
+---# Preparing log table upgrade...
+---{
+$request = upgrade_query("
+	SHOW COLUMNS
+	FROM {$db_prefix}log_topics");
+$upgradeLogTable = false;
+while ($request && $row = mysql_fetch_row($request))
+	$upgradeLogTable |= $row[0] == 'logTime';
+if ($request !== false)
+	mysql_free_result($request);
+
+if ($upgradeLogTable)
+{
+	$_GET['prep_lt'] = isset($_GET['prep_lt']) ? (int) $_GET['prep_lt'] : 0;
+	$step_progress['name'] = 'Preparing log table update';
+	$step_progress['current'] = $_GET['prep_lt'];
+	$custom_warning = 'This step may take quite some time. During this time it may appear that nothing is happening while
+		the databases MySQL tables are expanded. Please be patient.';
+
+	// All these changes need to be made, they may take a while, so let's timeout neatly.
+	$log_additions = array(
+		array(
+			'table' => 'log_topics',
+			'type' => 'index',
+			'method' => 'remove',
+			'name' => 'ID_MEMBER',
+			'target_columns' => array('ID_MEMBER'),
+			'text' => 'DROP INDEX ID_MEMBER',
+		),
+		array(
+			'table' => 'log_topics',
+			'type' => 'index',
+			'method' => 'change',
+			'name' => 'PRIMARY',
+			'target_columns' => array('ID_MEMBER', 'ID_TOPIC'),
+			'text' => '
+				DROP PRIMARY KEY,
+				ADD PRIMARY KEY (ID_MEMBER, ID_TOPIC)',
+		),
+		array(
+			'table' => 'log_topics',
+			'type' => 'index',
+			'method' => 'add',
+			'name' => 'logTime',
+			'target_columns' => array('logTime'),
+			'text' => 'ADD INDEX logTime (logTime)',
+		),
+		array(
+			'table' => 'log_boards',
+			'type' => 'column',
+			'method' => 'add',
+			'name' => 'ID_MSG',
+			'text' => 'ADD COLUMN ID_MSG mediumint(8) unsigned NOT NULL default \'0\'',
+		),
+		array(
+			'table' => 'log_mark_read',
+			'type' => 'column',
+			'method' => 'add',
+			'name' => 'ID_MSG',
+			'text' => 'ADD COLUMN ID_MSG mediumint(8) unsigned NOT NULL default \'0\'',
+		),
+		array(
+			'table' => 'log_topics',
+			'type' => 'column',
+			'method' => 'add',
+			'name' => 'ID_MSG',
+			'text' => 'ADD COLUMN ID_MSG mediumint(8) unsigned NOT NULL default \'0\'',
+		),
+		array(
+			'table' => 'messages',
+			'type' => 'column',
+			'method' => 'add',
+			'name' => 'ID_MSG_MODIFIED',
+			'text' => 'ADD COLUMN ID_MSG_MODIFIED mediumint(8) unsigned NOT NULL default \'0\' AFTER ID_MEMBER',
+		),
+		array(
+			'table' => 'boards',
+			'type' => 'column',
+			'method' => 'add',
+			'name' => 'ID_MSG_UPDATED',
+			'text' => 'ADD COLUMN ID_MSG_UPDATED mediumint(8) unsigned NOT NULL default \'0\' AFTER ID_LAST_MSG',
+		),
+		array(
+			'table' => 'boards',
+			'type' => 'index',
+			'method' => 'add',
+			'name' => 'ID_MSG_UPDATED',
+			'target_columns' => array('ID_MSG_UPDATED'),
+			'text' => 'ADD INDEX ID_MSG_UPDATED (ID_MSG_UPDATED)',
+		),
+	);
+	$step_progress['total'] = count($log_additions);
+
+	// Now we loop through the changes and work out where the hell we are.
+	foreach ($log_additions as $ind => $change)
+	{
+		// Already done it?
+		if ($_GET['prep_lt'] > $ind)
+			continue;
+
+		// Make the index, with all the protection and all.
+		protected_alter($change, $substep);
+
+		// Store this for the next table.
+		$_GET['prep_lt']++;
+		$step_progress['current'] = $_GET['prep_lt'];
+	}
+
+	// Clean up.
+	unset($_GET['prep_lt']);
+}
+---}
+---#
+
+---# Converting log tables (this might take some time!)...
+---{
+$request = upgrade_query("
+	SHOW COLUMNS
+	FROM {$db_prefix}log_topics");
+$upgradeLogTable = false;
+while ($request && $row = mysql_fetch_row($request))
+	$upgradeLogTable |= $row[0] == 'logTime';
+if ($request !== false)
+	mysql_free_result($request);
+
+if ($upgradeLogTable)
+{
+	$request = upgrade_query("
+		SELECT MAX(ID_MSG)
+		FROM {$db_prefix}messages");
+	list($maxMsg) = mysql_fetch_row($request);
+	mysql_free_result($request);
+
+	if (empty($maxMsg))
+		$maxMsg = 0;
+
+	$_GET['m'] = isset($_GET['m']) ? (int) $_GET['m'] : 0;
+	$step_progress['name'] = 'Converting Log Tables';
+	$step_progress['current'] = $_GET['m'];
+	$step_progress['total'] = $maxMsg;
+	$custom_warning = 'This step is converting all your log tables and may take quite some time on a large forum (Several hours for a forum with ~500,000 messages).';
+
+	// Only adjust the structure if this is the first message.
+	if ($_GET['m'] === 0)
+	{
+		// By default a message is modified when it was written.
+		upgrade_query("
+			UPDATE {$db_prefix}messages
+			SET ID_MSG_MODIFIED = ID_MSG");
+
+		$request = upgrade_query("
+			SELECT posterTime
+			FROM {$db_prefix}messages
+			WHERE ID_MSG = $maxMsg");
+		list($maxPosterTime) = mysql_fetch_row($request);
+		mysql_free_result($request);
+
+		if (empty($maxPosterTime))
+			$maxPosterTime = 0;
+
+		upgrade_query("
+			UPDATE {$db_prefix}log_boards
+			SET ID_MSG = $maxMsg
+			WHERE logTime >= $maxPosterTime");
+		upgrade_query("
+			UPDATE {$db_prefix}log_mark_read
+			SET ID_MSG = $maxMsg
+			WHERE logTime >= $maxPosterTime");
+		upgrade_query("
+			UPDATE {$db_prefix}log_topics
+			SET ID_MSG = $maxMsg
+			WHERE logTime >= $maxPosterTime");
+		upgrade_query("
+			UPDATE {$db_prefix}messages
+			SET ID_MSG_MODIFIED = $maxMsg
+			WHERE modifiedTime >= $maxPosterTime");
+
+		// Timestamp 1 is where it all starts.
+		$lower_limit = 1;
+	}
+	else
+	{
+		// Determine the lower limit.
+		$request = upgrade_query("
+			SELECT MAX(posterTime) + 1
+			FROM {$db_prefix}messages
+			WHERE ID_MSG < $_GET[m]");
+		list($lower_limit) = mysql_fetch_row($request);
+		mysql_free_result($request);
+
+		if (empty($lower_limit))
+			$lower_limit = 1;
+
+		if (empty($maxPosterTime))
+			$maxPosterTime = 1;
+	}
+
+	while ($_GET['m'] <= $maxMsg)
+	{
+		$condition = '';
+		$lowest_limit = $lower_limit;
+		$request = upgrade_query("
+			SELECT MAX(ID_MSG) AS ID_MSG, posterTime
+			FROM {$db_prefix}messages
+			WHERE ID_MSG BETWEEN $_GET[m] AND " . ($_GET['m'] + 300) . "
+			GROUP BY posterTime
+			ORDER BY posterTime
+			LIMIT 300");
+		while ($row = mysql_fetch_assoc($request))
+		{
+			if ($condition === '')
+				$condition = "IF(logTime BETWEEN $lower_limit AND $row[posterTime], $row[ID_MSG], %else%)";
+			else
+				$condition = strtr($condition, array('%else%' => "IF(logTime <= $row[posterTime], $row[ID_MSG], %else%)"));
+
+			$lower_limit = $row['posterTime'] + 1;
+		}
+		mysql_free_result($request);
+
+		if ($condition !== '')
+		{
+			$condition = strtr($condition, array('%else%' => '0'));
+			$highest_limit = $lower_limit;
+
+			upgrade_query("
+				UPDATE {$db_prefix}log_boards
+				SET ID_MSG = $condition
+				WHERE logTime BETWEEN $lowest_limit AND $highest_limit
+					AND ID_MSG = 0");
+			upgrade_query("
+				UPDATE {$db_prefix}log_mark_read
+				SET ID_MSG = $condition
+				WHERE logTime BETWEEN $lowest_limit AND $highest_limit
+					AND ID_MSG = 0");
+			upgrade_query("
+				UPDATE {$db_prefix}log_topics
+				SET ID_MSG = $condition
+				WHERE logTime BETWEEN $lowest_limit AND $highest_limit
+					AND ID_MSG = 0");
+			upgrade_query("
+				UPDATE {$db_prefix}messages
+				SET ID_MSG_MODIFIED = " . strtr($condition, array('logTime' => 'modifiedTime')) . "
+				WHERE modifiedTime BETWEEN $lowest_limit AND $highest_limit
+					AND modifiedTime > 0");
+		}
+
+		$_GET['m'] += 300;
+		nextSubstep($substep);
+	}
+	unset($_GET['m']);
+}
+---}
+---#
+
+---# Updating last message IDs for boards.
+---{
+
+$request = upgrade_query("
+	SHOW COLUMNS
+	FROM {$db_prefix}boards");
+$upgradeBoardsTable = false;
+while ($request && $row = mysql_fetch_row($request))
+	$upgradeBoardsTable |= $row[0] == 'lastUpdated';
+if ($request !== false)
+	mysql_free_result($request);
+
+if ($upgradeBoardsTable)
+{
+	$request = upgrade_query("
+		SELECT MAX(ID_BOARD)
+		FROM {$db_prefix}boards");
+	list ($maxBoard) = mysql_fetch_row($request);
+	mysql_free_result($request);
+
+	$_GET['bdi'] = isset($_GET['bdi']) ? (int) $_GET['bdi'] : 0;
+	$step_progress['name'] = 'Updating Last Board ID';
+	$step_progress['current'] = $_GET['bdi'];
+	$step_progress['total'] = $maxBoard;
+
+	// OK, we need to get the last updated message.
+	$request = upgrade_query("
+		SELECT ID_BOARD, lastUpdated
+		FROM {$db_prefix}boards");
+	while ($row = mysql_fetch_assoc($request))
+	{
+		// Done this?
+		if ($row['ID_BOARD'] < $_GET['bdi'])
+			continue;
+
+		// Maybe we don't have any?
+		if ($row['lastUpdated'] == 0)
+			$ID_MSG = 0;
+		// Otherwise need to query it?
+		else
+		{
+			$request2 = upgrade_query("
+				SELECT MIN(ID_MSG)
+				FROM {$db_prefix}messages
+				WHERE posterTime >= $row[lastUpdated]");
+			list ($ID_MSG) = mysql_fetch_row($request2);
+
+			if (empty($ID_MSG))
+				$ID_MSG = 0;
+		}
+
+		upgrade_query("
+			UPDATE {$db_prefix}boards
+			SET ID_MSG_UPDATED = $ID_MSG
+			WHERE ID_BOARD = $row[ID_BOARD]");
+
+		$_GET['bdi']++;
+		$step_progress['current'] = $_GET['bdi'];
+		nextSubstep($substep);
+	}
+	unset($_GET['bdi']);
+}
+---}
+---#
+
+---# Cleaning up old log indexes...
+---{
+$request = upgrade_query("
+	SHOW COLUMNS
+	FROM {$db_prefix}log_topics");
+$upgradeLogTable = false;
+while ($request && $row = mysql_fetch_row($request))
+	$upgradeLogTable |= $row[0] == 'logTime';
+if ($request !== false)
+	mysql_free_result($request);
+
+if ($upgradeLogTable)
+{
+	$_GET['prep_lt'] = isset($_GET['prep_lt']) ? (int) $_GET['prep_lt'] : 0;
+	$step_progress['name'] = 'Cleaning up old log table index\'s';
+	$step_progress['current'] = $_GET['prep_lt'];
+	$custom_warning = 'This step may take quite some time. During this time it may appear that nothing is happening while
+		the databases MySQL tables are cleaned. Please be patient.';
+
+	// Here we remove all the unused indexes
+	$log_deletions = array(
+		array(
+			'table' => 'boards',
+			'type' => 'index',
+			'method' => 'remove',
+			'name' => 'lastUpdated',
+			'target_columns' => array('lastUpdated'),
+			'text' => 'DROP INDEX lastUpdated',
+		),
+		array(
+			'table' => 'messages',
+			'type' => 'index',
+			'method' => 'remove',
+			'name' => 'posterTime',
+			'target_columns' => array('posterTime'),
+			'text' => 'DROP INDEX posterTime',
+		),
+		array(
+			'table' => 'messages',
+			'type' => 'index',
+			'method' => 'remove',
+			'name' => 'modifiedTime',
+			'target_columns' => array('modifiedTime'),
+			'text' => 'DROP INDEX modifiedTime',
+		),
+		array(
+			'table' => 'log_topics',
+			'type' => 'column',
+			'method' => 'remove',
+			'name' => 'logTime',
+			'text' => 'DROP COLUMN logTime',
+		),
+		array(
+			'table' => 'log_boards',
+			'type' => 'column',
+			'method' => 'remove',
+			'name' => 'logTime',
+			'text' => 'DROP COLUMN logTime',
+		),
+		array(
+			'table' => 'log_mark_read',
+			'type' => 'column',
+			'method' => 'remove',
+			'name' => 'logTime',
+			'text' => 'DROP COLUMN logTime',
+		),
+		array(
+			'table' => 'boards',
+			'type' => 'column',
+			'method' => 'remove',
+			'name' => 'lastUpdated',
+			'text' => 'DROP COLUMN lastUpdated',
+		),
+	);
+	$step_progress['total'] = count($log_deletions);
+
+	// Now we loop through the changes and work out where the hell we are.
+	foreach ($log_deletions as $ind => $change)
+	{
+		// Already done it?
+		if ($_GET['prep_lt'] > $ind)
+			continue;
+
+		// Make the index, with all the protection and all.
+		protected_alter($change, $substep);
+
+		// Store this for the next table.
+		$_GET['prep_lt']++;
+		$step_progress['current'] = $_GET['prep_lt'];
+	}
+
+	// Clean up.
+	unset($_GET['prep_lt']);
+	$step_progress = array();
+}
+---}
+---#
+
+/******************************************************************************/
+--- Making SMF MySQL strict compatible...
+/******************************************************************************/
+
+---# Preparing messages table for strict upgrade
+ALTER IGNORE TABLE {$db_prefix}messages
+DROP INDEX ipIndex;
+---#
+
+---# Adjusting text fields
+---#
+---{
+// Note we move on by one as there is no point ALTER'ing the same thing twice.
+$_GET['strict_step'] = isset($_GET['strict_step']) ? (int) $_GET['strict_step'] + 1 : 0;
+$step_progress['name'] = 'Adding MySQL strict compatibility';
+$step_progress['current'] = $_GET['strict_step'];
+
+// Take care with the body column from messages, just in case it's been enlarged by others.
+$request = upgrade_query("
+	SHOW COLUMNS
+	FROM {$db_prefix}messages
+	LIKE 'body'");
+$body_row = mysql_fetch_assoc($request);
+mysql_free_result($request);
+
+$body_type = $body_row['Type'];
+
+$textfield_updates = array(
+	array(
+		'table' => 'attachments',
+		'column' => 'filename',
+		'type' => 'tinytext',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'ban_groups',
+		'column' => 'reason',
+		'type' => 'tinytext',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'ban_items',
+		'column' => 'hostname',
+		'type' => 'tinytext',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'ban_items',
+		'column' => 'email_address',
+		'type' => 'tinytext',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'boards',
+		'column' => 'name',
+		'type' => 'tinytext',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'boards',
+		'column' => 'description',
+		'type' => 'text',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'categories',
+		'column' => 'name',
+		'type' => 'tinytext',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'log_actions',
+		'column' => 'extra',
+		'type' => 'text',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'log_banned',
+		'column' => 'email',
+		'type' => 'tinytext',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'log_banned',
+		'column' => 'email',
+		'type' => 'tinytext',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'log_errors',
+		'column' => 'url',
+		'type' => 'text',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'log_errors',
+		'column' => 'message',
+		'type' => 'text',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'log_online',
+		'column' => 'url',
+		'type' => 'text',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'membergroups',
+		'column' => 'stars',
+		'type' => 'tinytext',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'members',
+		'column' => 'lngfile',
+		'type' => 'tinytext',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'members',
+		'column' => 'realName',
+		'type' => 'tinytext',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'members',
+		'column' => 'buddy_list',
+		'type' => 'tinytext',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'members',
+		'column' => 'pm_ignore_list',
+		'type' => 'text',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'members',
+		'column' => 'messageLabels',
+		'type' => 'text',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'members',
+		'column' => 'emailAddress',
+		'type' => 'tinytext',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'members',
+		'column' => 'personalText',
+		'type' => 'tinytext',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'members',
+		'column' => 'websiteTitle',
+		'type' => 'tinytext',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'members',
+		'column' => 'websiteUrl',
+		'type' => 'tinytext',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'members',
+		'column' => 'location',
+		'type' => 'tinytext',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'members',
+		'column' => 'ICQ',
+		'type' => 'tinytext',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'members',
+		'column' => 'MSN',
+		'type' => 'tinytext',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'members',
+		'column' => 'signature',
+		'type' => 'text',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'members',
+		'column' => 'avatar',
+		'type' => 'tinytext',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'members',
+		'column' => 'usertitle',
+		'type' => 'tinytext',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'members',
+		'column' => 'memberIP',
+		'type' => 'tinytext',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'members',
+		'column' => 'secretQuestion',
+		'type' => 'tinytext',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'members',
+		'column' => 'additionalGroups',
+		'type' => 'tinytext',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'messages',
+		'column' => 'subject',
+		'type' => 'tinytext',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'messages',
+		'column' => 'posterName',
+		'type' => 'tinytext',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'messages',
+		'column' => 'posterEmail',
+		'type' => 'tinytext',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'messages',
+		'column' => 'posterIP',
+		'type' => 'tinytext',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'messages',
+		'column' => 'modifiedName',
+		'type' => 'tinytext',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'messages',
+		'column' => 'body',
+		'type' => $body_type,
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'personal_messages',
+		'column' => 'body',
+		'type' => 'text',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'package_servers',
+		'column' => 'name',
+		'type' => 'tinytext',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'personal_messages',
+		'column' => 'fromName',
+		'type' => 'tinytext',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'personal_messages',
+		'column' => 'subject',
+		'type' => 'tinytext',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'personal_messages',
+		'column' => 'body',
+		'type' => 'text',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'polls',
+		'column' => 'question',
+		'type' => 'tinytext',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'polls',
+		'column' => 'posterName',
+		'type' => 'tinytext',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'poll_choices',
+		'column' => 'label',
+		'type' => 'tinytext',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'settings',
+		'column' => 'variable',
+		'type' => 'tinytext',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'settings',
+		'column' => 'value',
+		'type' => 'text',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'sessions',
+		'column' => 'data',
+		'type' => 'text',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'themes',
+		'column' => 'variable',
+		'type' => 'tinytext',
+		'null_allowed' => false,
+	),
+	array(
+		'table' => 'themes',
+		'column' => 'value',
+		'type' => 'text',
+		'null_allowed' => false,
+	),
+);
+$step_progress['total'] = count($textfield_updates);
+
+foreach ($textfield_updates as $ind => $change)
+{
+	// Already done it?
+	if ($_GET['strict_step'] > $ind)
+		continue;
+
+	// Make the index, with all the protection and all.
+	textfield_alter($change, $substep);
+
+	// Store this for the next table.
+	$_GET['strict_step']++;
+	$step_progress['current'] = $_GET['strict_step'];
+}
+
+$step_progress = array();
+---}
+---#
+
+---# Replacing messages index.
+ALTER TABLE {$db_prefix}messages
+ADD INDEX ipIndex (posterIP(15), ID_TOPIC);
+---#
+
+---# Adding log_topics index.
+---{
+upgrade_query("
+	ALTER TABLE {$db_prefix}log_topics
+	ADD INDEX ID_TOPIC (ID_TOPIC)", true);
+---}
+---#
+
+/******************************************************************************/
+--- Adding more room for the buddy list
+/******************************************************************************/
+
+---# Updating the members table ...
+ALTER TABLE {$db_prefix}members
+CHANGE COLUMN buddy_list buddy_list text NOT NULL;
+---#
+
+/******************************************************************************/
+--- Change some column types to accomodate more messages.
+/******************************************************************************/
+
+---# Expanding message column size.
+---{
+$_GET['msg_change'] = isset($_GET['msg_change']) ? (int) $_GET['msg_change'] : 0;
+$step_progress['name'] = 'Expanding Message Capacity';
+$step_progress['current'] = $_GET['msg_change'];
+
+// The array holding all the changes.
+$columnChanges = array(
+	array(
+		'table' => 'boards',
+		'type' => 'column',
+		'method' => 'change',
+		'name' => 'ID_LAST_MSG',
+		'text' => 'CHANGE ID_LAST_MSG ID_LAST_MSG int(10) unsigned NOT NULL default \'0\'',
+	),
+	array(
+		'table' => 'boards',
+		'type' => 'column',
+		'method' => 'change',
+		'name' => 'ID_MSG_UPDATED',
+		'text' => 'CHANGE ID_MSG_UPDATED ID_MSG_UPDATED int(10) unsigned NOT NULL default \'0\'',
+	),
+	array(
+		'table' => 'log_boards',
+		'type' => 'column',
+		'method' => 'change',
+		'name' => 'ID_MSG',
+		'text' => 'CHANGE ID_MSG ID_MSG int(10) unsigned NOT NULL default \'0\'',
+	),
+	array(
+		'table' => 'log_mark_read',
+		'type' => 'column',
+		'method' => 'change',
+		'name' => 'ID_MSG',
+		'text' => 'CHANGE ID_MSG ID_MSG int(10) unsigned NOT NULL default \'0\'',
+	),
+	array(
+		'table' => 'log_topics',
+		'type' => 'column',
+		'method' => 'change',
+		'name' => 'ID_MSG',
+		'text' => 'CHANGE ID_MSG ID_MSG int(10) unsigned NOT NULL default \'0\'',
+	),
+	array(
+		'table' => 'messages',
+		'type' => 'column',
+		'method' => 'change',
+		'name' => 'ID_MSG_MODIFIED',
+		'text' => 'CHANGE ID_MSG_MODIFIED ID_MSG_MODIFIED int(10) unsigned NOT NULL default \'0\'',
+	),
+);
+
+if (!empty($modSettings['search_custom_index_config']))
+	$columnChanges[] = array(
+		'table' => 'log_search_words',
+		'type' => 'column',
+		'method' => 'change',
+		'name' => 'ID_MSG',
+		'text' => 'CHANGE ID_MSG ID_MSG int(10) unsigned NOT NULL default \'0\'',
+	);
+
+$step_progress['total'] = count($columnChanges);
+
+// Now we do all the changes...
+foreach ($columnChanges as $index => $change)
+{
+	// Already done it?
+	if ($_GET['msg_change'] > $ind)
+		continue;
+
+	// Now change the column at last.
+	protected_alter($change, $substep);
+
+	// Update where we are...
+	$_GET['msg_change']++;
+	$step_progress['current'] = $_GET['msg_change'];
+}
+
+// Clean up.
+unset($_GET['msg_change']);
+---}
+---#
+
+/******************************************************************************/
+--- Final clean up...
+/******************************************************************************/
+
+---# Sorting the boards...
+ALTER TABLE {$db_prefix}categories
+ORDER BY catOrder;
+
+ALTER TABLE {$db_prefix}boards
+ORDER BY boardOrder;
+---#
+
+---# Removing upgrade loop protection...
+DELETE FROM {$db_prefix}settings
+WHERE variable IN ('dont_repeat_smtp', 'dont_repeat_theme');
+---#

+ 3134 - 0
other/upgrade_2-0_mysql.sql

@@ -0,0 +1,3134 @@
+/* ATTENTION: You don't need to run or use this file!  The upgrade.php script does everything for you! */
+
+/******************************************************************************/
+--- Changing column names.
+/******************************************************************************/
+
+---# Renaming table columns.
+---{
+// The array holding all the changes.
+$nameChanges = array(
+	'admin_info_files' => array(
+		'ID_FILE' => 'ID_FILE id_file tinyint(4) unsigned NOT NULL auto_increment',
+	),
+	'approval_queue' => array(
+		'ID_MSG' => 'ID_MSG id_msg int(10) unsigned NOT NULL default \'0\'',
+		'ID_ATTACH' => 'ID_ATTACH id_attach int(10) unsigned NOT NULL default \'0\'',
+		'ID_EVENT' => 'ID_EVENT id_event smallint(5) unsigned NOT NULL default \'0\'',
+		'attachmentType' => 'attachmentType attachment_type tinyint(3) unsigned NOT NULL default \'0\'',
+	),
+	'attachments' => array(
+		'ID_ATTACH' => 'ID_ATTACH id_attach int(10) unsigned NOT NULL auto_increment',
+		'ID_THUMB' => 'ID_THUMB id_thumb int(10) unsigned NOT NULL default \'0\'',
+		'ID_MSG' => 'ID_MSG id_msg int(10) unsigned NOT NULL default \'0\'',
+		'ID_MEMBER' => 'ID_MEMBER id_member mediumint(8) unsigned NOT NULL default \'0\'',
+		'attachmentType' => 'attachmentType attachment_type tinyint(3) unsigned NOT NULL default \'0\'',
+	),
+	'ban_groups' => array(
+		'ID_BAN_GROUP' => 'ID_BAN_GROUP id_ban_group mediumint(8) unsigned NOT NULL auto_increment',
+	),
+	'ban_items' => array(
+		'ID_BAN' => 'ID_BAN id_ban mediumint(8) unsigned NOT NULL auto_increment',
+		'ID_BAN_GROUP' => 'ID_BAN_GROUP id_ban_group smallint(5) unsigned NOT NULL default \'0\'',
+		'ID_MEMBER' => 'ID_MEMBER id_member mediumint(8) unsigned NOT NULL default \'0\'',
+	),
+	'board_permissions' => array(
+		'ID_GROUP' => 'ID_GROUP id_group smallint(5) NOT NULL default \'0\'',
+		'ID_PROFILE' => 'ID_PROFILE id_profile smallint(5) NOT NULL default \'0\'',
+		'addDeny' => 'addDeny add_deny tinyint(4) NOT NULL default \'1\'',
+	),
+	'boards' => array(
+		'ID_BOARD' => 'ID_BOARD id_board smallint(5) unsigned NOT NULL auto_increment',
+		'ID_CAT' => 'ID_CAT id_cat tinyint(4) unsigned NOT NULL default \'0\'',
+		'childLevel' => 'childLevel child_level tinyint(4) unsigned NOT NULL default \'0\'',
+		'ID_PARENT' => 'ID_PARENT id_parent smallint(5) unsigned NOT NULL default \'0\'',
+		'boardOrder' => 'boardOrder board_order smallint(5) NOT NULL default \'0\'',
+		'ID_LAST_MSG' => 'ID_LAST_MSG id_last_msg int(10) unsigned NOT NULL default \'0\'',
+		'ID_MSG_UPDATED' => 'ID_MSG_UPDATED id_msg_updated int(10) unsigned NOT NULL default \'0\'',
+		'memberGroups' => 'memberGroups member_groups varchar(255) NOT NULL default \'-1,0\'',
+		'ID_PROFILE' => 'ID_PROFILE id_profile smallint(5) unsigned NOT NULL default \'1\'',
+		'numTopics' => 'numTopics num_topics mediumint(8) unsigned NOT NULL default \'0\'',
+		'numPosts' => 'numPosts num_posts mediumint(8) unsigned NOT NULL default \'0\'',
+		'countPosts' => 'countPosts count_posts tinyint(4) NOT NULL default \'0\'',
+		'ID_THEME' => 'ID_THEME id_theme tinyint(4) unsigned NOT NULL default \'0\'',
+		'unapprovedPosts' => 'unapprovedPosts unapproved_posts smallint(5) NOT NULL default \'0\'',
+		'unapprovedTopics' => 'unapprovedTopics unapproved_topics smallint(5) NOT NULL default \'0\'',
+	),
+	'calendar' => array(
+		'ID_EVENT' => 'ID_EVENT id_event smallint(5) unsigned NOT NULL auto_increment',
+		'ID_MEMBER' => 'ID_MEMBER id_member mediumint(8) unsigned NOT NULL default \'0\'',
+		'ID_BOARD' => 'ID_BOARD id_board smallint(5) unsigned NOT NULL default \'0\'',
+		'ID_TOPIC' => 'ID_TOPIC id_topic mediumint(8) unsigned NOT NULL default \'0\'',
+		'startDate' => 'startDate start_date date NOT NULL default \'0001-01-01\'',
+		'endDate' => 'endDate end_date date NOT NULL default \'0001-01-01\'',
+	),
+	'calendar_holidays' => array(
+		'ID_HOLIDAY' => 'ID_HOLIDAY id_holiday smallint(5) unsigned NOT NULL auto_increment',
+		'eventDate' => 'eventDate event_date date NOT NULL default \'0001-01-01\'',
+	),
+	'categories' => array(
+		'ID_CAT' => 'ID_CAT id_cat tinyint(4) unsigned NOT NULL auto_increment',
+		'catOrder' => 'catOrder cat_order tinyint(4) NOT NULL default \'0\'',
+		'canCollapse' => 'canCollapse can_collapse tinyint(1) NOT NULL default \'1\'',
+	),
+	'collapsed_categories' => array(
+		'ID_MEMBER' => 'ID_MEMBER id_member mediumint(8) unsigned NOT NULL default \'0\'',
+		'ID_CAT' => 'ID_CAT id_cat tinyint(4) unsigned NOT NULL',
+	),
+	'custom_fields' => array(
+		'ID_FIELD' => 'ID_FIELD id_field smallint(5) NOT NULL auto_increment',
+		'colName' => 'colName col_name varchar(12) NOT NULL default \'\'',
+		'fieldName' => 'fieldName field_name varchar(40) NOT NULL default \'\'',
+		'fieldDesc' => 'fieldDesc field_desc varchar(255) NOT NULL default \'\'',
+		'fieldType' => 'fieldType field_type varchar(8) NOT NULL default \'text\'',
+		'fieldLength' => 'fieldLength field_length smallint(5) NOT NULL default \'255\'',
+		'fieldOptions' => 'fieldOptions field_options text NOT NULL',
+		'showReg' => 'showReg show_reg tinyint(3) NOT NULL default \'0\'',
+		'showDisplay' => 'showDisplay show_display tinyint(3) NOT NULL default \'0\'',
+		'showProfile' => 'showProfile show_profile varchar(20) NOT NULL default \'forumprofile\'',
+		'defaultValue' => 'defaultValue default_value varchar(8) NOT NULL default \'0\'',
+	),
+	'group_moderators' => array(
+		'ID_MEMBER' => 'ID_MEMBER id_member mediumint(8) unsigned NOT NULL default \'0\'',
+		'ID_GROUP' => 'ID_GROUP id_group smallint(5) unsigned NOT NULL default \'0\'',
+	),
+	'log_actions' => array(
+		'ID_ACTION' => 'ID_ACTION id_action int(10) unsigned NOT NULL auto_increment',
+		'ID_MEMBER' => 'ID_MEMBER id_member mediumint(8) unsigned NOT NULL default \'0\'',
+		'logTime' => 'logTime log_time int(10) unsigned NOT NULL default \'0\'',
+		'ID_MSG' => 'ID_MSG id_msg int(10) unsigned NOT NULL default \'0\'',
+		'ID_TOPIC' => 'ID_TOPIC id_topic mediumint(8) unsigned NOT NULL default \'0\'',
+		'ID_BOARD' => 'ID_BOARD id_board smallint(5) unsigned NOT NULL default \'0\'',
+	),
+	'log_activity' => array(
+		'mostOn' => 'mostOn most_on smallint(5) unsigned NOT NULL default \'0\'',
+	),
+	'log_banned' => array(
+		'ID_BAN_LOG' => 'ID_BAN_LOG id_ban_log mediumint(8) unsigned NOT NULL auto_increment',
+		'ID_MEMBER' => 'ID_MEMBER id_member mediumint(8) unsigned NOT NULL default \'0\'',
+		'logTime' => 'logTime log_time int(10) unsigned NOT NULL default \'0\'',
+	),
+	'log_boards' => array(
+		'ID_MEMBER' => 'ID_MEMBER id_member mediumint(8) unsigned NOT NULL default \'0\'',
+		'ID_MSG' => 'ID_MSG id_msg int(10) unsigned NOT NULL default \'0\'',
+		'ID_BOARD' => 'ID_BOARD id_board smallint(5) unsigned NOT NULL default \'0\'',
+	),
+	'log_digest' => array(
+		'ID_TOPIC' => 'ID_TOPIC id_topic mediumint(8) unsigned NOT NULL default \'0\'',
+		'ID_MSG' => 'ID_MSG id_msg int(10) unsigned NOT NULL default \'0\'',
+	),
+	'log_errors' => array(
+		'ID_ERROR' => 'ID_ERROR id_error mediumint(8) unsigned NOT NULL auto_increment',
+		'logTime' => 'logTime log_time int(10) unsigned NOT NULL default \'0\'',
+		'ID_MEMBER' => 'ID_MEMBER id_member mediumint(8) unsigned NOT NULL default \'0\'',
+		'errorType' => 'errorType error_type char(15) NOT NULL default \'general\'',
+	),
+	'log_floodcontrol' => array(
+		'logTime' => 'logTime log_time int(10) unsigned NOT NULL default \'0\'',
+	),
+	'log_group_requests' => array(
+		'ID_REQUEST' => 'ID_REQUEST id_request mediumint(8) unsigned NOT NULL auto_increment',
+		'ID_MEMBER' => 'ID_MEMBER id_member mediumint(8) unsigned NOT NULL default \'0\'',
+		'ID_GROUP' => 'ID_GROUP id_group smallint(5) unsigned NOT NULL default \'0\'',
+	),
+	'log_karma' => array(
+		'ID_TARGET' => 'ID_TARGET id_target mediumint(8) unsigned NOT NULL default \'0\'',
+		'ID_EXECUTOR' => 'ID_EXECUTOR id_executor mediumint(8) unsigned NOT NULL default \'0\'',
+		'logTime' => 'logTime log_time int(10) unsigned NOT NULL default \'0\'',
+	),
+	'log_mark_read' => array(
+		'ID_MEMBER' => 'ID_MEMBER id_member mediumint(8) unsigned NOT NULL default \'0\'',
+		'ID_MSG' => 'ID_MSG id_msg int(10) unsigned NOT NULL default \'0\'',
+		'ID_BOARD' => 'ID_BOARD id_board smallint(5) unsigned NOT NULL default \'0\'',
+	),
+	'log_notify' => array(
+		'ID_MEMBER' => 'ID_MEMBER id_member mediumint(8) unsigned NOT NULL default \'0\'',
+		'ID_TOPIC' => 'ID_TOPIC id_topic mediumint(8) unsigned NOT NULL default \'0\'',
+		'ID_BOARD' => 'ID_BOARD id_board smallint(5) unsigned NOT NULL default \'0\'',
+	),
+	'log_packages' => array(
+		'ID_INSTALL' => 'ID_INSTALL id_install int(10) NOT NULL auto_increment',
+		'ID_MEMBER_INSTALLED' => 'ID_MEMBER_INSTALLED id_member_installed mediumint(8) NOT NULL default \'0\'',
+		'ID_MEMBER_REMOVED' => 'ID_MEMBER_REMOVED id_member_removed mediumint(8) NOT NULL default \'0\'',
+	),
+	'log_polls' => array(
+		'ID_MEMBER' => 'ID_MEMBER id_member mediumint(8) unsigned NOT NULL default \'0\'',
+		'ID_CHOICE' => 'ID_CHOICE id_choice tinyint(3) unsigned NOT NULL default \'0\'',
+		'ID_POLL' => 'ID_POLL id_poll mediumint(8) unsigned NOT NULL default \'0\'',
+	),
+	'log_reported' => array(
+		'ID_REPORT' => 'ID_REPORT id_report mediumint(8) unsigned NOT NULL auto_increment',
+		'ID_MEMBER' => 'ID_MEMBER id_member mediumint(8) unsigned NOT NULL default \'0\'',
+		'ID_MSG' => 'ID_MSG id_msg int(10) unsigned NOT NULL default \'0\'',
+		'ID_TOPIC' => 'ID_TOPIC id_topic mediumint(8) unsigned NOT NULL default \'0\'',
+		'ID_BOARD' => 'ID_BOARD id_board smallint(5) unsigned NOT NULL default \'0\'',
+	),
+	'log_reported_comments' => array(
+		'ID_COMMENT' => 'ID_COMMENT id_comment mediumint(8) unsigned NOT NULL auto_increment',
+		'ID_REPORT' => 'ID_REPORT id_report mediumint(8) NOT NULL default \'0\'',
+		'ID_MEMBER' => 'ID_MEMBER id_member mediumint(8) unsigned NOT NULL default \'0\'',
+	),
+	'log_scheduled_tasks' => array(
+		'ID_LOG' => 'ID_LOG id_log mediumint(8) NOT NULL auto_increment',
+		'ID_TASK' => 'ID_TASK id_task smallint(5) NOT NULL default \'0\'',
+		'timeRun' => 'timeRun time_run int(10) NOT NULL default \'0\'',
+		'timeTaken' => 'timeTaken time_taken float NOT NULL default \'0\'',
+	),
+	'log_search_messages' => array(
+		'ID_SEARCH' => 'ID_SEARCH id_search tinyint(3) unsigned NOT NULL default \'0\'',
+		'ID_MSG' => 'ID_MSG id_msg int(10) unsigned NOT NULL default \'0\'',
+	),
+	'log_search_results' => array(
+		'ID_TOPIC' => 'ID_TOPIC id_topic mediumint(8) unsigned NOT NULL default \'0\'',
+		'ID_MSG' => 'ID_MSG id_msg int(10) unsigned NOT NULL default \'0\'',
+		'ID_SEARCH' => 'ID_SEARCH id_search tinyint(3) unsigned NOT NULL default \'0\'',
+	),
+	'log_search_subjects' => array(
+		'ID_TOPIC' => 'ID_TOPIC id_topic mediumint(8) unsigned NOT NULL default \'0\'',
+	),
+	'log_search_topics' => array(
+		'ID_SEARCH' => 'ID_SEARCH id_search tinyint(3) unsigned NOT NULL default \'0\'',
+		'ID_TOPIC' => 'ID_TOPIC id_topic mediumint(8) unsigned NOT NULL default \'0\'',
+	),
+	'log_subscribed' => array(
+		'ID_SUBLOG' => 'ID_SUBLOG id_sublog int(10) unsigned NOT NULL auto_increment',
+		'ID_SUBSCRIBE' => 'ID_SUBSCRIBE id_subscribe mediumint(8) unsigned NOT NULL default \'0\'',
+		'OLD_ID_GROUP' => 'OLD_ID_GROUP old_id_group smallint(5) NOT NULL default \'0\'',
+		'startTime' => 'startTime start_time int(10) NOT NULL default \'0\'',
+		'endTime' => 'endTime end_time int(10) NOT NULL default \'0\'',
+	),
+	'log_topics' => array(
+		'ID_MEMBER' => 'ID_MEMBER id_member mediumint(8) unsigned NOT NULL default \'0\'',
+		'ID_MSG' => 'ID_MSG id_msg int(10) unsigned NOT NULL default \'0\'',
+		'ID_TOPIC' => 'ID_TOPIC id_topic mediumint(8) unsigned NOT NULL default \'0\'',
+	),
+	'mail_queue' => array(
+		'ID_MAIL' => 'ID_MAIL id_mail int(10) unsigned NOT NULL auto_increment',
+	),
+	'members' => array(
+		'ID_MEMBER' => 'ID_MEMBER id_member mediumint(8) unsigned NOT NULL auto_increment',
+		'memberName' => 'memberName member_name varchar(80) NOT NULL default \'\'',
+		'dateRegistered' => 'dateRegistered date_registered int(10) unsigned NOT NULL default \'0\'',
+		'ID_GROUP' => 'ID_GROUP id_group smallint(5) unsigned NOT NULL default \'0\'',
+		'lastLogin' => 'lastLogin last_login int(10) unsigned NOT NULL default \'0\'',
+		'realName' => 'realName real_name varchar(255) NOT NULL default \'\'',
+		'instantMessages' => 'instantMessages instant_messages smallint(5) NOT NULL default \'0\'',
+		'unreadMessages' => 'unreadMessages unread_messages smallint(5) NOT NULL default \'0\'',
+		'messageLabels' => 'messageLabels message_labels text NOT NULL',
+		'emailAddress' => 'emailAddress email_address varchar(255) NOT NULL default \'\'',
+		'personalText' => 'personalText personal_text varchar(255) NOT NULL default \'\'',
+		'websiteTitle' => 'websiteTitle website_title varchar(255) NOT NULL default \'\'',
+		'websiteUrl' => 'websiteUrl website_url varchar(255) NOT NULL default \'\'',
+		'ICQ' => 'ICQ icq varchar(255) NOT NULL default \'\'',
+		'AIM' => 'AIM aim varchar(255) NOT NULL default \'\'',
+		'YIM' => 'YIM yim varchar(32) NOT NULL default \'\'',
+		'MSN' => 'MSN msn varchar(255) NOT NULL default \'\'',
+		'hideEmail' => 'hideEmail hide_email tinyint(4) NOT NULL default \'0\'',
+		'showOnline' => 'showOnline show_online tinyint(4) NOT NULL default \'1\'',
+		'timeFormat' => 'timeFormat time_format varchar(80) NOT NULL default \'\'',
+		'timeOffset' => 'timeOffset time_offset float NOT NULL default \'0\'',
+		'karmaBad' => 'karmaBad karma_bad smallint(5) unsigned NOT NULL default \'0\'',
+		'karmaGood' => 'karmaGood karma_good smallint(5) unsigned NOT NULL default \'0\'',
+		'notifyAnnouncements' => 'notifyAnnouncements notify_announcements tinyint(4) NOT NULL default \'1\'',
+		'notifyRegularity' => 'notifyRegularity notify_regularity tinyint(4) NOT NULL default \'1\'',
+		'notifySendBody' => 'notifySendBody notify_send_body tinyint(4) NOT NULL default \'0\'',
+		'notifyTypes' => 'notifyTypes notify_types tinyint(4) NOT NULL default \'2\'',
+		'memberIP' => 'memberIP member_ip varchar(255) NOT NULL default \'\'',
+		'secretQuestion' => 'secretQuestion secret_question varchar(255) NOT NULL default \'\'',
+		'secretAnswer' => 'secretAnswer secret_answer varchar(64) NOT NULL default \'\'',
+		'ID_THEME' => 'ID_THEME id_theme tinyint(4) unsigned NOT NULL default \'0\'',
+		'ID_MSG_LAST_VISIT' => 'ID_MSG_LAST_VISIT id_msg_last_visit int(10) unsigned NOT NULL default \'0\'',
+		'additionalGroups' => 'additionalGroups additional_groups varchar(255) NOT NULL default \'\'',
+		'smileySet' => 'smileySet smiley_set varchar(48) NOT NULL default \'\'',
+		'ID_POST_GROUP' => 'ID_POST_GROUP id_post_group smallint(5) unsigned NOT NULL default \'0\'',
+		'totalTimeLoggedIn' => 'totalTimeLoggedIn total_time_logged_in int(10) unsigned NOT NULL default \'0\'',
+		'passwordSalt' => 'passwordSalt password_salt varchar(255) NOT NULL default \'\'',
+		'ignoreBoards' => 'ignoreBoards ignore_boards text NOT NULL',
+		'memberIP2' => 'memberIP2 member_ip2 varchar(255) NOT NULL default \'\'',
+	),
+	'messages' => array(
+		'ID_MSG' => 'ID_MSG id_msg int(10) unsigned NOT NULL auto_increment',
+		'ID_TOPIC' => 'ID_TOPIC id_topic mediumint(8) unsigned NOT NULL default \'0\'',
+		'ID_BOARD' => 'ID_BOARD id_board smallint(5) unsigned NOT NULL default \'0\'',
+		'posterTime' => 'posterTime poster_time int(10) unsigned NOT NULL default \'0\'',
+		'ID_MEMBER' => 'ID_MEMBER id_member mediumint(8) unsigned NOT NULL default \'0\'',
+		'ID_MSG_MODIFIED' => 'ID_MSG_MODIFIED id_msg_modified int(10) unsigned NOT NULL default \'0\'',
+		'posterName' => 'posterName poster_name varchar(255) NOT NULL default \'\'',
+		'posterEmail' => 'posterEmail poster_email varchar(255) NOT NULL default \'\'',
+		'posterIP' => 'posterIP poster_ip varchar(255) NOT NULL default \'\'',
+		'smileysEnabled' => 'smileysEnabled smileys_enabled tinyint(4) NOT NULL default \'1\'',
+		'modifiedTime' => 'modifiedTime modified_time int(10) unsigned NOT NULL default \'0\'',
+		'modifiedName' => 'modifiedName modified_name varchar(255) NOT NULL default \'\'',
+	),
+	'membergroups' => array(
+		'ID_GROUP' => 'ID_GROUP id_group smallint(5) unsigned NOT NULL auto_increment',
+		'ID_PARENT' => 'ID_PARENT id_parent smallint(5) NOT NULL default \'-2\'',
+		'groupName' => 'groupName group_name varchar(80) NOT NULL default \'\'',
+		'onlineColor' => 'onlineColor online_color varchar(20) NOT NULL default \'\'',
+		'minPosts' => 'minPosts min_posts mediumint(9) NOT NULL default \'-1\'',
+		'maxMessages' => 'maxMessages max_messages smallint(5) unsigned NOT NULL default \'0\'',
+		'groupType' => 'groupType group_type tinyint(3) NOT NULL default \'0\'',
+	),
+	'message_icons' => array(
+		'ID_ICON' => 'ID_ICON id_icon smallint(5) unsigned NOT NULL auto_increment',
+		'iconOrder' => 'iconOrder icon_order smallint(5) unsigned NOT NULL default \'0\'',
+		'ID_BOARD' => 'ID_BOARD id_board smallint(5) unsigned NOT NULL default \'0\'',
+	),
+	'moderators' => array(
+		'ID_MEMBER' => 'ID_MEMBER id_member mediumint(8) unsigned NOT NULL default \'0\'',
+		'ID_BOARD' => 'ID_BOARD id_board smallint(5) unsigned NOT NULL default \'0\'',
+	),
+	'package_servers' => array(
+		'ID_SERVER' => 'ID_SERVER id_server smallint(5) unsigned NOT NULL auto_increment',
+	),
+	'personal_messages' => array(
+		'ID_PM' => 'ID_PM id_pm int(10) unsigned NOT NULL auto_increment',
+		'ID_MEMBER_FROM' => 'ID_MEMBER_FROM id_member_from mediumint(8) unsigned NOT NULL default \'0\'',
+		'deletedBySender' => 'deletedBySender deleted_by_sender tinyint(3) unsigned NOT NULL default \'0\'',
+		'fromName' => 'fromName from_name varchar(255) NOT NULL default \'\'',
+	),
+	'permission_profiles' => array(
+		'ID_PROFILE' => 'ID_PROFILE id_profile smallint(5) NOT NULL auto_increment',
+	),
+	'permissions' => array(
+		'ID_GROUP' => 'ID_GROUP id_group smallint(5) NOT NULL default \'0\'',
+		'addDeny' => 'addDeny add_deny tinyint(4) NOT NULL default \'1\'',
+	),
+	'pm_recipients' => array(
+		'ID_PM' => 'ID_PM id_pm int(10) unsigned NOT NULL default \'0\'',
+		'ID_MEMBER' => 'ID_MEMBER id_member mediumint(8) unsigned NOT NULL default \'0\'',
+	),
+	'polls' => array(
+		'ID_POLL' => 'ID_POLL id_poll mediumint(8) unsigned NOT NULL auto_increment',
+		'ID_MEMBER' => 'ID_MEMBER id_member mediumint(8) unsigned NOT NULL default \'0\'',
+		'votingLocked' => 'votingLocked voting_locked tinyint(1) NOT NULL default \'0\'',
+		'maxVotes' => 'maxVotes max_votes tinyint(3) unsigned NOT NULL default \'1\'',
+		'expireTime' => 'expireTime expire_time int(10) unsigned NOT NULL default \'0\'',
+		'hideResults' => 'hideResults hide_results tinyint(3) unsigned NOT NULL default \'0\'',
+		'changeVote' => 'changeVote change_vote tinyint(3) unsigned NOT NULL default \'0\'',
+		'posterName' => 'posterName poster_name varchar(255) NOT NULL default \'\'',
+	),
+	'poll_choices' => array(
+		'ID_CHOICE' => 'ID_CHOICE id_choice tinyint(3) unsigned NOT NULL default \'0\'',
+		'ID_POLL' => 'ID_POLL id_poll mediumint(8) unsigned NOT NULL default \'0\'',
+	),
+	'scheduled_tasks' => array(
+		'ID_TASK' => 'ID_TASK id_task smallint(5) NOT NULL auto_increment',
+		'nextTime' => 'nextTime next_time int(10) NOT NULL default \'0\'',
+		'timeRegularity' => 'timeRegularity time_regularity smallint(5) NOT NULL default \'0\'',
+		'timeOffset' => 'timeOffset time_offset int(10) NOT NULL default \'0\'',
+		'timeUnit' => 'timeUnit time_unit varchar(1) NOT NULL default \'h\'',
+	),
+	'smileys' => array(
+		'ID_SMILEY' => 'ID_SMILEY id_smiley smallint(5) unsigned NOT NULL auto_increment',
+		'smileyRow' => 'smileyRow smiley_row tinyint(4) unsigned NOT NULL default \'0\'',
+		'smileyOrder' => 'smileyOrder smiley_order smallint(5) unsigned NOT NULL default \'0\'',
+	),
+	'subscriptions' => array(
+		'ID_SUBSCRIBE' => 'ID_SUBSCRIBE id_subscribe mediumint(8) unsigned NOT NULL auto_increment',
+		'ID_GROUP' => 'ID_GROUP id_group smallint(5) NOT NULL default \'0\'',
+		'addGroups' => 'addGroups add_groups varchar(40) NOT NULL default \'\'',
+		'allowPartial' => 'allowPartial allow_partial tinyint(3) NOT NULL default \'0\'',
+	),
+	'themes' => array(
+		'ID_MEMBER' => 'ID_MEMBER id_member mediumint(8) NOT NULL default \'0\'',
+		'ID_THEME' => 'ID_THEME id_theme tinyint(4) unsigned NOT NULL default \'1\'',
+	),
+	'topics' => array(
+		'ID_TOPIC' => 'ID_TOPIC id_topic mediumint(8) unsigned NOT NULL auto_increment',
+		'isSticky' => 'isSticky is_sticky tinyint(4) NOT NULL default \'0\'',
+		'ID_BOARD' => 'ID_BOARD id_board smallint(5) unsigned NOT NULL default \'0\'',
+		'ID_FIRST_MSG' => 'ID_FIRST_MSG id_first_msg int(10) unsigned NOT NULL default \'0\'',
+		'ID_LAST_MSG' => 'ID_LAST_MSG id_last_msg int(10) unsigned NOT NULL default \'0\'',
+		'ID_MEMBER_STARTED' => 'ID_MEMBER_STARTED id_member_started mediumint(8) unsigned NOT NULL default \'0\'',
+		'ID_MEMBER_UPDATED' => 'ID_MEMBER_UPDATED id_member_updated mediumint(8) unsigned NOT NULL default \'0\'',
+		'ID_POLL' => 'ID_POLL id_poll mediumint(8) unsigned NOT NULL default \'0\'',
+		'numReplies' => 'numReplies num_replies int(10) unsigned NOT NULL default \'0\'',
+		'numViews' => 'numViews num_views int(10) unsigned NOT NULL default \'0\'',
+		'unapprovedPosts' => 'unapprovedPosts unapproved_posts smallint(5) NOT NULL default \'0\'',
+	),
+);
+
+$_GET['ren_col'] = isset($_GET['ren_col']) ? (int) $_GET['ren_col'] : 0;
+$step_progress['name'] = 'Renaming columns';
+$step_progress['current'] = $_GET['ren_col'];
+$step_progress['total'] = count($nameChanges);
+
+$count = 0;
+// Now do every table...
+foreach ($nameChanges as $table_name => $table)
+{
+	// Already done this?
+	$count++;
+	if ($_GET['ren_col'] > $count)
+		continue;
+	$_GET['ren_col'] = $count;
+
+	// Check the table exists!
+	$request = upgrade_query("
+		SHOW TABLES
+		LIKE '{$db_prefix}$table_name'");
+	if (mysql_num_rows($request) == 0)
+	{
+		mysql_free_result($request);
+		continue;
+	}
+	mysql_free_result($request);
+
+	// Check each column!
+	$actualChanges = array();
+	foreach ($table as $colname => $coldef)
+	{
+		$change = array(
+			'table' => $table_name,
+			'name' => $colname,
+			'type' => 'column',
+			'method' => 'change_remove',
+			'text' => 'CHANGE ' . $coldef,
+		);
+
+		// Check if this change may need a special edit.
+		checkChange($change);
+
+		if (protected_alter($change, $substep, true) == false)
+			$actualChanges[] = ' CHANGE COLUMN ' . $coldef;
+	}
+
+	// Do the query - if it needs doing.
+	if (!empty($actualChanges))
+	{
+		$change = array(
+			'table' => $table_name,
+			'name' => 'na',
+			'type' => 'table',
+			'method' => 'full_change',
+			'text' => implode(', ', $actualChanges),
+		);
+
+		// Here we go - hold on!
+		protected_alter($change, $substep);
+	}
+
+	// Update where we are!
+	$step_progress['current'] = $_GET['ren_col'];
+}
+
+// All done!
+unset($_GET['ren_col']);
+---}
+---#
+
+---# Converting "log_online".
+DROP TABLE IF EXISTS {$db_prefix}log_online;
+CREATE TABLE {$db_prefix}log_online (
+	session varchar(32) NOT NULL default '',
+	log_time int(10) NOT NULL default '0',
+	id_member mediumint(8) unsigned NOT NULL default '0',
+	id_spider smallint(5) unsigned NOT NULL default '0',
+	ip int(10) unsigned NOT NULL default '0',
+	url text NOT NULL,
+	PRIMARY KEY (session),
+	KEY log_time (log_time),
+	KEY id_member (id_member)
+) ENGINE=MyISAM{$db_collation};
+---#
+
+/******************************************************************************/
+--- Adding new board specific features.
+/******************************************************************************/
+
+---# Implementing board redirects.
+ALTER TABLE {$db_prefix}boards
+ADD COLUMN redirect varchar(255) NOT NULL default '';
+---#
+
+/******************************************************************************/
+--- Adding search engine tracking.
+/******************************************************************************/
+
+---# Creating spider table.
+CREATE TABLE IF NOT EXISTS {$db_prefix}spiders (
+	id_spider smallint(5) unsigned NOT NULL auto_increment,
+	spider_name varchar(255) NOT NULL default '',
+	user_agent varchar(255) NOT NULL default '',
+	ip_info varchar(255) NOT NULL default '',
+	PRIMARY KEY id_spider(id_spider)
+) ENGINE=MyISAM{$db_collation};
+
+INSERT IGNORE INTO {$db_prefix}spiders
+	(id_spider, spider_name, user_agent, ip_info)
+VALUES
+	(1, 'Google', 'googlebot', ''),
+	(2, 'Yahoo!', 'slurp', ''),
+	(3, 'MSN', 'msnbot', ''),
+	(4, 'Google (Mobile)', 'Googlebot-Mobile', ''),
+	(5, 'Google (Image)', 'Googlebot-Image', ''),
+	(6, 'Google (AdSense)', 'Mediapartners-Google', ''),
+	(7, 'Google (Adwords)', 'AdsBot-Google', ''),
+	(8, 'Yahoo! (Mobile)', 'YahooSeeker/M1A1-R2D2', ''),
+	(9, 'Yahoo! (Image)', 'Yahoo-MMCrawler', ''),
+	(10, 'MSN (Mobile)', 'MSNBOT_Mobile', ''),
+	(11, 'MSN (Media)', 'msnbot-media', ''),
+	(12, 'Cuil', 'twiceler', ''),
+	(13, 'Ask', 'Teoma', ''),
+	(14, 'Baidu', 'Baiduspider', ''),
+	(15, 'Gigablast', 'Gigabot', ''),
+	(16, 'InternetArchive', 'ia_archiver-web.archive.org', ''),
+	(17, 'Alexa', 'ia_archiver', ''),
+	(18, 'Omgili', 'omgilibot', ''),
+	(19, 'EntireWeb', 'Speedy Spider', '');
+---#
+
+---# Removing a spider.
+---{
+	upgrade_query("
+		DELETE FROM {$db_prefix}spiders
+		WHERE user_agent = 'yahoo'
+			AND spider_name = 'Yahoo! (Publisher)'
+	");
+---}
+---#
+
+---# Creating spider hit tracking table.
+CREATE TABLE IF NOT EXISTS {$db_prefix}log_spider_hits (
+	id_hit int(10) unsigned NOT NULL auto_increment,
+	id_spider smallint(5) unsigned NOT NULL default '0',
+	log_time int(10) unsigned NOT NULL default '0',
+	url varchar(255) NOT NULL default '',
+	processed tinyint(3) unsigned NOT NULL default '0',
+	PRIMARY KEY (id_hit),
+	KEY id_spider(id_spider),
+	KEY log_time(log_time),
+	KEY processed (processed)
+) ENGINE=MyISAM{$db_collation};
+---#
+
+---# Making some changes to spider hit table...
+ALTER TABLE {$db_prefix}log_spider_hits
+ADD COLUMN id_hit int(10) unsigned NOT NULL auto_increment,
+ADD PRIMARY KEY (id_hit);
+---#
+
+---# Creating spider statistic table.
+CREATE TABLE IF NOT EXISTS {$db_prefix}log_spider_stats (
+	id_spider smallint(5) unsigned NOT NULL default '0',
+	page_hits smallint(5) unsigned NOT NULL default '0',
+	last_seen int(10) unsigned NOT NULL default '0',
+	stat_date date NOT NULL default '0001-01-01',
+	PRIMARY KEY (stat_date, id_spider)
+) ENGINE=MyISAM{$db_collation};
+---#
+
+/******************************************************************************/
+--- Adding new forum settings.
+/******************************************************************************/
+
+---# Resetting settings_updated.
+REPLACE INTO {$db_prefix}settings
+	(variable, value)
+VALUES
+	('settings_updated', '0'),
+	('last_mod_report_action', '0'),
+	('search_floodcontrol_time', '5'),
+	('next_task_time', UNIX_TIMESTAMP());
+---#
+
+---# Changing stats settings.
+---{
+$request = upgrade_query("
+	SELECT value
+	FROM {$db_prefix}themes
+	WHERE variable = 'show_sp1_info'");
+if (mysql_num_rows($request) != 0)
+{
+	upgrade_query("
+		DELETE FROM {$db_prefix}themes
+		WHERE variable = 'show_stats_index'");
+
+	upgrade_query("
+		UPDATE {$db_prefix}themes
+		SET variable = 'show_stats_index'
+		WHERE variable = 'show_sp1_info'");
+}
+upgrade_query("
+	DELETE FROM {$db_prefix}themes
+	WHERE variable = 'show_sp1_info'");
+---}
+---#
+
+---# Enable cache if upgrading from 1.1 and lower.
+---{
+if (isset($modSettings['smfVersion']) && $modSettings['smfVersion'] <= '2.0 Beta 1')
+{
+	$request = upgrade_query("
+		SELECT value
+		FROM {$db_prefix}settings
+		WHERE variable = 'cache_enable'");
+	list ($cache_enable) = $smcFunc['db_fetch_row']($request);
+
+	// No cache before 1.1.
+	if ($smcFunc['db_num_rows']($request) == 0)
+		upgrade_query("
+			INSERT INTO {$db_prefix}settings
+				(variable, value)
+			VALUES ('cache_enable', '1')");
+	elseif (empty($cache_enable))
+		upgrade_query("
+			UPDATE {$db_prefix}settings
+			SET value = '1'
+			WHERE variable = 'cache_enable'");
+}
+---}
+---#
+
+---# Changing visual verification setting.
+---{
+$request = upgrade_query("
+	SELECT value
+	FROM {$db_prefix}settings
+	WHERE variable = 'disable_visual_verification'");
+if (mysql_num_rows($request) != 0)
+{
+	list ($oldValue) = mysql_fetch_row($request);
+	if ($oldValue != 0)
+	{
+		// We have changed the medium setting from SMF 1.1.2.
+		if ($oldValue == 4)
+			$oldValue = 5;
+
+		upgrade_query("
+			UPDATE {$db_prefix}settings
+			SET variable = 'visual_verification_type', value = $oldValue
+			WHERE variable = 'disable_visual_verification'");
+	}
+}
+upgrade_query("
+	DELETE FROM {$db_prefix}settings
+	WHERE variable = 'disable_visual_verification'");
+---}
+---#
+
+---# Changing visual verification setting, again.
+---{
+$request = upgrade_query("
+	SELECT value
+	FROM {$db_prefix}settings
+	WHERE variable = 'reg_verification'");
+if (mysql_num_rows($request) == 0)
+{
+	// Upgrade visual verification again!
+	if (!empty($modSettings['visual_verification_type']))
+	{
+		upgrade_query("
+			UPDATE {$db_prefix}settings
+			SET value = value - 1
+			WHERE variable = 'visual_verification_type'");
+		$modSettings['visual_verification_type']--;
+	}
+	// Never set?
+	elseif (!isset($modSettings['visual_verification_type']))
+	{
+		upgrade_query("
+			INSERT INTO {$db_prefix}settings
+				(variable, value)
+			VALUES
+				('visual_verification_type', '3')");
+		$modSettings['visual_verification_type'] = 3;
+	}
+
+	upgrade_query("
+		INSERT INTO {$db_prefix}settings
+			(variable, value)
+		VALUES
+			('reg_verification', '" . (!empty($modSettings['visual_verification_type']) ? 1 : 0) . "')");
+}
+---}
+---#
+
+---# Changing default personal text setting.
+UPDATE {$db_prefix}settings
+SET variable = 'default_personal_text'
+WHERE variable = 'default_personalText';
+
+DELETE FROM {$db_prefix}settings
+WHERE variable = 'default_personalText';
+---#
+
+---# Removing allow hide email setting.
+DELETE FROM {$db_prefix}settings
+WHERE variable = 'allow_hideEmail'
+	OR variable = 'allow_hide_email';
+---#
+
+---# Ensuring stats index setting present...
+INSERT IGNORE INTO {$db_prefix}themes
+	(id_theme, variable, value)
+VALUES
+	(1, 'show_stats_index', '0');
+---#
+
+---# Ensuring forum width setting present...
+INSERT IGNORE INTO {$db_prefix}themes
+	(id_theme, variable, value)
+VALUES
+	(1, 'forum_width', '90%');
+---#
+
+---# Replacing old calendar settings...
+---{
+// Only try it if one of the "new" settings doesn't yet exist.
+if (!isset($modSettings['cal_showholidays']) || !isset($modSettings['cal_showbdays']) || !isset($modSettings['cal_showevents']))
+{
+	// Default to just the calendar setting.
+	$modSettings['cal_showholidays'] = empty($modSettings['cal_showholidaysoncalendar']) ? 0 : 1;
+	$modSettings['cal_showbdays'] = empty($modSettings['cal_showbdaysoncalendar']) ? 0 : 1;
+	$modSettings['cal_showevents'] = empty($modSettings['cal_showeventsoncalendar']) ? 0 : 1;
+
+	// Then take into account board index.
+	if (!empty($modSettings['cal_showholidaysonindex']))
+		$modSettings['cal_showholidays'] = $modSettings['cal_showholidays'] === 1 ? 2 : 3;
+	if (!empty($modSettings['cal_showbdaysonindex']))
+		$modSettings['cal_showbdays'] = $modSettings['cal_showbdays'] === 1 ? 2 : 3;
+	if (!empty($modSettings['cal_showeventsonindex']))
+		$modSettings['cal_showevents'] = $modSettings['cal_showevents'] === 1 ? 2 : 3;
+
+	// Actually save the settings.
+	upgrade_query("
+		INSERT IGNORE INTO {$db_prefix}settings
+			(variable, value)
+		VALUES
+			('cal_showholidays', $modSettings[cal_showholidays]),
+			('cal_showbdays', $modSettings[cal_showbdays]),
+			('cal_showevents', $modSettings[cal_showevents])");
+}
+
+---}
+---#
+
+---# Deleting old calendar settings...
+	DELETE FROM {$db_prefix}settings
+	WHERE VARIABLE IN ('cal_showholidaysonindex', 'cal_showbdaysonindex', 'cal_showeventsonindex',
+		'cal_showholidaysoncalendar', 'cal_showbdaysoncalendar', 'cal_showeventsoncalendar',
+		'cal_holidaycolor', 'cal_bdaycolor', 'cal_eventcolor');
+---#
+
+---# Adjusting calendar maximum year...
+---{
+if (!isset($modSettings['cal_maxyear']) || $modSettings['cal_maxyear'] == '2010')
+{
+	upgrade_query("
+		REPLACE INTO {$db_prefix}settings
+			(variable, value)
+		VALUES
+			('cal_maxyear', '2020')");
+}
+---}
+---#
+
+---# Adding advanced signature settings...
+---{
+if (empty($modSettings['signature_settings']))
+{
+	if (isset($modSettings['max_signatureLength']))
+		$modSettings['signature_settings'] = '1,' . $modSettings['max_signatureLength'] . ',0,0,0,0,0,0:';
+	else
+		$modSettings['signature_settings'] = '1,300,0,0,0,0,0,0:';
+
+	upgrade_query("
+		INSERT IGNORE INTO {$db_prefix}settings
+			(variable, value)
+		VALUES
+			('signature_settings', '$modSettings[signature_settings]')");
+
+	upgrade_query("
+		DELETE FROM {$db_prefix}settings
+		WHERE variable = 'max_signatureLength'");
+}
+---}
+---#
+
+---# Updating spam protection settings.
+---{
+if (empty($modSettings['pm_spam_settings']))
+{
+	if (isset($modSettings['max_pm_recipients']))
+		$modSettings['pm_spam_settings'] = $modSettings['max_pm_recipients'] . ',5,20';
+	else
+		$modSettings['pm_spam_settings'] = '10,5,20';
+}
+elseif (substr_count($modSettings['pm_spam_settings'], ',') == 1)
+{
+	$modSettings['pm_spam_settings'] .= ',20';
+}
+
+upgrade_query("
+	INSERT IGNORE INTO {$db_prefix}settings
+		(variable, value)
+	VALUES
+		('pm_spam_settings', '$modSettings[pm_spam_settings]')");
+
+upgrade_query("
+	DELETE FROM {$db_prefix}settings
+	WHERE variable = 'max_pm_recipients'");
+---}
+---#
+
+---# Adjusting timezone settings...
+---{
+	if (!isset($modSettings['default_timezone']) && function_exists('date_default_timezone_set'))
+	{
+		$server_offset = mktime(0, 0, 0, 1, 1, 1970);
+		$timezone_id = 'Etc/GMT' . ($server_offset > 0 ? '+' : '') . ($server_offset / 3600);
+		if (date_default_timezone_set($timezone_id))
+			upgrade_query("
+				REPLACE INTO {$db_prefix}settings
+					(variable, value)
+				VALUES
+					('default_timezone', '$timezone_id')");
+	}
+---}
+---#
+
+---# Checking theme layers are correct for default themes.
+---{
+$request = upgrade_query("
+	SELECT id_theme, value, variable
+	FROM {$db_prefix}themes
+	WHERE variable = 'theme_layers'
+		OR variable = 'theme_dir'");
+$themeLayerChanges = array();
+while ($row = mysql_fetch_assoc($request))
+{
+	$themeLayerChanges[$row['id_theme']][$row['variable']] = $row['value'];
+}
+mysql_free_result($request);
+
+foreach ($themeLayerChanges as $id_theme => $data)
+{
+	// Has to be a SMF provided theme and have custom layers defined.
+	if (!isset($data['theme_layers']) || !isset($data['theme_dir']) || !in_array(substr($data['theme_dir'], -7), array('default', 'babylon', 'classic')))
+		continue;
+
+	$layers = explode(',', $data['theme_layers']);
+	foreach ($layers as $k => $v)
+		if ($v == 'main')
+		{
+			$layers[$k] = 'html,body';
+			upgrade_query("
+				UPDATE {$db_prefix}themes
+				SET value = '" . implode(',', $layers) . "'
+				WHERE id_theme = $id_theme
+					AND variable = 'theme_layers'");
+			break;
+		}
+}
+---}
+---#
+
+---# Adding index to log_notify table...
+ALTER TABLE {$db_prefix}log_notify
+ADD INDEX id_topic (id_topic, id_member);
+---#
+
+/******************************************************************************/
+--- Adding custom profile fields.
+/******************************************************************************/
+
+---# Creating "custom_fields" table...
+CREATE TABLE IF NOT EXISTS {$db_prefix}custom_fields (
+	id_field smallint(5) NOT NULL auto_increment,
+	col_name varchar(12) NOT NULL default '',
+	field_name varchar(40) NOT NULL default '',
+	field_desc varchar(255) NOT NULL default '',
+	field_type varchar(8) NOT NULL default 'text',
+	field_length smallint(5) NOT NULL default '255',
+	field_options text NOT NULL,
+	mask varchar(255) NOT NULL default '',
+	show_reg tinyint(3) NOT NULL default '0',
+	show_display tinyint(3) NOT NULL default '0',
+	show_profile varchar(20) NOT NULL default 'forumprofile',
+	private tinyint(3) NOT NULL default '0',
+	active tinyint(3) NOT NULL default '1',
+	bbc tinyint(3) NOT NULL default '0',
+	default_value varchar(255) NOT NULL default '',
+	PRIMARY KEY (id_field),
+	UNIQUE col_name (col_name)
+) ENGINE=MyISAM{$db_collation};
+---#
+
+---# Adding search ability to custom fields.
+ALTER TABLE {$db_prefix}custom_fields
+ADD COLUMN can_search tinyint(3) NOT NULL default '0' AFTER bbc;
+---#
+
+---# Fixing default value field length.
+ALTER TABLE {$db_prefix}custom_fields
+CHANGE COLUMN default_value default_value varchar(255) NOT NULL default '';
+---#
+
+---# Enhancing privacy settings for custom fields.
+---{
+if (isset($modSettings['smfVersion']) && $modSettings['smfVersion'] <= '2.0 Beta 1')
+{
+upgrade_query("
+	UPDATE {$db_prefix}custom_fields
+	SET private = 2
+	WHERE private = 1");
+}
+if (isset($modSettings['smfVersion']) && $modSettings['smfVersion'] < '2.0 Beta 4')
+{
+upgrade_query("
+	UPDATE {$db_prefix}custom_fields
+	SET private = 3
+	WHERE private = 2");
+}
+---}
+---#
+
+---# Checking display fields setup correctly..
+---{
+if (isset($modSettings['smfVersion']) && $modSettings['smfVersion'] <= '2.0 Beta 1' && isset($modSettings['displayFields']) && @unserialize($modSettings['displayFields']) == false)
+{
+$request = upgrade_query("
+	SELECT col_name, field_name, bbc
+	FROM {$db_prefix}custom_fields
+	WHERE show_display = 1
+		AND active = 1
+		AND private != 2");
+$fields = array();
+while ($row = mysql_fetch_assoc($request))
+{
+	$fields[] = array(
+		'c' => strtr($row['col_name'], array('|' => '', ';' => '')),
+		'f' => strtr($row['field_name'], array('|' => '', ';' => '')),
+		'b' => ($row['bbc'] ? '1' : '0')
+	);
+}
+mysql_free_result($request);
+
+upgrade_query("
+	UPDATE {$db_prefix}settings
+	SET value = '" . mysql_real_escape_string(serialize($fields)) . "'
+	WHERE variable = 'displayFields'");
+}
+---}
+---#
+
+---# Adding new custom fields columns.
+ALTER TABLE {$db_prefix}custom_fields
+ADD enclose text NOT NULL;
+
+ALTER TABLE {$db_prefix}custom_fields
+ADD placement tinyint(3) NOT NULL default '0';
+---#
+
+/******************************************************************************/
+--- Adding email digest functionality.
+/******************************************************************************/
+
+---# Creating "log_digest" table...
+CREATE TABLE IF NOT EXISTS {$db_prefix}log_digest (
+	id_topic mediumint(8) unsigned NOT NULL default '0',
+	id_msg int(10) unsigned NOT NULL default '0',
+	note_type varchar(10) NOT NULL default 'post',
+	daily tinyint(3) unsigned NOT NULL default '0',
+	exclude mediumint(8) unsigned NOT NULL default '0'
+) ENGINE=MyISAM{$db_collation};
+---#
+
+---# Adding digest option to "members" table...
+ALTER TABLE {$db_prefix}members
+CHANGE COLUMN notifyOnce notify_regularity tinyint(4) unsigned NOT NULL default '1';
+---#
+
+/******************************************************************************/
+--- Making changes to the package manager.
+/******************************************************************************/
+
+---# Creating "log_packages" table...
+CREATE TABLE IF NOT EXISTS {$db_prefix}log_packages (
+	id_install int(10) NOT NULL auto_increment,
+	filename varchar(255) NOT NULL default '',
+	package_id varchar(255) NOT NULL default '',
+	name varchar(255) NOT NULL default '',
+	version varchar(255) NOT NULL default '',
+	id_member_installed mediumint(8) NOT NULL default '0',
+	member_installed varchar(255) NOT NULL default '',
+	time_installed int(10) NOT NULL default '0',
+	id_member_removed mediumint(8) NOT NULL default '0',
+	member_removed varchar(255) NOT NULL default '',
+	time_removed int(10) NOT NULL default '0',
+	install_state tinyint(3) NOT NULL default '1',
+	failed_steps text NOT NULL,
+	themes_installed varchar(255) NOT NULL default '',
+	db_changes text NOT NULL,
+	PRIMARY KEY (id_install),
+	KEY filename (filename(15))
+) ENGINE=MyISAM{$db_collation};
+---#
+
+---# Adding extra "log_packages" columns...
+ALTER TABLE {$db_prefix}log_packages
+ADD db_changes text NOT NULL AFTER themes_installed;
+---#
+
+---# Changing URL to SMF package server...
+UPDATE {$db_prefix}package_servers
+SET url = 'http://custom.simplemachines.org/packages/mods'
+WHERE url = 'http://mods.simplemachines.org';
+---#
+
+/******************************************************************************/
+--- Creating mail queue functionality.
+/******************************************************************************/
+
+---# Creating "mail_queue" table...
+CREATE TABLE IF NOT EXISTS {$db_prefix}mail_queue (
+	id_mail int(10) unsigned NOT NULL auto_increment,
+	time_sent int(10) NOT NULL default '0',
+	recipient varchar(255) NOT NULL default '',
+	body text NOT NULL,
+	subject varchar(255) NOT NULL default '',
+	headers text NOT NULL,
+	send_html tinyint(3) NOT NULL default '0',
+	priority tinyint(3) NOT NULL default '1',
+	PRIMARY KEY (id_mail),
+	KEY time_sent (time_sent),
+	KEY mail_priority (priority, id_mail)
+) ENGINE=MyISAM{$db_collation};
+---#
+
+---# Adding new mail queue settings...
+---{
+if (!isset($modSettings['mail_next_send']))
+{
+	upgrade_query("
+		INSERT INTO {$db_prefix}settings
+			(variable, value)
+		VALUES
+			('mail_next_send', '0'),
+			('mail_recent', '0000000000|0')");
+}
+---}
+---#
+
+---# Change mail queue indexes...
+ALTER TABLE {$db_prefix}mail_queue
+DROP INDEX priority;
+
+ALTER TABLE {$db_prefix}mail_queue
+ADD INDEX mail_priority (priority, id_mail);
+---#
+
+---# Adding type to mail queue...
+ALTER TABLE {$db_prefix}mail_queue
+ADD private tinyint(1) NOT NULL default '0';
+---#
+
+/******************************************************************************/
+--- Creating moderation center tables.
+/******************************************************************************/
+
+---# Creating "log_reported" table...
+CREATE TABLE IF NOT EXISTS {$db_prefix}log_reported (
+	id_report mediumint(8) unsigned NOT NULL auto_increment,
+	id_msg int(10) unsigned NOT NULL default '0',
+	id_topic mediumint(8) unsigned NOT NULL default '0',
+	id_board smallint(5) unsigned NOT NULL default '0',
+	id_member mediumint(8) unsigned NOT NULL default '0',
+	membername varchar(255) NOT NULL default '',
+	subject varchar(255) NOT NULL default '',
+	body text NOT NULL,
+	time_started int(10) NOT NULL default '0',
+	time_updated int(10) NOT NULL default '0',
+	num_reports mediumint(6) NOT NULL default '0',
+	closed tinyint(3) NOT NULL default '0',
+	ignore_all tinyint(3) NOT NULL default '0',
+	PRIMARY KEY (id_report),
+	KEY id_member (id_member),
+	KEY id_topic (id_topic),
+	KEY closed (closed),
+	KEY time_started (time_started),
+	KEY id_msg (id_msg)
+) ENGINE=MyISAM{$db_collation};
+---#
+
+---# Creating "log_reported_comments" table...
+CREATE TABLE IF NOT EXISTS {$db_prefix}log_reported_comments (
+	id_comment mediumint(8) unsigned NOT NULL auto_increment,
+	id_report mediumint(8) NOT NULL default '0',
+	id_member mediumint(8) NOT NULL,
+	membername varchar(255) NOT NULL default '',
+	comment varchar(255) NOT NULL default '',
+	time_sent int(10) NOT NULL,
+	PRIMARY KEY (id_comment),
+	KEY id_report (id_report),
+	KEY id_member (id_member),
+	KEY time_sent (time_sent)
+) ENGINE=MyISAM{$db_collation};
+---#
+
+---# Adding moderator center permissions...
+---{
+// Don't do this twice!
+if (@$modSettings['smfVersion'] < '2.0')
+{
+	// Try find people who probably should see the moderation center.
+	$request = upgrade_query("
+		SELECT id_group, add_deny, permission
+		FROM {$db_prefix}permissions
+		WHERE permission = 'calendar_edit_any'");
+	$inserts = array();
+	while ($row = mysql_fetch_assoc($request))
+	{
+		$inserts[] = "($row[id_group], 'access_mod_center', $row[add_deny])";
+	}
+	mysql_free_result($request);
+
+	if (!empty($inserts))
+		upgrade_query("
+			INSERT IGNORE INTO {$db_prefix}permissions
+				(id_group, permission, add_deny)
+			VALUES
+				" . implode(',', $inserts));
+}
+---}
+---#
+
+---# Adding moderation center preferences...
+ALTER TABLE {$db_prefix}members
+ADD mod_prefs varchar(20) NOT NULL default '';
+---#
+
+/******************************************************************************/
+--- Adding user warnings.
+/******************************************************************************/
+
+---# Creating member notices table...
+CREATE TABLE IF NOT EXISTS {$db_prefix}log_member_notices (
+	id_notice mediumint(8) unsigned NOT NULL auto_increment,
+	subject varchar(255) NOT NULL default '',
+	body text NOT NULL,
+	PRIMARY KEY (id_notice)
+) ENGINE=MyISAM{$db_collation};
+---#
+
+---# Creating comments table...
+CREATE TABLE IF NOT EXISTS {$db_prefix}log_comments (
+	id_comment mediumint(8) unsigned NOT NULL auto_increment,
+	id_member mediumint(8) unsigned NOT NULL default '0',
+	member_name varchar(80) NOT NULL default '',
+	comment_type varchar(8) NOT NULL default 'warning',
+	id_recipient mediumint(8) unsigned NOT NULL default '0',
+	recipient_name varchar(255) NOT NULL default '',
+	log_time int(10) NOT NULL default '0',
+	id_notice mediumint(8) unsigned NOT NULL default '0',
+	counter tinyint(3) NOT NULL default '0',
+	body text NOT NULL,
+	PRIMARY KEY (id_comment),
+	KEY id_recipient (id_recipient),
+	KEY log_time (log_time),
+	KEY comment_type (comment_type(8))
+) ENGINE=MyISAM{$db_collation};
+---#
+
+---# Adding user warning column...
+ALTER TABLE {$db_prefix}members
+ADD warning tinyint(4) NOT NULL default '0';
+
+ALTER TABLE {$db_prefix}members
+ADD INDEX warning (warning);
+---#
+
+---# Ensuring warning settings are present...
+---{
+// Only do this if not already done.
+if (empty($modSettings['warning_settings']))
+{
+	upgrade_query("
+		INSERT IGNORE INTO {$db_prefix}settings
+			(variable, value)
+		VALUES
+			('warning_settings', '1,20,0'),
+			('warning_watch', '10'),
+			('warning_moderate', '35'),
+			('warning_mute', '60')");
+}
+---}
+---#
+
+/******************************************************************************/
+--- Enhancing membergroups.
+/******************************************************************************/
+
+---# Creating "log_group_requests" table...
+CREATE TABLE IF NOT EXISTS {$db_prefix}log_group_requests (
+	id_request mediumint(8) unsigned NOT NULL auto_increment,
+	id_member mediumint(8) unsigned NOT NULL default '0',
+	id_group smallint(5) unsigned NOT NULL default '0',
+	time_applied int(10) unsigned NOT NULL default '0',
+	reason text NOT NULL,
+	PRIMARY KEY (id_request),
+	UNIQUE id_member (id_member, id_group)
+) ENGINE=MyISAM{$db_collation};
+---#
+
+---# Adding new membergroup table columns...
+ALTER TABLE {$db_prefix}membergroups
+ADD description text NOT NULL AFTER group_name;
+
+ALTER TABLE {$db_prefix}membergroups
+ADD group_type tinyint(3) NOT NULL default '0';
+
+ALTER TABLE {$db_prefix}membergroups
+ADD hidden tinyint(3) NOT NULL default '0';
+---#
+
+---# Creating "group_moderators" table...
+CREATE TABLE IF NOT EXISTS {$db_prefix}group_moderators (
+	id_group smallint(5) unsigned NOT NULL default '0',
+	id_member mediumint(8) unsigned NOT NULL default '0',
+	PRIMARY KEY (id_group, id_member)
+) ENGINE=MyISAM{$db_collation};
+---#
+
+/******************************************************************************/
+--- Updating attachment data...
+/******************************************************************************/
+
+---# Altering attachment table.
+ALTER TABLE {$db_prefix}attachments
+ADD COLUMN fileext varchar(8) NOT NULL default '',
+ADD COLUMN mime_type varchar(20) NOT NULL default '';
+
+ALTER TABLE {$db_prefix}attachments
+ADD COLUMN id_folder tinyint(3) NOT NULL default '1';
+---#
+
+---# Adding file hash.
+ALTER TABLE {$db_prefix}attachments
+ADD COLUMN file_hash varchar(40) NOT NULL default '';
+---#
+
+---# Populate the attachment extension.
+UPDATE {$db_prefix}attachments
+SET fileext = LOWER(SUBSTRING(filename, 1 - (INSTR(REVERSE(filename), '.'))))
+WHERE fileext = ''
+	AND INSTR(filename, '.')
+	AND attachment_type != 3;
+---#
+
+---# Updating thumbnail attachments JPG.
+UPDATE {$db_prefix}attachments
+SET fileext = 'jpg'
+WHERE attachment_type = 3
+	AND fileext = ''
+	AND RIGHT(filename, 9) = 'JPG_thumb';
+---#
+
+---# Updating thumbnail attachments PNG.
+UPDATE {$db_prefix}attachments
+SET fileext = 'png'
+WHERE attachment_type = 3
+	AND fileext = ''
+	AND RIGHT(filename, 9) = 'PNG_thumb';
+---#
+
+---# Calculating attachment mime types.
+---{
+// Don't ever bother doing this twice.
+if (@$modSettings['smfVersion'] < '2.0' || @$modSettings['smfVersion'] === '2.0 a')
+{
+	$request = upgrade_query("
+		SELECT MAX(id_attach)
+		FROM {$db_prefix}attachments");
+	list ($step_progress['total']) = $smcFunc['db_fetch_row']($request);
+	$smcFunc['db_free_result']($request);
+
+	$_GET['a'] = isset($_GET['a']) ? (int) $_GET['a'] : 0;
+	$step_progress['name'] = 'Calculating MIME Types';
+	$step_progress['current'] = $_GET['a'];
+
+	if (!function_exists('getAttachmentFilename'))
+	{
+		function getAttachmentFilename($filename, $attachment_id)
+		{
+			global $modSettings;
+
+			$clean_name = strtr($filename, 'ŠŽšžŸÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÑÒÓÔÕÖØÙÚÛÜÝàáâãäåçèéêëìíîïñòóôõöøùúûüýÿ', 'SZszYAAAAAACEEEEIIIINOOOOOOUUUUYaaaaaaceeeeiiiinoooooouuuuyy');
+			$clean_name = strtr($clean_name, array('Þ' => 'TH', 'þ' => 'th', 'Ð' => 'DH', 'ð' => 'dh', 'ß' => 'ss', 'Œ' => 'OE', 'œ' => 'oe', 'Æ' => 'AE', 'æ' => 'ae', 'µ' => 'u'));
+			$clean_name = preg_replace(array('/\s/', '/[^\w_\.\-]/'), array('_', ''), $clean_name);
+			$enc_name = $attachment_id . '_' . strtr($clean_name, '.', '_') . md5($clean_name);
+			$clean_name = preg_replace('~\.[\.]+~', '.', $clean_name);
+
+			if ($attachment_id == false)
+				return $clean_name;
+
+			if (file_exists($modSettings['attachmentUploadDir'] . '/' . $enc_name))
+				$filename = $modSettings['attachmentUploadDir'] . '/' . $enc_name;
+			else
+				$filename = $modSettings['attachmentUploadDir'] . '/' . $clean_name;
+
+			return $filename;
+		}
+	}
+
+	$ext_updates = array();
+
+	// What headers are valid results for getimagesize?
+	$validTypes = array(
+		1 => 'gif',
+		2 => 'jpeg',
+		3 => 'png',
+		5 => 'psd',
+		6 => 'bmp',
+		7 => 'tiff',
+		8 => 'tiff',
+		9 => 'jpeg',
+		14 => 'iff',
+	);
+
+	$is_done = false;
+	while (!$is_done)
+	{
+		nextSubStep($substep);
+
+		$request = upgrade_query("
+			SELECT id_attach, filename, fileext
+			FROM {$db_prefix}attachments
+			WHERE fileext != ''
+				AND mime_type = ''
+			LIMIT $_GET[a], 100");
+		// Finished?
+		if ($smcFunc['db_num_rows']($request) == 0)
+			$is_done = true;
+		while ($row = $smcFunc['db_fetch_assoc']($request))
+		{
+			$filename = getAttachmentFilename($row['filename'], $row['id_attach']);
+			if (!file_exists($filename))
+				continue;
+
+			// Is it an image?
+			$size = @getimagesize($filename);
+			// Nothing valid?
+			if (empty($size) || empty($size[0]))
+				continue;
+			// Got the mime?
+			elseif (!empty($size['mime']))
+				$mime = $size['mime'];
+			// Otherwise is it valid?
+			elseif (!isset($validTypes[$size[2]]))
+				continue;
+			else
+				$mime = 'image/' . $validTypes[$size[2]];
+
+			// Let's try keep updates to a minimum.
+			if (!isset($ext_updates[$row['fileext'] . $size['mime']]))
+				$ext_updates[$row['fileext'] . $size['mime']] = array(
+					'fileext' => $row['fileext'],
+					'mime' => $mime,
+					'files' => array(),
+				);
+			$ext_updates[$row['fileext'] . $size['mime']]['files'][] = $row['id_attach'];
+		}
+		$smcFunc['db_free_result']($request);
+
+		// Do the updates?
+		foreach ($ext_updates as $key => $update)
+		{
+			upgrade_query("
+				UPDATE {$db_prefix}attachments
+				SET mime_type = '$update[mime]'
+				WHERE id_attach IN (" . implode(',', $update['files']) . ")");
+
+			// Remove it.
+			unset($ext_updates[$key]);
+		}
+
+		$_GET['a'] += 100;
+		$step_progress['current'] = $_GET['a'];
+	}
+
+	unset($_GET['a']);
+}
+---}
+---#
+
+/******************************************************************************/
+--- Adding Post Moderation.
+/******************************************************************************/
+
+---# Creating "approval_queue" table...
+CREATE TABLE IF NOT EXISTS {$db_prefix}approval_queue (
+	id_msg int(10) unsigned NOT NULL default '0',
+	id_attach int(10) unsigned NOT NULL default '0',
+	id_event smallint(5) unsigned NOT NULL default '0'
+) ENGINE=MyISAM{$db_collation};
+---#
+
+---# Adding approved column to attachments table...
+ALTER TABLE {$db_prefix}attachments
+ADD approved tinyint(3) NOT NULL default '1';
+---#
+
+---# Adding approved column to messages table...
+ALTER TABLE {$db_prefix}messages
+ADD approved tinyint(3) NOT NULL default '1';
+
+ALTER TABLE {$db_prefix}messages
+ADD INDEX approved (approved);
+---#
+
+---# Adding unapproved count column to topics table...
+ALTER TABLE {$db_prefix}topics
+ADD unapproved_posts smallint(5) NOT NULL default '0';
+---#
+
+---# Adding approved column to topics table...
+ALTER TABLE {$db_prefix}topics
+ADD approved tinyint(3) NOT NULL default '1',
+ADD INDEX approved (approved);
+---#
+
+---# Adding approved columns to boards table...
+ALTER TABLE {$db_prefix}boards
+ADD unapproved_posts smallint(5) NOT NULL default '0',
+ADD unapproved_topics smallint(5) NOT NULL default '0';
+---#
+
+---# Adding post moderation permissions...
+---{
+// We *cannot* do this twice!
+if (@$modSettings['smfVersion'] < '2.0')
+{
+	// Anyone who can currently edit posts we assume can approve them...
+	$request = upgrade_query("
+		SELECT id_group, id_board, add_deny, permission
+		FROM {$db_prefix}board_permissions
+		WHERE permission = 'modify_any'");
+	$inserts = array();
+	while ($row = mysql_fetch_assoc($request))
+	{
+		$inserts[] = "($row[id_group], $row[id_board], 'approve_posts', $row[add_deny])";
+	}
+	mysql_free_result($request);
+
+	if (!empty($inserts))
+		upgrade_query("
+			INSERT IGNORE INTO {$db_prefix}board_permissions
+				(id_group, id_board, permission, add_deny)
+			VALUES
+				" . implode(',', $inserts));
+}
+---}
+---#
+
+/******************************************************************************/
+--- Upgrading the error log.
+/******************************************************************************/
+
+---# Adding columns to log_errors table...
+ALTER TABLE {$db_prefix}log_errors
+ADD error_type char(15) NOT NULL default 'general';
+ALTER TABLE {$db_prefix}log_errors
+ADD file varchar(255) NOT NULL default '',
+ADD line mediumint(8) unsigned NOT NULL default '0';
+---#
+
+---# Updating error log table...
+---{
+$request = upgrade_query("
+	SELECT COUNT(*)
+	FROM {$db_prefix}log_errors");
+list($totalActions) = mysql_fetch_row($request);
+mysql_free_result($request);
+
+$_GET['m'] = !empty($_GET['m']) ? (int) $_GET['m'] : '0';
+$step_progress['total'] = $totalActions;
+$step_progress['current'] = $_GET['m'];
+
+while ($_GET['m'] < $totalActions)
+{
+	nextSubStep($substep);
+
+	$request = upgrade_query("
+		SELECT id_error, message, file, line
+		FROM {$db_prefix}log_errors
+		LIMIT $_GET[m], 500");
+	while($row = mysql_fetch_assoc($request))
+	{
+		preg_match('~<br />(%1\$s: )?([\w\. \\\\/\-_:]+)<br />(%2\$s: )?([\d]+)~', $row['message'], $matches);
+		if (!empty($matches[2]) && !empty($matches[4]) && empty($row['file']) && empty($row['line']))
+		{
+			$row['file'] = addslashes(str_replace('\\', '/', $matches[2]));
+			$row['line'] = (int) $matches[4];
+			$row['message'] = addslashes(preg_replace('~<br />(%1\$s: )?([\w\. \\\\/\-_:]+)<br />(%2\$s: )?([\d]+)~', '', $row['message']));
+		}
+		else
+			continue;
+
+		upgrade_query("
+			UPDATE {$db_prefix}log_errors
+			SET file = SUBSTRING('$row[file]', 1, 255),
+				line = $row[line],
+				message = SUBSTRING('$row[message]', 1, 65535)
+			WHERE id_error = $row[id_error]
+			LIMIT 1");
+	}
+
+	$_GET['m'] += 500;
+	$step_progress['current'] = $_GET['m'];
+}
+unset($_GET['m']);
+---}
+---#
+
+/******************************************************************************/
+--- Adding Scheduled Tasks Data.
+/******************************************************************************/
+
+---# Creating Scheduled Task Table...
+CREATE TABLE IF NOT EXISTS {$db_prefix}scheduled_tasks (
+	id_task smallint(5) NOT NULL auto_increment,
+	next_time int(10) NOT NULL default '0',
+	time_offset int(10) NOT NULL default '0',
+	time_regularity smallint(5) NOT NULL default '0',
+	time_unit varchar(1) NOT NULL default 'h',
+	disabled tinyint(3) NOT NULL default '0',
+	task varchar(24) NOT NULL default '',
+	PRIMARY KEY (id_task),
+	KEY next_time (next_time),
+	KEY disabled (disabled),
+	UNIQUE task (task)
+) ENGINE=MyISAM{$db_collation};
+---#
+
+---# Populating Scheduled Task Table...
+INSERT IGNORE INTO {$db_prefix}scheduled_tasks
+	(next_time, time_offset, time_regularity, time_unit, disabled, task)
+VALUES
+	(0, 0, 2, 'h', 0, 'approval_notification'),
+	(0, 0, 7, 'd', 0, 'auto_optimize'),
+	(0, 60, 1, 'd', 0, 'daily_maintenance'),
+	(0, 0, 1, 'd', 0, 'daily_digest'),
+	(0, 0, 1, 'w', 0, 'weekly_digest'),
+	(0, 0, 1, 'd', 1, 'birthdayemails'),
+	(0, 120, 1, 'd', 0, 'paid_subscriptions');
+---#
+
+---# Adding the simple machines scheduled task.
+---{
+// Randomise the time.
+$randomTime = 82800 + rand(0, 86399);
+upgrade_query("
+	INSERT IGNORE INTO {$db_prefix}scheduled_tasks
+		(next_time, time_offset, time_regularity, time_unit, disabled, task)
+	VALUES
+		(0, {$randomTime}, 1, 'd', 0, 'fetchSMfiles')");
+---}
+---#
+
+---# Deleting old scheduled task items...
+DELETE FROM {$db_prefix}scheduled_tasks
+WHERE task = 'clean_cache';
+---#
+
+---# Moving auto optimise settings to scheduled task...
+---{
+if (!isset($modSettings['next_task_time']) && isset($modSettings['autoOptLastOpt']))
+{
+	// Try move over the regularity...
+	if (isset($modSettings['autoOptDatabase']))
+	{
+		$disabled = empty($modSettings['autoOptDatabase']) ? 1 : 0;
+		$regularity = $disabled ? 7 : $modSettings['autoOptDatabase'];
+		$next_time = $modSettings['autoOptLastOpt'] + 3600 * 24 * $modSettings['autoOptDatabase'];
+
+		// Update the task accordingly.
+		upgrade_query("
+			UPDATE {$db_prefix}scheduled_tasks
+			SET disabled = $disabled, time_regularity = $regularity, next_time = $next_time
+			WHERE task = 'auto_optimize'");
+	}
+
+	// Delete the old settings!
+	upgrade_query("
+		DELETE FROM {$db_prefix}settings
+		WHERE VARIABLE IN ('autoOptLastOpt', 'autoOptDatabase')");
+}
+---}
+---#
+
+---# Creating Scheduled Task Log Table...
+CREATE TABLE IF NOT EXISTS {$db_prefix}log_scheduled_tasks (
+	id_log mediumint(8) NOT NULL auto_increment,
+	id_task smallint(5) NOT NULL default '0',
+	time_run int(10) NOT NULL default '0',
+	time_taken float NOT NULL default '0',
+	PRIMARY KEY (id_log)
+) ENGINE=MyISAM{$db_collation};
+---#
+
+---# Adding new scheduled task setting...
+---{
+if (!isset($modSettings['next_task_time']))
+{
+	upgrade_query("
+		INSERT INTO {$db_prefix}settings
+			(variable, value)
+		VALUES
+			('next_task_time', '0')");
+}
+---}
+---#
+
+---# Setting the birthday email template if not set...
+---{
+if (!isset($modSettings['birthday_email']))
+{
+	upgrade_query("
+		INSERT INTO {$db_prefix}settings
+			(variable, value)
+		VALUES
+			('birthday_email', 'happy_birthday')");
+}
+---}
+---#
+
+/******************************************************************************/
+--- Adding permission profiles for boards.
+/******************************************************************************/
+
+---# Creating "permission_profiles" table...
+CREATE TABLE IF NOT EXISTS {$db_prefix}permission_profiles (
+	id_profile smallint(5) NOT NULL auto_increment,
+	profile_name varchar(255) NOT NULL default '',
+	PRIMARY KEY (id_profile)
+) ENGINE=MyISAM{$db_collation};
+---#
+
+---# Adding profile columns to boards table...
+ALTER TABLE {$db_prefix}boards
+ADD id_profile smallint(5) unsigned NOT NULL default '1' AFTER member_groups;
+---#
+
+---# Adding profile columns to board permission table...
+ALTER TABLE {$db_prefix}board_permissions
+ADD id_profile smallint(5) unsigned NOT NULL default '1' AFTER id_group;
+
+ALTER TABLE {$db_prefix}board_permissions
+DROP PRIMARY KEY;
+
+ALTER TABLE {$db_prefix}board_permissions
+ADD PRIMARY KEY (id_group, id_profile, permission);
+---#
+
+---# Cleaning up some 2.0 Beta 1 permission profile bits...
+---{
+$request = upgrade_query("
+	SELECT id_profile
+	FROM {$db_prefix}permission_profiles
+	WHERE profile_name = ''");
+$profiles = array();
+while ($row = mysql_fetch_assoc($request))
+	$profiles[] = $row['id_profile'];
+mysql_free_result($request);
+
+if (!empty($profiles))
+{
+	$request = upgrade_query("
+		SELECT id_profile, name
+		FROM {$db_prefix}boards
+		WHERE id_profile IN (" . implode(',', $profiles) . ")");
+	$done_ids = array();
+	while ($row = mysql_fetch_assoc($request))
+	{
+		if (isset($done_ids[$row['id_profile']]))
+			continue;
+		$done_ids[$row['id_profile']] = true;
+
+		$row['name'] = mysql_real_escape_string($row['name']);
+
+		upgrade_query("
+			UPDATE {$db_prefix}permission_profiles
+			SET profile_name = '$row[name]'
+			WHERE id_profile = $row[id_profile]");
+	}
+	mysql_free_result($request);
+}
+---}
+---#
+
+---# Migrating old board profiles to profile system
+---{
+
+// Doing this twice would be awful!
+$request = upgrade_query("
+	SELECT COUNT(*)
+	FROM {$db_prefix}permission_profiles");
+list ($profileCount) = mysql_fetch_row($request);
+mysql_free_result($request);
+
+if ($profileCount == 0)
+{
+	// Everything starts off invalid.
+	upgrade_query("
+		UPDATE {$db_prefix}board_permissions
+		SET id_profile = 0");
+
+	// Insert a boat load of default profile permissions.
+	upgrade_query("
+		INSERT INTO {$db_prefix}permission_profiles
+			(id_profile, profile_name)
+		VALUES
+			(1, 'default'),
+			(2, 'no_polls'),
+			(3, 'reply_only'),
+			(4, 'read_only')");
+
+	// Update the default permissions, this is easy!
+	upgrade_query("
+		UPDATE {$db_prefix}board_permissions
+		SET id_profile = 1
+		WHERE id_board = 0");
+
+	// Load all the other permissions
+	$request = upgrade_query("
+		SELECT id_board, id_group, permission, add_deny
+		FROM {$db_prefix}board_permissions
+		WHERE id_profile = 0");
+	$all_perms = array();
+	while ($row = mysql_fetch_assoc($request))
+		$all_perms[$row['id_board']][$row['id_group']][$row['permission']] = $row['add_deny'];
+	mysql_free_result($request);
+
+	// Now we have the profile profiles for this installation. We now need to go through each board and work out what the permission profile should be!
+	$request = upgrade_query("
+		SELECT id_board, name, permission_mode
+		FROM {$db_prefix}boards");
+	$board_updates = array();
+	while ($row = mysql_fetch_assoc($request))
+	{
+		$row['name'] = addslashes($row['name']);
+
+		// Is it a truely local permission board? If so this is a new profile!
+		if ($row['permission_mode'] == 1)
+		{
+			// I know we could cache this, but I think we need to be practical - this is slow but guaranteed to work.
+			upgrade_query("
+				INSERT INTO {$db_prefix}permission_profiles
+					(profile_name)
+				VALUES
+					('$row[name]')");
+			$board_updates[mysql_insert_id()][] = $row['id_board'];
+		}
+		// Otherwise, dear god, this is an old school "simple" permission...
+		elseif ($row['permission_mode'] > 1 && $row['permission_mode'] < 5)
+		{
+			$board_updates[$row['permission_mode']][] = $row['id_board'];
+		}
+		// Otherwise this is easy. It becomes default.
+		else
+			$board_updates[1][] = $row['id_board'];
+	}
+	mysql_free_result($request);
+
+	// Update the board tables.
+	foreach ($board_updates as $profile => $boards)
+	{
+		if (empty($boards))
+			continue;
+
+		$boards = implode(',', $boards);
+
+		upgrade_query("
+			UPDATE {$db_prefix}boards
+			SET id_profile = $profile
+			WHERE id_board IN ($boards)");
+
+		// If it's a custom profile then update this too.
+		if ($profile > 4)
+			upgrade_query("
+				UPDATE {$db_prefix}board_permissions
+				SET id_profile = $profile
+				WHERE id_board IN ($boards)
+					AND id_profile = 0");
+	}
+
+	// Just in case we have any random permissions that didn't have boards.
+	upgrade_query("
+		DELETE FROM {$db_prefix}board_permissions
+		WHERE id_profile = 0");
+}
+---}
+---#
+
+---# Removing old board permissions column...
+ALTER TABLE {$db_prefix}board_permissions
+DROP COLUMN id_board;
+---#
+
+---# Check the predefined profiles all have the right permissions.
+---{
+// What are all the permissions people can have.
+$mod_permissions = array(
+	'moderate_board', 'post_new', 'post_reply_own', 'post_reply_any', 'poll_post', 'poll_add_any',
+	'poll_remove_any', 'poll_view', 'poll_vote', 'poll_lock_any', 'poll_edit_any', 'report_any',
+	'lock_own', 'send_topic', 'mark_any_notify', 'mark_notify', 'delete_own', 'modify_own', 'make_sticky',
+	'lock_any', 'remove_any', 'move_any', 'merge_any', 'split_any', 'delete_any', 'modify_any', 'approve_posts',
+	'post_attachment', 'view_attachments', 'post_unapproved_replies_any', 'post_unapproved_replies_own',
+	'post_unapproved_attachments', 'post_unapproved_topics',
+);
+
+$no_poll_reg = array(
+	'post_new', 'post_reply_own', 'post_reply_any', 'poll_view', 'poll_vote', 'report_any',
+	'lock_own', 'send_topic', 'mark_any_notify', 'mark_notify', 'delete_own', 'modify_own',
+	'post_attachment', 'view_attachments', 'remove_own', 'post_unapproved_replies_any', 'post_unapproved_replies_own',
+	'post_unapproved_attachments', 'post_unapproved_topics',
+);
+
+$reply_only_reg = array(
+	'post_reply_own', 'post_reply_any', 'poll_view', 'poll_vote', 'report_any',
+	'lock_own', 'send_topic', 'mark_any_notify', 'mark_notify', 'delete_own', 'modify_own',
+	'post_attachment', 'view_attachments', 'remove_own', 'post_unapproved_replies_any', 'post_unapproved_replies_own',
+	'post_unapproved_attachments',
+);
+
+$read_only_reg = array(
+	'poll_view', 'poll_vote', 'report_any', 'send_topic', 'mark_any_notify', 'mark_notify', 'view_attachments',
+);
+
+// Clear all the current predefined profiles.
+upgrade_query("
+	DELETE FROM {$db_prefix}board_permissions
+	WHERE id_profile IN (2,3,4)");
+
+// Get all the membergroups - cheating to use the fact id_group = 1 exists to get a group of 0.
+$request = upgrade_query("
+	SELECT IF(id_group = 1, 0, id_group) AS id_group
+	FROM {$db_prefix}membergroups
+	WHERE id_group != 0
+		AND min_posts = -1");
+$inserts = array();
+while ($row = mysql_fetch_assoc($request))
+{
+	if ($row['id_group'] == 2 || $row['id_group'] == 3)
+	{
+		foreach ($mod_permissions as $permission)
+		{
+			$inserts[] = "($row[id_group], 2, '$permission')";
+			$inserts[] = "($row[id_group], 3, '$permission')";
+			$inserts[] = "($row[id_group], 4, '$permission')";
+		}
+	}
+	else
+	{
+		foreach ($no_poll_reg as $permission)
+			$inserts[] = "($row[id_group], 2, '$permission')";
+		foreach ($reply_only_reg as $permission)
+			$inserts[] = "($row[id_group], 3, '$permission')";
+		foreach ($read_only_reg as $permission)
+			$inserts[] = "($row[id_group], 4, '$permission')";
+	}
+}
+mysql_free_result($request);
+
+upgrade_query("
+	INSERT INTO {$db_prefix}board_permissions
+		(id_group, id_profile, permission)
+	VALUES (-1, 2, 'poll_view'),
+		(-1, 3, 'poll_view'),
+		(-1, 4, 'poll_view'),
+		" . implode(', ', $inserts));
+
+---}
+---#
+
+---# Adding inherited permissions...
+ALTER TABLE {$db_prefix}membergroups
+ADD id_parent smallint(5) NOT NULL default '-2';
+---#
+
+---# Make sure admins and moderators don't inherit...
+UPDATE {$db_prefix}membergroups
+SET id_parent = -2
+WHERE id_group = 1
+	OR id_group = 3;
+---#
+
+---# Deleting old permission settings...
+DELETE FROM {$db_prefix}settings
+WHERE VARIABLE IN ('permission_enable_by_board', 'autoOptDatabase');
+---#
+
+---# Removing old permission_mode column...
+ALTER TABLE {$db_prefix}boards
+DROP COLUMN permission_mode;
+---#
+
+/******************************************************************************/
+--- Adding Some Additional Functionality.
+/******************************************************************************/
+
+---# Adding column to hold the boards being ignored ...
+ALTER TABLE {$db_prefix}members
+ADD ignore_boards text NOT NULL;
+---#
+
+---# Purge flood control ...
+DELETE FROM {$db_prefix}log_floodcontrol;
+---#
+
+---# Adding advanced flood control ...
+ALTER TABLE {$db_prefix}log_floodcontrol
+ADD log_type varchar(8) NOT NULL default 'post';
+---#
+
+---# Sorting out flood control keys ...
+ALTER TABLE {$db_prefix}log_floodcontrol
+DROP PRIMARY KEY,
+ADD PRIMARY KEY (ip(16), log_type(8));
+---#
+
+---# Adding guest voting ...
+ALTER TABLE {$db_prefix}polls
+ADD guest_vote tinyint(3) NOT NULL default '0';
+
+DELETE FROM {$db_prefix}log_polls
+WHERE id_member < 0;
+
+ALTER TABLE {$db_prefix}log_polls
+DROP PRIMARY KEY;
+
+ALTER TABLE {$db_prefix}log_polls
+ADD INDEX id_poll (id_poll, id_member, id_choice);
+---#
+
+---# Implementing admin feature toggles.
+---{
+if (!isset($modSettings['admin_features']))
+{
+	// Work out what they used to have enabled.
+	$enabled_features = array('rg');
+	if (!empty($modSettings['cal_enabled']))
+		$enabled_features[] = 'cd';
+	if (!empty($modSettings['karmaMode']))
+		$enabled_features[] = 'k';
+	if (!empty($modSettings['modlog_enabled']))
+		$enabled_features[] = 'ml';
+	if (!empty($modSettings['paid_enabled']))
+		$enabled_features[] = 'ps';
+
+	$enabled_features = implode(',', $enabled_features);
+
+	upgrade_query("
+		INSERT INTO {$db_prefix}settings
+			(variable, value)
+		VALUES
+			('admin_features', '$enabled_features')");
+}
+---}
+---#
+
+---# Adding advanced password brute force protection to "members" table...
+ALTER TABLE {$db_prefix}members
+ADD passwd_flood varchar(12) NOT NULL default '';
+---#
+
+/******************************************************************************/
+--- Adding some columns to moderation log
+/******************************************************************************/
+---# Add the columns and the keys to log_actions ...
+ALTER TABLE {$db_prefix}log_actions
+ADD id_board smallint(5) unsigned NOT NULL default '0',
+ADD id_topic mediumint(8) unsigned NOT NULL default '0',
+ADD id_msg int(10) unsigned NOT NULL default '0',
+ADD KEY id_board (id_board),
+ADD KEY id_msg (id_msg);
+---#
+
+---# Add the user log...
+ALTER TABLE {$db_prefix}log_actions
+ADD id_log tinyint(3) unsigned NOT NULL default '1',
+ADD KEY id_log (id_log);
+---#
+
+---# Update the information already in log_actions
+---{
+$request = upgrade_query("
+	SELECT COUNT(*)
+	FROM {$db_prefix}log_actions");
+list($totalActions) = mysql_fetch_row($request);
+mysql_free_result($request);
+
+$_GET['m'] = !empty($_GET['m']) ? (int) $_GET['m'] : '0';
+$step_progress['total'] = $totalActions;
+$step_progress['current'] = $_GET['m'];
+
+while ($_GET['m'] < $totalActions)
+{
+	nextSubStep($substep);
+
+	$mrequest = upgrade_query("
+		SELECT id_action, extra, id_board, id_topic, id_msg
+		FROM {$db_prefix}log_actions
+		LIMIT $_GET[m], 500");
+
+	while ($row = mysql_fetch_assoc($mrequest))
+	{
+		if (!empty($row['id_board']) || !empty($row['id_topic']) || !empty($row['id_msg']))
+			continue;
+		$row['extra'] = @unserialize($row['extra']);
+		// Corrupt?
+		$row['extra'] = is_array($row['extra']) ? $row['extra'] : array();
+		if (!empty($row['extra']['board']))
+		{
+			$board_id = (int) $row['extra']['board'];
+			unset($row['extra']['board']);
+		}
+		else
+			$board_id = '0';
+		if (!empty($row['extra']['board_to']) && empty($board_id))
+		{
+			$board_id = (int) $row['extra']['board_to'];
+			unset($row['extra']['board_to']);
+		}
+
+		if (!empty($row['extra']['topic']))
+		{
+			$topic_id = (int) $row['extra']['topic'];
+			unset($row['extra']['topic']);
+			if (empty($board_id))
+			{
+				$trequest = upgrade_query("
+					SELECT id_board
+					FROM {$db_prefix}topics
+					WHERE id_topic=$topic_id
+					LIMIT 1");
+				if (mysql_num_rows($trequest))
+					list($board_id) = mysql_fetch_row($trequest);
+				mysql_free_result($trequest);
+			}
+		}
+		else
+			$topic_id = '0';
+
+		if(!empty($row['extra']['message']))
+		{
+			$msg_id = (int) $row['extra']['message'];
+			unset($row['extra']['message']);
+			if (empty($topic_id) || empty($board_id))
+			{
+				$trequest = upgrade_query("
+					SELECT id_board, id_topic
+					FROM {$db_prefix}messages
+					WHERE id_msg=$msg_id
+					LIMIT 1");
+				if (mysql_num_rows($trequest))
+					list($board_id, $topic_id) = mysql_fetch_row($trequest);
+				mysql_free_result($trequest);
+			}
+		}
+		else
+			$msg_id = '0';
+		$row['extra'] = addslashes(serialize($row['extra']));
+		upgrade_query("UPDATE {$db_prefix}log_actions SET id_board=$board_id, id_topic=$topic_id, id_msg=$msg_id, extra='$row[extra]' WHERE id_action=$row[id_action]");
+	}
+	$_GET['m'] += 500;
+	$step_progress['current'] = $_GET['m'];
+}
+unset($_GET['m']);
+---}
+---#
+
+/******************************************************************************/
+--- Create a repository for the javascript files from Simple Machines...
+/******************************************************************************/
+
+---# Creating repository table ...
+CREATE TABLE IF NOT EXISTS {$db_prefix}admin_info_files (
+  id_file tinyint(4) unsigned NOT NULL auto_increment,
+  filename varchar(255) NOT NULL default '',
+  path varchar(255) NOT NULL default '',
+  parameters varchar(255) NOT NULL default '',
+  data text NOT NULL,
+  filetype varchar(255) NOT NULL default '',
+  PRIMARY KEY (id_file),
+  KEY filename (filename(30))
+) ENGINE=MyISAM{$db_collation};
+---#
+
+---# Add in the files to get from Simple Machines...
+INSERT IGNORE INTO {$db_prefix}admin_info_files
+	(id_file, filename, path, parameters)
+VALUES
+	(1, 'current-version.js', '/smf/', 'version=%3$s'),
+	(2, 'detailed-version.js', '/smf/', 'language=%1$s&version=%3$s'),
+	(3, 'latest-news.js', '/smf/', 'language=%1$s&format=%2$s'),
+	(4, 'latest-packages.js', '/smf/', 'language=%1$s&version=%3$s'),
+	(5, 'latest-smileys.js', '/smf/', 'language=%1$s&version=%3$s'),
+	(6, 'latest-support.js', '/smf/', 'language=%1$s&version=%3$s'),
+	(7, 'latest-themes.js', '/smf/', 'language=%1$s&version=%3$s');
+---#
+
+---# Ensure that the table has the filetype column
+ALTER TABLE {$db_prefix}admin_info_files
+ADD filetype varchar(255) NOT NULL default '';
+---#
+
+---# Set the filetype for the files
+UPDATE {$db_prefix}admin_info_files
+SET filetype='text/javascript'
+WHERE id_file IN (1,2,3,4,5,6,7);
+---#
+
+---# Ensure that the files from Simple Machines get updated
+UPDATE {$db_prefix}scheduled_tasks
+SET next_time = UNIX_TIMESTAMP()
+WHERE id_task = 7
+LIMIT 1;
+---#
+
+/******************************************************************************/
+--- Adding new personal messaging functionality.
+/******************************************************************************/
+
+---# Adding personal message rules table...
+CREATE TABLE IF NOT EXISTS {$db_prefix}pm_rules (
+	id_rule int(10) unsigned NOT NULL auto_increment,
+	id_member int(10) unsigned NOT NULL default '0',
+	rule_name varchar(60) NOT NULL,
+	criteria text NOT NULL,
+	actions text NOT NULL,
+	delete_pm tinyint(3) unsigned NOT NULL default '0',
+	is_or tinyint(3) unsigned NOT NULL default '0',
+	PRIMARY KEY (id_rule),
+	KEY id_member (id_member),
+	KEY delete_pm (delete_pm)
+) ENGINE=MyISAM{$db_collation};
+---#
+
+---# Adding new message status columns...
+ALTER TABLE {$db_prefix}members
+ADD COLUMN new_pm tinyint(3) NOT NULL default '0';
+
+ALTER TABLE {$db_prefix}members
+ADD COLUMN pm_prefs mediumint(8) NOT NULL default '0';
+
+ALTER TABLE {$db_prefix}pm_recipients
+ADD COLUMN is_new tinyint(3) NOT NULL default '0';
+---#
+
+---# Set the new status to be correct....
+---{
+// Don't do this twice!
+if (@$modSettings['smfVersion'] < '2.0')
+{
+	// Set all unread messages as new.
+	upgrade_query("
+		UPDATE {$db_prefix}pm_recipients
+		SET is_new = 1
+		WHERE is_read = 0");
+
+	// Also set members to have a new pm if they have any unread.
+	upgrade_query("
+		UPDATE {$db_prefix}members
+		SET new_pm = 1
+		WHERE unread_messages > 0");
+}
+---}
+---#
+
+---# Adding personal message tracking column...
+ALTER TABLE {$db_prefix}personal_messages
+ADD id_pm_head int(10) unsigned default '0' NOT NULL AFTER id_pm,
+ADD INDEX id_pm_head (id_pm_head);
+---#
+
+---# Adding personal message tracking column...
+UPDATE {$db_prefix}personal_messages
+SET id_pm_head = id_pm
+WHERE id_pm_head = 0;
+---#
+
+/******************************************************************************/
+--- Adding Open ID support.
+/******************************************************************************/
+
+---# Adding Open ID Assocation table...
+CREATE TABLE IF NOT EXISTS {$db_prefix}openid_assoc (
+	server_url text NOT NULL,
+	handle varchar(255) NOT NULL default '',
+	secret text NOT NULL,
+	issued int(10) NOT NULL default '0',
+	expires int(10) NOT NULL default '0',
+	assoc_type varchar(64) NOT NULL,
+	PRIMARY KEY (server_url(125), handle(125)),
+	KEY expires (expires)
+) ENGINE=MyISAM{$db_collation};
+---#
+
+---# Adding column to hold Open ID URL...
+ALTER TABLE {$db_prefix}members
+ADD openid_uri text NOT NULL;
+---#
+
+/******************************************************************************/
+--- Adding paid subscriptions.
+/******************************************************************************/
+
+---# Creating subscriptions table...
+CREATE TABLE IF NOT EXISTS {$db_prefix}subscriptions(
+	id_subscribe mediumint(8) unsigned NOT NULL auto_increment,
+	name varchar(60) NOT NULL default '',
+	description varchar(255) NOT NULL default '',
+	cost text NOT NULL,
+	length varchar(6) NOT NULL default '',
+	id_group smallint(5) NOT NULL default '0',
+	add_groups varchar(40) NOT NULL default '',
+	active tinyint(3) NOT NULL default '1',
+	repeatable tinyint(3) NOT NULL default '0',
+	allow_partial tinyint(3) NOT NULL default '0',
+	reminder tinyint(3) NOT NULL default '0',
+	email_complete text NOT NULL,
+	PRIMARY KEY (id_subscribe),
+	KEY active (active)
+) ENGINE=MyISAM{$db_collation};
+---#
+
+---# Creating log_subscribed table...
+CREATE TABLE IF NOT EXISTS {$db_prefix}log_subscribed(
+	id_sublog int(10) unsigned NOT NULL auto_increment,
+	id_subscribe mediumint(8) unsigned NOT NULL default '0',
+	id_member int(10) NOT NULL default '0',
+	old_id_group smallint(5) NOT NULL default '0',
+	start_time int(10) NOT NULL default '0',
+	end_time int(10) NOT NULL default '0',
+	status tinyint(3) NOT NULL default '0',
+	payments_pending tinyint(3) NOT NULL default '0',
+	pending_details text NOT NULL,
+	reminder_sent tinyint(3) NOT NULL default '0',
+	vendor_ref varchar(255) NOT NULL default '',
+	PRIMARY KEY (id_sublog),
+	UNIQUE KEY id_subscribe (id_subscribe, id_member),
+	KEY end_time (end_time),
+	KEY reminder_sent (reminder_sent),
+	KEY payments_pending (payments_pending),
+	KEY id_member (id_member)
+) ENGINE=MyISAM{$db_collation};
+---#
+
+---# Clean up any pre-2.0 mod settings.
+UPDATE {$db_prefix}settings
+SET variable = 'paid_currency_code'
+WHERE variable = 'currency_code';
+
+UPDATE {$db_prefix}settings
+SET variable = 'paid_currency_symbol'
+WHERE variable = 'currency_symbol';
+
+DELETE FROM {$db_prefix}settings
+WHERE variable = 'currency_code'
+	OR variable = 'currency_symbol';
+---#
+
+---# Clean up any pre-2.0 mod settings (part 2).
+---{
+$request = upgrade_query("
+	SHOW COLUMNS
+	FROM {$db_prefix}subscriptions");
+$new_cols = array('repeatable', 'reminder', 'email_complete', 'allow_partial');
+$new_cols = array_flip($new_cols);
+while ($request && $row = mysql_fetch_row($request))
+{
+	$row[0] = strtolower($row[0]);
+	if (isset($new_cols[$row[0]]))
+		unset($new_cols[$row[0]]);
+}
+if ($request)
+	mysql_free_result($request);
+
+if (isset($new_cols['repeatable']))
+	upgrade_query("
+		ALTER TABLE {$db_prefix}subscriptions
+		ADD COLUMN Repeatable tinyint(3) NOT NULL default '0'");
+if (isset($new_cols['reminder']))
+	upgrade_query("
+		ALTER TABLE {$db_prefix}subscriptions
+		ADD COLUMN reminder tinyint(3) NOT NULL default '0'");
+if (isset($new_cols['email_complete']))
+	upgrade_query("
+		ALTER TABLE {$db_prefix}subscriptions
+		ADD COLUMN email_complete text NOT NULL");
+if (isset($new_cols['allowpartial']))
+	upgrade_query("
+		ALTER TABLE {$db_prefix}subscriptions
+		ADD COLUMN allow_partial tinyint(3) NOT NULL default '0'");
+
+$request = upgrade_query("
+	SHOW COLUMNS
+	FROM {$db_prefix}log_subscribed");
+$new_cols = array('reminder_sent', 'vendor_ref', 'payments_pending', 'pending_details');
+$new_cols = array_flip($new_cols);
+while ($request && $row = mysql_fetch_row($request))
+{
+	if (isset($new_cols[$row[0]]))
+		unset($new_cols[$row[0]]);
+}
+if ($request)
+	mysql_free_result($request);
+
+if (isset($new_cols['reminder_sent']))
+	upgrade_query("
+		ALTER TABLE {$db_prefix}log_subscribed
+		ADD COLUMN reminder_sent tinyint(3) NOT NULL default '0'");
+if (isset($new_cols['vendor_ref']))
+	upgrade_query("
+		ALTER TABLE {$db_prefix}log_subscribed
+		ADD COLUMN vendor_ref varchar(255) NOT NULL default ''");
+if (isset($new_cols['payments_pending']))
+	upgrade_query("
+		ALTER TABLE {$db_prefix}log_subscribed
+		ADD COLUMN payments_pending tinyint(3) NOT NULL default '0'");
+if (isset($new_cols['pending_details']))
+{
+	upgrade_query("
+		UPDATE {$db_prefix}log_subscribed
+		SET status = 0
+		WHERE status = 1");
+	upgrade_query("
+		UPDATE {$db_prefix}log_subscribed
+		SET status = 1
+		WHERE status = 2");
+	upgrade_query("
+		ALTER TABLE {$db_prefix}log_subscribed
+		ADD COLUMN pending_details text NOT NULL");
+}
+---}
+---#
+
+---# Confirming paid subscription keys are in place ...
+ALTER TABLE {$db_prefix}log_subscribed
+ADD KEY reminder_sent (reminder_sent),
+ADD KEY end_time (end_time),
+ADD KEY payments_pending (payments_pending),
+ADD KEY status (status);
+---#
+
+/******************************************************************************/
+--- Adding weekly maintenance task.
+/******************************************************************************/
+
+---# Adding scheduled task...
+INSERT IGNORE INTO {$db_prefix}scheduled_tasks (next_time, time_offset, time_regularity, time_unit, disabled, task) VALUES (0, 0, 1, 'w', 0, 'weekly_maintenance');
+---#
+
+/******************************************************************************/
+--- Adding log pruning.
+/******************************************************************************/
+
+---# Adding pruning option...
+INSERT IGNORE INTO {$db_prefix}settings (variable, value) VALUES ('pruningOptions', '30,180,180,180,30,0');
+---#
+
+/******************************************************************************/
+--- Adding restore topic from recycle.
+/******************************************************************************/
+
+---# Adding restore from recycle feature...
+ALTER TABLE {$db_prefix}topics
+ADD COLUMN id_previous_board smallint(5) NOT NULL default '0',
+ADD COLUMN id_previous_topic mediumint(8) NOT NULL default '0';
+---#
+
+/******************************************************************************/
+--- Providing more room for apf options.
+/******************************************************************************/
+
+---# Changing field_options column to a larger field type...
+ALTER TABLE {$db_prefix}custom_fields
+CHANGE field_options field_options text NOT NULL;
+---#
+
+/******************************************************************************/
+--- Providing more room for ignoring boards.
+/******************************************************************************/
+
+---# Changing ignore_boards column to a larger field type...
+ALTER TABLE {$db_prefix}members
+CHANGE ignore_boards ignore_boards text NOT NULL;
+---#
+
+/******************************************************************************/
+--- Allow for longer calendar event/holiday titles.
+/******************************************************************************/
+
+---# Changing event title column to a larger field type...
+ALTER TABLE {$db_prefix}calendar
+CHANGE title title varchar(255) NOT NULL default '';
+---#
+
+---# Changing holidays title column to a larger field type...
+ALTER TABLE {$db_prefix}calendar_holidays
+CHANGE title title varchar(255) NOT NULL default '';
+---#
+
+/******************************************************************************/
+--- Adding extra columns to polls.
+/******************************************************************************/
+
+---# Adding reset poll timestamp and guest voters counter...
+ALTER TABLE {$db_prefix}polls
+ADD COLUMN reset_poll int(10) unsigned NOT NULL default '0' AFTER guest_vote,
+ADD COLUMN num_guest_voters int(10) unsigned NOT NULL default '0' AFTER guest_vote;
+---#
+
+---# Fixing guest voter tallys on existing polls...
+---{
+$request = upgrade_query("
+	SELECT p.id_poll, count(lp.id_member) as guest_voters
+	FROM {$db_prefix}polls AS p
+		LEFT JOIN {$db_prefix}log_polls AS lp ON (lp.id_poll = p.id_poll AND lp.id_member = 0)
+	WHERE lp.id_member = 0
+		AND p.num_guest_voters = 0
+	GROUP BY p.id_poll");
+
+while ($request && $row = $smcFunc['db_fetch_assoc']($request))
+	upgrade_query("
+		UPDATE {$db_prefix}polls
+		SET num_guest_voters = ". $row['guest_voters']. "
+		WHERE id_poll = " . $row['id_poll'] . "
+			AND num_guest_voters = 0");
+---}
+---#
+
+/******************************************************************************/
+--- Changing all tinytext columns to varchar(255).
+/******************************************************************************/
+
+---# Changing all tinytext columns to varchar(255)...
+---{
+// The array holding all the changes.
+$nameChanges = array(
+	'admin_info_files' => array(
+		'filename' => 'filename filename varchar(255) NOT NULL default \'\'',
+		'path' => 'path path varchar(255) NOT NULL default \'\'',
+		'parameters' => 'parameters parameters varchar(255) NOT NULL default \'\'',
+		'filetype' => 'filetype filetype varchar(255) NOT NULL default \'\'',
+	),
+	'attachments' => array(
+		'filename' => 'filename filename varchar(255) NOT NULL default \'\'',
+	),
+	'ban_groups' => array(
+		'reason' => 'reason reason varchar(255) NOT NULL default \'\'',
+	),
+	'ban_items' => array(
+		'hostname' => 'hostname hostname varchar(255) NOT NULL default \'\'',
+		'email_address' => 'email_address email_address varchar(255) NOT NULL default \'\'',
+	),
+	'boards' => array(
+		'name' => 'name name varchar(255) NOT NULL default \'\'',
+	),
+	'categories' => array(
+		'name' => 'name name varchar(255) NOT NULL default \'\'',
+	),
+	'custom_fields' => array(
+		'field_desc' => 'field_desc field_desc varchar(255) NOT NULL default \'\'',
+		'mask' => 'mask mask varchar(255) NOT NULL default \'\'',
+		'default_value' => 'default_value default_value varchar(255) NOT NULL default \'\'',
+	),
+	'log_banned' => array(
+		'email' => 'email email varchar(255) NOT NULL default \'\'',
+	),
+	'log_comments' => array(
+		'recipient_name' => 'recipient_name recipient_name varchar(255) NOT NULL default \'\'',
+	),
+	'log_errors' => array(
+		'file' => 'file file varchar(255) NOT NULL default \'\'',
+	),
+	'log_member_notices' => array(
+		'subject' => 'subject subject varchar(255) NOT NULL default \'\'',
+	),
+	'log_packages' => array(
+		'filename' => 'filename filename varchar(255) NOT NULL default \'\'',
+		'package_id' => 'package_id package_id varchar(255) NOT NULL default \'\'',
+		'name' => 'name name varchar(255) NOT NULL default \'\'',
+		'version' => 'version version varchar(255) NOT NULL default \'\'',
+		'member_installed' => 'member_installed member_installed varchar(255) NOT NULL default \'\'',
+		'member_removed' => 'member_removed member_removed varchar(255) NOT NULL default \'\'',
+		'themes_installed' => 'themes_installed themes_installed varchar(255) NOT NULL default \'\'',
+	),
+	'log_reported' => array(
+		'membername' => 'membername membername varchar(255) NOT NULL default \'\'',
+		'subject' => 'subject subject varchar(255) NOT NULL default \'\'',
+	),
+	'log_reported_comments' => array(
+		'membername' => 'membername membername varchar(255) NOT NULL default \'\'',
+		'comment' => 'comment comment varchar(255) NOT NULL default \'\'',
+	),
+	'log_spider_hits' => array(
+		'url' => 'url url varchar(255) NOT NULL default \'\'',
+	),
+	'log_subscribed' => array(
+		'vendor_ref' => 'vendor_ref vendor_ref varchar(255) NOT NULL default \'\'',
+	),
+	'mail_queue' => array(
+		'recipient' => 'recipient recipient varchar(255) NOT NULL default \'\'',
+		'subject' => 'subject subject varchar(255) NOT NULL default \'\'',
+	),
+	'membergroups' => array(
+		'stars' => 'stars stars varchar(255) NOT NULL default \'\'',
+	),
+	'members' => array(
+		'lngfile' => 'lngfile lngfile varchar(255) NOT NULL default \'\'',
+		'real_name' => 'real_name real_name varchar(255) NOT NULL default \'\'',
+		'pm_ignore_list' => 'pm_ignore_list pm_ignore_list varchar(255) NOT NULL default \'\'',
+		'email_address' => 'email_address email_address varchar(255) NOT NULL default \'\'',
+		'personal_text' => 'personal_text personal_text varchar(255) NOT NULL default \'\'',
+		'website_title' => 'website_title website_title varchar(255) NOT NULL default \'\'',
+		'website_url' => 'website_url website_url varchar(255) NOT NULL default \'\'',
+		'location' => 'location location varchar(255) NOT NULL default \'\'',
+		'icq' => 'icq icq varchar(255) NOT NULL default \'\'',
+		'aim' => 'aim aim varchar(255) NOT NULL default \'\'',
+		'msn' => 'msn msn varchar(255) NOT NULL default \'\'',
+		'avatar' => 'avatar avatar varchar(255) NOT NULL default \'\'',
+		'usertitle' => 'usertitle usertitle varchar(255) NOT NULL default \'\'',
+		'member_ip' => 'member_ip member_ip varchar(255) NOT NULL default \'\'',
+		'member_ip2' => 'member_ip2 member_ip2 varchar(255) NOT NULL default \'\'',
+		'secret_question' => 'secret_question secret_question varchar(255) NOT NULL default \'\'',
+		'additional_groups' => 'additional_groups additional_groups varchar(255) NOT NULL default \'\'',
+	),
+	'messages' => array(
+		'subject' => 'subject subject varchar(255) NOT NULL default \'\'',
+		'poster_name' => 'poster_name poster_name varchar(255) NOT NULL default \'\'',
+		'poster_email' => 'poster_email poster_email varchar(255) NOT NULL default \'\'',
+		'poster_ip' => 'poster_ip poster_ip varchar(255) NOT NULL default \'\'',
+		'modified_name' => 'modified_name modified_name varchar(255) NOT NULL default \'\'',
+	),
+	'openid_assoc' => array(
+		'handle' => 'handle handle varchar(255) NOT NULL default \'\'',
+	),
+	'package_servers' => array(
+		'name' => 'name name varchar(255) NOT NULL default \'\'',
+		'url' => 'url url varchar(255) NOT NULL default \'\'',
+	),
+	'permission_profiles' => array(
+		'profile_name' => 'profile_name profile_name varchar(255) NOT NULL default \'\'',
+	),
+	'personal_messages' => array(
+		'from_name' => 'from_name from_name varchar(255) NOT NULL default \'\'',
+		'subject' => 'subject subject varchar(255) NOT NULL default \'\'',
+	),
+	'polls' => array(
+		'question' => 'question question varchar(255) NOT NULL default \'\'',
+		'poster_name' => 'poster_name poster_name varchar(255) NOT NULL default \'\'',
+	),
+	'poll_choices' => array(
+		'label' => 'label label varchar(255) NOT NULL default \'\'',
+	),
+	'settings' => array(
+		'variable' => 'variable variable varchar(255) NOT NULL default \'\'',
+	),
+	'spiders' => array(
+		'spider_name' => 'spider_name spider_name varchar(255) NOT NULL default \'\'',
+		'user_agent' => 'user_agent user_agent varchar(255) NOT NULL default \'\'',
+		'ip_info' => 'ip_info ip_info varchar(255) NOT NULL default \'\'',
+	),
+	'subscriptions' => array(
+		'description' => 'description description varchar(255) NOT NULL default \'\'',
+	),
+	'themes' => array(
+		'variable' => 'variable variable varchar(255) NOT NULL default \'\'',
+	),
+);
+
+$_GET['ren_col'] = isset($_GET['ren_col']) ? (int) $_GET['ren_col'] : 0;
+$step_progress['name'] = 'Changing tinytext columns to varchar(255)';
+$step_progress['current'] = $_GET['ren_col'];
+$step_progress['total'] = count($nameChanges);
+
+$count = 0;
+// Now do every table...
+foreach ($nameChanges as $table_name => $table)
+{
+	// Already done this?
+	$count++;
+	if ($_GET['ren_col'] > $count)
+		continue;
+	$_GET['ren_col'] = $count;
+
+	// Check the table exists!
+	$request = upgrade_query("
+		SHOW TABLES
+		LIKE '{$db_prefix}$table_name'");
+	if (mysql_num_rows($request) == 0)
+	{
+		mysql_free_result($request);
+		continue;
+	}
+	mysql_free_result($request);
+
+	// Converting is intensive, so make damn sure that we need to do it.
+	$request = upgrade_query("
+		SHOW FIELDS
+		FROM `{$db_prefix}$table_name`");
+	$tinytextColumns = array();
+	while($row = mysql_fetch_assoc($request))
+	{
+		// Tinytext detected so store column name.
+		if ($row['Type'] == 'tinytext')
+			$tinytextColumns[$row['Field']] = $row['Field'];
+	}
+	mysql_free_result($request);
+
+	// Check each column!
+	$actualChanges = array();
+	foreach ($table as $colname => $coldef)
+	{
+		// Column was not detected as tinytext so skip it
+		// Either it was already converted or was changed eg text (so do not break it)
+		if (!isset($tinytextColumns[$colname]))
+			continue;
+
+		$change = array(
+			'table' => $table_name,
+			'name' => $colname,
+			'type' => 'column',
+			'method' => 'change_remove',
+			'text' => 'CHANGE ' . $coldef,
+		);
+		if (protected_alter($change, $substep, true) == false)
+			$actualChanges[] = ' CHANGE COLUMN ' . $coldef;
+	}
+
+	// Do the query - if it needs doing.
+	if (!empty($actualChanges))
+	{
+		$change = array(
+			'table' => $table_name,
+			'name' => 'na',
+			'type' => 'table',
+			'method' => 'full_change',
+			'text' => implode(', ', $actualChanges),
+		);
+
+		// Here we go - hold on!
+		protected_alter($change, $substep);
+	}
+
+	// Update where we are!
+	$step_progress['current'] = $_GET['ren_col'];
+}
+
+// All done!
+unset($_GET['ren_col']);
+---}
+---#
+
+/******************************************************************************/
+--- Adding new personal message setting.
+/******************************************************************************/
+
+---# Adding column that stores the PM receiving setting...
+ALTER TABLE {$db_prefix}members
+ADD COLUMN pm_receive_from tinyint(4) unsigned NOT NULL default '1';
+---#
+
+---# Enable the buddy and ignore lists if we have not done so thus far...
+---{
+
+// Don't do this if we've done this already.
+if (empty($modSettings['dont_repeat_buddylists']))
+{
+	// Make sure the pm_receive_from column has the right default value - early adoptors might have a '0' set here.
+	upgrade_query("
+		ALTER TABLE {$db_prefix}members
+		CHANGE pm_receive_from pm_receive_from tinyint(3) unsigned NOT NULL default '1'");
+
+	// Update previous ignore lists if they're set to ignore all.
+	upgrade_query("
+		UPDATE {$db_prefix}members
+		SET pm_receive_from = 3, pm_ignore_list = ''
+		WHERE pm_ignore_list = '*'");
+
+	// Ignore posts made by ignored users by default.
+	upgrade_query("
+		REPLACE INTO {$db_prefix}themes
+			(id_member, id_theme, variable, value)
+		VALUES
+			(-1, 1, 'posts_apply_ignore_list', '1')");
+
+	// Enable buddy and ignore lists, and make sure not to skip this step next time we run this.
+	upgrade_query("
+		REPLACE INTO {$db_prefix}settings
+			(variable, value)
+		VALUES
+			('enable_buddylist', '1'),
+			('dont_repeat_buddylists', '1')");
+}
+
+// And yet, and yet... We might have a small hiccup here...
+if (!empty($modSettings['dont_repeat_buddylists']) && !isset($modSettings['enable_buddylist']))
+{
+	// Correct RC3 adopters setting here...
+	if (isset($modSettings['enable_buddylists']))
+	{
+		upgrade_query("
+		REPLACE INTO {$db_prefix}settings
+			(variable, value)
+		VALUES
+			('enable_buddylist', '" . $modSettings['enable_buddylists'] . "')");
+	}
+	else
+	{
+		// This should never happen :)
+		upgrade_query("
+		REPLACE INTO {$db_prefix}settings
+			(variable, value)
+		VALUES
+			('enable_buddylist', '1')");
+	}
+}
+
+---}
+---#
+
+/******************************************************************************/
+--- Adding settings for attachments and avatars.
+/******************************************************************************/
+
+---# Add new security settings for attachments and avatars...
+---{
+
+// Don't do this if we've done this already.
+if (!isset($modSettings['attachment_image_reencode']))
+{
+	// Enable image re-encoding by default.
+	upgrade_query("
+		REPLACE INTO {$db_prefix}settings
+			(variable, value)
+		VALUES
+			('attachment_image_reencode', '1')");
+}
+if (!isset($modSettings['attachment_image_paranoid']))
+{
+	// Disable draconic checks by default.
+	upgrade_query("
+		REPLACE INTO {$db_prefix}settings
+			(variable, value)
+		VALUES
+			('attachment_image_paranoid', '0')");
+}
+if (!isset($modSettings['avatar_reencode']))
+{
+	// Enable image re-encoding by default.
+	upgrade_query("
+		REPLACE INTO {$db_prefix}settings
+			(variable, value)
+		VALUES
+			('avatar_reencode', '1')");
+}
+if (!isset($modSettings['avatar_paranoid']))
+{
+	// Disable draconic checks by default.
+	upgrade_query("
+		REPLACE INTO {$db_prefix}settings
+			(variable, value)
+		VALUES
+			('avatar_paranoid', '0')");
+}
+
+---}
+---#
+
+---# Add other attachment settings...
+---{
+if (!isset($modSettings['attachment_thumb_png']))
+{
+	// Make image attachment thumbnail as PNG by default.
+	upgrade_query("
+		REPLACE INTO {$db_prefix}settings
+			(variable, value)
+		VALUES
+			('attachment_thumb_png', '1')");
+}
+
+---}
+---#
+
+/******************************************************************************/
+--- Installing new default theme...
+/******************************************************************************/
+
+---# Installing theme settings...
+---{
+// This is Grudge's secret "I'm not a developer" theme install code - keep this quiet ;)
+
+// Firstly, I'm going out of my way to not do this twice!
+if ((!isset($modSettings['smfVersion']) || $modSettings['smfVersion'] <= '2.0 RC5' || $modSettings['smfVersion'] === '2.0 a') && empty($modSettings['dont_repeat_theme_core']))
+{
+	// Check it's not already here, just in case.
+	$theme_request = upgrade_query("
+		SELECT id_theme
+		FROM {$db_prefix}themes
+		WHERE variable = 'theme_dir'
+			AND value LIKE '%core'");
+	// Only do the upgrade if it doesn't find the theme already.
+	if (mysql_num_rows($theme_request) == 0)
+	{
+		// Try to get some settings from the current default theme.
+		$request = upgrade_query("
+			SELECT t1.value AS theme_dir, t2.value AS theme_url, t3.value AS images_url
+			FROM ({$db_prefix}themes AS t1, {$db_prefix}themes AS t2, {$db_prefix}themes AS t3)
+			WHERE t1.id_theme = 1
+				AND t1.id_member = 0
+				AND t1.variable = 'theme_dir'
+				AND t2.id_theme = 1
+				AND t2.id_member = 0
+				AND t2.variable = 'theme_url'
+				AND t3.id_theme = 1
+				AND t3.id_member = 0
+				AND t3.variable = 'images_url'
+			LIMIT 1");
+		if (mysql_num_rows($request) != 0)
+		{
+			$curve = mysql_fetch_assoc($request);
+
+			if (substr_count($curve['theme_dir'], 'default') === 1)
+				$core['theme_dir'] = strtr($curve['theme_dir'], array('default' => 'core'));
+			if (substr_count($curve['theme_url'], 'default') === 1)
+				$core['theme_url'] = strtr($curve['theme_url'], array('default' => 'core'));
+			if (substr_count($curve['images_url'], 'default') === 1)
+				$core['images_url'] = strtr($curve['images_url'], array('default' => 'core'));
+		}
+		mysql_free_result($request);
+
+		if (!isset($core['theme_dir']))
+			$core['theme_dir'] = addslashes($GLOBALS['boarddir']) . '/Themes/core';
+		if (!isset($core['theme_url']))
+			$core['theme_url'] = $GLOBALS['boardurl'] . '/Themes/core';
+		if (!isset($core['images_url']))
+			$core['images_url'] = $GLOBALS['boardurl'] . '/Themes/core/images';
+
+		// Get an available id_theme first...
+		$request = upgrade_query("
+			SELECT MAX(id_theme) + 1
+			FROM {$db_prefix}themes");
+		list ($id_core_theme) = mysql_fetch_row($request);
+		mysql_free_result($request);
+
+		// Insert the core theme into the tables.
+		upgrade_query("
+			INSERT INTO {$db_prefix}themes
+				(id_member, id_theme, variable, value)
+			VALUES
+				(0, $id_core_theme, 'name', 'Core Theme'),
+				(0, $id_core_theme, 'theme_url', '$core[theme_url]'),
+				(0, $id_core_theme, 'images_url', '$core[images_url]'),
+				(0, $id_core_theme, 'theme_dir', '$core[theme_dir]')");
+
+		// Update the name of the default theme in the database.
+		upgrade_query("
+			UPDATE {$db_prefix}themes
+			SET value = 'SMF Default Theme - Curve'
+			WHERE id_theme = 1
+				AND variable = 'name'");
+
+		// If known themes aren't set, let's just pick all themes available.
+		if (empty($modSettings['knownThemes']))
+		{
+			$request = upgrade_query("
+				SELECT DISTINCT id_theme
+				FROM {$db_prefix}themes");
+			$themes = array();
+			while ($row = mysql_fetch_assoc($request))
+				$themes[] = $row['id_theme'];
+			$modSettings['knownThemes'] = implode(',', $themes);
+			upgrade_query("
+				UPDATE {$db_prefix}settings
+				SET value = '$modSettings[knownThemes]'
+				WHERE variable = 'knownThemes'");
+		}
+
+		// Known themes.
+		$allThemes = explode(',', $modSettings['knownThemes']);
+		$allThemes[] = $id_core_theme;
+		$newSettings = array();
+		$newSettings[] = "('knownThemes', '" . implode(',', $allThemes) . "')";
+
+		upgrade_query("
+			REPLACE INTO {$db_prefix}settings
+				(variable, value)
+			VALUES
+				" . implode(', ', $newSettings));
+
+		// The other themes used to use core as their base theme.
+		if (isset($core['theme_dir']) && isset($core['theme_url']))
+		{
+			$coreBasedThemes = array_diff($allThemes, array(1));
+
+			// Exclude the themes that already have a base_theme_dir.
+			$request = upgrade_query("
+				SELECT DISTINCT id_theme
+				FROM {$db_prefix}themes
+				WHERE variable = 'base_theme_dir'");
+			while ($row = mysql_fetch_assoc($request))
+				$coreBasedThemes = array_diff($coreBasedThemes, array($row['id_theme']));
+			mysql_free_result($request);
+
+			// Only base themes if there are templates that need a fall-back.
+			$insertRows = array();
+			$request = upgrade_query("
+				SELECT id_theme, value AS theme_dir
+				FROM {$db_prefix}themes
+				WHERE id_theme IN (" . implode(', ', $coreBasedThemes) . ")
+					AND id_member = 0
+					AND variable = 'theme_dir'");
+			while ($row = mysql_fetch_assoc($request))
+			{
+				if (!file_exists($row['theme_dir'] . '/BoardIndex.template.php') || !file_exists($row['theme_dir'] . '/Display.template.php') || !file_exists($row['theme_dir'] . '/index.template.php') || !file_exists($row['theme_dir'] . '/MessageIndex.template.php') || !file_exists($row['theme_dir'] . '/Settings.template.php'))
+				{
+					$insertRows[] = "(0, $row[id_theme], 'base_theme_dir', '" . addslashes($core['theme_dir']) . "')";
+					$insertRows[] = "(0, $row[id_theme], 'base_theme_url', '" . addslashes($core['theme_url']) . "')";
+				}
+			}
+			mysql_free_result($request);
+
+			if (!empty($insertRows))
+				upgrade_query("
+					INSERT IGNORE INTO {$db_prefix}themes
+						(id_member, id_theme, variable, value)
+					VALUES
+						" . implode(',
+						', $insertRows));
+		}
+	}
+	mysql_free_result($theme_request);
+
+	// This ain't running twice either.
+	upgrade_query("
+		REPLACE INTO {$db_prefix}settings
+			(variable, value)
+		VALUES
+			('dont_repeat_theme_core', '1')");
+}
+
+---}
+---#
+
+/******************************************************************************/
+--- Installing new smileys sets...
+/******************************************************************************/
+
+---# Installing new smiley sets...
+---{
+// Don't do this twice!
+if (empty($modSettings['installed_new_smiley_sets_20']))
+{
+	// First, the entries.
+	upgrade_query("
+		UPDATE {$db_prefix}settings
+		SET value = CONCAT(value, ',aaron,akyhne')
+		WHERE variable = 'smiley_sets_known'");
+
+	// Second, the names.
+	upgrade_query("
+		UPDATE {$db_prefix}settings
+		SET value = CONCAT(value, '\nAaron\nAkyhne')
+		WHERE variable = 'smiley_sets_names'");
+
+	// This ain't running twice either.
+	upgrade_query("
+		REPLACE INTO {$db_prefix}settings
+			(variable, value)
+		VALUES
+			('installed_new_smiley_sets_20', '1')");
+}
+---}
+---#
+
+/******************************************************************************/
+--- Adding new indexes to the topics table.
+/******************************************************************************/
+
+---# Adding index member_started...
+ALTER TABLE {$db_prefix}topics
+ADD INDEX member_started (id_member_started, id_board);
+---#
+
+---# Adding index last_message_sticky...
+ALTER TABLE {$db_prefix}topics
+ADD INDEX last_message_sticky (id_board, is_sticky, id_last_msg);
+---#
+
+---# Adding index board_news...
+ALTER TABLE {$db_prefix}topics
+ADD INDEX board_news (id_board, id_first_msg);
+---#
+
+/******************************************************************************/
+--- Adding new indexes to members table.
+/******************************************************************************/
+
+---# Adding index on total_time_logged_in...
+ALTER TABLE {$db_prefix}members
+ADD INDEX total_time_logged_in (total_time_logged_in);
+---#
+
+---# Adding index on id_theme...
+ALTER TABLE {$db_prefix}members
+ADD INDEX id_theme (id_theme);
+---#
+
+---# Dropping index on real_name(30) ...
+---{
+// Detect existing index with limited length
+$request = upgrade_query("
+	SHOW INDEXES
+	FROM {$db_prefix}members"
+);
+
+// Drop the existing index before we recreate it.
+while ($row = mysql_fetch_assoc($request))
+{
+	if ($row['Key_name'] === 'real_name' && $row['Sub_part'] == 30)
+	{
+		upgrade_query("
+			ALTER TABLE {$db_prefix}members
+			DROP INDEX real_name"
+		);
+		break;
+	}
+}
+
+mysql_free_result($request);
+---}
+---#
+
+---# Adding index on real_name...
+ALTER TABLE {$db_prefix}members
+ADD INDEX real_name (real_name);
+---#
+
+---# Dropping index member_name(30)...
+---{
+// Detect existing index with limited length
+$request = upgrade_query("
+	SHOW INDEXES
+	FROM {$db_prefix}members"
+);
+
+// Drop the existing index before we recreate it.
+while ($row = mysql_fetch_assoc($request))
+{
+	if ($row['Key_name'] === 'member_name' && $row['Sub_part'] == 30)
+	{
+		upgrade_query("
+			ALTER TABLE {$db_prefix}members
+			DROP INDEX member_name"
+		);
+		break;
+	}
+}
+
+mysql_free_result($request);
+
+---}
+---#
+
+---# Adding index on member_name...
+ALTER TABLE {$db_prefix}members
+ADD INDEX member_name (member_name);
+---#
+
+/******************************************************************************/
+--- Adding new indexes to messages table.
+/******************************************************************************/
+
+---# Adding index id_member_msg...
+ALTER TABLE {$db_prefix}messages
+ADD INDEX id_member_msg (id_member, approved, id_msg);
+---#
+
+---# Adding index current_topic...
+ALTER TABLE {$db_prefix}messages
+ADD INDEX current_topic (id_topic, id_msg, id_member, approved);
+---#
+
+---# Adding index related_ip...
+ALTER TABLE {$db_prefix}messages
+ADD INDEX related_ip (id_member, poster_ip, id_msg);
+---#
+
+/******************************************************************************/
+--- Adding new indexes to attachments table.
+/******************************************************************************/
+
+---# Adding index on attachment_type...
+ALTER TABLE {$db_prefix}attachments
+ADD INDEX attachment_type (attachment_type);
+---#
+
+/******************************************************************************/
+--- Dropping unnecessary indexes...
+/******************************************************************************/
+
+---# Removing index on hits...
+ALTER TABLE {$db_prefix}log_activity
+DROP INDEX hits;
+---#
+
+/******************************************************************************/
+--- Adding extra columns to reported post comments
+/******************************************************************************/
+
+---# Adding email address and member ip columns...
+ALTER TABLE {$db_prefix}log_reported_comments
+ADD COLUMN member_ip varchar(255) NOT NULL default '' AFTER membername,
+ADD COLUMN email_address varchar(255) NOT NULL default '' AFTER membername;
+---#
+
+/******************************************************************************/
+--- Adjusting group types.
+/******************************************************************************/
+
+---# Fixing the group types.
+---{
+// Get the admin group type.
+$request = upgrade_query("
+	SELECT group_type
+	FROM {$db_prefix}membergroups
+	WHERE id_group = 1
+	LIMIT 1");
+list ($admin_group_type) = mysql_fetch_row($request);
+mysql_free_result($request);
+
+// Not protected means we haven't updated yet!
+if ($admin_group_type != 1)
+{
+	// Increase by one.
+	upgrade_query("
+		UPDATE {$db_prefix}membergroups
+		SET group_type = group_type + 1
+		WHERE group_type > 0");
+}
+---}
+---#
+
+---# Changing the group type for Administrator group.
+UPDATE {$db_prefix}membergroups
+SET group_type = 1
+WHERE id_group = 1;
+---#
+
+/******************************************************************************/
+--- Final clean up...
+/******************************************************************************/
+
+---# Sorting the boards...
+ALTER TABLE {$db_prefix}categories
+ORDER BY cat_order;
+
+ALTER TABLE {$db_prefix}boards
+ORDER BY board_order;
+---#

+ 1380 - 0
other/upgrade_2-0_postgresql.sql

@@ -0,0 +1,1380 @@
+/* ATTENTION: You don't need to run or use this file!  The upgrade.php script does everything for you! */
+
+/******************************************************************************/
+--- Adding Open ID support.
+/******************************************************************************/
+
+---# Adding Open ID Assocation table...
+CREATE TABLE {$db_prefix}openid_assoc (
+	server_url text NOT NULL,
+	handle varchar(255) NOT NULL,
+	secret text NOT NULL,
+	issued int NOT NULL,
+	expires int NOT NULL,
+	assoc_type varchar(64) NOT NULL,
+	PRIMARY KEY (server_url, handle)
+);
+---#
+
+/******************************************************************************/
+--- Updating custom fields.
+/******************************************************************************/
+
+---# Adding search ability to custom fields.
+---{
+if ($smcFunc['db_server_info'] < 8.0)
+{
+	upgrade_query("
+		ALTER TABLE {$db_prefix}custom_fields
+		ADD COLUMN can_search smallint");
+
+	upgrade_query("
+		UPDATE {$db_prefix}custom_fields
+		SET can_search = 0");
+
+	upgrade_query("
+		ALTER TABLE {$db_prefix}custom_fields
+		ALTER COLUMN can_search SET NOT NULL");
+
+	upgrade_query("
+		ALTER TABLE {$db_prefix}custom_fields
+		ALTER COLUMN can_search SET default '0'");
+}
+else
+{
+	upgrade_query("
+		ALTER TABLE {$db_prefix}custom_fields
+		ADD COLUMN can_search smallint NOT NULL default '0'");
+}
+---}
+---#
+
+---# Enhancing privacy settings for custom fields.
+---{
+if (isset($modSettings['smfVersion']) && $modSettings['smfVersion'] <= '2.0 Beta 1')
+{
+upgrade_query("
+	UPDATE {$db_prefix}custom_fields
+	SET private = 2
+	WHERE private = 1");
+}
+if (isset($modSettings['smfVersion']) && $modSettings['smfVersion'] < '2.0 Beta 4')
+{
+upgrade_query("
+	UPDATE {$db_prefix}custom_fields
+	SET private = 3
+	WHERE private = 2");
+}
+---}
+---#
+
+---# Changing default_values column to a larger field type...
+ALTER TABLE {$db_prefix}custom_fields
+ALTER COLUMN default_value TYPE varchar(255);
+---#
+
+---# Adding new custom fields columns.
+ALTER TABLE {$db_prefix}custom_fields
+ADD enclose text NOT NULL;
+
+ALTER TABLE {$db_prefix}custom_fields
+ADD placement smallint NOT NULL default '0';
+---#
+
+---# Fixing default value for the "show_profile" column
+ALTER TABLE {$db_prefix}custom_fields
+ALTER COLUMN show_profile SET DEFAULT 'forumprofile';
+
+UPDATE {$db_prefix}custom_fields
+SET show_profile='forumprofile' WHERE show_profile='forumProfile';
+---#
+
+/******************************************************************************/
+--- Adding new board specific features.
+/******************************************************************************/
+
+---# Implementing board redirects.
+---{
+if ($db_type == 'postgresql' && $smcFunc['db_server_info'] < 8.0)
+{
+	upgrade_query("
+		ALTER TABLE {$db_prefix}boards
+		ADD COLUMN redirect varchar(255)");
+
+	upgrade_query("
+		UPDATE {$db_prefix}boards
+		SET redirect = ''");
+
+	upgrade_query("
+		ALTER TABLE {$db_prefix}boards
+		ALTER COLUMN redirect SET NOT NULL");
+
+	upgrade_query("
+		ALTER TABLE {$db_prefix}boards
+		ALTER COLUMN redirect SET default ''");
+}
+else
+{
+	upgrade_query("
+		ALTER TABLE {$db_prefix}boards
+		ADD COLUMN redirect varchar(255) NOT NULL DEFAULT ''");
+}
+---}
+---#
+
+/******************************************************************************/
+--- Adding search engine tracking.
+/******************************************************************************/
+
+---# Creating spider sequence.
+CREATE SEQUENCE {$db_prefix}spiders_seq;
+---#
+
+---# Creating spider table.
+CREATE TABLE {$db_prefix}spiders (
+	id_spider smallint NOT NULL default nextval('{$db_prefix}spiders_seq'),
+	spider_name varchar(255) NOT NULL,
+	user_agent varchar(255) NOT NULL,
+	ip_info varchar(255) NOT NULL,
+	PRIMARY KEY (id_spider)
+);
+
+INSERT INTO {$db_prefix}spiders	(id_spider, spider_name, user_agent, ip_info) VALUES (1, 'Google', 'googlebot', '');
+INSERT INTO {$db_prefix}spiders	(id_spider, spider_name, user_agent, ip_info) VALUES (2, 'Yahoo!', 'slurp', '');
+INSERT INTO {$db_prefix}spiders	(id_spider, spider_name, user_agent, ip_info) VALUES (3, 'MSN', 'msnbot', '');
+INSERT INTO {$db_prefix}spiders	(id_spider, spider_name, user_agent, ip_info) VALUES (4, 'Google (Mobile)', 'Googlebot-Mobile', '');
+INSERT INTO {$db_prefix}spiders	(id_spider, spider_name, user_agent, ip_info) VALUES (5, 'Google (Image)', 'Googlebot-Image', '');
+INSERT INTO {$db_prefix}spiders	(id_spider, spider_name, user_agent, ip_info) VALUES (6, 'Google (AdSense)', 'Mediapartners-Google', '');
+INSERT INTO {$db_prefix}spiders	(id_spider, spider_name, user_agent, ip_info) VALUES (7, 'Google (Adwords)', 'AdsBot-Google', '');
+INSERT INTO {$db_prefix}spiders	(id_spider, spider_name, user_agent, ip_info) VALUES (8, 'Yahoo! (Mobile)', 'YahooSeeker/M1A1-R2D2', '');
+INSERT INTO {$db_prefix}spiders	(id_spider, spider_name, user_agent, ip_info) VALUES (9, 'Yahoo! (Image)', 'Yahoo-MMCrawler', '');
+INSERT INTO {$db_prefix}spiders	(id_spider, spider_name, user_agent, ip_info) VALUES (10, 'MSN (Mobile)', 'MSNBOT_Mobile', '');
+INSERT INTO {$db_prefix}spiders	(id_spider, spider_name, user_agent, ip_info) VALUES (11, 'MSN (Media)', 'msnbot-media', '');
+INSERT INTO {$db_prefix}spiders	(id_spider, spider_name, user_agent, ip_info) VALUES (12, 'Cuil', 'twiceler', '');
+INSERT INTO {$db_prefix}spiders	(id_spider, spider_name, user_agent, ip_info) VALUES (13, 'Ask', 'Teoma', '');
+INSERT INTO {$db_prefix}spiders	(id_spider, spider_name, user_agent, ip_info) VALUES (14, 'Baidu', 'Baiduspider', '');
+INSERT INTO {$db_prefix}spiders	(id_spider, spider_name, user_agent, ip_info) VALUES (15, 'Gigablast', 'Gigabot', '');
+INSERT INTO {$db_prefix}spiders	(id_spider, spider_name, user_agent, ip_info) VALUES (16, 'InternetArchive', 'ia_archiver-web.archive.org', '');
+INSERT INTO {$db_prefix}spiders	(id_spider, spider_name, user_agent, ip_info) VALUES (17, 'Alexa', 'ia_archiver', '');
+INSERT INTO {$db_prefix}spiders	(id_spider, spider_name, user_agent, ip_info) VALUES (18, 'Omgili', 'omgilibot', '');
+INSERT INTO {$db_prefix}spiders	(id_spider, spider_name, user_agent, ip_info) VALUES (19, 'EntireWeb', 'Speedy Spider', '');
+---#
+
+---# Removing a spider.
+---{
+	upgrade_query("
+		DELETE FROM {$db_prefix}spiders
+		WHERE user_agent = 'yahoo'
+			AND spider_name = 'Yahoo! (Publisher)'
+	");
+---}
+---#
+
+---# Sequence for table log_spider_hits.
+CREATE SEQUENCE {$db_prefix}log_spider_hits_seq;
+---#
+
+---# Creating spider hit tracking table.
+CREATE TABLE {$db_prefix}log_spider_hits (
+	id_hit int default nextval('{$db_prefix}log_spider_hits_seq'),
+	id_spider smallint NOT NULL default '0',
+	log_time int NOT NULL,
+	url varchar(255) NOT NULL,
+	processed smallint NOT NULL default '0'
+);
+
+CREATE INDEX {$db_prefix}log_spider_hits_id_spider ON {$db_prefix}log_spider_hits (id_spider);
+CREATE INDEX {$db_prefix}log_spider_hits_log_time ON {$db_prefix}log_spider_hits (log_time);
+CREATE INDEX {$db_prefix}log_spider_hits_processed ON {$db_prefix}log_spider_hits (processed);
+---#
+
+---# Creating spider statistic table.
+CREATE TABLE {$db_prefix}log_spider_stats (
+  id_spider smallint NOT NULL default '0',
+  page_hits smallint NOT NULL default '0',
+  last_seen int NOT NULL default '0',
+  stat_date date NOT NULL default '0001-01-01',
+  PRIMARY KEY (stat_date, id_spider)
+);
+---#
+
+/******************************************************************************/
+--- Adding new forum settings.
+/******************************************************************************/
+
+---# Enable cache if upgrading from 2.0 beta 1 and lower.
+---{
+if (isset($modSettings['smfVersion']) && $modSettings['smfVersion'] <= '2.0 Beta 1')
+{
+	$request = upgrade_query("
+		SELECT value
+		FROM {$db_prefix}settings
+		WHERE variable = 'cache_enable'");
+	list ($cache_enable) = $smcFunc['db_fetch_row']($request);
+
+	// No cache before
+	if ($smcFunc['db_num_rows']($request) == 0)
+		upgrade_query("
+			INSERT INTO {$db_prefix}settings
+				(variable, value)
+			VALUES ('cache_enable', '1')");
+	elseif (empty($cache_enable))
+		upgrade_query("
+			UPDATE {$db_prefix}settings
+			SET value = '1'
+			WHERE variable = 'cache_enable'");
+}
+---}
+---#
+
+---# Ensuring forum width setting present...
+---{
+// Don't do this twice!
+$smcFunc['db_insert']('ignore',
+	'{db_prefix}themes',
+	array('id_theme' => 'int', 'variable' => 'string-255', 'value' => 'string-255'),
+	array(1, 'forum_width', '90%'),
+	array('id_theme', 'variable', 'value')
+);
+---}
+---#
+
+/******************************************************************************/
+--- Adding misc functionality.
+/******************************************************************************/
+
+---# Converting "log_online".
+ALTER TABLE {$db_prefix}log_online DROP CONSTRAINT {$db_prefix}log_online_log_time;
+ALTER TABLE {$db_prefix}log_online DROP CONSTRAINT {$db_prefix}log_online_id_member;
+DROP TABLE {$db_prefix}log_online;
+CREATE TABLE {$db_prefix}log_online (
+  session varchar(32) NOT NULL default '',
+  log_time int NOT NULL default '0',
+  id_member int NOT NULL default '0',
+  id_spider smallint NOT NULL default '0',
+  ip int NOT NULL default '0',
+  url text NOT NULL,
+  PRIMARY KEY (session)
+);
+CREATE INDEX {$db_prefix}log_online_log_time ON {$db_prefix}log_online (log_time);
+CREATE INDEX {$db_prefix}log_online_id_member ON {$db_prefix}log_online (id_member);
+---#
+
+---# Adding guest voting - part 1...
+---{
+if ($smcFunc['db_server_info'] < 8.0)
+{
+	upgrade_query("
+		ALTER TABLE {$db_prefix}polls
+		ADD COLUMN guest_vote smallint");
+
+	upgrade_query("
+		UPDATE {$db_prefix}polls
+		SET guest_vote = 0");
+
+	upgrade_query("
+		ALTER TABLE {$db_prefix}polls
+		ALTER COLUMN guest_vote SET NOT NULL");
+
+	upgrade_query("
+		ALTER TABLE {$db_prefix}polls
+		ALTER COLUMN guest_vote SET default '0'");
+}
+else
+{
+	upgrade_query("
+		ALTER TABLE {$db_prefix}polls
+		ADD COLUMN guest_vote smallint NOT NULL default '0'");
+}
+---}
+---#
+
+---# Adding guest voting - part 2...
+DELETE FROM {$db_prefix}log_polls
+WHERE id_member < 0;
+
+ALTER TABLE {$db_prefix}log_polls DROP CONSTRAINT {$db_prefix}log_polls_pkey;
+
+CREATE INDEX {$db_prefix}log_polls_id_poll ON {$db_prefix}log_polls (id_poll, id_member, id_choice);
+---#
+
+---# Adding admin log...
+---{
+if ($db_type == 'postgresql' && $smcFunc['db_server_info'] < 8.0)
+{
+	upgrade_query("
+		ALTER TABLE {$db_prefix}log_actions
+		ADD COLUMN id_log smallint");
+
+	upgrade_query("
+		UPDATE {$db_prefix}log_actions
+		SET id_log = 1");
+
+	upgrade_query("
+		ALTER TABLE {$db_prefix}log_actions
+		ALTER COLUMN id_log SET NOT NULL");
+
+	upgrade_query("
+		ALTER TABLE {$db_prefix}log_actions
+		ALTER COLUMN id_log SET default '1'");
+}
+else
+{
+	upgrade_query("
+		ALTER TABLE {$db_prefix}log_actions
+		ADD COLUMN id_log smallint NOT NULL default '1'");
+}
+---}
+---#
+
+---# Adding search ability to custom fields.
+---{
+if ($smcFunc['db_server_info'] < 8.0)
+{
+	upgrade_query("
+		ALTER TABLE {$db_prefix}members
+		ADD COLUMN passwd_flood varchar(12)");
+
+	upgrade_query("
+		UPDATE {$db_prefix}members
+		SET passwd_flood = ''");
+
+	upgrade_query("
+		ALTER TABLE {$db_prefix}members
+		ALTER COLUMN passwd_flood SET NOT NULL");
+
+	upgrade_query("
+		ALTER TABLE {$db_prefix}members
+		ALTER COLUMN passwd_flood SET default ''");
+}
+else
+{
+	upgrade_query("
+		ALTER TABLE {$db_prefix}members
+		ADD COLUMN passwd_flood varchar(12) NOT NULL default ''");
+}
+---}
+---#
+
+/******************************************************************************/
+--- Adding weekly maintenance task.
+/******************************************************************************/
+
+---# Adding weekly maintenance task...
+INSERT INTO {$db_prefix}scheduled_tasks (next_time, time_offset, time_regularity, time_unit, disabled, task) VALUES (0, 0, 1, 'w', 0, 'weekly_maintenance');
+---#
+
+---# Setting the birthday email template if not set...
+---{
+if (!isset($modSettings['birthday_email']))
+{
+	upgrade_query("
+		INSERT INTO {$db_prefix}settings
+			(variable, value)
+		VALUES
+			('birthday_email', 'happy_birthday')");
+}
+---}
+---#
+
+/******************************************************************************/
+--- Adding log pruning.
+/******************************************************************************/
+
+---# Adding pruning option...
+INSERT INTO {$db_prefix}settings (variable, value) VALUES ('pruningOptions', '30,180,180,180,30');
+---#
+
+/******************************************************************************/
+--- Updating mail queue functionality.
+/******************************************************************************/
+
+---# Adding private to mail queue...
+---{
+if ($smcFunc['db_server_info'] < 8.0)
+{
+	upgrade_query("
+		ALTER TABLE {$db_prefix}mail_queue
+		ADD COLUMN private smallint");
+
+	upgrade_query("
+		UPDATE {$db_prefix}mail_queue
+		SET private = 0");
+
+	upgrade_query("
+		ALTER TABLE {$db_prefix}mail_queue
+		ALTER COLUMN private SET NOT NULL");
+
+	upgrade_query("
+		ALTER TABLE {$db_prefix}mail_queue
+		ALTER COLUMN private SET default '0'");
+}
+else
+{
+	upgrade_query("
+		ALTER TABLE {$db_prefix}mail_queue
+		ADD COLUMN private smallint NOT NULL default '0'");
+}
+---}
+---#
+
+/******************************************************************************/
+--- Updating attachments.
+/******************************************************************************/
+
+---# Adding multiple attachment path functionality.
+---{
+if ($smcFunc['db_server_info'] < 8.0)
+{
+	upgrade_query("
+		ALTER TABLE {$db_prefix}attachments
+		ADD COLUMN id_folder smallint");
+
+	upgrade_query("
+		UPDATE {$db_prefix}attachments
+		SET id_folder = 1");
+
+	upgrade_query("
+		ALTER TABLE {$db_prefix}attachments
+		ALTER COLUMN id_folder SET NOT NULL");
+
+	upgrade_query("
+		ALTER TABLE {$db_prefix}attachments
+		ALTER COLUMN id_folder SET default '1'");
+}
+else
+{
+	upgrade_query("
+		ALTER TABLE {$db_prefix}attachments
+		ADD COLUMN id_folder smallint NOT NULL default '1'");
+}
+---}
+---#
+
+---# Adding file hash.
+---{
+	upgrade_query("
+		ALTER TABLE {$db_prefix}attachments
+		ADD COLUMN file_hash varchar(40) NOT NULL default ''");
+---}
+---#
+
+/******************************************************************************/
+--- Adding restore topic from recycle.
+/******************************************************************************/
+
+---# Adding restore topic from recycle feature...
+---{
+if ($db_type == 'postgresql' && $smcFunc['db_server_info'] < 8.0)
+{
+	upgrade_query("
+		ALTER TABLE {$db_prefix}topics
+		ADD COLUMN id_previous_board smallint");
+	upgrade_query("
+		ALTER TABLE {$db_prefix}topics
+		ADD COLUMN id_previous_topic int");
+
+	upgrade_query("
+		UPDATE {$db_prefix}topics
+		SET
+			id_previous_board = 0,
+			id_previous_topic = 0");
+
+	upgrade_query("
+		ALTER TABLE {$db_prefix}topics
+		ALTER COLUMN id_previous_board SET NOT NULL");
+	upgrade_query("
+		ALTER TABLE {$db_prefix}topics
+		ALTER COLUMN id_previous_topic SET NOT NULL");
+
+	upgrade_query("
+		ALTER TABLE {$db_prefix}topics
+		ALTER COLUMN id_previous_board SET default '0'");
+	upgrade_query("
+		ALTER TABLE {$db_prefix}topics
+		ALTER COLUMN id_previous_topic SET default '0'");
+}
+else
+{
+	upgrade_query("
+		ALTER TABLE {$db_prefix}topics
+		ADD COLUMN id_previous_board smallint NOT NULL default '0'");
+	upgrade_query("
+		ALTER TABLE {$db_prefix}topics
+		ADD COLUMN id_previous_topic int NOT NULL default '0'");
+}
+---}
+---#
+
+/******************************************************************************/
+--- Making changes to the package manager.
+/******************************************************************************/
+
+---# Changing URL to SMF package server...
+UPDATE {$db_prefix}package_servers
+SET url = 'http://custom.simplemachines.org/packages/mods'
+WHERE url = 'http://mods.simplemachines.org';
+---#
+
+/******************************************************************************/
+--- Adding new indexes to the topics table.
+/******************************************************************************/
+
+---# Adding index member_started...
+CREATE INDEX {$db_prefix}topics_member_started ON {$db_prefix}topics (id_member_started, id_board);
+---#
+
+---# Adding index last_message_sticky...
+CREATE INDEX {$db_prefix}topics_last_message_sticky ON {$db_prefix}topics (id_board, is_sticky, id_last_msg);
+---#
+
+---# Adding index board_news...
+CREATE INDEX {$db_prefix}topics_board_news ON {$db_prefix}topics (id_board, id_first_msg);
+---#
+
+/******************************************************************************/
+--- Adding new indexes to members table.
+/******************************************************************************/
+
+---# Adding index on total_time_logged_in...
+CREATE INDEX {$db_prefix}members_total_time_logged_in ON {$db_prefix}members (total_time_logged_in);
+---#
+
+---# Adding index on id_theme...
+CREATE INDEX {$db_prefix}members_id_theme ON {$db_prefix}members (id_theme);
+---#
+
+---# Adding index on real_name...
+CREATE INDEX {$db_prefix}members_real_name ON {$db_prefix}members (real_name);
+---#
+
+/******************************************************************************/
+--- Adding new indexes to messages table.
+/******************************************************************************/
+
+---# Adding index id_member_msg...
+CREATE INDEX {$db_prefix}messages_id_member_msg ON {$db_prefix}messages (id_member, approved, id_msg);
+---#
+
+---# Adding index current_topic...
+CREATE INDEX {$db_prefix}messages_current_topic ON {$db_prefix}messages (id_topic, id_msg, id_member, approved);
+---#
+
+---# Adding index related_ip...
+CREATE INDEX {$db_prefix}messages_related_ip ON {$db_prefix}messages (id_member, poster_ip, id_msg);
+---#
+
+/******************************************************************************/
+--- Adding new indexes to attachments table.
+/******************************************************************************/
+
+---# Adding index on attachment_type...
+CREATE INDEX {$db_prefix}attachments_attachment_type ON {$db_prefix}attachments (attachment_type);
+---#
+
+/******************************************************************************/
+--- Providing more room for ignoring boards.
+/******************************************************************************/
+
+---# Changing ignore_boards column to a larger field type...
+ALTER TABLE {$db_prefix}members
+ALTER COLUMN ignore_boards TYPE text;
+---#
+
+/******************************************************************************/
+--- Adding default values to a couple of columns in log_subscribed
+/******************************************************************************/
+
+---# Adding default value for pending_details column
+ALTER TABLE {$db_prefix}log_subscribed
+ALTER COLUMN pending_details
+SET DEFAULT '';
+---#
+
+---# Adding default value for vendor_ref column
+ALTER TABLE {$db_prefix}log_subscribed
+ALTER COLUMN vendor_ref
+SET DEFAULT '';
+---#
+
+/*****************************************************************************/
+--- Fixing aim on members for longer nicks.
+/*****************************************************************************/
+
+---# Changing 'aim' to varchar to allow using email...
+ALTER TABLE {$db_prefix}members
+ALTER COLUMN aim TYPE varchar(255);
+
+ALTER TABLE {$db_prefix}members
+ALTER COLUMN aim SET DEFAULT '';
+---#
+
+/*****************************************************************************/
+--- Fixing column types in log_errors
+/*****************************************************************************/
+
+---# Changing 'ip' from char to varchar
+ALTER TABLE {$db_prefix}log_errors
+ALTER COLUMN ip TYPE varchar(16);
+
+ALTER TABLE {$db_prefix}log_errors
+ALTER COLUMN ip SET DEFAULT '';
+---#
+
+---# Changing 'error_type' from char to varchar
+ALTER TABLE {$db_prefix}log_errors
+ALTER COLUMN error_type TYPE varchar(15);
+---#
+
+/******************************************************************************/
+--- Allow for longer calendar event/holiday titles.
+/******************************************************************************/
+
+---# Changing event title column to a larger field type...
+ALTER TABLE {$db_prefix}calendar
+ALTER COLUMN title TYPE varchar(255);
+---#
+
+---# Changing holiday title column to a larger field type...
+ALTER TABLE {$db_prefix}calendar_holidays
+ALTER COLUMN title TYPE varchar(255);
+---#
+
+/******************************************************************************/
+--- Providing more room for apf options.
+/******************************************************************************/
+
+---# Changing field_options column to a larger field type...
+ALTER TABLE {$db_prefix}custom_fields
+ALTER COLUMN field_options TYPE text;
+---#
+
+/******************************************************************************/
+--- Adding extra columns to polls.
+/******************************************************************************/
+
+---# Adding reset poll timestamp and guest voters counter.
+---{
+if ($smcFunc['db_server_info'] < 8.0)
+{
+	upgrade_query("
+		ALTER TABLE {$db_prefix}polls
+		ADD COLUMN reset_poll int");
+
+	upgrade_query("
+		UPDATE {$db_prefix}polls
+		SET reset_poll = '0'
+		WHERE reset_poll < 1");
+
+	upgrade_query("
+		ALTER TABLE {$db_prefix}polls
+		ALTER COLUMN reset_poll SET NOT NULL");
+
+	upgrade_query("
+		ALTER TABLE {$db_prefix}polls
+		ALTER COLUMN reset_poll SET default '0'");
+
+	upgrade_query("
+		ALTER TABLE {$db_prefix}polls
+		ADD COLUMN num_guest_voters int");
+
+	upgrade_query("
+		UPDATE {$db_prefix}polls
+		SET num_guest_voters = '0'
+		WHERE num_guest_voters < 1");
+
+	upgrade_query("
+		ALTER TABLE {$db_prefix}polls
+		ALTER COLUMN num_guest_voters SET NOT NULL");
+
+	upgrade_query("
+		ALTER TABLE {$db_prefix}polls
+		ALTER COLUMN num_guest_voters SET default '0'");
+}
+else
+{
+	upgrade_query("
+		ALTER TABLE {$db_prefix}polls
+		ADD COLUMN reset_poll int NOT NULL default '0'");
+	upgrade_query("
+		ALTER TABLE {$db_prefix}polls
+		ADD COLUMN num_guest_voters int NOT NULL default '0'");
+}
+---}
+---#
+
+---# Fixing guest voter tallys on existing polls...
+---{
+$request = upgrade_query("
+	SELECT p.id_poll, count(lp.id_member) as guest_voters
+	FROM {$db_prefix}polls AS p
+		LEFT JOIN {$db_prefix}log_polls AS lp ON (lp.id_poll = p.id_poll AND lp.id_member = 0)
+	WHERE lp.id_member = 0
+		AND p.num_guest_voters = 0
+	GROUP BY p.id_poll");
+
+while ($request && $row = $smcFunc['db_fetch_assoc']($request))
+	upgrade_query("
+		UPDATE {$db_prefix}polls
+		SET num_guest_voters = ". $row['guest_voters']. "
+		WHERE id_poll = " . $row['id_poll'] . "
+			AND num_guest_voters = 0");
+---}
+---#
+
+/*****************************************************************************/
+--- Fixing a bug with the inet_aton() function.
+/*****************************************************************************/
+
+---# Changing inet_aton function to use bigint instead of int...
+CREATE OR REPLACE FUNCTION INET_ATON(text) RETURNS bigint AS
+  'SELECT
+	CASE WHEN
+		$1 !~ ''^[0-9]?[0-9]?[0-9]?\.[0-9]?[0-9]?[0-9]?\.[0-9]?[0-9]?[0-9]?\.[0-9]?[0-9]?[0-9]?$'' THEN 0
+	ELSE
+		split_part($1, ''.'', 1)::int8 * (256 * 256 * 256) +
+		split_part($1, ''.'', 2)::int8 * (256 * 256) +
+		split_part($1, ''.'', 3)::int8 * 256 +
+		split_part($1, ''.'', 4)::int8
+	END AS result'
+LANGUAGE 'sql';
+---#
+
+/*****************************************************************************/
+--- Making additional changes to handle results from fixed inet_aton().
+/*****************************************************************************/
+
+---# Adding an IFNULL to handle 8-bit integers returned by inet_aton
+CREATE OR REPLACE FUNCTION IFNULL(int8, int8) RETURNS int8 AS
+  'SELECT COALESCE($1, $2) AS result'
+LANGUAGE 'sql';
+---#
+
+---# Changing ip column in log_online to int8
+ALTER TABLE {$db_prefix}log_online
+ALTER COLUMN ip TYPE int8;
+---#
+
+/******************************************************************************/
+--- Dropping unnecessary indexes...
+/******************************************************************************/
+
+---# Removing index on hits...
+---{
+$smcFunc['db_remove_index']($db_prefix . 'log_activity', $db_prefix . 'log_activity_hits');
+---}
+---#
+
+
+/******************************************************************************/
+--- Adding new personal message setting.
+/******************************************************************************/
+
+---# Adding column that stores the PM receiving setting...
+---{
+	upgrade_query("
+		ALTER TABLE {$db_prefix}members
+		ADD COLUMN pm_receive_from smallint NOT NULL default '1'");
+---}
+---#
+
+---# Enable the buddy and ignore lists if we have not done so thus far...
+---{
+
+// Don't do this if we've done this already.
+if (empty($modSettings['dont_repeat_buddylists']))
+{
+	// Make sure the pm_receive_from column has the right default value - early adoptors might have a '0' set here.
+	upgrade_query("
+		ALTER TABLE {$db_prefix}members
+		ALTER COLUMN pm_receive_from SET DEFAULT '1'");
+
+	// Update previous ignore lists if they're set to ignore all.
+	upgrade_query("
+		UPDATE {$db_prefix}members
+		SET pm_receive_from = 3, pm_ignore_list = ''
+		WHERE pm_ignore_list = '*'");
+
+	// Enable buddy and ignore lists.
+	$smcFunc['db_insert']('replace',
+		'{db_prefix}settings',
+		array('variable' => 'string-255', 'value' => 'string-255'),
+		array('enable_buddylist', '1'),
+		array('variable', 'value')
+	);
+
+	// Ignore posts made by ignored users by default, too.
+	$smcFunc['db_insert']('replace',
+		'{db_prefix}themes',
+		array('id_member' => 'int', 'id_theme' => 'int', 'variable' => 'string-255', 'value' => 'string-255'),
+		array(-1, 1, 'posts_apply_ignore_list', '1'),
+		array('id_member', 'id_theme', 'variable', 'value')
+	);
+
+	// Make sure not to skip this step next time we run this.
+	$smcFunc['db_insert']('replace',
+		'{db_prefix}settings',
+		array('variable' => 'string-255', 'value' => 'string-255'),
+		array('dont_repeat_buddylists', '1'),
+		array('variable', 'value')
+	);
+}
+
+// And yet, and yet... We might have a small hiccup here...
+if (!empty($modSettings['dont_repeat_buddylists']) && !isset($modSettings['enable_buddylist']))
+{
+	// Correct RC3 adopters setting here...
+	if (isset($modSettings['enable_buddylists']))
+	{
+		$smcFunc['db_insert']('replace',
+			'{db_prefix}settings',
+			array('variable' => 'string-255', 'value' => 'string-255'),
+			array('enable_buddylist', $modSettings['enable_buddylists']),
+			array('variable', 'value')
+		);
+	}
+	else
+	{
+		// This should never happen :)
+		$smcFunc['db_insert']('replace',
+			'{db_prefix}settings',
+			array('variable' => 'string-255', 'value' => 'string-255'),
+			array('enable_buddylist', '1'),
+			array('variable', 'value')
+		);
+	}
+}
+
+---}
+---#
+
+/******************************************************************************/
+--- Adding settings for attachments and avatars.
+/******************************************************************************/
+
+---# Add new security settings for attachments and avatars...
+---{
+
+// Don't do this if we've done this already.
+if (!isset($modSettings['attachment_image_reencode']))
+{
+	// Enable image re-encoding by default.
+	$smcFunc['db_insert']('replace',
+		'{db_prefix}settings',
+		array('variable' => 'string-255', 'value' => 'string-255'),
+		array('attachment_image_reencode', '1'),
+		array('variable', 'value')
+	);
+}
+if (!isset($modSettings['attachment_image_paranoid']))
+{
+	// Disable draconic checks by default.
+	$smcFunc['db_insert']('replace',
+		'{db_prefix}settings',
+		array('variable' => 'string-255', 'value' => 'string-255'),
+		array('attachment_image_paranoid', '0'),
+		array('variable', 'value')
+	);
+}
+if (!isset($modSettings['avatar_reencode']))
+{
+	// Enable image re-encoding by default.
+	$smcFunc['db_insert']('replace',
+		'{db_prefix}settings',
+		array('variable' => 'string-255', 'value' => 'string-255'),
+		array('avatar_reencode', '1'),
+		array('variable', 'value')
+	);
+}
+if (!isset($modSettings['avatar_paranoid']))
+{
+	// Disable draconic checks by default.
+	$smcFunc['db_insert']('replace',
+		'{db_prefix}settings',
+		array('variable' => 'string-255', 'value' => 'string-255'),
+		array('avatar_paranoid', '0'),
+		array('variable', 'value')
+	);
+}
+---}
+---#
+
+---# Add other attachment settings...
+---{
+if (!isset($modSettings['attachment_thumb_png']))
+{
+	// Make image attachment thumbnail as PNG by default.
+	$smcFunc['db_insert']('replace',
+		'{db_prefix}settings',
+		array('variable' => 'string-255', 'value' => 'string-255'),
+		array('attachment_thumb_png', '1'),
+		array('variable', 'value')
+	);
+}
+---}
+---#
+
+/******************************************************************************/
+--- Installing new default theme...
+/******************************************************************************/
+
+---# Installing theme settings...
+---{
+// This is Grudge's secret "I'm not a developer" theme install code - keep this quiet ;)
+
+// Firstly, I'm going out of my way to not do this twice!
+if ((!isset($modSettings['smfVersion']) || $modSettings['smfVersion'] <= '2.0 RC2') && empty($modSettings['dont_repeat_theme_core']))
+{
+	// Check it's not already here, just in case.
+	$theme_request = upgrade_query("
+		SELECT id_theme
+		FROM {$db_prefix}themes
+		WHERE variable = 'theme_dir'
+			AND value LIKE '%core'");
+	// Only do the upgrade if it doesn't find the theme already.
+	if ($smcFunc['db_num_rows']($theme_request) == 0)
+	{
+		// Try to get some settings from the current default theme.
+		$request = upgrade_query("
+			SELECT t1.value AS theme_dir, t2.value AS theme_url, t3.value AS images_url
+			FROM ({$db_prefix}themes AS t1, {$db_prefix}themes AS t2, {$db_prefix}themes AS t3)
+			WHERE t1.id_theme = 1
+				AND t1.id_member = 0
+				AND t1.variable = 'theme_dir'
+				AND t2.id_theme = 1
+				AND t2.id_member = 0
+				AND t2.variable = 'theme_url'
+				AND t3.id_theme = 1
+				AND t3.id_member = 0
+				AND t3.variable = 'images_url'
+			LIMIT 1");
+		if ($smcFunc['db_num_rows']($request) != 0)
+		{
+			$curve = $smcFunc['db_fetch_assoc']($request);
+
+			if (substr_count($curve['theme_dir'], 'default') === 1)
+				$core['theme_dir'] = strtr($curve['theme_dir'], array('default' => 'core'));
+			if (substr_count($curve['theme_url'], 'default') === 1)
+				$core['theme_url'] = strtr($curve['theme_url'], array('default' => 'core'));
+			if (substr_count($curve['images_url'], 'default') === 1)
+				$core['images_url'] = strtr($curve['images_url'], array('default' => 'core'));
+		}
+		$smcFunc['db_free_result']($request);
+
+		if (!isset($core['theme_dir']))
+			$core['theme_dir'] = addslashes($GLOBALS['boarddir']) . '/Themes/core';
+		if (!isset($core['theme_url']))
+			$core['theme_url'] = $GLOBALS['boardurl'] . '/Themes/core';
+		if (!isset($core['images_url']))
+			$core['images_url'] = $GLOBALS['boardurl'] . '/Themes/core/images';
+
+		// Get an available id_theme first...
+		$request = upgrade_query("
+			SELECT MAX(id_theme) + 1
+			FROM {$db_prefix}themes");
+		list ($id_core_theme) = $smcFunc['db_fetch_row']($request);
+		$smcFunc['db_free_result']($request);
+
+		// Insert the core theme into the tables.
+		$smcFunc['db_insert']('ignore',
+			'{db_prefix}themes',
+				array('id_member' => 'int', 'id_theme' => 'int', 'variable' => 'string-255', 'value' => 'string-255'),
+				array(
+					array(0, $id_core_theme, 'name', 'Core Theme'),
+					array(0, $id_core_theme, 'theme_url', $core['theme_url']),
+					array(0, $id_core_theme, 'images_url', $core['images_url']),
+					array(0, $id_core_theme, 'theme_dir', $core['theme_dir'])
+				),
+				array()
+		);
+
+		// Update the name of the default theme in the database.
+		upgrade_query("
+			UPDATE {$db_prefix}themes
+			SET value = 'SMF Default Theme - Curve'
+			WHERE id_theme = 1
+				AND variable = 'name'");
+
+		$newSettings = array();
+		// Now that we have the old theme details - switch anyone who used the default to it (Make sense?!)
+		if (!empty($modSettings['theme_default']) && $modSettings['theme_default'] == 1)
+			$newSettings[] = "('theme_default', $id_core_theme)";
+		// Did guests use to use the default?
+		if (!empty($modSettings['theme_guests']) && $modSettings['theme_guests'] == 1)
+			$newSettings[] = "('theme_guests', $id_core_theme)";
+
+		// If known themes aren't set, let's just pick all themes available.
+		if (empty($modSettings['knownThemes']))
+		{
+			$request = upgrade_query("
+				SELECT DISTINCT id_theme
+				FROM {$db_prefix}themes");
+			$themes = array();
+			while ($row = $smcFunc['db_fetch_assoc']($request))
+				$themes[] = $row['id_theme'];
+			$modSettings['knownThemes'] = implode(',', $themes);
+			upgrade_query("
+				UPDATE {$db_prefix}settings
+				SET value = '$modSettings[knownThemes]'
+				WHERE variable = 'knownThemes'");
+		}
+
+		// Known themes.
+		$allThemes = explode(',', $modSettings['knownThemes']);
+		$allThemes[] = $id_core_theme;
+		$newSettings[] = "('knownThemes', '" . implode(',', $allThemes) . "')";
+
+		// Since we want to do a replace, just delete the old settings and re-insert them
+		upgrade_query("
+			DELETE FROM {$db_prefix}settings
+			WHERE variable IN ('theme_default', 'theme_guests', 'knownThemes')");
+
+		foreach ($new_settings AS $a_new_setting)
+		{
+			upgrade_query("
+				INSERT INTO {$db_prefix}settings
+				(variable, value)
+				VALUES " . implode(', ', $a_new_setting));
+		}
+
+		// What about members?
+		upgrade_query("
+			UPDATE {$db_prefix}members
+			SET id_theme = $id_core_theme
+			WHERE id_theme = 1");
+
+		// Boards?
+		upgrade_query("
+			UPDATE {$db_prefix}boards
+			SET id_theme = $id_core_theme
+			WHERE id_theme = 1");
+
+		// The other themes used to use core as their base theme.
+		if (isset($core['theme_dir']) && isset($core['theme_url']))
+		{
+			$coreBasedThemes = array_diff($allThemes, array(1));
+
+			// Exclude the themes that already have a base_theme_dir.
+			$request = upgrade_query("
+				SELECT DISTINCT id_theme
+				FROM {$db_prefix}themes
+				WHERE variable = 'base_theme_dir'");
+			while ($row = $smcFunc['db_fetch_assoc']($request))
+				$coreBasedThemes = array_diff($coreBasedThemes, array($row['id_theme']));
+			$smcFunc['db_free_result']($request);
+
+			// Only base themes if there are templates that need a fall-back.
+			$insertRows = array();
+			$request = upgrade_query("
+				SELECT id_theme, value AS theme_dir
+				FROM {$db_prefix}themes
+				WHERE id_theme IN (" . implode(', ', $coreBasedThemes) . ")
+					AND id_member = 0
+					AND variable = 'theme_dir'");
+			while ($row = $smcFunc['db_fetch_assoc']($request))
+			{
+				if (!file_exists($row['theme_dir'] . '/BoardIndex.template.php') || !file_exists($row['theme_dir'] . '/Display.template.php') || !file_exists($row['theme_dir'] . '/index.template.php') || !file_exists($row['theme_dir'] . '/MessageIndex.template.php') || !file_exists($row['theme_dir'] . '/Settings.template.php'))
+				{
+					$insertRows[] = "(0, $row[id_theme], 'base_theme_dir', '" . addslashes($core['theme_dir']) . "')";
+					$insertRows[] = "(0, $row[id_theme], 'base_theme_url', '" . addslashes($core['theme_url']) . "')";
+				}
+			}
+			$smcFunc['db_free_result']($request);
+
+			if (!empty($insertRows))
+				upgrade_query("
+					INSERT IGNORE INTO {$db_prefix}themes
+						(id_member, id_theme, variable, value)
+					VALUES
+						" . implode(',
+						', $insertRows));
+		}
+	}
+	$smcFunc['db_free_result']($theme_request);
+
+	// This ain't running twice either - not with the risk of log_tables timing us all out!
+	$smcFunc['db_insert']('replace',
+		'{db_prefix}settings',
+		array('variable' => 'string-255', 'value' => 'string-255'),
+		array('dont_repeat_theme_core', '1'),
+		array('variable', 'value')
+	);
+}
+
+---}
+---#
+
+/******************************************************************************/
+--- Installing new smileys sets...
+/******************************************************************************/
+
+---# Installing new smiley sets...
+---{
+// Don't do this twice!
+if (empty($modSettings['installed_new_smiley_sets_20']))
+{
+	// First, the entries.
+	upgrade_query("
+		UPDATE {$db_prefix}settings
+		SET value = CONCAT(value, ',aaron,akyhne')
+		WHERE variable = 'smiley_sets_known'");
+
+	// Second, the names.
+	upgrade_query("
+		UPDATE {$db_prefix}settings
+		SET value = CONCAT(value, '\nAaron\nAkyhne')
+		WHERE variable = 'smiley_sets_names'");
+
+	// This ain't running twice either.
+	$smcFunc['db_insert']('replace',
+		'{db_prefix}settings',
+		array('variable' => 'string-255', 'value' => 'string-255'),
+		array('installed_new_smiley_sets_20', '1'),
+		array('variable', 'value')
+	);
+}
+---}
+---#
+
+/*****************************************************************************/
+--- Adding additional functions
+/*****************************************************************************/
+
+---# Adding instr()
+---{
+if ($smcFunc['db_server_info'] < 8.2)
+{
+	$request = upgrade_query("
+		SELECT type_udt_name
+		FROM information_schema.routines
+		WHERE routine_name = 'inet_aton'
+	");
+
+	// Assume there's only one such function called inet_aton()
+	$return_type = $smcFunc['db_fetch_assoc']($request);
+
+	// No point in dropping and recreating it if it's already what we want
+	if ($return_type['type_udt_name'] != 'int4')
+	{
+		upgrade_query("
+			DROP FUNCTION INSTR(text, text)");
+	}
+}
+else
+{
+	upgrade_query("
+		DROP FUNCTION IF EXISTS INSTR(text, text)");
+}
+---}
+CREATE OR REPLACE FUNCTION INSTR(text, text) RETURNS integer AS
+  'SELECT POSITION($2 IN $1) AS result'
+LANGUAGE 'sql';
+---#
+
+---# Adding date_format()
+CREATE OR REPLACE FUNCTION DATE_FORMAT (timestamp, text) RETURNS text AS
+  'SELECT
+    REPLACE(
+        REPLACE($2, ''%m'', to_char($1, ''MM'')),
+    ''%d'', to_char($1, ''DD'')) AS result'
+LANGUAGE 'sql';
+---#
+
+---# Adding day()
+CREATE OR REPLACE FUNCTION day(date) RETURNS integer AS
+  'SELECT EXTRACT(DAY FROM DATE($1))::integer AS result'
+LANGUAGE 'sql';
+---#
+
+---# Adding IFNULL(varying, varying)
+CREATE OR REPLACE FUNCTION IFNULL (character varying, character varying) RETURNS character varying AS
+  'SELECT COALESCE($1, $2) AS result'
+LANGUAGE 'sql';
+---#
+
+---# Adding IFNULL(varying, bool)
+CREATE OR REPLACE FUNCTION IFNULL(character varying, boolean) RETURNS character varying AS
+  'SELECT COALESCE($1, CAST(CAST($2 AS int) AS varchar)) AS result'
+LANGUAGE 'sql';
+---#
+
+---# Adding IFNULL(int, bool)
+CREATE OR REPLACE FUNCTION IFNULL(int, boolean) RETURNS int AS
+  'SELECT COALESCE($1, CAST($2 AS int)) AS result'
+LANGUAGE 'sql';
+---#
+
+---# Adding bool_not_eq_int()
+CREATE OR REPLACE FUNCTION bool_not_eq_int (boolean, integer) RETURNS boolean AS
+  'SELECT CAST($1 AS integer) != $2 AS result'
+LANGUAGE 'sql';
+---#
+
+---# Creating operator bool_not_eq_int()
+---{
+$result = upgrade_query("SELECT oprname FROM pg_operator WHERE oprcode='bool_not_eq_int'::regproc");
+if($smcFunc['db_num_rows']($result) == 0)
+{
+	upgrade_query("
+		CREATE OPERATOR != (PROCEDURE = bool_not_eq_int, LEFTARG = boolean, RIGHTARG = integer)");
+}
+---}
+---#
+
+---# Recreating function FIND_IN_SET()
+---{
+if ($smcFunc['db_server_info'] < 8.2)
+{
+	$query = upgrade_query("SELECT * FROM pg_proc WHERE proname = 'find_in_set' AND proargtypes = '25 25'");
+	if ($smcFunc['db_num_rows']($query) != 0)
+	{
+		upgrade_query("DROP FUNCTION FIND_IN_SET(text, text)");
+	}
+
+	$query = upgrade_query("SELECT * FROM pg_proc WHERE proname = 'find_in_set' AND proargtypes = '23 1043'");
+	if ($smcFunc['db_num_rows']($query) != 0)
+	{
+		upgrade_query("DROP FUNCTION FIND_IN_SET(integer, character varying)");
+	}
+}
+else
+{
+	upgrade_query("DROP FUNCTION IF EXISTS FIND_IN_SET(text, text)");
+	upgrade_query("DROP FUNCTION IF EXISTS FIND_IN_SET(integer, character varying)");
+}
+---}
+CREATE OR REPLACE FUNCTION FIND_IN_SET(needle text, haystack text) RETURNS integer AS '
+	SELECT i AS result
+	FROM generate_series(1, array_upper(string_to_array($2,'',''), 1)) AS g(i)
+	WHERE  (string_to_array($2,'',''))[i] = $1
+		UNION ALL
+	SELECT 0
+	LIMIT 1'
+LANGUAGE 'sql';
+
+CREATE OR REPLACE FUNCTION FIND_IN_SET(needle integer, haystack text) RETURNS integer AS '
+	SELECT i AS result
+	FROM generate_series(1, array_upper(string_to_array($2,'',''), 1)) AS g(i)
+	WHERE  (string_to_array($2,'',''))[i] = CAST($1 AS text)
+		UNION ALL
+	SELECT 0
+	LIMIT 1'
+LANGUAGE 'sql';
+---#
+
+CREATE OR REPLACE FUNCTION DATE_FORMAT (timestamp, text) RETURNS text AS
+  'SELECT
+    REPLACE(
+        REPLACE($2, ''%m'', to_char($1, ''MM'')),
+    ''%d'', to_char($1, ''DD'')) AS result'
+LANGUAGE 'sql';
+
+---# Updating TO_DAYS()
+CREATE OR REPLACE FUNCTION TO_DAYS (timestamp) RETURNS integer AS
+  'SELECT DATE_PART(''DAY'', $1 - ''0001-01-01bc'')::integer AS result'
+LANGUAGE 'sql';
+---#
+
+/******************************************************************************/
+--- Adding extra columns to reported post comments
+/******************************************************************************/
+
+---# Adding email address and member ip columns...
+---{
+if ($smcFunc['db_server_info'] < 8.0)
+{
+	upgrade_query("
+		ALTER TABLE {$db_prefix}log_reported_comments
+		ADD COLUMN email_address varchar(255)");
+
+	upgrade_query("
+		UPDATE {$db_prefix}log_reported_comments
+		SET email_address = ''");
+
+	upgrade_query("
+		ALTER TABLE {$db_prefix}log_reported_comments
+		ALTER COLUMN email_address SET NOT NULL");
+
+	upgrade_query("
+		ALTER TABLE {$db_prefix}log_reported_comments
+		ALTER COLUMN email_address SET default ''");
+
+	upgrade_query("
+		ALTER TABLE {$db_prefix}log_reported_comments
+		ADD COLUMN member_ip varchar(255)");
+
+	upgrade_query("
+		UPDATE {$db_prefix}log_reported_comments
+		SET member_ip = ''");
+
+	upgrade_query("
+		ALTER TABLE {$db_prefix}log_reported_comments
+		ALTER COLUMN member_ip SET NOT NULL");
+
+	upgrade_query("
+		ALTER TABLE {$db_prefix}log_reported_comments
+		ALTER COLUMN member_ip SET default ''");
+}
+else
+{
+	upgrade_query("
+		ALTER TABLE {$db_prefix}log_reported_comments
+		ADD COLUMN email_address varchar(255) NOT NULL default ''");
+
+	upgrade_query("
+		ALTER TABLE {$db_prefix}log_reported_comments
+		ADD COLUMN member_ip varchar(255) NOT NULL default ''");
+}
+---}
+---#
+
+/******************************************************************************/
+--- Adjusting group types.
+/******************************************************************************/
+
+---# Fixing the group types.
+---{
+// Get the admin group type.
+$request = upgrade_query("
+	SELECT group_type
+	FROM {$db_prefix}membergroups
+	WHERE id_group = 1
+	LIMIT 1");
+list ($admin_group_type) = pg_fetch_row($request);
+pg_free_result($request);
+
+// Not protected means we haven't updated yet!
+if ($admin_group_type != 1)
+{
+	// Increase by one.
+	upgrade_query("
+		UPDATE {$db_prefix}membergroups
+		SET group_type = group_type + 1
+		WHERE group_type > 0");
+}
+---}
+---#
+
+---# Changing the group type for Administrator group.
+UPDATE {$db_prefix}membergroups
+SET group_type = 1
+WHERE id_group = 1;
+---#
+
+/******************************************************************************/
+--- Adjusting calendar maximum year.
+/******************************************************************************/
+
+---# Adjusting calendar maximum year.
+---{
+if (!isset($modSettings['cal_maxyear']) || $modSettings['cal_maxyear'] == '2010')
+{
+	$smcFunc['db_insert']('replace',
+		'{db_prefix}settings',
+		array('variable' => 'string-255', 'value' => 'string-255'),
+		array('cal_maxyear', '2020'),
+		array('variable', 'value')
+	);
+}
+---}
+---#

+ 995 - 0
other/upgrade_2-0_sqlite.sql

@@ -0,0 +1,995 @@
+/* ATTENTION: You don't need to run or use this file!  The upgrade.php script does everything for you! */
+
+/******************************************************************************/
+--- Updating custom fields.
+/******************************************************************************/
+
+---# Adding search ability to custom fields.
+---{
+$smcFunc['db_alter_table']('{db_prefix}custom_fields', array(
+	'add' => array(
+		'can_search' => array(
+			'name' => 'can_search',
+			'null' => false,
+			'default' => 0,
+			'type' => 'smallint',
+			'size' => 255,
+			'auto' => false,
+		),
+	),
+));
+
+if (isset($modSettings['smfVersion']) && $modSettings['smfVersion'] < '2.0 Beta 4')
+{
+upgrade_query("
+	UPDATE {$db_prefix}custom_fields
+	SET private = 3
+	WHERE private = 2");
+}
+---}
+---#
+
+---# Adding new custom fields columns.
+---{
+$smcFunc['db_alter_table']('{db_prefix}custom_fields', array(
+	'add' => array(
+		'enclose' => array(
+			'name' => 'enclose',
+			'null' => false,
+			'default' => '',
+			'type' => 'text',
+			'auto' => false,
+		),
+	)
+));
+
+$smcFunc['db_alter_table']('{db_prefix}custom_fields', array(
+	'add' => array(
+		'placement' => array(
+			'name' => 'placement',
+			'null' => false,
+			'default' => '',
+			'type' => 'smallint',
+			'auto' => false,
+		),
+	)
+));
+---}
+---#
+
+---# Fixing default value for the "show_profile" column
+---{
+$smcFunc['db_alter_table']('{db_prefix}custom_fields', array(
+	'change' => array(
+		'show_profile' => array(
+			'name' => 'show_profile',
+			'null' => false,
+			'default' => 'forumprofile',
+			'type' => 'varchar(20)',
+			'auto' => false,
+		),
+	)
+));
+---}
+---#
+
+ALTER TABLE {$db_prefix}custom_fields
+ALTER COLUMN show_profile DEFAULT 'forumprofile';
+---#
+
+/******************************************************************************/
+--- Adding search engine tracking.
+/******************************************************************************/
+
+---# Creating spider table.
+CREATE TABLE {$db_prefix}spiders (
+	id_spider integer primary key,
+	spider_name varchar(255) NOT NULL,
+	user_agent varchar(255) NOT NULL,
+	ip_info varchar(255) NOT NULL
+);
+---#
+
+---# Inserting the search engines.
+---{
+$smcFunc['db_insert']('ignore',
+	'{db_prefix}spiders',
+	array('id_spider' => 'int', 'spider_name' => 'string-255', 'user_agent' => 'string-255', 'ip_info' => 'string-255'),
+	array(
+		array(1, 'Google', 'googlebot', ''),
+		array(2, 'Yahoo!', 'slurp', ''),
+		array(3, 'MSN', 'msnbot', ''),
+		array(4, 'Google (Mobile)', 'Googlebot-Mobile', ''),
+		array(5, 'Google (Image)', 'Googlebot-Image', ''),
+		array(6, 'Google (AdSense)', 'Mediapartners-Google', ''),
+		array(7, 'Google (Adwords)', 'AdsBot-Google', ''),
+		array(8, 'Yahoo! (Mobile)', 'YahooSeeker/M1A1-R2D2', ''),
+		array(9, 'Yahoo! (Image)', 'Yahoo-MMCrawler', ''),
+		array(10, 'MSN (Mobile)', 'MSNBOT_Mobile', ''),
+		array(11, 'MSN (Media)', 'msnbot-media', ''),
+		array(12, 'Cuil', 'twiceler', ''),
+		array(13, 'Ask', 'Teoma', ''),
+		array(14, 'Baidu', 'Baiduspider', ''),
+		array(15, 'Gigablast', 'Gigabot', ''),
+		array(16, 'InternetArchive', 'ia_archiver-web.archive.org', ''),
+		array(17, 'Alexa', 'ia_archiver', ''),
+		array(18, 'Omgili', 'omgilibot', ''),
+		array(19, 'EntireWeb', 'Speedy Spider', '')
+	),
+	array('user_agent')
+);
+---}
+---#
+
+---# Removing a spider.
+---{
+	upgrade_query("
+		DELETE FROM {$db_prefix}spiders
+		WHERE user_agent = 'yahoo'
+			AND spider_name = 'Yahoo! (Publisher)'
+	");
+---}
+---#
+
+---# Creating spider hit tracking table.
+CREATE TABLE {$db_prefix}log_spider_hits (
+	id_spider integer NOT NULL default '0',
+	session varchar(32) NOT NULL default '',
+	log_time int NOT NULL,
+	url varchar(255) NOT NULL,
+	processed smallint NOT NULL default '0'
+);
+
+CREATE INDEX {$db_prefix}log_spider_hits_id_spider ON {$db_prefix}log_spider_hits (id_spider);
+CREATE INDEX {$db_prefix}log_spider_hits_log_time ON {$db_prefix}log_spider_hits (log_time);
+CREATE INDEX {$db_prefix}log_spider_hits_processed ON {$db_prefix}log_spider_hits (processed);
+---#
+
+---# Creating spider statistic table.
+CREATE TABLE {$db_prefix}log_spider_stats (
+	id_spider integer NOT NULL default '0',
+	unique_visits smallint NOT NULL default '0',
+	page_hits smallint NOT NULL default '0',
+	last_seen int NOT NULL default '0',
+	stat_date date NOT NULL default '0001-01-01',
+	PRIMARY KEY (stat_date, id_spider)
+);
+---#
+
+/******************************************************************************/
+--- Adding new forum settings.
+/******************************************************************************/
+
+---# Enable cache if upgrading from 2.0 beta 1 and lower.
+---{
+if (isset($modSettings['smfVersion']) && $modSettings['smfVersion'] <= '2.0 Beta 1')
+{
+	$request = upgrade_query("
+		SELECT value
+		FROM {$db_prefix}settings
+		WHERE variable = 'cache_enable'");
+	list ($cache_enable) = $smcFunc['db_fetch_row']($request);
+
+	// No cache before
+	if ($smcFunc['db_num_rows']($request) == 0)
+		upgrade_query("
+			INSERT INTO {$db_prefix}settings
+				(variable, value)
+			VALUES ('cache_enable', '1')");
+	elseif (empty($cache_enable))
+		upgrade_query("
+			UPDATE {$db_prefix}settings
+			SET value = '1'
+			WHERE variable = 'cache_enable'");
+}
+---}
+---#
+
+---# Adding advanced password brute force protection to "members" table...
+---{
+$smcFunc['db_alter_table']('{db_prefix}members', array(
+	'add' => array(
+		'passwd_flood' => array(
+			'name' => 'passwd_flood',
+			'null' => false,
+			'default' => '',
+			'type' => 'varchar',
+			'size' => 12,
+			'auto' => false,
+		),
+	)
+));
+---}
+---#
+
+---# Ensuring forum width setting present...
+---{
+// Don't do this twice!
+$smcFunc['db_insert']('ignore',
+	'{db_prefix}themes',
+	array('id_theme' => 'int', 'variable' => 'string-255', 'value' => 'string-255'),
+	array(1, 'forum_width', '90%'),
+	array('id_theme', 'variable', 'value')
+);
+---}
+---#
+
+/******************************************************************************/
+--- Adding weekly maintenance task.
+/******************************************************************************/
+
+---# Adding weekly maintenance task...
+---{
+$smcFunc['db_insert']('ignore',
+	'{db_prefix}scheduled_tasks',
+	array(
+		'next_time' => 'int', 'time_offset' => 'int', 'time_regularity' => 'int',
+		'time_unit' => 'string', 'disabled' => 'int', 'task' => 'string',
+	),
+	array(
+		0, 0, 1, 'w', 0, 'weekly_maintenance',
+	),
+	array('task')
+);
+---}
+---#
+
+---# Setting the birthday email template if not set...
+---{
+if (!isset($modSettings['birthday_email']))
+{
+	upgrade_query("
+		INSERT INTO {$db_prefix}settings
+			(variable, value)
+		VALUES
+			('birthday_email', 'happy_birthday')");
+}
+---}
+---#
+
+/******************************************************************************/
+--- Adding log pruning.
+/******************************************************************************/
+
+---# Adding pruning option...
+---{
+$smcFunc['db_insert']('ignore',
+	'{db_prefix}settings',
+	array('variable' => 'string-255', 'value' => 'string-65534'),
+	array('pruningOptions', '30,180,180,180,30'),
+	array('variable')
+);
+---}
+---#
+
+/******************************************************************************/
+--- Updating mail queue functionality.
+/******************************************************************************/
+
+---# Adding type to mail queue...
+---{
+$smcFunc['db_alter_table']('{db_prefix}mail_queue', array(
+	'add' => array(
+		'private' => array(
+			'name' => 'private',
+			'null' => false,
+			'default' => 0,
+			'type' => 'smallint',
+			'size' => 1,
+			'auto' => false,
+		),
+	)
+));
+---}
+---#
+
+/******************************************************************************/
+--- Updating attachments.
+/******************************************************************************/
+
+---# Adding multiple attachment path functionality.
+---{
+$smcFunc['db_alter_table']('{db_prefix}attachments', array(
+	'add' => array(
+		'id_folder' => array(
+			'name' => 'id_folder',
+			'null' => false,
+			'default' => 1,
+			'type' => 'smallint',
+			'size' => 255,
+			'auto' => false,
+		),
+	)
+));
+---}
+---#
+
+---# Adding file hash.
+---{
+$smcFunc['db_alter_table']('{db_prefix}attachments', array(
+	'add' => array(
+		'file_hash' => array(
+			'name' => 'file_hash',
+			'null' => false,
+			'default' => '',
+			'type' => 'varchar',
+			'size' => 40,
+			'auto' => false,
+		),
+	)
+));
+---}
+---#
+
+/******************************************************************************/
+--- Providing more room for apf options.
+/******************************************************************************/
+
+---# Changing field_options column to a larger field type...
+---{
+$smcFunc['db_alter_table']('{db_prefix}custom_fields', array(
+	'change' => array(
+		'aim' => array(
+			'name' => 'field_options',
+			'null' => false,
+			'type' => 'text',
+			'default' => ''
+		)
+	)
+));
+---}
+---#
+
+/******************************************************************************/
+--- Adding extra columns to polls.
+/******************************************************************************/
+
+---# Adding reset poll timestamp and guest voters counter...
+---{
+$smcFunc['db_alter_table']('{db_prefix}polls', array(
+	'add' => array(
+		'reset_poll' => array(
+			'name' => 'reset_poll',
+			'null' => false,
+			'default' => 0,
+			'type' => 'int',
+			'size' => 10,
+			'auto' => false,
+		),
+		'num_guest_voters' => array(
+			'name' => 'num_guest_voters',
+			'null' => false,
+			'default' => 0,
+			'type' => 'int',
+			'size' => 10,
+			'auto' => false,
+		),
+	)
+));
+---}
+---#
+
+---# Fixing guest voter tallys on existing polls...
+---{
+$request = upgrade_query("
+	SELECT p.id_poll, count(lp.id_member) as guest_voters
+	FROM {$db_prefix}polls AS p
+		LEFT JOIN {$db_prefix}log_polls AS lp ON (lp.id_poll = p.id_poll AND lp.id_member = 0)
+	WHERE lp.id_member = 0
+		AND p.num_guest_voters = 0
+	GROUP BY p.id_poll");
+
+while ($request && $row = $smcFunc['db_fetch_assoc']($request))
+	upgrade_query("
+		UPDATE {$db_prefix}polls
+		SET num_guest_voters = ". $row['guest_voters']. "
+		WHERE id_poll = " . $row['id_poll'] . "
+			AND num_guest_voters = 0");
+---}
+---#
+
+/******************************************************************************/
+--- Adding restore topic from recycle.
+/******************************************************************************/
+
+---# Adding restore from recycle feature...
+---{
+$smcFunc['db_alter_table']('{db_prefix}topics', array(
+	'add' => array(
+		'id_previous_board' => array(
+			'name' => 'id_previous_board',
+			'null' => false,
+			'default' => 0,
+			'type' => 'smallint',
+			'auto' => false,
+		),
+		'id_previous_topic' => array(
+			'name' => 'id_previous_topic',
+			'null' => false,
+			'default' => 0,
+			'type' => 'int',
+			'auto' => false,
+		),
+	)
+));
+---}
+---#
+
+/******************************************************************************/
+--- Fixing aim on members for longer nicks.
+/******************************************************************************/
+
+---# Changing 'aim' to varchar to allow using email...
+---{
+$smcFunc['db_alter_table']('{db_prefix}members', array(
+	'change' => array(
+		'aim' => array(
+			'name' => 'aim',
+			'null' => false,
+			'type' => 'varchar',
+			'size' => 255,
+			'default' => ''
+		)
+	)
+));
+---}
+---#
+
+/******************************************************************************/
+--- Allow for longer calendar event/holiday titles.
+/******************************************************************************/
+
+---# Changing event title column to a larger field type...
+---{
+$smcFunc['db_alter_table']('{db_prefix}calendar', array(
+	'change' => array(
+		'title' => array(
+			'name' => 'title',
+			'null' => false,
+			'type' => 'varchar',
+			'size' => 255,
+			'default' => ''
+		)
+	)
+));
+---}
+---#
+
+---# Changing holiday title column to a larger field type...
+---{
+$smcFunc['db_alter_table']('{db_prefix}calendar_holidays', array(
+	'change' => array(
+		'title' => array(
+			'name' => 'title',
+			'null' => false,
+			'type' => 'varchar',
+			'size' => 255,
+			'default' => ''
+		)
+	)
+));
+---}
+---#
+
+/******************************************************************************/
+--- Making changes to the package manager.
+/******************************************************************************/
+
+---# Changing URL to SMF package server...
+UPDATE {$db_prefix}package_servers
+SET url = 'http://custom.simplemachines.org/packages/mods'
+WHERE url = 'http://mods.simplemachines.org';
+---#
+
+/******************************************************************************/
+--- Adding new indexes to the topics table.
+/******************************************************************************/
+
+---# Adding index member_started...
+CREATE INDEX {$db_prefix}topics_member_started ON {$db_prefix}topics (id_member_started, id_board);
+---#
+
+---# Adding index last_message_sticky...
+CREATE INDEX {$db_prefix}topics_last_message_sticky ON {$db_prefix}topics (id_board, is_sticky, id_last_msg);
+---#
+
+---# Adding index board_news...
+CREATE INDEX {$db_prefix}topics_board_news ON {$db_prefix}topics (id_board, id_first_msg);
+---#
+
+/******************************************************************************/
+--- Adding new indexes to members table.
+/******************************************************************************/
+
+---# Adding index on total_time_logged_in...
+CREATE INDEX {$db_prefix}members_total_time_logged_in ON {$db_prefix}members (total_time_logged_in);
+---#
+
+---# Adding index on id_theme...
+CREATE INDEX {$db_prefix}members_id_theme ON {$db_prefix}members (id_theme);
+---#
+
+---# Adding index on real_name...
+CREATE INDEX {$db_prefix}members_real_name ON {$db_prefix}members (real_name);
+---#
+
+/******************************************************************************/
+--- Adding new indexes to messages table.
+/******************************************************************************/
+
+---# Adding index id_member_msg...
+CREATE INDEX {$db_prefix}messages_id_member_msg ON {$db_prefix}messages (id_member, approved, id_msg);
+---#
+
+---# Adding index current_topic...
+CREATE INDEX {$db_prefix}messages_current_topic ON {$db_prefix}messages (id_topic, id_msg, id_member, approved);
+---#
+
+---# Adding index related_ip...
+CREATE INDEX {$db_prefix}messages_related_ip ON {$db_prefix}messages (id_member, poster_ip, id_msg);
+---#
+
+/******************************************************************************/
+--- Adding new indexes to attachments table.
+/******************************************************************************/
+
+---# Adding index on attachment_type...
+CREATE INDEX {$db_prefix}attachments_attachment_type ON {$db_prefix}attachments (attachment_type);
+---#
+
+/******************************************************************************/
+--- Dropping unnecessary indexes...
+/******************************************************************************/
+
+---# Removing index on hits...
+---{
+$smcFunc['db_remove_index']($db_prefix . 'log_activity', $db_prefix . 'log_activity_hits');
+---}
+---#
+
+/******************************************************************************/
+--- Adding new personal message setting.
+/******************************************************************************/
+
+---# Adding column that stores the PM receiving setting...
+---{
+$smcFunc['db_alter_table']('{db_prefix}members', array(
+	'add' => array(
+		'pm_receive_from' => array(
+			'name' => 'pm_receive_from',
+			'null' => false,
+			'type' => 'tinyint',
+			'size' => 4,
+			'default' => '1'
+		)
+	)
+));
+---}
+---#
+
+---# Enable the buddy and ignore lists if we have not done so thus far...
+---{
+
+// Don't do this if we've done this already.
+if (empty($modSettings['dont_repeat_buddylists']))
+{
+	// Make sure the pm_receive_from column has the right default value - early adoptors might have a '0' set here.
+	$smcFunc['db_alter_table']('{db_prefix}members', array(
+		'change' => array(
+			'pm_receive_from' => array(
+				'name' => 'pm_receive_from',
+				'null' => false,
+				'type' => 'tinyint',
+				'size' => 4,
+				'default' => '1'
+			)
+		)
+	));
+
+	// Update previous ignore lists if they're set to ignore all.
+	upgrade_query("
+		UPDATE {$db_prefix}members
+		SET pm_receive_from = 3, pm_ignore_list = ''
+		WHERE pm_ignore_list = '*'");
+
+	// Enable buddy and ignore lists.
+	upgrade_query("
+		REPLACE INTO {$db_prefix}settings
+			(variable, value)
+		VALUES
+			('enable_buddylist', '1')");
+
+	// Ignore posts made by ignored users by default, too.
+	upgrade_query("
+		REPLACE INTO {$db_prefix}themes
+			(id_member, id_theme, variable, value)
+		VALUES
+			(-1, 1, 'posts_apply_ignore_list', '1')");
+
+	// Make sure not to skip this step next time we run this.
+	upgrade_query("
+		REPLACE INTO {$db_prefix}settings
+			(variable, value)
+		VALUES
+			('dont_repeat_buddylists', '1')");
+}
+
+// And yet, and yet... We might have a small hiccup here...
+if (!empty($modSettings['dont_repeat_buddylists']) && !isset($modSettings['enable_buddylist']))
+{
+	// Correct RC3 adopters setting here...
+	if (isset($modSettings['enable_buddylists']))
+	{
+		upgrade_query("
+		REPLACE INTO {$db_prefix}settings
+			(variable, value)
+		VALUES
+			('enable_buddylist', '". $modSettings['enable_buddylists']. "')");
+	}
+	else
+	{
+		// This should never happen :)
+		upgrade_query("
+		REPLACE INTO {$db_prefix}settings
+			(variable, value)
+		VALUES
+			('enable_buddylist', '1')");
+	}
+}
+---}
+---#
+
+/******************************************************************************/
+--- Adding settings for attachments and avatars.
+/******************************************************************************/
+
+---# Add new security settings for attachments and avatars...
+---{
+
+// Don't do this if we've done this already.
+if (!isset($modSettings['attachment_image_reencode']))
+{
+	// Enable image re-encoding by default.
+	upgrade_query("
+		REPLACE INTO {$db_prefix}settings
+			(variable, value)
+		VALUES
+			('attachment_image_reencode', '1')");
+}
+if (!isset($modSettings['attachment_image_paranoid']))
+{
+	// Disable draconic checks by default.
+	upgrade_query("
+		REPLACE INTO {$db_prefix}settings
+			(variable, value)
+		VALUES
+			('attachment_image_paranoid', '0')");
+}
+if (!isset($modSettings['avatar_reencode']))
+{
+	// Enable image re-encoding by default.
+	upgrade_query("
+		REPLACE INTO {$db_prefix}settings
+			(variable, value)
+		VALUES
+			('avatar_reencode', '1')");
+}
+if (!isset($modSettings['avatar_paranoid']))
+{
+	// Disable draconic checks by default.
+	upgrade_query("
+		REPLACE INTO {$db_prefix}settings
+			(variable, value)
+		VALUES
+			('avatar_paranoid', '0')");
+}
+
+---}
+---#
+
+---# Add other attachment settings...
+---{
+if (!isset($modSettings['attachment_thumb_png']))
+{
+	// Make image attachment thumbnail as PNG by default.
+	upgrade_query("
+		REPLACE INTO {$db_prefix}settings
+			(variable, value)
+		VALUES
+			('attachment_thumb_png', '1')");
+}
+
+---}
+---#
+
+/******************************************************************************/
+--- Installing new default theme...
+/******************************************************************************/
+
+---# Installing theme settings...
+---{
+// This is Grudge's secret "I'm not a developer" theme install code - keep this quiet ;)
+
+// Firstly, I'm going out of my way to not do this twice!
+if ((!isset($modSettings['smfVersion']) || $modSettings['smfVersion'] <= '2.0 RC2') && empty($modSettings['dont_repeat_theme_core']))
+{
+	// Check it's not already here, just in case.
+	$theme_request = upgrade_query("
+		SELECT id_theme
+		FROM {$db_prefix}themes
+		WHERE variable = 'theme_dir'
+			AND value LIKE '%core'");
+	// Only do the upgrade if it doesn't find the theme already.
+	if ($smcFunc['db_num_rows']($theme_request) == 0)
+	{
+		// Try to get some settings from the current default theme.
+		$request = upgrade_query("
+			SELECT t1.value AS theme_dir, t2.value AS theme_url, t3.value AS images_url
+			FROM {$db_prefix}themes AS t1, {$db_prefix}themes AS t2, {$db_prefix}themes AS t3
+			WHERE t1.id_theme = 1
+				AND t1.id_member = 0
+				AND t1.variable = 'theme_dir'
+				AND t2.id_theme = 1
+				AND t2.id_member = 0
+				AND t2.variable = 'theme_url'
+				AND t3.id_theme = 1
+				AND t3.id_member = 0
+				AND t3.variable = 'images_url'
+			LIMIT 1");
+		if ($smcFunc['db_num_rows']($request) != 0)
+		{
+			$curve = $smcFunc['db_fetch_assoc']($request);
+
+			if (substr_count($curve['theme_dir'], 'default') === 1)
+				$core['theme_dir'] = strtr($curve['theme_dir'], array('default' => 'core'));
+			if (substr_count($curve['theme_url'], 'default') === 1)
+				$core['theme_url'] = strtr($curve['theme_url'], array('default' => 'core'));
+			if (substr_count($curve['images_url'], 'default') === 1)
+				$core['images_url'] = strtr($curve['images_url'], array('default' => 'core'));
+		}
+		$smcFunc['db_free_result']($request);
+
+		if (!isset($core['theme_dir']))
+			$core['theme_dir'] = addslashes($GLOBALS['boarddir']) . '/Themes/core';
+		if (!isset($core['theme_url']))
+			$core['theme_url'] = $GLOBALS['boardurl'] . '/Themes/core';
+		if (!isset($core['images_url']))
+			$core['images_url'] = $GLOBALS['boardurl'] . '/Themes/core/images';
+
+		// Get an available id_theme first...
+		$request = upgrade_query("
+			SELECT MAX(id_theme) + 1
+			FROM {$db_prefix}themes");
+		list ($id_core_theme) = $smcFunc['db_fetch_row']($request);
+		$smcFunc['db_free_result']($request);
+
+		// Insert the core theme into the tables.
+		$smcFunc['db_insert']('ignore',
+			'{db_prefix}themes',
+				array('id_member' => 'int', 'id_theme' => 'int', 'variable' => 'string-255', 'value' => 'string-255'),
+				array(
+					array(0, $id_core_theme, 'name', 'Core Theme'),
+					array(0, $id_core_theme, 'theme_url', $core['theme_url']),
+					array(0, $id_core_theme, 'images_url', $core['images_url']),
+					array(0, $id_core_theme, 'theme_dir', $core['theme_dir'])
+				),
+				array()
+		);
+
+		// Update the name of the default theme in the database.
+		upgrade_query("
+			UPDATE {$db_prefix}themes
+			SET value = 'SMF Default Theme - Curve'
+			WHERE id_theme = 1
+				AND variable = 'name'");
+
+		$newSettings = array();
+		// Now that we have the old theme details - switch anyone who used the default to it (Make sense?!)
+		if (!empty($modSettings['theme_default']) && $modSettings['theme_default'] == 1)
+			$newSettings[] = "('theme_default', $id_core_theme)";
+		// Did guests use to use the default?
+		if (!empty($modSettings['theme_guests']) && $modSettings['theme_guests'] == 1)
+			$newSettings[] = "('theme_guests', $id_core_theme)";
+
+		// If known themes aren't set, let's just pick all themes available.
+		if (empty($modSettings['knownThemes']))
+		{
+			$request = upgrade_query("
+				SELECT DISTINCT id_theme
+				FROM {$db_prefix}themes");
+			$themes = array();
+			while ($row = $smcFunc['db_fetch_assoc']($request))
+				$themes[] = $row['id_theme'];
+			$modSettings['knownThemes'] = implode(',', $themes);
+			upgrade_query("
+				UPDATE {$db_prefix}settings
+				SET value = '$modSettings[knownThemes]'
+				WHERE variable = 'knownThemes'");
+		}
+
+		// Known themes.
+		$allThemes = explode(',', $modSettings['knownThemes']);
+		$allThemes[] = $id_core_theme;
+		$newSettings[] = "('knownThemes', '" . implode(',', $allThemes) . "')";
+
+		upgrade_query("
+			REPLACE INTO {$db_prefix}settings
+				(variable, value)
+			VALUES
+				" . implode(', ', $newSettings));
+
+		// What about members?
+		upgrade_query("
+			UPDATE {$db_prefix}members
+			SET id_theme = $id_core_theme
+			WHERE id_theme = 1");
+
+		// Boards?
+		upgrade_query("
+			UPDATE {$db_prefix}boards
+			SET id_theme = $id_core_theme
+			WHERE id_theme = 1");
+
+		// The other themes used to use core as their base theme.
+		if (isset($core['theme_dir']) && isset($core['theme_url']))
+		{
+			$coreBasedThemes = array_diff($allThemes, array(1));
+
+			// Exclude the themes that already have a base_theme_dir.
+			$request = upgrade_query("
+				SELECT DISTINCT id_theme
+				FROM {$db_prefix}themes
+				WHERE variable = 'base_theme_dir'");
+			while ($row = $smcFunc['db_fetch_assoc']($request))
+				$coreBasedThemes = array_diff($coreBasedThemes, array($row['id_theme']));
+			$smcFunc['db_free_result']($request);
+
+			// Only base themes if there are templates that need a fall-back.
+			$insertRows = array();
+			$request = upgrade_query("
+				SELECT id_theme, value AS theme_dir
+				FROM {$db_prefix}themes
+				WHERE id_theme IN (" . implode(', ', $coreBasedThemes) . ")
+					AND id_member = 0
+					AND variable = 'theme_dir'");
+			while ($row = $smcFunc['db_fetch_assoc']($request))
+			{
+				if (!file_exists($row['theme_dir'] . '/BoardIndex.template.php') || !file_exists($row['theme_dir'] . '/Display.template.php') || !file_exists($row['theme_dir'] . '/index.template.php') || !file_exists($row['theme_dir'] . '/MessageIndex.template.php') || !file_exists($row['theme_dir'] . '/Settings.template.php'))
+				{
+					$insertRows[] = "(0, $row[id_theme], 'base_theme_dir', '" . addslashes($core['theme_dir']) . "')";
+					$insertRows[] = "(0, $row[id_theme], 'base_theme_url', '" . addslashes($core['theme_url']) . "')";
+				}
+			}
+			$smcFunc['db_free_result']($request);
+
+			if (!empty($insertRows))
+				upgrade_query("
+					INSERT IGNORE INTO {$db_prefix}themes
+						(id_member, id_theme, variable, value)
+					VALUES
+						" . implode(',
+						', $insertRows));
+		}
+	}
+	$smcFunc['db_free_result']($theme_request);
+
+	// This ain't running twice either - not with the risk of log_tables timing us all out!
+	upgrade_query("
+		REPLACE INTO {$db_prefix}settings
+			(variable, value)
+		VALUES
+			('dont_repeat_theme_core', '1')");
+}
+
+---}
+---#
+
+/******************************************************************************/
+--- Installing new smileys sets...
+/******************************************************************************/
+
+---# Installing new smiley sets...
+---{
+// Don't do this twice!
+if (empty($modSettings['installed_new_smiley_sets_20']))
+{
+	// First, the entries.
+	upgrade_query("
+		UPDATE {$db_prefix}settings
+		SET value = CONCAT(value, ',aaron,akyhne')
+		WHERE variable = 'smiley_sets_known'");
+
+	// Second, the names.
+	upgrade_query("
+		UPDATE {$db_prefix}settings
+		SET value = CONCAT(value, '\nAaron\nAkyhne')
+		WHERE variable = 'smiley_sets_names'");
+
+	// This ain't running twice either.
+	upgrade_query("
+		REPLACE INTO {$db_prefix}settings
+			(variable, value)
+		VALUES
+			('installed_new_smiley_sets_20', '1')");
+}
+---}
+---#
+
+/******************************************************************************/
+--- Adding extra columns to reported post comments
+/******************************************************************************/
+
+---# Adding email address and member ip columns...
+---{
+$smcFunc['db_alter_table']('{db_prefix}log_reported_comments', array(
+	'add' => array(
+		'email_address' => array(
+			'name' => 'email_address',
+			'null' => false,
+			'default' => '',
+			'type' => 'varchar',
+			'size' => 255,
+			'auto' => false,
+		),
+		'member_ip' => array(
+			'name' => 'member_ip',
+			'null' => false,
+			'default' => '',
+			'type' => 'varchar',
+			'size' => 255,
+			'auto' => false,
+		),
+	)
+));
+---}
+---#
+
+/******************************************************************************/
+--- Adjusting group types.
+/******************************************************************************/
+
+---# Fixing the group types.
+---{
+// Get the admin group type.
+$request = upgrade_query("
+	SELECT group_type
+	FROM {$db_prefix}membergroups
+	WHERE id_group = 1
+	LIMIT 1");
+list ($admin_group_type) = mysql_fetch_row($request);
+mysql_free_result($request);
+
+// Not protected means we haven't updated yet!
+if ($admin_group_type != 1)
+{
+	// Increase by one.
+	upgrade_query("
+		UPDATE {$db_prefix}membergroups
+		SET group_type = group_type + 1
+		WHERE group_type > 0");
+}
+---}
+---#
+
+---# Changing the group type for Administrator group.
+UPDATE {$db_prefix}membergroups
+SET group_type = 1
+WHERE id_group = 1;
+---#
+
+/******************************************************************************/
+--- Adjusting calendar maximum year.
+/******************************************************************************/
+
+---# Adjusting calendar maximum year.
+---{
+if (!isset($modSettings['cal_maxyear']) || $modSettings['cal_maxyear'] == '2010')
+{
+	upgrade_query("
+		REPLACE INTO {$db_prefix}settings
+			(variable, value)
+		VALUES
+			('cal_maxyear', '2020')");
+}
+---}
+---#