From 784a8dfdd4cc963573409fa3c5323ef469156fe2 Mon Sep 17 00:00:00 2001 From: Trevor Slocum Date: Sun, 20 Jul 2014 12:12:00 -0700 Subject: [PATCH] Add database migration tool (flatfile -> mysql) --- README.md | 22 +++++++++++++ imgboard.php | 69 +++++++++++++++++++++++++++++++++++++++++ inc/database_mysql.php | 38 ++--------------------- inc/database_mysqli.php | 40 ++---------------------- inc/defines.php | 3 ++ inc/functions.php | 38 +++++++++++++++++++++++ inc/html.php | 2 +- settings.default.php | 1 + 8 files changed, 139 insertions(+), 74 deletions(-) diff --git a/README.md b/README.md index c298b4f..e6acb85 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,28 @@ Updating - Visit [GitHub](https://github.com/tslocum/TinyIB) and review the changes made in the update. - Ensure the update does not interfere with your changes. +Migrating +------------ + +TinyIB includes a database migration tool, which currently only supports migrating from flat file to MySQL. While the migration is in progress, visitors will not be able to create or delete posts. + + 1. Edit **settings.php** + - Ensure ``TINYIB_DBMODE`` is still set to ``flatfile``. + - Set ``TINYIB_DBMIGRATE`` to ``true``. + - Configure all MySQL-related settings. + 2. Open the management panel. + 3. Click **Migrate Database** + 4. Click **Start the migration** + 5. If the migration was successful: + - Edit **settings.php** + - Set ``TINYIB_DBMODE`` to ``mysqli``. + - Set ``TINYIB_DBMIGRATE`` to ``false``. + - Click **Rebuild All** and ensure the board still looks the way it should. + +If there was a warning about AUTO_INCREMENT not being updated, you'll need to update it manually via a more privileged MySQL user. Run the following query for one or both of the tables, dependant of the warnings you were issued: + +``ALTER TABLE (table name) AUTO_INCREMENT = (value to be set)`` + Support ------------ diff --git a/imgboard.php b/imgboard.php index 882da8f..6572077 100644 --- a/imgboard.php +++ b/imgboard.php @@ -59,6 +59,10 @@ if (TINYIB_TRIPSEED == '' || TINYIB_ADMINPASS == '') { $redirect = true; // Check if the request is to make a post if (isset($_POST['message']) || isset($_POST['file'])) { + if (TINYIB_DBMIGRATE) { + fancyDie('Posting is currently disabled.
Please try again in a few moments.'); + } + list($loggedin, $isadmin) = manageCheckLogIn(); $rawpost = isRawPost(); if (!$loggedin) { @@ -262,6 +266,10 @@ if (isset($_POST['message']) || isset($_POST['file'])) { fancyDie('Tick the box next to a post and click "Delete" to delete it.'); } + if (TINYIB_DBMIGRATE) { + fancyDie('Post deletion is currently disabled.
Please try again in a few moments.'); + } + $post = postByID($_POST['delete']); if ($post) { list($loggedin, $isadmin) = manageCheckLogIn(); @@ -348,6 +356,67 @@ if (isset($_POST['message']) || isset($_POST['file'])) { $text .= '

TinyIB was not installed via Git.

If you installed TinyIB without Git, you must update manually. If you did install with Git, ensure the script has read and write access to the .git folder.

'; } + } elseif (isset($_GET['dbmigrate'])) { + if (TINYIB_DBMIGRATE) { + if (isset($_GET['go'])) { + if (TINYIB_DBMODE == 'flatfile') { + if (function_exists('mysqli_connect')) { + $link = @mysqli_connect(TINYIB_DBHOST, TINYIB_DBUSERNAME, TINYIB_DBPASSWORD); + if (!$link) { + fancyDie("Could not connect to database: " . ((is_object($link)) ? mysqli_error($link) : (($link_error = mysqli_connect_error()) ? $link_error : '(unknown error)'))); + } + $db_selected = @mysqli_query($link, "USE " . constant('TINYIB_DBNAME')); + if (!$db_selected) { + fancyDie("Could not select database: " . ((is_object($link)) ? mysqli_error($link) : (($link_error = mysqli_connect_error()) ? $link_error : '(unknown error'))); + } + + if (mysqli_num_rows(mysqli_query($link, "SHOW TABLES LIKE '" . TINYIB_DBPOSTS . "'")) == 0) { + if (mysqli_num_rows(mysqli_query($link, "SHOW TABLES LIKE '" . TINYIB_DBBANS . "'")) == 0) { + mysqli_query($link, $posts_sql); + mysqli_query($link, $bans_sql); + + $max_id = 0; + $threads = allThreads(); + foreach ($threads as $thread) { + $posts = postsInThreadByID($thread['id']); + foreach ($posts as $post) { + mysqli_query($link, "INSERT INTO `" . TINYIB_DBPOSTS . "` (`id`, `parent`, `timestamp`, `bumped`, `ip`, `name`, `tripcode`, `email`, `nameblock`, `subject`, `message`, `password`, `file`, `file_hex`, `file_original`, `file_size`, `file_size_formatted`, `image_width`, `image_height`, `thumb`, `thumb_width`, `thumb_height`) VALUES (" . $post['id'] . ", " . $post['parent'] . ", " . time() . ", " . time() . ", '" . $_SERVER['REMOTE_ADDR'] . "', '" . mysqli_real_escape_string($link, $post['name']) . "', '" . mysqli_real_escape_string($link, $post['tripcode']) . "', '" . mysqli_real_escape_string($link, $post['email']) . "', '" . mysqli_real_escape_string($link, $post['nameblock']) . "', '" . mysqli_real_escape_string($link, $post['subject']) . "', '" . mysqli_real_escape_string($link, $post['message']) . "', '" . mysqli_real_escape_string($link, $post['password']) . "', '" . $post['file'] . "', '" . $post['file_hex'] . "', '" . mysqli_real_escape_string($link, $post['file_original']) . "', " . $post['file_size'] . ", '" . $post['file_size_formatted'] . "', " . $post['image_width'] . ", " . $post['image_height'] . ", '" . $post['thumb'] . "', " . $post['thumb_width'] . ", " . $post['thumb_height'] . ")"); + $max_id = max($max_id, $post['id']); + } + } + if ($max_id > 0 && !mysqli_query($link, "ALTER TABLE `" . TINYIB_DBPOSTS . "` AUTO_INCREMENT = " . ($max_id + 1))) { + $text .= '

Warning: Unable to update the AUTO_INCREMENT value for table ' . TINYIB_DBPOSTS . ', please set it to ' . ($max_id + 1) . '.

'; + } + + $max_id = 0; + $bans = allBans(); + foreach ($bans as $ban) { + $max_id = max($max_id, $ban['id']); + mysqli_query($link, "INSERT INTO `" . TINYIB_DBBANS . "` (`id`, `ip`, `timestamp`, `expire`, `reason`) VALUES ('" . mysqli_real_escape_string($link, $ban['id']) . "', '" . mysqli_real_escape_string($link, $ban['ip']) . "', '" . mysqli_real_escape_string($link, $ban['timestamp']) . "', '" . mysqli_real_escape_string($link, $ban['expire']) . "', '" . mysqli_real_escape_string($link, $ban['reason']) . "')"); + } + if ($max_id > 0 && !mysqli_query($link, "ALTER TABLE `" . TINYIB_DBBANS . "` AUTO_INCREMENT = " . ($max_id + 1))) { + $text .= '

Warning: Unable to update the AUTO_INCREMENT value for table ' . TINYIB_DBBANS . ', please set it to ' . ($max_id + 1) . '.

'; + } + + $text .= '

Database migration complete. Set TINYIB_DBMODE to mysqli and TINYIB_DBMIGRATE to false, then click Rebuild All above and ensure everything looks the way it should.

'; + } else { + fancyDie('Bans table (' . TINYIB_DBBANS . ') already exists! Please DROP this table and try again.'); + } + } else { + fancyDie('Posts table (' . TINYIB_DBPOSTS . ') already exists! Please DROP this table and try again.'); + } + } else { + fancyDie('Please install the MySQLi extension and try again.'); + } + } else { + fancyDie('Set TINYIB_DBMODE to flatfile and enter in your MySQL settings in settings.php before migrating.'); + } + } else { + $text .= '

This tool currently only supports migration from a flat file database to MySQL. Your original database will not be deleted. If the migration fails, disable the tool and your board will be unaffected. See the README (alternate link) for instructions.

Start the migration

'; + } + } else { + fancyDie('Set TINYIB_DBMIGRATE to true in settings.php to use this feature.'); + } } } diff --git a/inc/database_mysql.php b/inc/database_mysql.php index 44f0e3e..34547ae 100644 --- a/inc/database_mysql.php +++ b/inc/database_mysql.php @@ -18,46 +18,12 @@ if (!$db_selected) { // Create the posts table if it does not exist if (mysql_num_rows(mysql_query("SHOW TABLES LIKE '" . TINYIB_DBPOSTS . "'")) == 0) { - mysql_query("CREATE TABLE `" . TINYIB_DBPOSTS . "` ( - `id` mediumint(7) unsigned NOT NULL auto_increment, - `parent` mediumint(7) unsigned NOT NULL, - `timestamp` int(20) NOT NULL, - `bumped` int(20) NOT NULL, - `ip` varchar(15) NOT NULL, - `name` varchar(75) NOT NULL, - `tripcode` varchar(10) NOT NULL, - `email` varchar(75) NOT NULL, - `nameblock` varchar(255) NOT NULL, - `subject` varchar(75) NOT NULL, - `message` text NOT NULL, - `password` varchar(255) NOT NULL, - `file` varchar(75) NOT NULL, - `file_hex` varchar(75) NOT NULL, - `file_original` varchar(255) NOT NULL, - `file_size` int(20) unsigned NOT NULL default '0', - `file_size_formatted` varchar(75) NOT NULL, - `image_width` smallint(5) unsigned NOT NULL default '0', - `image_height` smallint(5) unsigned NOT NULL default '0', - `thumb` varchar(255) NOT NULL, - `thumb_width` smallint(5) unsigned NOT NULL default '0', - `thumb_height` smallint(5) unsigned NOT NULL default '0', - PRIMARY KEY (`id`), - KEY `parent` (`parent`), - KEY `bumped` (`bumped`) - ) ENGINE=MyISAM"); + mysql_query($posts_sql); } // Create the bans table if it does not exist if (mysql_num_rows(mysql_query("SHOW TABLES LIKE '" . TINYIB_DBBANS . "'")) == 0) { - mysql_query("CREATE TABLE `" . TINYIB_DBBANS . "` ( - `id` mediumint(7) unsigned NOT NULL auto_increment, - `ip` varchar(15) NOT NULL, - `timestamp` int(20) NOT NULL, - `expire` int(20) NOT NULL, - `reason` text NOT NULL, - PRIMARY KEY (`id`), - KEY `ip` (`ip`) - ) ENGINE=MyISAM"); + mysql_query($bans_sql); } # Post Functions diff --git a/inc/database_mysqli.php b/inc/database_mysqli.php index 568dc0f..7806435 100644 --- a/inc/database_mysqli.php +++ b/inc/database_mysqli.php @@ -18,46 +18,12 @@ if (!$db_selected) { // Create the posts table if it does not exist if (mysqli_num_rows(mysqli_query($link, "SHOW TABLES LIKE '" . TINYIB_DBPOSTS . "'")) == 0) { - mysqli_query($link, "CREATE TABLE `" . TINYIB_DBPOSTS . "` ( - `id` mediumint(7) unsigned NOT NULL auto_increment, - `parent` mediumint(7) unsigned NOT NULL, - `timestamp` int(20) NOT NULL, - `bumped` int(20) NOT NULL, - `ip` varchar(15) NOT NULL, - `name` varchar(75) NOT NULL, - `tripcode` varchar(10) NOT NULL, - `email` varchar(75) NOT NULL, - `nameblock` varchar(255) NOT NULL, - `subject` varchar(75) NOT NULL, - `message` text NOT NULL, - `password` varchar(255) NOT NULL, - `file` varchar(75) NOT NULL, - `file_hex` varchar(75) NOT NULL, - `file_original` varchar(255) NOT NULL, - `file_size` int(20) unsigned NOT NULL default '0', - `file_size_formatted` varchar(75) NOT NULL, - `image_width` smallint(5) unsigned NOT NULL default '0', - `image_height` smallint(5) unsigned NOT NULL default '0', - `thumb` varchar(255) NOT NULL, - `thumb_width` smallint(5) unsigned NOT NULL default '0', - `thumb_height` smallint(5) unsigned NOT NULL default '0', - PRIMARY KEY (`id`), - KEY `parent` (`parent`), - KEY `bumped` (`bumped`) - ) ENGINE=MyISAM"); + mysqli_query($link, $posts_sql); } // Create the bans table if it does not exist if (mysqli_num_rows(mysqli_query($link, "SHOW TABLES LIKE '" . TINYIB_DBBANS . "'")) == 0) { - mysqli_query($link, "CREATE TABLE `" . TINYIB_DBBANS . "` ( - `id` mediumint(7) unsigned NOT NULL auto_increment, - `ip` varchar(15) NOT NULL, - `timestamp` int(20) NOT NULL, - `expire` int(20) NOT NULL, - `reason` text NOT NULL, - PRIMARY KEY (`id`), - KEY `ip` (`ip`) - ) ENGINE=MyISAM"); + mysqli_query($link, $bans_sql); } # Post Functions @@ -228,7 +194,7 @@ function allBans() { function insertBan($ban) { global $link; - mysqli_query($link, "INSERT INTO `" . TINYIB_DBBANS . "` (`ip`, `timestamp`, `expire`, `reason`) VALUES ('" . mysqli_real_escape_string($link, $ban['ip']) . "')"); + mysqli_query($link, "INSERT INTO `" . TINYIB_DBBANS . "` (`ip`, `timestamp`, `expire`, `reason`) VALUES ('" . mysqli_real_escape_string($link, $ban['ip']) . "', '" . time() . "', '" . mysqli_real_escape_string($link, $ban['expire']) . "', '" . mysqli_real_escape_string($link, $ban['reason']) . "')"); return mysqli_insert_id($link); } diff --git a/inc/defines.php b/inc/defines.php index 098d8b7..7af2f49 100644 --- a/inc/defines.php +++ b/inc/defines.php @@ -27,3 +27,6 @@ if (!defined('TINYIB_SWF')) { if (!defined('TINYIB_WEBM')) { define('TINYIB_WEBM', false); } +if (!defined('TINYIB_DBMIGRATE')) { + define('TINYIB_DBMIGRATE', false); +} diff --git a/inc/functions.php b/inc/functions.php index b1ea56a..27b0f97 100644 --- a/inc/functions.php +++ b/inc/functions.php @@ -3,6 +3,44 @@ if (!defined('TINYIB_BOARD')) { die(''); } +$posts_sql = "CREATE TABLE `" . TINYIB_DBPOSTS . "` ( + `id` mediumint(7) unsigned NOT NULL auto_increment, + `parent` mediumint(7) unsigned NOT NULL, + `timestamp` int(20) NOT NULL, + `bumped` int(20) NOT NULL, + `ip` varchar(15) NOT NULL, + `name` varchar(75) NOT NULL, + `tripcode` varchar(10) NOT NULL, + `email` varchar(75) NOT NULL, + `nameblock` varchar(255) NOT NULL, + `subject` varchar(75) NOT NULL, + `message` text NOT NULL, + `password` varchar(255) NOT NULL, + `file` varchar(75) NOT NULL, + `file_hex` varchar(75) NOT NULL, + `file_original` varchar(255) NOT NULL, + `file_size` int(20) unsigned NOT NULL default '0', + `file_size_formatted` varchar(75) NOT NULL, + `image_width` smallint(5) unsigned NOT NULL default '0', + `image_height` smallint(5) unsigned NOT NULL default '0', + `thumb` varchar(255) NOT NULL, + `thumb_width` smallint(5) unsigned NOT NULL default '0', + `thumb_height` smallint(5) unsigned NOT NULL default '0', + PRIMARY KEY (`id`), + KEY `parent` (`parent`), + KEY `bumped` (`bumped`) +) ENGINE=MyISAM"; + +$bans_sql = "CREATE TABLE `" . TINYIB_DBBANS . "` ( + `id` mediumint(7) unsigned NOT NULL auto_increment, + `ip` varchar(15) NOT NULL, + `timestamp` int(20) NOT NULL, + `expire` int(20) NOT NULL, + `reason` text NOT NULL, + PRIMARY KEY (`id`), + KEY `ip` (`ip`) +) ENGINE=MyISAM"; + function cleanString($string) { $search = array("<", ">"); $replace = array("<", ">"); diff --git a/inc/html.php b/inc/html.php index 020cc77..309daa6 100644 --- a/inc/html.php +++ b/inc/html.php @@ -379,7 +379,7 @@ function adminBar() { if (!$loggedin) { return $return; } - return '[Status] [' . (($isadmin) ? 'Bans] [' : '') . 'Moderate Post] [Raw Post] [' . (($isadmin) ? 'Rebuild All] [' : '') . 'Log Out] · ' . $return; + return '[Status] [' . (($isadmin) ? 'Bans] [' : '') . 'Moderate Post] [Raw Post] [' . (($isadmin) ? 'Rebuild All] [' : '') . (($isadmin && TINYIB_DBMIGRATE) ? 'Migrate Database] [' : '') . 'Log Out] · ' . $return; } function managePage($text, $onload = '') { diff --git a/settings.default.php b/settings.default.php index b8fe2e8..ac9c5ed 100644 --- a/settings.default.php +++ b/settings.default.php @@ -21,6 +21,7 @@ define('TINYIB_TRIPSEED', ""); // Enter some random text - Used when generating define('TINYIB_ADMINPASS', ""); // Text entered at the manage prompt to gain administrator access define('TINYIB_MODPASS', ""); // Moderators only have access to delete posts ["" to disable] define('TINYIB_DBMODE', "flatfile"); // Choose: flatfile / mysql / mysqli / sqlite (flatfile is not recommended for popular sites) +define('TINYIB_DBMIGRATE', false); // Enable database migration tool (see README for instructions) // Note: The following only apply when TINYIB_DBMODE is set to mysql or mysqli (recommended) define('TINYIB_DBHOST', "localhost");