PageRenderTime 60ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/forum/admin/db_update.php

https://github.com/veb/lifelitup
PHP | 2033 lines | 1488 code | 353 blank | 192 comment | 228 complexity | 8267c7830a37144095db33fa1a4570c4 MD5 | raw file
Possible License(s): BSD-3-Clause, GPL-3.0, GPL-2.0, LGPL-2.1

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /**
  3. * Database updating script.
  4. *
  5. * Updates the database to the latest version.
  6. *
  7. * @copyright (C) 2008-2009 PunBB, partially based on code (C) 2008-2009 FluxBB.org
  8. * @license http://www.gnu.org/licenses/gpl.html GPL version 2 or higher
  9. * @package PunBB
  10. */
  11. define('UPDATE_TO', '1.3.4');
  12. define('UPDATE_TO_DB_REVISION', 4);
  13. // The number of items to process per pageview (lower this if the update script times out during UTF-8 conversion)
  14. define('PER_PAGE', 300);
  15. define('MIN_MYSQL_VERSION', '4.1.2');
  16. // Make sure we are running at least PHP 4.3.0
  17. if (!function_exists('version_compare') || version_compare(PHP_VERSION, '4.3.0', '<'))
  18. exit('You are running PHP version '.PHP_VERSION.'. '.UPDATE_TO.' requires at least PHP 4.3.0 to run properly. You must upgrade your PHP installation before you can continue.');
  19. define('FORUM_ROOT', '../');
  20. // Attempt to load the configuration file config.php
  21. if (file_exists(FORUM_ROOT.'config.php'))
  22. include FORUM_ROOT.'config.php';
  23. if (defined('PUN'))
  24. define('FORUM', 1);
  25. // If FORUM isn't defined, config.php is missing or corrupt or we are outside the root directory
  26. if (!defined('FORUM'))
  27. exit('Cannot find config.php, are you sure it exists?');
  28. // Enable debug mode
  29. if (!defined('FORUM_DEBUG'))
  30. define('FORUM_DEBUG', 1);
  31. // Turn on full PHP error reporting
  32. error_reporting(E_ALL);
  33. // Turn off magic_quotes_runtime
  34. set_magic_quotes_runtime(0);
  35. // Turn off PHP time limit
  36. @set_time_limit(0);
  37. // If a cookie name is not specified in config.php, we use the default (forum_cookie)
  38. if (empty($cookie_name))
  39. $cookie_name = 'forum_cookie';
  40. // If the cache directory is not specified, we use the default setting
  41. if (!defined('FORUM_CACHE_DIR'))
  42. define('FORUM_CACHE_DIR', FORUM_ROOT.'cache/');
  43. // Load the functions script
  44. require FORUM_ROOT.'include/functions.php';
  45. // Load UTF-8 functions
  46. require FORUM_ROOT.'include/utf8/utf8.php';
  47. require FORUM_ROOT.'include/utf8/ucwords.php';
  48. require FORUM_ROOT.'include/utf8/trim.php';
  49. // Strip out "bad" UTF-8 characters
  50. forum_remove_bad_characters();
  51. // If the request_uri is invalid try fix it
  52. if (!defined('FORUM_IGNORE_REQUEST_URI'))
  53. forum_fix_request_uri();
  54. // Instruct DB abstraction layer that we don't want it to "SET NAMES". If we need to, we'll do it ourselves below.
  55. define('FORUM_NO_SET_NAMES', 1);
  56. // Load DB abstraction layer and try to connect
  57. require FORUM_ROOT.'include/dblayer/common_db.php';
  58. // Check current version
  59. $query = array(
  60. 'SELECT' => 'conf_value',
  61. 'FROM' => 'config',
  62. 'WHERE' => 'conf_name = \'o_cur_version\''
  63. );
  64. $result = $forum_db->query_build($query);
  65. $cur_version = $forum_db->result($result);
  66. if (version_compare($cur_version, '1.2', '<'))
  67. error('Version mismatch. The database \''.$db_name.'\' doesn\'t seem to be running a PunBB database schema supported by this update script.', __FILE__, __LINE__);
  68. // If we've already done charset conversion in a previous update, we have to do SET NAMES
  69. $forum_db->set_names(strpos($cur_version, '1.3') === 0 ? 'utf8' : 'latin1');
  70. // If MySQL, make sure it's at least 4.1.2
  71. if ($db_type == 'mysql' || $db_type == 'mysqli')
  72. {
  73. $mysql_info = $forum_db->get_version();
  74. if (version_compare($mysql_info['version'], MIN_MYSQL_VERSION, '<'))
  75. error('You are running MySQL version '.$mysql_version.'. PunBB '.UPDATE_TO.' requires at least MySQL '.MIN_MYSQL_VERSION.' to run properly. You must upgrade your MySQL installation before you can continue.');
  76. }
  77. // Get the forum config
  78. $query = array(
  79. 'SELECT' => '*',
  80. 'FROM' => 'config'
  81. );
  82. $result = $forum_db->query_build($query);
  83. while ($cur_config_item = $forum_db->fetch_row($result))
  84. $forum_config[$cur_config_item[0]] = $cur_config_item[1];
  85. // Check the database revision and the current version
  86. if (isset($forum_config['o_database_revision']) && $forum_config['o_database_revision'] >= UPDATE_TO_DB_REVISION && version_compare($forum_config['o_cur_version'], UPDATE_TO, '>='))
  87. error('Your database is already as up-to-date as this script can make it.');
  88. // If $base_url isn't set, use o_base_url from config
  89. if (!isset($base_url))
  90. $base_url = $forum_config['o_base_url'];
  91. // There's no $forum_user, but we need the style element
  92. // We default to Oxygen if the default style is invalid (a 1.2 to 1.3 upgrade most likely)
  93. if (file_exists(FORUM_ROOT.'style/'.$forum_config['o_default_style'].'/'.$forum_config['o_default_style'].'.php'))
  94. $forum_user['style'] = $forum_config['o_default_style'];
  95. else
  96. {
  97. $forum_user['style'] = 'Oxygen';
  98. $query = array(
  99. 'UPDATE' => 'config',
  100. 'SET' => 'conf_value = \'Oxygen\'',
  101. 'WHERE' => 'conf_name = \'o_default_style\''
  102. );
  103. $forum_db->query_build($query) or error(__FILE__, __LINE__);
  104. }
  105. // Make sure the default language exists
  106. // We default to English if the default language is invalid (a 1.2 to 1.3 upgrade most likely)
  107. if (!file_exists(FORUM_ROOT.'lang/'.$forum_config['o_default_lang'].'/common.php'))
  108. {
  109. $query = array(
  110. 'UPDATE' => 'config',
  111. 'SET' => 'conf_value = \'English\'',
  112. 'WHERE' => 'conf_name = \'o_default_lang\''
  113. );
  114. $forum_db->query_build($query) or error(__FILE__, __LINE__);
  115. }
  116. //
  117. // Determines whether $str is UTF-8 encoded or not
  118. //
  119. function seems_utf8($str)
  120. {
  121. $str_len = strlen($str);
  122. for ($i = 0; $i < $str_len; ++$i)
  123. {
  124. if (ord($str[$i]) < 0x80) continue; # 0bbbbbbb
  125. else if ((ord($str[$i]) & 0xE0) == 0xC0) $n=1; # 110bbbbb
  126. else if ((ord($str[$i]) & 0xF0) == 0xE0) $n=2; # 1110bbbb
  127. else if ((ord($str[$i]) & 0xF8) == 0xF0) $n=3; # 11110bbb
  128. else if ((ord($str[$i]) & 0xFC) == 0xF8) $n=4; # 111110bb
  129. else if ((ord($str[$i]) & 0xFE) == 0xFC) $n=5; # 1111110b
  130. else return false; # Does not match any model
  131. for ($j = 0; $j < $n; ++$j) # n bytes matching 10bbbbbb follow ?
  132. {
  133. if ((++$i == strlen($str)) || ((ord($str[$i]) & 0xC0) != 0x80))
  134. return false;
  135. }
  136. }
  137. return true;
  138. }
  139. //
  140. // Translates the number from an HTML numeric entity into an UTF-8 character
  141. //
  142. function dcr2utf8($src)
  143. {
  144. $dest = '';
  145. if ($src < 0)
  146. return false;
  147. else if ($src <= 0x007f)
  148. $dest .= chr($src);
  149. else if ($src <= 0x07ff)
  150. {
  151. $dest .= chr(0xc0 | ($src >> 6));
  152. $dest .= chr(0x80 | ($src & 0x003f));
  153. }
  154. else if ($src == 0xFEFF)
  155. {
  156. // nop -- zap the BOM
  157. }
  158. else if ($src >= 0xD800 && $src <= 0xDFFF)
  159. {
  160. // found a surrogate
  161. return false;
  162. }
  163. else if ($src <= 0xffff)
  164. {
  165. $dest .= chr(0xe0 | ($src >> 12));
  166. $dest .= chr(0x80 | (($src >> 6) & 0x003f));
  167. $dest .= chr(0x80 | ($src & 0x003f));
  168. }
  169. else if ($src <= 0x10ffff)
  170. {
  171. $dest .= chr(0xf0 | ($src >> 18));
  172. $dest .= chr(0x80 | (($src >> 12) & 0x3f));
  173. $dest .= chr(0x80 | (($src >> 6) & 0x3f));
  174. $dest .= chr(0x80 | ($src & 0x3f));
  175. }
  176. else
  177. {
  178. // out of range
  179. return false;
  180. }
  181. return $dest;
  182. }
  183. //
  184. // Attemts to convert $str from $old_charset to UTF-8. Also converts HTML entities (including numeric entities) to UTF-8 characters.
  185. //
  186. function convert_to_utf8(&$str, $old_charset)
  187. {
  188. if ($str == '')
  189. return false;
  190. $save = $str;
  191. // Replace literal entities (for non-UTF-8 compliant html_entity_encode)
  192. if (version_compare(PHP_VERSION, '5.0.0', '<') && $old_charset == 'ISO-8859-1' || $old_charset == 'ISO-8859-15')
  193. $str = html_entity_decode($str, ENT_QUOTES, $old_charset);
  194. if (!seems_utf8($str))
  195. {
  196. if ($old_charset == 'ISO-8859-1')
  197. $str = utf8_encode($str);
  198. else if (function_exists('iconv'))
  199. $str = iconv($old_charset, 'UTF-8', $str);
  200. else if (function_exists('mb_convert_encoding'))
  201. $str = mb_convert_encoding($str, 'UTF-8', $old_charset);
  202. }
  203. // Replace literal entities (for UTF-8 compliant html_entity_encode)
  204. if (version_compare(PHP_VERSION, '5.0.0', '>='))
  205. $str = html_entity_decode($str, ENT_QUOTES, 'UTF-8');
  206. // Replace numeric entities
  207. $str = preg_replace_callback('/&#([0-9]+);/', 'utf8_callback_1', $str);
  208. $str = preg_replace_callback('/&#x([a-f0-9]+);/i', 'utf8_callback_2', $str);
  209. return ($save != $str);
  210. }
  211. function utf8_callback_1($matches)
  212. {
  213. return dcr2utf8($matches[1]);
  214. }
  215. function utf8_callback_2($matches)
  216. {
  217. return dcr2utf8(hexdec($matches[1]));
  218. }
  219. //
  220. // Tries to determine whether post data in the database is UTF-8 encoded or not
  221. //
  222. function db_seems_utf8()
  223. {
  224. global $db_type, $forum_db;
  225. $seems_utf8 = true;
  226. $query = array(
  227. 'SELECT' => 'MIN(id), MAX(id), COUNT(id)',
  228. 'FROM' => 'posts'
  229. );
  230. $result = $forum_db->query_build($query) or error(__FILE__, __LINE__);
  231. list($min_id, $max_id, $count_id) = $forum_db->fetch_row($result);
  232. if ($count_id == 0)
  233. return false;
  234. // Get a random soup of data and check if it appears to be UTF-8
  235. for ($i = 0; $i < 100; ++$i)
  236. {
  237. $id = ($i == 0) ? $min_id : (($i == 1) ? $max_id : rand($min_id, $max_id));
  238. $query = array(
  239. 'SELECT' => 'p.message, p.poster, t.subject, f.forum_name',
  240. 'FROM' => 'posts AS p',
  241. 'JOINS' => array(
  242. array(
  243. 'INNER JOIN' => 'topics AS t',
  244. 'ON' => 't.id = p.topic_id'
  245. ),
  246. array(
  247. 'INNER JOIN' => 'forums AS f',
  248. 'ON' => 'f.id = t.forum_id'
  249. )
  250. ),
  251. 'WHERE' => 'p.id >= '.$id,
  252. 'LIMIT' => '1'
  253. );
  254. $result = $forum_db->query_build($query) or error(__FILE__, __LINE__);
  255. $random_row = $forum_db->fetch_row($result);
  256. if (!seems_utf8($random_row[0].$random_row[1].$random_row[2].$random_row[3]))
  257. {
  258. $seems_utf8 = false;
  259. break;
  260. }
  261. }
  262. return $seems_utf8;
  263. }
  264. //
  265. // Safely converts text type columns into utf8 (MySQL only)
  266. // Function based on update_convert_table_utf8() from the Drupal project (http://drupal.org/)
  267. //
  268. function convert_table_utf8($table)
  269. {
  270. global $forum_db;
  271. $types = array(
  272. 'char' => 'binary',
  273. 'varchar' => 'varbinary',
  274. 'tinytext' => 'tinyblob',
  275. 'mediumtext' => 'mediumblob',
  276. 'text' => 'blob',
  277. 'longtext' => 'longblob'
  278. );
  279. // Set table default charset to utf8
  280. $forum_db->query('ALTER TABLE `'.$table.'` CHARACTER SET utf8') or error(__FILE__, __LINE__);
  281. // Find out which columns need converting and build SQL statements
  282. $result = $forum_db->query('SHOW FULL COLUMNS FROM `'.$table.'`') or error(__FILE__, __LINE__);
  283. while ($cur_column = $forum_db->fetch_assoc($result))
  284. {
  285. list($type) = explode('(', $cur_column['Type']);
  286. if (isset($types[$type]) && strpos($cur_column['Collation'], 'utf8') === false)
  287. {
  288. $allow_null = ($cur_column['Null'] == 'YES');
  289. $forum_db->alter_field($table, $cur_column['Field'], preg_replace('/'.$type.'/i', $types[$type], $cur_column['Type']), $allow_null, $cur_column['Default']);
  290. $forum_db->alter_field($table, $cur_column['Field'], $cur_column['Type'].' CHARACTER SET utf8', $allow_null, $cur_column['Default']);
  291. }
  292. }
  293. }
  294. header('Content-type: text/html; charset=utf-8');
  295. // Empty all output buffers and stop buffering
  296. while (@ob_end_clean());
  297. $stage = isset($_GET['stage']) ? $_GET['stage'] : '';
  298. $old_charset = isset($_GET['req_old_charset']) ? str_replace('ISO8859', 'ISO-8859', strtoupper($_GET['req_old_charset'])) : 'ISO-8859-1';
  299. $start_at = isset($_GET['start_at']) ? intval($_GET['start_at']) : 0;
  300. $query_str = '';
  301. switch ($stage)
  302. {
  303. // Show form
  304. case '':
  305. $db_seems_utf8 = db_seems_utf8();
  306. ?>
  307. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  308. <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" dir="ltr">
  309. <head>
  310. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  311. <title>PunBB Database Update</title>
  312. <?php
  313. // Include the stylesheets
  314. require FORUM_ROOT.'style/'.$forum_user['style'].'/'.$forum_user['style'].'.php';
  315. ?>
  316. <script type="text/javascript" src="<?php echo $base_url ?>/include/js/common.js"></script>
  317. </head>
  318. <body>
  319. <div id="brd-update" class="brd-page">
  320. <div id="brd-wrap" class="brd">
  321. <div id="brd-head" class="gen-content">
  322. <p id="brd-title"><strong>PunBB Database Update</strong></p>
  323. <p id="brd-desc">Update database tables of current installation</p>
  324. </div>
  325. <div id="brd-main" class="main basic">
  326. <div class="main-head">
  327. <h1 class="hn"><span>PunBB Database Update: Perform update of database tables</span></h1>
  328. </div>
  329. <div class="main-content frm">
  330. <div class="ct-box info-box">
  331. <ul class="spaced">
  332. <li class="warn"><span><strong>WARNING!</strong> This script will update your PunBB forum database. The update procedure might take anything from a few seconds to a few minutes (or in extreme cases, hours) depending on the speed of the server, the size of the forum database and the number of changes required.</span></li>
  333. <li><span>Do not forget to make a backup of the database before continuing.</span></li>
  334. <li><span>Did you read the update instructions in the documentation? If not, start there.</span></li>
  335. <?php
  336. if (strpos($cur_version, '1.2') === 0 && (!$db_seems_utf8 || isset($_GET['force'])))
  337. {
  338. if (!function_exists('iconv') && !function_exists('mb_convert_encoding'))
  339. {
  340. ?>
  341. <li class="important"><strong>IMPORTANT!</strong> PunBB has detected that this PHP environment does not have support for the encoding mechanisms required to do UTF-8 conversion from character sets other than ISO-8859-1. What this means is that if the current character set is not ISO-8859-1, PunBB won't be able to convert your forum database to UTF-8 and you will have to do it manually. Instructions for doing manual charset conversion can be found in the update instructions.</span></li>
  342. <?php
  343. }
  344. }
  345. $current_url = get_current_url();
  346. if (strpos($cur_version, '1.2') === 0 && $db_seems_utf8 && !isset($_GET['force']))
  347. {
  348. ?>
  349. <li class="important"><span><strong>IMPORTANT!</strong> Based on a random selection of 100 posts, topic subjects, usernames and forum names from the database, it appears as if text in the database is currently UTF-8 encoded. This is a good thing. Based on this, the update process will not attempt to do charset conversion. If you have reason to believe that the charset conversion is required nonetheless, you can <a href="<?php echo $current_url.((substr_count($current_url, '?') == 1) ? '&amp;' : '?').'force=1' ?>">force the conversion to run</a>.</span></li>
  350. <?php
  351. }
  352. ?>
  353. </ul>
  354. </div>
  355. <form class="frm-form" method="get" accept-charset="utf-8" action="<?php echo $current_url ?>">
  356. <div class="hidden">
  357. <input type="hidden" name="stage" value="start" />
  358. </div>
  359. <?php
  360. if (strpos($cur_version, '1.2') === 0 && (!$db_seems_utf8 || isset($_GET['force'])))
  361. {
  362. ?>
  363. <div class="ct-box info-box">
  364. <p class="important"><strong>Enable conversion:</strong> When enabled this update script will, after it has made the required structural changes to the database, convert all text in the database from the current character set to UTF-8. This conversion is required if you're upgrading from PunBB 1.2 and you are not currently using an UTF-8 language pack.</p>
  365. <p class="important"><strong>Current character set:</strong> If the primary language in your forum is English, you can leave this at the default value. However, if your forum is non-English, you should enter the character set of the primary language pack used in the forum.</p>
  366. </div>
  367. <div id="req-msg" class="req-warn ct-box error-box">
  368. <p class="important"><strong>Important!</strong> All fields labelled <em>(Required)</em> must be completed before submitting this form.</p>
  369. </div>
  370. <fieldset class="frm-group group1">
  371. <legend class="group-legend"><span>Charset conversion</span></legend>
  372. <div class="sf-set set1">
  373. <div class="sf-box checkbox">
  374. <span class="fld-input"><input type="checkbox" id="fld1" name="convert_charset" value="1" checked="checked" /></span>
  375. <label for="fld1"><span>Enable conversion:</span> Perform database charset conversion.</label>
  376. </div>
  377. </div>
  378. <div class="sf-set set2">
  379. <div class="sf-box text required">
  380. <label for="fld2"><span>Current character set: <em>(Required)</em></span> <small>Accept default for English forums otherwise the character set of the primary langauge pack.</small></label><br />
  381. <span class="fld-input"><input type="text" id="fld2" name="req_old_charset" size="12" maxlength="20" value="ISO-8859-1" /></span>
  382. </div>
  383. </div>
  384. </fieldset>
  385. <?php
  386. }
  387. ?>
  388. <div class="frm-buttons">
  389. <span class="submit"><input type="submit" name="start" value="Start update" /></span>
  390. </div>
  391. </form>
  392. </div>
  393. </div>
  394. </div>
  395. </div>
  396. </body>
  397. </html>
  398. <?php
  399. break;
  400. // Start by updating the database structure
  401. case 'start':
  402. // Put back dropped search tables
  403. if (!$forum_db->table_exists('search_cache') && ($db_type == 'mysql' || $db_type == 'mysqli'))
  404. {
  405. $schema = array(
  406. 'FIELDS' => array(
  407. 'id' => array(
  408. 'datatype' => 'INT(10) UNSIGNED',
  409. 'allow_null' => false,
  410. 'default' => '0'
  411. ),
  412. 'ident' => array(
  413. 'datatype' => 'VARCHAR(200)',
  414. 'allow_null' => false,
  415. 'default' => '\'\''
  416. ),
  417. 'search_data' => array(
  418. 'datatype' => 'TEXT',
  419. 'allow_null' => true
  420. )
  421. ),
  422. 'PRIMARY KEY' => array('id'),
  423. 'INDEXES' => array(
  424. 'ident_idx' => array('ident(8)')
  425. )
  426. );
  427. $forum_db->create_table('search_cache', $schema);
  428. $schema = array(
  429. 'FIELDS' => array(
  430. 'post_id' => array(
  431. 'datatype' => 'INT(10) UNSIGNED',
  432. 'allow_null' => false,
  433. 'default' => '0'
  434. ),
  435. 'word_id' => array(
  436. 'datatype' => 'INT(10) UNSIGNED',
  437. 'allow_null' => false,
  438. 'default' => '0'
  439. ),
  440. 'subject_match' => array(
  441. 'datatype' => 'TINYINT(1)',
  442. 'allow_null' => false,
  443. 'default' => '0'
  444. )
  445. ),
  446. 'INDEXES' => array(
  447. 'word_id_idx' => array('word_id'),
  448. 'post_id_idx' => array('post_id')
  449. )
  450. );
  451. $forum_db->create_table('search_matches', $schema);
  452. $schema = array(
  453. 'FIELDS' => array(
  454. 'id' => array(
  455. 'datatype' => 'SERIAL',
  456. 'allow_null' => false
  457. ),
  458. 'word' => array(
  459. 'datatype' => 'VARCHAR(20)',
  460. 'allow_null' => false,
  461. 'default' => '\'\'',
  462. 'collation' => 'bin'
  463. )
  464. ),
  465. 'PRIMARY KEY' => array('word'),
  466. 'INDEXES' => array(
  467. 'id_idx' => array('id')
  468. )
  469. );
  470. $forum_db->create_table('search_words', $schema);
  471. }
  472. // Add the extensions table if it doesn't already exist
  473. if (!$forum_db->table_exists('extensions'))
  474. {
  475. $schema = array(
  476. 'FIELDS' => array(
  477. 'id' => array(
  478. 'datatype' => 'VARCHAR(150)',
  479. 'allow_null' => false,
  480. 'default' => '\'\''
  481. ),
  482. 'title' => array(
  483. 'datatype' => 'VARCHAR(255)',
  484. 'allow_null' => false,
  485. 'default' => '\'\''
  486. ),
  487. 'version' => array(
  488. 'datatype' => 'VARCHAR(25)',
  489. 'allow_null' => false,
  490. 'default' => '\'\''
  491. ),
  492. 'description' => array(
  493. 'datatype' => 'TEXT',
  494. 'allow_null' => true
  495. ),
  496. 'author' => array(
  497. 'datatype' => 'VARCHAR(50)',
  498. 'allow_null' => false,
  499. 'default' => '\'\''
  500. ),
  501. 'uninstall' => array(
  502. 'datatype' => 'TEXT',
  503. 'allow_null' => true
  504. ),
  505. 'uninstall_note' => array(
  506. 'datatype' => 'TEXT',
  507. 'allow_null' => true
  508. ),
  509. 'disabled' => array(
  510. 'datatype' => 'TINYINT(1)',
  511. 'allow_null' => false,
  512. 'default' => '0'
  513. ),
  514. 'dependencies' => array(
  515. 'datatype' => 'VARCHAR(255)',
  516. 'allow_null' => false,
  517. 'default' => '\'\''
  518. )
  519. ),
  520. 'PRIMARY KEY' => array('id')
  521. );
  522. $forum_db->create_table('extensions', $schema);
  523. }
  524. // Make sure the collation on "word" in the search_words table is utf8_bin
  525. if ($db_type == 'mysql' || $db_type == 'mysqli')
  526. {
  527. $result = $forum_db->query('SHOW FULL COLUMNS FROM '.$forum_db->prefix.'search_words') or error(__FILE__, __LINE__);
  528. while ($cur_column = $forum_db->fetch_assoc($result))
  529. {
  530. if ($cur_column['Field'] === 'word')
  531. {
  532. if ($cur_column['Collation'] !== 'utf8_bin')
  533. $forum_db->alter_field('search_words', 'word', 'VARCHAR(20) CHARACTER SET utf8 COLLATE utf8_bin', false, '');
  534. break;
  535. }
  536. }
  537. }
  538. // Add uninstall_note field to extensions
  539. $forum_db->add_field('extensions', 'uninstall_note', 'TEXT', true, null, 'uninstall');
  540. // Drop uninstall_notes (plural) field
  541. $forum_db->drop_field('extensions', 'uninstall_notes');
  542. // Add disabled field to extensions
  543. $forum_db->add_field('extensions', 'disabled', 'TINYINT(1)', false, 0, 'uninstall_note');
  544. // Add dependencies field to extensions
  545. $forum_db->add_field('extensions', 'dependencies', 'VARCHAR(255)', false, '', 'disabled');
  546. // Add the extension_hooks table
  547. if (!$forum_db->table_exists('extension_hooks'))
  548. {
  549. $schema = array(
  550. 'FIELDS' => array(
  551. 'id' => array(
  552. 'datatype' => 'VARCHAR(150)',
  553. 'allow_null' => false,
  554. 'default' => '\'\''
  555. ),
  556. 'extension_id' => array(
  557. 'datatype' => 'VARCHAR(50)',
  558. 'allow_null' => false,
  559. 'default' => '\'\''
  560. ),
  561. 'code' => array(
  562. 'datatype' => 'TEXT',
  563. 'allow_null' => true
  564. ),
  565. 'installed' => array(
  566. 'datatype' => 'INT(10) UNSIGNED',
  567. 'allow_null' => false,
  568. 'default' => '0'
  569. ),
  570. 'priority' => array(
  571. 'datatype' => 'TINYINT(1) UNSIGNED',
  572. 'allow_null' => false,
  573. 'default' => '5'
  574. )
  575. ),
  576. 'PRIMARY KEY' => array('id', 'extension_id')
  577. );
  578. $forum_db->create_table('extension_hooks', $schema);
  579. }
  580. // Add priority field to extension_hooks
  581. $forum_db->add_field('extension_hooks', 'priority', 'TINYINT(1)', false, 5, 'installed');
  582. // Extend id field in extension_hooks to 150
  583. $forum_db->alter_field('extension_hooks', 'id', 'VARCHAR(150)', false, '');
  584. // Make all e-mail fields VARCHAR(80)
  585. $forum_db->alter_field('bans', 'email', 'VARCHAR(80)', true);
  586. $forum_db->alter_field('posts', 'poster_email', 'VARCHAR(80)', true);
  587. $forum_db->alter_field('users', 'email', 'VARCHAR(80)', false, '');
  588. $forum_db->alter_field('users', 'jabber', 'VARCHAR(80)', true);
  589. $forum_db->alter_field('users', 'msn', 'VARCHAR(80)', true);
  590. $forum_db->alter_field('users', 'activate_string', 'VARCHAR(80)', true);
  591. // Remove NOT NULL from TEXT fields for consistency. See http://dev.punbb.org/changeset/596
  592. $forum_db->alter_field('posts', 'message', 'TEXT', true);
  593. $forum_db->alter_field('reports', 'message', 'TEXT', true);
  594. // Drop fulltext indexes (should only apply to SVN installs)
  595. if ($db_type == 'mysql' || $db_type == 'mysqli')
  596. {
  597. $forum_db->drop_index('topics', 'subject_idx');
  598. $forum_db->drop_index('posts', 'message_idx');
  599. }
  600. // Make all IP fields VARCHAR(39) to support IPv6
  601. $forum_db->alter_field('posts', 'poster_ip', 'VARCHAR(39)', true);
  602. $forum_db->alter_field('users', 'registration_ip', 'VARCHAR(39)', false, '0.0.0.0');
  603. // Add the DST option to the users table
  604. $forum_db->add_field('users', 'dst', 'TINYINT(1)', false, 0, 'timezone');
  605. // Add the salt field to the users table
  606. $forum_db->add_field('users', 'salt', 'VARCHAR(12)', true, null, 'password');
  607. // Add the access_keys field to the users table
  608. $forum_db->add_field('users', 'access_keys', 'TINYINT(1)', false, 0, 'show_sig');
  609. // Add the CSRF token field to the online table
  610. $forum_db->add_field('online', 'csrf_token', 'VARCHAR(40)', false, '', null);
  611. // Add the prev_url field to the online table
  612. $forum_db->add_field('online', 'prev_url', 'VARCHAR(255)', true, null, null);
  613. // Add the last_post field to the online table
  614. $forum_db->add_field('online', 'last_post', 'INT(10) UNSIGNED', true, null, null);
  615. // Add the last_search field to the online table
  616. $forum_db->add_field('online', 'last_search', 'INT(10) UNSIGNED', true, null, null);
  617. // Drop use_avatar column from users table
  618. $forum_db->drop_field('users', 'use_avatar');
  619. // Drop save_pass column from users table
  620. $forum_db->drop_field('users', 'save_pass');
  621. // Drop g_edit_subjects_interval column from groups table
  622. $forum_db->drop_field('groups', 'g_edit_subjects_interval');
  623. $new_config = array();
  624. // Add quote depth option
  625. if (!array_key_exists('o_quote_depth', $forum_config))
  626. $new_config[] = '\'o_quote_depth\', \'3\'';
  627. // Add database revision number
  628. if (!array_key_exists('o_database_revision', $forum_config))
  629. $new_config[] = '\'o_database_revision\', \'0\'';
  630. // Add default email setting option
  631. if (!array_key_exists('o_default_email_setting', $forum_config))
  632. $new_config[] = '\'o_default_email_setting\', \'1\'';
  633. // Make sure we have o_additional_navlinks (was added in 1.2.1)
  634. if (!array_key_exists('o_additional_navlinks', $forum_config))
  635. $new_config[] = '\'o_additional_navlinks\', \'\'';
  636. // Insert new config options o_sef
  637. if (!array_key_exists('o_sef', $forum_config))
  638. $new_config[] = '\'o_sef\', \'Default\'';
  639. // Insert new config option o_topic_views
  640. if (!array_key_exists('o_topic_views', $forum_config))
  641. $new_config[] = '\'o_topic_views\', \'1\'';
  642. // Insert new config option o_signatures
  643. if (!array_key_exists('o_signatures', $forum_config))
  644. $new_config[] = '\'o_signatures\', \'1\'';
  645. // Insert new config option o_smtp_ssl
  646. if (!array_key_exists('o_smtp_ssl', $forum_config))
  647. $new_config[] = '\'o_smtp_ssl\', \'0\'';
  648. // Insert new config option o_check_for_updates
  649. if (!array_key_exists('o_check_for_updates', $forum_config))
  650. {
  651. $check_for_updates = (function_exists('curl_init') || function_exists('fsockopen') || in_array(strtolower(@ini_get('allow_url_fopen')), array('on', 'true', '1'))) ? 1 : 0;
  652. $new_config[] = '\'o_check_for_updates\', \''.$check_for_updates.'\'';
  653. }
  654. // Insert new config option o_check_for_version
  655. if (!array_key_exists('o_check_for_versions', $forum_config))
  656. {
  657. $o_check_for_versions = array_key_exists('o_check_for_updates', $forum_config) ? $forum_config['o_check_for_updates'] : $check_for_updates;
  658. $new_config[] = '\'o_check_for_versions\', \''.$o_check_for_versions.'\'';
  659. }
  660. // Insert new config option o_announcement_heading
  661. if (!array_key_exists('o_announcement_heading', $forum_config))
  662. $new_config[] = '\'o_announcement_heading\', \'\'';
  663. // Insert new config option o_default_dst
  664. if (!array_key_exists('o_default_dst', $forum_config))
  665. $new_config[] = '\'o_default_dst\', \'0\'';
  666. if (!empty($new_config))
  667. {
  668. $query = array(
  669. 'INSERT' => 'conf_name, conf_value',
  670. 'INTO' => 'config',
  671. 'VALUES' => $new_config
  672. );
  673. $forum_db->query_build($query) or error(__FILE__, __LINE__);
  674. }
  675. unset($new_config);
  676. // Server timezone is now simply the default timezone
  677. if (!array_key_exists('o_default_timezone', $forum_config))
  678. {
  679. $query = array(
  680. 'UPDATE' => 'config',
  681. 'SET' => 'conf_name = \'o_default_timezone\'',
  682. 'WHERE' => 'conf_name = \'o_server_timezone\''
  683. );
  684. $forum_db->query_build($query) or error(__FILE__, __LINE__);
  685. }
  686. // Increase visit timeout to 30 minutes (only if it hasn't been changed from the default)
  687. if ($forum_config['o_timeout_visit'] == '600')
  688. {
  689. $query = array(
  690. 'UPDATE' => 'config',
  691. 'SET' => 'conf_value = \'1800\'',
  692. 'WHERE' => 'conf_name = \'o_timeout_visit\''
  693. );
  694. $forum_db->query_build($query) or error(__FILE__, __LINE__);
  695. }
  696. // Remove obsolete g_post_polls permission from groups table
  697. $forum_db->drop_field('groups', 'g_post_polls');
  698. // Make room for multiple moderator groups
  699. if (!$forum_db->field_exists('groups', 'g_moderator'))
  700. {
  701. // Add g_moderator column to groups table
  702. $forum_db->add_field('groups', 'g_moderator', 'TINYINT(1)', false, 0, 'g_user_title');
  703. // Give the moderator group moderator privileges
  704. $query = array(
  705. 'UPDATE' => 'groups',
  706. 'SET' => 'g_moderator = 1',
  707. 'WHERE' => 'g_id = 2'
  708. );
  709. $forum_db->query_build($query) or error(__FILE__, __LINE__);
  710. // Shuffle the group IDs around a bit
  711. $query = array(
  712. 'SELECT' => 'MAX(g_id) + 1',
  713. 'FROM' => 'groups'
  714. );
  715. $result = $forum_db->query_build($query) or error(__FILE__, __LINE__);
  716. $temp_id = $forum_db->result($result);
  717. $query = array(
  718. 'UPDATE' => 'groups',
  719. 'SET' => 'g_id='.$temp_id,
  720. 'WHERE' => 'g_id=2'
  721. );
  722. $forum_db->query_build($query) or error(__FILE__, __LINE__);
  723. $query = array(
  724. 'UPDATE' => 'groups',
  725. 'SET' => 'g_id=2',
  726. 'WHERE' => 'g_id=3'
  727. );
  728. $forum_db->query_build($query) or error(__FILE__, __LINE__);
  729. $query = array(
  730. 'UPDATE' => 'groups',
  731. 'SET' => 'g_id=3',
  732. 'WHERE' => 'g_id=4'
  733. );
  734. $forum_db->query_build($query) or error(__FILE__, __LINE__);
  735. $query = array(
  736. 'UPDATE' => 'groups',
  737. 'SET' => 'g_id=4',
  738. 'WHERE' => 'g_id='.$temp_id
  739. );
  740. $forum_db->query_build($query) or error(__FILE__, __LINE__);
  741. $query = array(
  742. 'UPDATE' => 'users',
  743. 'SET' => 'group_id='.$temp_id,
  744. 'WHERE' => 'group_id=2'
  745. );
  746. $forum_db->query_build($query) or error(__FILE__, __LINE__);
  747. $query = array(
  748. 'UPDATE' => 'users',
  749. 'SET' => 'group_id=2',
  750. 'WHERE' => 'group_id=3'
  751. );
  752. $forum_db->query_build($query) or error(__FILE__, __LINE__);
  753. $query = array(
  754. 'UPDATE' => 'users',
  755. 'SET' => 'group_id=3',
  756. 'WHERE' => 'group_id=4'
  757. );
  758. $forum_db->query_build($query) or error(__FILE__, __LINE__);
  759. $query = array(
  760. 'UPDATE' => 'users',
  761. 'SET' => 'group_id=4',
  762. 'WHERE' => 'group_id='.$temp_id
  763. );
  764. $forum_db->query_build($query) or error(__FILE__, __LINE__);
  765. $query = array(
  766. 'UPDATE' => 'forum_perms',
  767. 'SET' => 'group_id='.$temp_id,
  768. 'WHERE' => 'group_id=2'
  769. );
  770. $forum_db->query_build($query) or error(__FILE__, __LINE__);
  771. $query = array(
  772. 'UPDATE' => 'forum_perms',
  773. 'SET' => 'group_id=2',
  774. 'WHERE' => 'group_id=3'
  775. );
  776. $forum_db->query_build($query) or error(__FILE__, __LINE__);
  777. $query = array(
  778. 'UPDATE' => 'forum_perms',
  779. 'SET' => 'group_id=3',
  780. 'WHERE' => 'group_id=4'
  781. );
  782. $forum_db->query_build($query) or error(__FILE__, __LINE__);
  783. $query = array(
  784. 'UPDATE' => 'forum_perms',
  785. 'SET' => 'group_id=4',
  786. 'WHERE' => 'group_id='.$temp_id
  787. );
  788. $forum_db->query_build($query) or error(__FILE__, __LINE__);
  789. // Update the default usergroup if it uses the old ID for the members group
  790. $query = array(
  791. 'UPDATE' => 'config',
  792. 'SET' => 'conf_value = \'3\'',
  793. 'WHERE' => 'conf_name = \'o_default_user_group\' and conf_value = \'4\''
  794. );
  795. $forum_db->query_build($query) or error(__FILE__, __LINE__);
  796. }
  797. // Replace obsolete p_mod_edit_users config setting with new per-group permission
  798. if (array_key_exists('p_mod_edit_users', $forum_config))
  799. {
  800. $query = array(
  801. 'DELETE' => 'config',
  802. 'WHERE' => 'conf_name = \'p_mod_edit_users\''
  803. );
  804. $forum_db->query_build($query) or error(__FILE__, __LINE__);
  805. $forum_db->add_field('groups', 'g_mod_edit_users', 'TINYINT(1)', false, 0, 'g_moderator');
  806. $query = array(
  807. 'UPDATE' => 'groups',
  808. 'SET' => 'g_mod_edit_users = '.$forum_config['p_mod_edit_users'],
  809. 'WHERE' => 'g_moderator = 1'
  810. );
  811. $forum_db->query_build($query) or error(__FILE__, __LINE__);
  812. }
  813. // Replace obsolete p_mod_rename_users config setting with new per-group permission
  814. if (array_key_exists('p_mod_rename_users', $forum_config))
  815. {
  816. $query = array(
  817. 'DELETE' => 'config',
  818. 'WHERE' => 'conf_name = \'p_mod_rename_users\''
  819. );
  820. $forum_db->query_build($query) or error(__FILE__, __LINE__);
  821. $forum_db->add_field('groups', 'g_mod_rename_users', 'TINYINT(1)', false, 0, 'g_mod_edit_users');
  822. $query = array(
  823. 'UPDATE' => 'groups',
  824. 'SET' => 'g_mod_rename_users = '.$forum_config['p_mod_rename_users'],
  825. 'WHERE' => 'g_moderator = 1'
  826. );
  827. $forum_db->query_build($query) or error(__FILE__, __LINE__);
  828. }
  829. // Replace obsolete p_mod_change_passwords config setting with new per-group permission
  830. if (array_key_exists('p_mod_change_passwords', $forum_config))
  831. {
  832. $query = array(
  833. 'DELETE' => 'config',
  834. 'WHERE' => 'conf_name = \'p_mod_change_passwords\''
  835. );
  836. $forum_db->query_build($query) or error(__FILE__, __LINE__);
  837. $forum_db->add_field('groups', 'g_mod_change_passwords', 'TINYINT(1)', false, 0, 'g_mod_rename_users');
  838. $query = array(
  839. 'UPDATE' => 'groups',
  840. 'SET' => 'g_mod_change_passwords = '.$forum_config['p_mod_change_passwords'],
  841. 'WHERE' => 'g_moderator = 1'
  842. );
  843. $forum_db->query_build($query) or error(__FILE__, __LINE__);
  844. }
  845. // Replace obsolete p_mod_ban_users config setting with new per-group permission
  846. if (array_key_exists('p_mod_ban_users', $forum_config))
  847. {
  848. $query = array(
  849. 'DELETE' => 'config',
  850. 'WHERE' => 'conf_name = \'p_mod_ban_users\''
  851. );
  852. $forum_db->query_build($query) or error(__FILE__, __LINE__);
  853. $forum_db->add_field('groups', 'g_mod_ban_users', 'TINYINT(1)', false, 0, 'g_mod_change_passwords');
  854. $query = array(
  855. 'UPDATE' => 'groups',
  856. 'SET' => 'g_mod_ban_users = '.$forum_config['p_mod_ban_users'],
  857. 'WHERE' => 'g_moderator = 1'
  858. );
  859. $forum_db->query_build($query) or error(__FILE__, __LINE__);
  860. }
  861. // We need to add a unique index to avoid users having multiple rows in the online table
  862. if (!$forum_db->index_exists('online', 'user_id_ident_idx'))
  863. {
  864. $query = array(
  865. 'DELETE' => 'online'
  866. );
  867. $forum_db->query_build($query) or error(__FILE__, __LINE__);
  868. switch ($db_type)
  869. {
  870. case 'mysql':
  871. case 'mysqli':
  872. $forum_db->add_index('online', 'user_id_ident_idx', array('user_id', 'ident(25)'), true);
  873. break;
  874. default:
  875. $forum_db->add_index('online', 'user_id_ident_idx', array('user_id', 'ident'), true);
  876. break;
  877. }
  878. }
  879. // Remove the redundant user_id_idx on the online table
  880. $forum_db->drop_index('online', 'user_id_idx');
  881. // Add an index to ident on the online table
  882. switch ($db_type)
  883. {
  884. case 'mysql':
  885. case 'mysqli':
  886. $forum_db->add_index('online', 'ident_idx', array('ident(25)'));
  887. break;
  888. default:
  889. $forum_db->add_index('online', 'ident_idx', array('ident'));
  890. break;
  891. }
  892. // Add an index to logged on the online table
  893. $forum_db->add_index('online', 'logged_idx', array('logged'));
  894. // Add an index on last_post in the topics table
  895. $forum_db->add_index('topics', 'last_post_idx', array('last_post'));
  896. // Remove any remnants of the now defunct post approval system
  897. $forum_db->drop_field('forums', 'approval');
  898. $forum_db->drop_field('groups', 'g_posts_approved');
  899. $forum_db->drop_field('posts', 'approved');
  900. // Add g_view_users field to groups table
  901. $forum_db->add_field('groups', 'g_view_users', 'TINYINT(1)', false, 1, 'g_read_board');
  902. // Add the time/date format settings to the user table
  903. $forum_db->add_field('users', 'time_format', 'INT(10)', false, 0, 'dst');
  904. $forum_db->add_field('users', 'date_format', 'INT(10)', false, 0, 'dst');
  905. // Add the last_search column to the users table
  906. $forum_db->add_field('users', 'last_search', 'INT(10)', true, null, 'last_post');
  907. // Add the last_email_sent column to the users table and the g_send_email and
  908. // g_email_flood columns to the groups table
  909. $forum_db->add_field('users', 'last_email_sent', 'INT(10)', true, null, 'last_search');
  910. $forum_db->add_field('groups', 'g_send_email', 'TINYINT(1)', false, 1, 'g_search_users');
  911. $forum_db->add_field('groups', 'g_email_flood', 'INT(10)', false, 60, 'g_search_flood');
  912. // Set non-default g_send_email and g_flood_email values properly
  913. $query = array(
  914. 'UPDATE' => 'groups',
  915. 'SET' => 'g_send_email = 0',
  916. 'WHERE' => 'g_id = 2'
  917. );
  918. $forum_db->query_build($query) or error(__FILE__, __LINE__);
  919. $query = array(
  920. 'UPDATE' => 'groups',
  921. 'SET' => 'g_email_flood = 0',
  922. 'WHERE' => 'g_id IN (1,2,4)'
  923. );
  924. $forum_db->query_build($query) or error(__FILE__, __LINE__);
  925. // Add the auto notify/subscription option to the users table
  926. $forum_db->add_field('users', 'auto_notify', 'TINYINT(1)', false, 0, 'notify_with_post');
  927. // Add the first_post_id column to the topics table
  928. if (!$forum_db->field_exists('topics', 'first_post_id'))
  929. {
  930. $forum_db->add_field('topics', 'first_post_id', 'INT(10) UNSIGNED', false, 0, 'posted');
  931. $forum_db->add_index('topics', 'first_post_id_idx', array('first_post_id'));
  932. // Now that we've added the column and indexed it, we need to give it correct data
  933. $query = array(
  934. 'SELECT' => 'MIN(id) AS first_post, topic_id',
  935. 'FROM' => 'posts',
  936. 'GROUP BY' => 'topic_id'
  937. );
  938. $result = $forum_db->query_build($query) or error(__FILE__, __LINE__);
  939. while ($cur_post = $forum_db->fetch_assoc($result))
  940. {
  941. $query = array(
  942. 'UPDATE' => 'topics',
  943. 'SET' => 'first_post_id = '.$cur_post['first_post'],
  944. 'WHERE' => 'id = '.$cur_post['topic_id']
  945. );
  946. $forum_db->query_build($query) or error(__FILE__, __LINE__);
  947. }
  948. }
  949. // Move any users with the old unverified status to their new group
  950. $query = array(
  951. 'UPDATE' => 'users',
  952. 'SET' => 'group_id=0',
  953. 'WHERE' => 'group_id=32000'
  954. );
  955. $forum_db->query_build($query) or error(__FILE__, __LINE__);
  956. // Add the ban_creator column to the bans table
  957. $forum_db->add_field('bans', 'ban_creator', 'INT(10) UNSIGNED', false, 0);
  958. // Remove any hotfix extensions this update supersedes
  959. $query = array(
  960. 'SELECT' => 'id',
  961. 'FROM' => 'extensions',
  962. 'WHERE' => 'id LIKE \'hotfix_%\' AND version != \''.UPDATE_TO.'\''
  963. );
  964. $result = $forum_db->query_build($query) or error(__FILE__, __LINE__);
  965. while ($cur_ext = $forum_db->fetch_assoc($result))
  966. {
  967. $query = array(
  968. 'DELETE' => 'extension_hooks',
  969. 'WHERE' => 'extension_id = \''.$cur_ext['id'].'\''
  970. );
  971. $forum_db->query_build($query) or error(__FILE__, __LINE__);
  972. $query = array(
  973. 'DELETE' => 'extensions',
  974. 'WHERE' => 'id = \''.$cur_ext['id'].'\''
  975. );
  976. $forum_db->query_build($query) or error(__FILE__, __LINE__);
  977. }
  978. // Should we do charset conversion or not?
  979. if (strpos($cur_version, '1.2') === 0 && isset($_GET['convert_charset']))
  980. $query_str = '?stage=conv_misc&req_old_charset='.$old_charset.'&req_per_page='.PER_PAGE;
  981. else
  982. $query_str = '?stage=conv_tables';
  983. break;
  984. // Convert config, categories, forums, groups, ranks and censor words
  985. case 'conv_misc':
  986. if (strpos($cur_version, '1.2') !== 0)
  987. {
  988. $query_str = '?stage=conv_tables';
  989. break;
  990. }
  991. // We need to set names to utf8 before we execute update query
  992. $forum_db->set_names('utf8');
  993. // Convert config
  994. echo 'Converting configuration…'."<br />\n";
  995. foreach ($forum_config as $conf_name => $conf_value)
  996. {
  997. if (convert_to_utf8($conf_value, $old_charset))
  998. {
  999. $query = array(
  1000. 'UPDATE' => 'config',
  1001. 'SET' => 'conf_value = \''.$forum_db->escape($conf_value).'\'',
  1002. 'WHERE' => 'conf_name = \''.$conf_name.'\''
  1003. );
  1004. $forum_db->query_build($query) or error(__FILE__, __LINE__);
  1005. }
  1006. }
  1007. // Convert categories
  1008. echo 'Converting categories…'."<br />\n";
  1009. $query = array(
  1010. 'SELECT' => 'id, cat_name',
  1011. 'FROM' => 'categories',
  1012. 'ORDER BY' => 'id'
  1013. );
  1014. $result = $forum_db->query_build($query) or error(__FILE__, __LINE__);
  1015. while ($cur_item = $forum_db->fetch_assoc($result))
  1016. {
  1017. if (convert_to_utf8($cur_item['cat_name'], $old_charset))
  1018. {
  1019. $query = array(
  1020. 'UPDATE' => 'categories',
  1021. 'SET' => 'cat_name = \''.$forum_db->escape($cur_item['cat_name']).'\'',
  1022. 'WHERE' => 'id = '.$cur_item['id']
  1023. );
  1024. $forum_db->query_build($query) or error(__FILE__, __LINE__);
  1025. }
  1026. }
  1027. // Convert forums
  1028. echo 'Converting forums…'."<br />\n";
  1029. $query = array(
  1030. 'SELECT' => 'id, forum_name, forum_desc, moderators',
  1031. 'FROM' => 'forums',
  1032. 'ORDER BY' => 'id'
  1033. );
  1034. $result = $forum_db->query_build($query) or error(__FILE__, __LINE__);
  1035. while ($cur_item = $forum_db->fetch_assoc($result))
  1036. {
  1037. $moderators = ($cur_item['moderators'] != '') ? unserialize($cur_item['moderators']) : array();
  1038. $moderators_utf8 = array();
  1039. foreach ($moderators as $mod_username => $mod_user_id)
  1040. {
  1041. convert_to_utf8($mod_username, $old_charset);
  1042. $moderators_utf8[$mod_username] = $mod_user_id;
  1043. }
  1044. if (convert_to_utf8($cur_item['forum_name'], $old_charset) | convert_to_utf8($cur_item['forum_desc'], $old_charset) || $moderators !== $moderators_utf8)
  1045. {
  1046. $cur_item['forum_desc'] = $cur_item['forum_desc'] != '' ? '\''.$forum_db->escape($cur_item['forum_desc']).'\'' : 'NULL';
  1047. $cur_item['moderators'] = !empty($moderators_utf8) ? '\''.$forum_db->escape(serialize($moderators_utf8)).'\'' : 'NULL';
  1048. $query = array(
  1049. 'UPDATE' => 'forums',
  1050. 'SET' => 'forum_name = \''.$forum_db->escape($cur_item['forum_name']).'\', forum_desc = '.$cur_item['forum_desc'].', moderators = '.$cur_item['moderators'],
  1051. 'WHERE' => 'id = '.$cur_item['id']
  1052. );
  1053. $forum_db->query_build($query) or error(__FILE__, __LINE__);
  1054. }
  1055. }
  1056. // Convert groups
  1057. echo 'Converting groups…'."<br />\n";
  1058. $query = array(
  1059. 'SELECT' => 'g_id, g_title, g_user_title',
  1060. 'FROM' => 'groups',
  1061. 'ORDER BY' => 'g_id'
  1062. );
  1063. $result = $forum_db->query_build($query) or error(__FILE__, __LINE__);
  1064. while ($cur_item = $forum_db->fetch_assoc($result))
  1065. {
  1066. if (convert_to_utf8($cur_item['g_title'], $old_charset) | convert_to_utf8($cur_item['g_user_title'], $old_charset))
  1067. {
  1068. $cur_item['g_user_title'] = $cur_item['g_user_title'] != '' ? '\''.$forum_db->escape($cur_item['g_user_title']).'\'' : 'NULL';
  1069. $query = array(
  1070. 'UPDATE' => 'groups',
  1071. 'SET' => 'g_title = \''.$forum_db->escape($cur_item['g_title']).'\', g_user_title = '.$cur_item['g_user_title'].'',
  1072. 'WHERE' => 'g_id = '.$cur_item['g_id']
  1073. );
  1074. $forum_db->query_build($query) or error(__FILE__, __LINE__);
  1075. }
  1076. }
  1077. // Convert ranks
  1078. echo 'Converting ranks…'."<br />\n";
  1079. $query = array(
  1080. 'SELECT' => 'id, rank',
  1081. 'FROM' => 'ranks',
  1082. 'ORDER BY' => 'id'
  1083. );
  1084. $result = $forum_db->query_build($query) or error(__FILE__, __LINE__);
  1085. while ($cur_item = $forum_db->fetch_assoc($result))
  1086. {
  1087. if (convert_to_utf8($cur_item['rank'], $old_charset))
  1088. {
  1089. $query = array(
  1090. 'UPDATE' => 'ranks',
  1091. 'SET' => 'rank = \''.$forum_db->escape($cur_item['rank']).'\'',
  1092. 'WHERE' => 'id = '.$cur_item['id']
  1093. );
  1094. $forum_db->query_build($query) or error(__FILE__, __LINE__);
  1095. }
  1096. }
  1097. // Convert censor words
  1098. echo 'Converting censor words…'."<br />\n";
  1099. $query = array(
  1100. 'SELECT' => 'id, search_for, replace_with',
  1101. 'FROM' => 'censoring',
  1102. 'ORDER BY' => 'id'
  1103. );
  1104. $result = $forum_db->query_build($query) or error(__FILE__, __LINE__);
  1105. while ($cur_item = $forum_db->fetch_assoc($result))
  1106. {
  1107. if (convert_to_utf8($cur_item['search_for'], $old_charset) | convert_to_utf8($cur_item['replace_with'], $old_charset))
  1108. {
  1109. $query = array(
  1110. 'UPDATE' => 'censoring',
  1111. 'SET' => 'search_for = \''.$forum_db->escape($cur_item['search_for']).'\', replace_with = \''.$forum_db->escape($cur_item['replace_with']).'\'',
  1112. 'WHERE' => 'id = '.$cur_item['id']
  1113. );
  1114. $forum_db->query_build($query) or error(__FILE__, __LINE__);
  1115. }
  1116. }
  1117. $query_str = '?stage=conv_reports&req_old_charset='.$old_charset.'&req_per_page='.PER_PAGE;
  1118. break;
  1119. // Convert reports
  1120. case 'conv_reports':
  1121. if (strpos($cur_version, '1.2') !== 0)
  1122. {
  1123. $query_str = '?stage=conv_tables';
  1124. break;
  1125. }
  1126. // We need to set names to utf8 before we execute update query
  1127. $forum_db->set_names('utf8');
  1128. // Determine where to start
  1129. if ($start_at == 0)
  1130. {
  1131. // Get the first report ID from the db
  1132. $query = array(
  1133. 'SELECT' => 'id',
  1134. 'FROM' => 'reports',
  1135. 'ORDER BY' => 'id',
  1136. 'LIMIT' => '1'
  1137. );
  1138. $result = $forum_db->query_build($query) or error(__FILE__, __LINE__);
  1139. if ($forum_db->num_rows($result))
  1140. $start_at = $forum_db->result($result);
  1141. }
  1142. $end_at = $start_at + PER_PAGE;
  1143. // Fetch reports to process this cycle
  1144. $query = array(
  1145. 'SELECT' => 'id, message',
  1146. 'FROM' => 'reports',
  1147. 'WHERE' => 'id >= '.$start_at.' AND id < '.$end_at,
  1148. 'ORDER BY' => 'id'
  1149. );
  1150. $result = $forum_db->query_build($query) or error(__FILE__, __LINE__);
  1151. while ($cur_item = $forum_db->fetch_assoc($result))
  1152. {
  1153. echo 'Converting report '.$cur_item['id'].'…<br />'."\n";
  1154. if (convert_to_utf8($cur_item['message'], $old_charset))
  1155. {
  1156. $query = array(
  1157. 'UPDATE' => 'reports',
  1158. 'SET' => 'message = \''.$forum_db->escape($cur_item['message']).'\'',
  1159. 'WHERE' => 'id = '.$cur_item['id']
  1160. );
  1161. $forum_db->query_build($query) or error(__FILE__, __LINE__);
  1162. }
  1163. }
  1164. // Check if there is more work to do
  1165. $query = array(
  1166. 'SELECT' => 'id',
  1167. 'FROM' => 'reports',
  1168. 'WHERE' => 'id >= '.$end_at,
  1169. 'ORDER BY' => 'id ASC',
  1170. 'LIMIT' => '1'
  1171. );
  1172. $result = $forum_db->query_build($query) or error(__FILE__, __LINE__);
  1173. if ($forum_db->num_rows($result))
  1174. $query_str = '?stage=conv_reports&req_old_charset='.$old_charset.'&req_per_page='.PER_PAGE.'&start_at='.$forum_db->result($result);
  1175. else
  1176. $query_str = '?stage=conv_search_words&req_old_charset='.$old_charset.'&req_per_page='.PER_PAGE;
  1177. break;
  1178. // Convert search words
  1179. case 'conv_search_words':
  1180. if (strpos($cur_version, '1.2') !== 0)
  1181. {
  1182. $query_str = '?stage=conv_tables';
  1183. break;
  1184. }
  1185. // We need to set names to utf8 before we execute update query
  1186. $forum_db->set_names('utf8');
  1187. // Determine where to start
  1188. if ($start_at == 0)
  1189. {
  1190. // Get the first search word ID from the db
  1191. $query = array(
  1192. 'SELECT' => 'id',
  1193. 'FROM' => 'search_words',
  1194. 'ORDER BY' => 'id',
  1195. 'LIMIT' => '1'
  1196. );
  1197. $result = $forum_db->query_build($query) or error(__FILE__, __LINE__);
  1198. if ($forum_db->num_rows($result))
  1199. $start_at = $forum_db->result($result);
  1200. }
  1201. $end_at = $start_at + PER_PAGE;
  1202. // Fetch words to process this cycle
  1203. $query = array(
  1204. 'SELECT' => 'id, word',
  1205. 'FROM' => 'search_words',
  1206. 'WHERE' => 'id >= '.$start_at.' AND id < '.$end_at,
  1207. 'ORDER BY' => 'id'
  1208. );
  1209. $result = $forum_db->query_build($query) or error(__FILE__, __LINE__);
  1210. while ($cur_item = $forum_db->fetch_assoc($result))
  1211. {
  1212. echo 'Converting search word '.$cur_item['id'].'…<br />'."\n";
  1213. if (convert_to_utf8($cur_item['word'], $old_charset))
  1214. {
  1215. $query = array(
  1216. 'UPDATE' => 'search_words',
  1217. 'SET' => 'word = \''.$forum_db->escape($cur_item['word']).'\'',
  1218. 'WHERE' => 'id = '.$cur_item['id']
  1219. );
  1220. $forum_db->query_build($query) or error(__FILE__, __LINE__);
  1221. }
  1222. }
  1223. // Check if there is more work to do
  1224. $query = array(
  1225. 'SELECT' => 'id',
  1226. 'FROM' => 'search_words',
  1227. 'WHERE' => 'id >= '.$end_at,
  1228. 'ORDER BY' => 'id ASC',
  1229. 'LIMIT' => '1'
  1230. );
  1231. $result = $forum_db->query_build($query) or error(__FILE__, __LINE__);
  1232. if ($forum_db->num_rows($result))
  1233. $query_str = '?stage=conv_search_words&req_old_charset='.$old_charset.'&req_per_page='.PER_PAGE.'&start_at='.$forum_db->result($result);
  1234. else
  1235. $query_str = '?stage=conv_users&req_old_charset='.$old_charset.'&req_per_page='.PER_PAGE;
  1236. break;
  1237. // Convert users
  1238. case 'conv_users':
  1239. if (strpos($cur_version, '1.2') !== 0)
  1240. {
  1241. $query_str = '?stage=conv_tables';
  1242. break;
  1243. }
  1244. // We need to set names to utf8 before we execute update query
  1245. $forum_db->set_names('utf8');
  1246. // Determine where to start
  1247. if ($start_at == 0)
  1248. $start_at = 2;
  1249. $end_at = $start_at + PER_PAGE;
  1250. // Fetch users to process this cycle
  1251. $query = array(
  1252. 'SELECT' => 'id, username, title, realname, location, signature, admin_note',
  1253. 'FROM' => 'users',
  1254. 'WHERE' => 'id >= '.$start_at.' AND id < '.$end_at,
  1255. 'ORDER BY' => 'id'
  1256. );
  1257. $result = $forum_db->query_build($query) or error(__FILE__, __LINE__);
  1258. while ($cur_item = $forum_db->fetch_assoc($result))
  1259. {
  1260. echo 'Converting user '.$cur_item['id'].'…<br />'."\n";
  1261. if (convert_to_utf8($cur_item['username'], $old_charset) | convert_to_utf8($cur_item['title'], $old_charset) | convert_to_utf8($cur_item['realname'], $old_charset) | convert_to_utf8($cur_item['location'], $old_charset) | convert_to_utf8($cur_item['signature'], $old_charset) | convert_to_utf8($cur_item['admin_note'], $old_charset))
  1262. {
  1263. $cur_item['title'] = $cur_item['title'] != '' ? '\''.$forum_db->escape($cur_item['title']).'\'' : 'NULL';
  1264. $cur_item['realname'] = $cur_item['realname'] != '' ? '\''.$forum_db->escape($cur_item['realname']).'\'' : 'NULL';
  1265. $cur_item['location'] = $cur_item['location'] != '' ? '\''.$forum_db->escape($cur_item['location']).'\'' : 'NULL';
  1266. $cur_item['signature'] = $cur_item['signature'] != '' ? '\''.$forum_db->escape($cur_item['signature']).'\'' : 'NULL';
  1267. $cur_item['admin_note'] = $cur_item['admin_note'] != '' ? '\''.$forum_db->escape($cur_item['admin_note']).'\'' : 'NULL';
  1268. $query = array(
  1269. 'UPDATE' => 'users',
  1270. 'SET' => 'username = \''.$forum_db->escape($cur_item['username']).'\', title = '.$cur_item['title'].', realname = '.$cur_item['realname'].', location = '.$cur_item['location'].', signature = '.$cur_item['signature'].', admin_note = '.$cur_item['admin_note'],
  1271. 'WHERE' => 'id = '.$cur_item['id']
  1272. );
  1273. $forum_db->query_build($query) or error(__FILE__, __LINE__);
  1274. }
  1275. }
  1276. // Check if there is more work to do
  1277. $query = array(
  1278. 'SELECT' => 'id',
  1279. 'FROM' => 'users',
  1280. 'WHERE' => 'id >= '.$end_at,
  1281. 'ORDER BY' => 'id ASC',
  1282. 'LIMIT' => '1'
  1283. );
  1284. $result = $forum_db->query_build($query) or error(__FILE__, __LINE__);
  1285. if ($forum_db->num_rows($result))
  1286. $query_str = '?stage=conv_users&req_old_charset='.$old_charset.'&req_per_page='.PER_PAGE.'&start_at='.$forum_db->result($result);
  1287. else
  1288. $query_str = '?stage=conv_topics&req_old_charset='.$old_charset.'&req_per_page='.PER_PAGE;
  1289. break;
  1290. // Convert topics
  1291. case 'conv_topics':
  1292. if (strpos($cur_version, '1.2') !== 0)
  1293. {
  1294. $query_str = '?stage=conv_tables';
  1295. break;
  1296. }
  1297. // We need to set names to utf8 before we execute update query
  1298. $forum_db->set_names('utf8');
  1299. // Determine where to start
  1300. if ($start_at == 0)
  1301. {
  1302. // Get the first topic ID from the db
  1303. $query = array(
  1304. 'SELECT' => 'id',
  1305. 'FROM' => 'topics',
  1306. 'ORDER…

Large files files are truncated, but you can click here to view the full file