PageRenderTime 38ms CodeModel.GetById 10ms RepoModel.GetById 1ms app.codeStats 0ms

/station/forum/xxstall/database_update.php

https://github.com/bryanveloso/sayonarane
PHP | 3085 lines | 2351 code | 450 blank | 284 comment | 256 complexity | d4523dc400975049a61a0b7380dd5d3c MD5 | raw file
Possible License(s): AGPL-1.0
  1. <?php
  2. /**
  3. *
  4. * @package install
  5. * @version $Id: database_update.php 9058 2008-11-12 20:26:36Z acydburn $
  6. * @copyright (c) 2006 phpBB Group
  7. * @license http://opensource.org/licenses/gpl-license.php GNU Public License
  8. *
  9. */
  10. $updates_to_version = '3.0.3';
  11. // Return if we "just include it" to find out for which version the database update is responsible for
  12. if (defined('IN_PHPBB') && defined('IN_INSTALL'))
  13. {
  14. return;
  15. }
  16. /**
  17. */
  18. define('IN_PHPBB', true);
  19. define('IN_INSTALL', true);
  20. $phpbb_root_path = (defined('PHPBB_ROOT_PATH')) ? PHPBB_ROOT_PATH : './../';
  21. $phpEx = substr(strrchr(__FILE__, '.'), 1);
  22. // Report all errors, except notices
  23. //error_reporting(E_ALL ^ E_NOTICE);
  24. error_reporting(E_ALL);
  25. @set_time_limit(0);
  26. // Include essential scripts
  27. include($phpbb_root_path . 'config.' . $phpEx);
  28. if (!defined('PHPBB_INSTALLED') || empty($dbms) || empty($acm_type))
  29. {
  30. die("Please read: <a href='../docs/INSTALL.html'>INSTALL.html</a> before attempting to update.");
  31. }
  32. // Load Extensions
  33. if (!empty($load_extensions))
  34. {
  35. $load_extensions = explode(',', $load_extensions);
  36. foreach ($load_extensions as $extension)
  37. {
  38. @dl(trim($extension));
  39. }
  40. }
  41. // Include files
  42. require($phpbb_root_path . 'includes/acm/acm_' . $acm_type . '.' . $phpEx);
  43. require($phpbb_root_path . 'includes/cache.' . $phpEx);
  44. require($phpbb_root_path . 'includes/template.' . $phpEx);
  45. require($phpbb_root_path . 'includes/session.' . $phpEx);
  46. require($phpbb_root_path . 'includes/auth.' . $phpEx);
  47. require($phpbb_root_path . 'includes/functions.' . $phpEx);
  48. if (file_exists($phpbb_root_path . 'includes/functions_content.' . $phpEx))
  49. {
  50. require($phpbb_root_path . 'includes/functions_content.' . $phpEx);
  51. }
  52. require($phpbb_root_path . 'includes/functions_admin.' . $phpEx);
  53. require($phpbb_root_path . 'includes/constants.' . $phpEx);
  54. require($phpbb_root_path . 'includes/db/' . $dbms . '.' . $phpEx);
  55. require($phpbb_root_path . 'includes/utf/utf_tools.' . $phpEx);
  56. // If we are on PHP >= 6.0.0 we do not need some code
  57. if (version_compare(PHP_VERSION, '6.0.0-dev', '>='))
  58. {
  59. /**
  60. * @ignore
  61. */
  62. define('STRIP', false);
  63. }
  64. else
  65. {
  66. @set_magic_quotes_runtime(0);
  67. define('STRIP', (get_magic_quotes_gpc()) ? true : false);
  68. }
  69. $user = new user();
  70. $cache = new cache();
  71. $db = new $sql_db();
  72. // Add own hook handler, if present. :o
  73. if (file_exists($phpbb_root_path . 'includes/hooks/index.' . $phpEx))
  74. {
  75. require($phpbb_root_path . 'includes/hooks/index.' . $phpEx);
  76. $phpbb_hook = new phpbb_hook(array('exit_handler', 'phpbb_user_session_handler', 'append_sid', array('template', 'display')));
  77. foreach ($cache->obtain_hooks() as $hook)
  78. {
  79. @include($phpbb_root_path . 'includes/hooks/' . $hook . '.' . $phpEx);
  80. }
  81. }
  82. else
  83. {
  84. $phpbb_hook = false;
  85. }
  86. // Connect to DB
  87. $db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, false);
  88. // We do not need this any longer, unset for safety purposes
  89. unset($dbpasswd);
  90. $user->ip = (!empty($_SERVER['REMOTE_ADDR'])) ? htmlspecialchars($_SERVER['REMOTE_ADDR']) : '';
  91. $sql = "SELECT config_value
  92. FROM " . CONFIG_TABLE . "
  93. WHERE config_name = 'default_lang'";
  94. $result = $db->sql_query($sql);
  95. $row = $db->sql_fetchrow($result);
  96. $db->sql_freeresult($result);
  97. $language = basename(request_var('language', ''));
  98. if (!$language)
  99. {
  100. $language = $row['config_value'];
  101. }
  102. if (!file_exists($phpbb_root_path . 'language/' . $language))
  103. {
  104. die('No language found!');
  105. }
  106. // And finally, load the relevant language files
  107. include($phpbb_root_path . 'language/' . $language . '/common.' . $phpEx);
  108. include($phpbb_root_path . 'language/' . $language . '/acp/common.' . $phpEx);
  109. include($phpbb_root_path . 'language/' . $language . '/install.' . $phpEx);
  110. // Set PHP error handler to ours
  111. //set_error_handler('msg_handler');
  112. // Define some variables for the database update
  113. $inline_update = (request_var('type', 0)) ? true : false;
  114. // Database column types mapping
  115. $dbms_type_map = array(
  116. 'mysql_41' => array(
  117. 'INT:' => 'int(%d)',
  118. 'BINT' => 'bigint(20)',
  119. 'UINT' => 'mediumint(8) UNSIGNED',
  120. 'UINT:' => 'int(%d) UNSIGNED',
  121. 'TINT:' => 'tinyint(%d)',
  122. 'USINT' => 'smallint(4) UNSIGNED',
  123. 'BOOL' => 'tinyint(1) UNSIGNED',
  124. 'VCHAR' => 'varchar(255)',
  125. 'VCHAR:' => 'varchar(%d)',
  126. 'CHAR:' => 'char(%d)',
  127. 'XSTEXT' => 'text',
  128. 'XSTEXT_UNI'=> 'varchar(100)',
  129. 'STEXT' => 'text',
  130. 'STEXT_UNI' => 'varchar(255)',
  131. 'TEXT' => 'text',
  132. 'TEXT_UNI' => 'text',
  133. 'MTEXT' => 'mediumtext',
  134. 'MTEXT_UNI' => 'mediumtext',
  135. 'TIMESTAMP' => 'int(11) UNSIGNED',
  136. 'DECIMAL' => 'decimal(5,2)',
  137. 'VCHAR_UNI' => 'varchar(255)',
  138. 'VCHAR_UNI:'=> 'varchar(%d)',
  139. 'VCHAR_CI' => 'varchar(255)',
  140. 'VARBINARY' => 'varbinary(255)',
  141. ),
  142. 'mysql_40' => array(
  143. 'INT:' => 'int(%d)',
  144. 'BINT' => 'bigint(20)',
  145. 'UINT' => 'mediumint(8) UNSIGNED',
  146. 'UINT:' => 'int(%d) UNSIGNED',
  147. 'TINT:' => 'tinyint(%d)',
  148. 'USINT' => 'smallint(4) UNSIGNED',
  149. 'BOOL' => 'tinyint(1) UNSIGNED',
  150. 'VCHAR' => 'varbinary(255)',
  151. 'VCHAR:' => 'varbinary(%d)',
  152. 'CHAR:' => 'binary(%d)',
  153. 'XSTEXT' => 'blob',
  154. 'XSTEXT_UNI'=> 'blob',
  155. 'STEXT' => 'blob',
  156. 'STEXT_UNI' => 'blob',
  157. 'TEXT' => 'blob',
  158. 'TEXT_UNI' => 'blob',
  159. 'MTEXT' => 'mediumblob',
  160. 'MTEXT_UNI' => 'mediumblob',
  161. 'TIMESTAMP' => 'int(11) UNSIGNED',
  162. 'DECIMAL' => 'decimal(5,2)',
  163. 'VCHAR_UNI' => 'blob',
  164. 'VCHAR_UNI:'=> array('varbinary(%d)', 'limit' => array('mult', 3, 255, 'blob')),
  165. 'VCHAR_CI' => 'blob',
  166. 'VARBINARY' => 'varbinary(255)',
  167. ),
  168. 'firebird' => array(
  169. 'INT:' => 'INTEGER',
  170. 'BINT' => 'DOUBLE PRECISION',
  171. 'UINT' => 'INTEGER',
  172. 'UINT:' => 'INTEGER',
  173. 'TINT:' => 'INTEGER',
  174. 'USINT' => 'INTEGER',
  175. 'BOOL' => 'INTEGER',
  176. 'VCHAR' => 'VARCHAR(255) CHARACTER SET NONE',
  177. 'VCHAR:' => 'VARCHAR(%d) CHARACTER SET NONE',
  178. 'CHAR:' => 'CHAR(%d) CHARACTER SET NONE',
  179. 'XSTEXT' => 'BLOB SUB_TYPE TEXT CHARACTER SET NONE',
  180. 'STEXT' => 'BLOB SUB_TYPE TEXT CHARACTER SET NONE',
  181. 'TEXT' => 'BLOB SUB_TYPE TEXT CHARACTER SET NONE',
  182. 'MTEXT' => 'BLOB SUB_TYPE TEXT CHARACTER SET NONE',
  183. 'XSTEXT_UNI'=> 'VARCHAR(100) CHARACTER SET UTF8',
  184. 'STEXT_UNI' => 'VARCHAR(255) CHARACTER SET UTF8',
  185. 'TEXT_UNI' => 'BLOB SUB_TYPE TEXT CHARACTER SET UTF8',
  186. 'MTEXT_UNI' => 'BLOB SUB_TYPE TEXT CHARACTER SET UTF8',
  187. 'TIMESTAMP' => 'INTEGER',
  188. 'DECIMAL' => 'DOUBLE PRECISION',
  189. 'VCHAR_UNI' => 'VARCHAR(255) CHARACTER SET UTF8',
  190. 'VCHAR_UNI:'=> 'VARCHAR(%d) CHARACTER SET UTF8',
  191. 'VCHAR_CI' => 'VARCHAR(255) CHARACTER SET UTF8',
  192. 'VARBINARY' => 'CHAR(255) CHARACTER SET NONE',
  193. ),
  194. 'mssql' => array(
  195. 'INT:' => '[int]',
  196. 'BINT' => '[float]',
  197. 'UINT' => '[int]',
  198. 'UINT:' => '[int]',
  199. 'TINT:' => '[int]',
  200. 'USINT' => '[int]',
  201. 'BOOL' => '[int]',
  202. 'VCHAR' => '[varchar] (255)',
  203. 'VCHAR:' => '[varchar] (%d)',
  204. 'CHAR:' => '[char] (%d)',
  205. 'XSTEXT' => '[varchar] (1000)',
  206. 'STEXT' => '[varchar] (3000)',
  207. 'TEXT' => '[varchar] (8000)',
  208. 'MTEXT' => '[text]',
  209. 'XSTEXT_UNI'=> '[varchar] (100)',
  210. 'STEXT_UNI' => '[varchar] (255)',
  211. 'TEXT_UNI' => '[varchar] (4000)',
  212. 'MTEXT_UNI' => '[text]',
  213. 'TIMESTAMP' => '[int]',
  214. 'DECIMAL' => '[float]',
  215. 'VCHAR_UNI' => '[varchar] (255)',
  216. 'VCHAR_UNI:'=> '[varchar] (%d)',
  217. 'VCHAR_CI' => '[varchar] (255)',
  218. 'VARBINARY' => '[varchar] (255)',
  219. ),
  220. 'oracle' => array(
  221. 'INT:' => 'number(%d)',
  222. 'BINT' => 'number(20)',
  223. 'UINT' => 'number(8)',
  224. 'UINT:' => 'number(%d)',
  225. 'TINT:' => 'number(%d)',
  226. 'USINT' => 'number(4)',
  227. 'BOOL' => 'number(1)',
  228. 'VCHAR' => 'varchar2(255)',
  229. 'VCHAR:' => 'varchar2(%d)',
  230. 'CHAR:' => 'char(%d)',
  231. 'XSTEXT' => 'varchar2(1000)',
  232. 'STEXT' => 'varchar2(3000)',
  233. 'TEXT' => 'clob',
  234. 'MTEXT' => 'clob',
  235. 'XSTEXT_UNI'=> 'varchar2(300)',
  236. 'STEXT_UNI' => 'varchar2(765)',
  237. 'TEXT_UNI' => 'clob',
  238. 'MTEXT_UNI' => 'clob',
  239. 'TIMESTAMP' => 'number(11)',
  240. 'DECIMAL' => 'number(5, 2)',
  241. 'VCHAR_UNI' => 'varchar2(765)',
  242. 'VCHAR_UNI:'=> array('varchar2(%d)', 'limit' => array('mult', 3, 765, 'clob')),
  243. 'VCHAR_CI' => 'varchar2(255)',
  244. 'VARBINARY' => 'raw(255)',
  245. ),
  246. 'sqlite' => array(
  247. 'INT:' => 'int(%d)',
  248. 'BINT' => 'bigint(20)',
  249. 'UINT' => 'INTEGER UNSIGNED', //'mediumint(8) UNSIGNED',
  250. 'UINT:' => 'INTEGER UNSIGNED', // 'int(%d) UNSIGNED',
  251. 'TINT:' => 'tinyint(%d)',
  252. 'USINT' => 'INTEGER UNSIGNED', //'mediumint(4) UNSIGNED',
  253. 'BOOL' => 'INTEGER UNSIGNED', //'tinyint(1) UNSIGNED',
  254. 'VCHAR' => 'varchar(255)',
  255. 'VCHAR:' => 'varchar(%d)',
  256. 'CHAR:' => 'char(%d)',
  257. 'XSTEXT' => 'text(65535)',
  258. 'STEXT' => 'text(65535)',
  259. 'TEXT' => 'text(65535)',
  260. 'MTEXT' => 'mediumtext(16777215)',
  261. 'XSTEXT_UNI'=> 'text(65535)',
  262. 'STEXT_UNI' => 'text(65535)',
  263. 'TEXT_UNI' => 'text(65535)',
  264. 'MTEXT_UNI' => 'mediumtext(16777215)',
  265. 'TIMESTAMP' => 'INTEGER UNSIGNED', //'int(11) UNSIGNED',
  266. 'DECIMAL' => 'decimal(5,2)',
  267. 'VCHAR_UNI' => 'varchar(255)',
  268. 'VCHAR_UNI:'=> 'varchar(%d)',
  269. 'VCHAR_CI' => 'varchar(255)',
  270. 'VARBINARY' => 'blob',
  271. ),
  272. 'postgres' => array(
  273. 'INT:' => 'INT4',
  274. 'BINT' => 'INT8',
  275. 'UINT' => 'INT4', // unsigned
  276. 'UINT:' => 'INT4', // unsigned
  277. 'USINT' => 'INT2', // unsigned
  278. 'BOOL' => 'INT2', // unsigned
  279. 'TINT:' => 'INT2',
  280. 'VCHAR' => 'varchar(255)',
  281. 'VCHAR:' => 'varchar(%d)',
  282. 'CHAR:' => 'char(%d)',
  283. 'XSTEXT' => 'varchar(1000)',
  284. 'STEXT' => 'varchar(3000)',
  285. 'TEXT' => 'varchar(8000)',
  286. 'MTEXT' => 'TEXT',
  287. 'XSTEXT_UNI'=> 'varchar(100)',
  288. 'STEXT_UNI' => 'varchar(255)',
  289. 'TEXT_UNI' => 'varchar(4000)',
  290. 'MTEXT_UNI' => 'TEXT',
  291. 'TIMESTAMP' => 'INT4', // unsigned
  292. 'DECIMAL' => 'decimal(5,2)',
  293. 'VCHAR_UNI' => 'varchar(255)',
  294. 'VCHAR_UNI:'=> 'varchar(%d)',
  295. 'VCHAR_CI' => 'varchar_ci',
  296. 'VARBINARY' => 'bytea',
  297. ),
  298. );
  299. // A list of types being unsigned for better reference in some db's
  300. $unsigned_types = array('UINT', 'UINT:', 'USINT', 'BOOL', 'TIMESTAMP');
  301. // Only an example, but also commented out
  302. $database_update_info = array(
  303. // Changes from 3.0.RC2 to the next version
  304. '3.0.RC2' => array(
  305. // Change the following columns
  306. 'change_columns' => array(
  307. BANLIST_TABLE => array(
  308. 'ban_reason' => array('VCHAR_UNI', ''),
  309. 'ban_give_reason' => array('VCHAR_UNI', ''),
  310. ),
  311. ),
  312. ),
  313. // Changes from 3.0.RC3 to the next version
  314. '3.0.RC3' => array(
  315. // Change the following columns
  316. 'change_columns' => array(
  317. BANLIST_TABLE => array(
  318. 'ban_reason' => array('VCHAR_UNI', ''),
  319. 'ban_give_reason' => array('VCHAR_UNI', ''),
  320. ),
  321. STYLES_TABLE => array(
  322. 'style_id' => array('USINT', 0),
  323. 'template_id' => array('USINT', 0),
  324. 'theme_id' => array('USINT', 0),
  325. 'imageset_id' => array('USINT', 0),
  326. ),
  327. STYLES_TEMPLATE_TABLE => array(
  328. 'template_id' => array('USINT', 0),
  329. ),
  330. STYLES_TEMPLATE_DATA_TABLE => array(
  331. 'template_id' => array('USINT', 0),
  332. ),
  333. STYLES_THEME_TABLE => array(
  334. 'theme_id' => array('USINT', 0),
  335. ),
  336. STYLES_IMAGESET_TABLE => array(
  337. 'imageset_id' => array('USINT', 0),
  338. ),
  339. STYLES_IMAGESET_DATA_TABLE => array(
  340. 'imageset_id' => array('USINT', 0),
  341. ),
  342. USERS_TABLE => array(
  343. 'user_style' => array('USINT', 0),
  344. ),
  345. FORUMS_TABLE => array(
  346. 'forum_style' => array('USINT', 0),
  347. ),
  348. GROUPS_TABLE => array(
  349. 'group_avatar_type' => array('TINT:2', 0),
  350. 'group_avatar_width' => array('USINT', 0),
  351. 'group_avatar_height' => array('USINT', 0),
  352. ),
  353. ),
  354. ),
  355. // Changes from 3.0.RC4 to the next version
  356. '3.0.RC4' => array(
  357. // Change the following columns
  358. 'change_columns' => array(
  359. STYLES_TABLE => array(
  360. 'style_id' => array('USINT', NULL, 'auto_increment'),
  361. 'template_id' => array('USINT', 0),
  362. 'theme_id' => array('USINT', 0),
  363. 'imageset_id' => array('USINT', 0),
  364. ),
  365. STYLES_TEMPLATE_TABLE => array(
  366. 'template_id' => array('USINT', NULL, 'auto_increment'),
  367. ),
  368. STYLES_TEMPLATE_DATA_TABLE => array(
  369. 'template_id' => array('USINT', 0),
  370. ),
  371. STYLES_THEME_TABLE => array(
  372. 'theme_id' => array('USINT', NULL, 'auto_increment'),
  373. ),
  374. STYLES_IMAGESET_TABLE => array(
  375. 'imageset_id' => array('USINT', NULL, 'auto_increment'),
  376. ),
  377. STYLES_IMAGESET_DATA_TABLE => array(
  378. 'imageset_id' => array('USINT', 0),
  379. ),
  380. USERS_TABLE => array(
  381. 'user_style' => array('USINT', 0),
  382. ),
  383. FORUMS_TABLE => array(
  384. 'forum_style' => array('USINT', 0),
  385. ),
  386. GROUPS_TABLE => array(
  387. 'group_avatar_width' => array('USINT', 0),
  388. 'group_avatar_height' => array('USINT', 0),
  389. ),
  390. ),
  391. ),
  392. // Changes from 3.0.RC5 to the next version
  393. '3.0.RC5' => array(
  394. // Add the following columns
  395. 'add_columns' => array(
  396. USERS_TABLE => array(
  397. 'user_form_salt' => array('VCHAR_UNI:32', ''),
  398. ),
  399. ),
  400. // Change the following columns
  401. 'change_columns' => array(
  402. POSTS_TABLE => array(
  403. 'bbcode_uid' => array('VCHAR:8', ''),
  404. ),
  405. PRIVMSGS_TABLE => array(
  406. 'bbcode_uid' => array('VCHAR:8', ''),
  407. ),
  408. USERS_TABLE => array(
  409. 'user_sig_bbcode_uid' => array('VCHAR:8', ''),
  410. ),
  411. ),
  412. ),
  413. // Changes from 3.0.RC6 to the next version
  414. '3.0.RC6' => array(
  415. // Change the following columns
  416. 'change_columns' => array(
  417. FORUMS_TABLE => array(
  418. 'forum_desc_uid' => array('VCHAR:8', ''),
  419. 'forum_rules_uid' => array('VCHAR:8', ''),
  420. ),
  421. GROUPS_TABLE => array(
  422. 'group_desc_uid' => array('VCHAR:8', ''),
  423. ),
  424. USERS_TABLE => array(
  425. 'user_newpasswd' => array('VCHAR_UNI:40', ''),
  426. ),
  427. ),
  428. ),
  429. // Changes from 3.0.RC8 to the next version
  430. '3.0.RC8' => array(
  431. // Change the following columns
  432. 'change_columns' => array(
  433. USERS_TABLE => array(
  434. 'user_new_privmsg' => array('INT:4', 0),
  435. 'user_unread_privmsg' => array('INT:4', 0),
  436. ),
  437. ),
  438. ),
  439. // Changes from 3.0.0 to the next version
  440. '3.0.0' => array(
  441. // Add the following columns
  442. 'add_columns' => array(
  443. FORUMS_TABLE => array(
  444. 'display_subforum_list' => array('BOOL', 1),
  445. ),
  446. SESSIONS_TABLE => array(
  447. 'session_forum_id' => array('UINT', 0),
  448. ),
  449. ),
  450. 'add_index' => array(
  451. SESSIONS_TABLE => array(
  452. 'session_forum_id' => array('session_forum_id'),
  453. ),
  454. GROUPS_TABLE => array(
  455. 'group_legend_name' => array('group_legend', 'group_name'),
  456. ),
  457. ),
  458. 'drop_keys' => array(
  459. GROUPS_TABLE => array('group_legend'),
  460. ),
  461. ),
  462. // No changes from 3.0.1-RC1 to 3.0.1
  463. '3.0.1-RC1' => array(),
  464. // No changes from 3.0.1 to 3.0.2-RC1
  465. '3.0.1' => array(),
  466. // Changes from 3.0.2-RC1 to 3.0.2-RC2
  467. '3.0.2-RC1' => array(
  468. 'change_columns' => array(
  469. DRAFTS_TABLE => array(
  470. 'draft_subject' => array('STEXT_UNI', ''),
  471. ),
  472. FORUMS_TABLE => array(
  473. 'forum_last_post_subject' => array('STEXT_UNI', ''),
  474. ),
  475. POSTS_TABLE => array(
  476. 'post_subject' => array('STEXT_UNI', '', 'true_sort'),
  477. ),
  478. PRIVMSGS_TABLE => array(
  479. 'message_subject' => array('STEXT_UNI', ''),
  480. ),
  481. TOPICS_TABLE => array(
  482. 'topic_title' => array('STEXT_UNI', '', 'true_sort'),
  483. 'topic_last_post_subject' => array('STEXT_UNI', ''),
  484. ),
  485. ),
  486. 'drop_keys' => array(
  487. SESSIONS_TABLE => array('session_forum_id'),
  488. ),
  489. 'add_index' => array(
  490. SESSIONS_TABLE => array(
  491. 'session_fid' => array('session_forum_id'),
  492. ),
  493. ),
  494. ),
  495. // No changes from 3.0.2-RC2 to 3.0.2
  496. '3.0.2-RC2' => array(),
  497. // Changes from 3.0.2 to 3.0.3-RC1
  498. '3.0.2' => array(
  499. // Add the following columns
  500. 'add_columns' => array(
  501. STYLES_TEMPLATE_TABLE => array(
  502. 'template_inherits_id' => array('UINT:4', 0),
  503. 'template_inherit_path' => array('VCHAR', ''),
  504. ),
  505. GROUPS_TABLE => array(
  506. 'group_max_recipients' => array('UINT', 0),
  507. ),
  508. ),
  509. ),
  510. // No changes from 3.0.3-RC1 to 3.0.3
  511. '3.0.3-RC1' => array(),
  512. );
  513. // Determine mapping database type
  514. switch ($db->sql_layer)
  515. {
  516. case 'mysql':
  517. $map_dbms = 'mysql_40';
  518. break;
  519. case 'mysql4':
  520. if (version_compare($db->sql_server_info(true), '4.1.3', '>='))
  521. {
  522. $map_dbms = 'mysql_41';
  523. }
  524. else
  525. {
  526. $map_dbms = 'mysql_40';
  527. }
  528. break;
  529. case 'mysqli':
  530. $map_dbms = 'mysql_41';
  531. break;
  532. case 'mssql':
  533. case 'mssql_odbc':
  534. $map_dbms = 'mssql';
  535. break;
  536. default:
  537. $map_dbms = $db->sql_layer;
  538. break;
  539. }
  540. $error_ary = array();
  541. $errored = false;
  542. header('Content-type: text/html; charset=UTF-8');
  543. ?>
  544. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  545. <html xmlns="http://www.w3.org/1999/xhtml" dir="<?php echo $lang['DIRECTION']; ?>" lang="<?php echo $lang['USER_LANG']; ?>" xml:lang="<?php echo $lang['USER_LANG']; ?>">
  546. <head>
  547. <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
  548. <meta http-equiv="content-language" content="<?php echo $lang['USER_LANG']; ?>" />
  549. <meta http-equiv="content-style-type" content="text/css" />
  550. <meta http-equiv="imagetoolbar" content="no" />
  551. <title><?php echo $lang['UPDATING_TO_LATEST_STABLE']; ?></title>
  552. <link href="../adm/style/admin.css" rel="stylesheet" type="text/css" media="screen" />
  553. </head>
  554. <body>
  555. <div id="wrap">
  556. <div id="page-header">&nbsp;</div>
  557. <div id="page-body">
  558. <div id="acp">
  559. <div class="panel">
  560. <span class="corners-top"><span></span></span>
  561. <div id="content">
  562. <div id="main">
  563. <h1><?php echo $lang['UPDATING_TO_LATEST_STABLE']; ?></h1>
  564. <br />
  565. <p><?php echo $lang['DATABASE_TYPE']; ?> :: <strong><?php echo $db->sql_layer; ?></strong><br />
  566. <?php
  567. // To let set_config() calls succeed, we need to make the config array available globally
  568. $config = array();
  569. $sql = 'SELECT *
  570. FROM ' . CONFIG_TABLE;
  571. $result = $db->sql_query($sql);
  572. while ($row = $db->sql_fetchrow($result))
  573. {
  574. $config[$row['config_name']] = $row['config_value'];
  575. }
  576. $db->sql_freeresult($result);
  577. /*if ($debug_from_version !== false)
  578. {
  579. $config['version'] = $debug_from_version;
  580. }*/
  581. echo $lang['PREVIOUS_VERSION'] . ' :: <strong>' . $config['version'] . '</strong><br />';
  582. echo $lang['UPDATED_VERSION'] . ' :: <strong>' . $updates_to_version . '</strong></p>';
  583. $current_version = str_replace('rc', 'RC', strtolower($config['version']));
  584. $latest_version = str_replace('rc', 'RC', strtolower($updates_to_version));
  585. $orig_version = $config['version'];
  586. // If the latest version and the current version are 'unequal', we will update the version_update_from, else we do not update anything.
  587. if ($inline_update)
  588. {
  589. if ($current_version !== $latest_version)
  590. {
  591. set_config('version_update_from', $orig_version);
  592. }
  593. }
  594. else
  595. {
  596. // If not called from the update script, we will actually remove the traces
  597. $db->sql_query('DELETE FROM ' . CONFIG_TABLE . " WHERE config_name = 'version_update_from'");
  598. }
  599. // Checks/Operations that have to be completed prior to starting the update itself
  600. $exit = false;
  601. if (version_compare($current_version, '3.0.RC8', '<=')) /* && $debug_from_version === false) */
  602. {
  603. // Define missing language entries...
  604. if (!isset($lang['CLEANING_USERNAMES']))
  605. {
  606. $lang = array_merge($lang, array(
  607. 'CLEANING_USERNAMES' => 'Cleaning usernames',
  608. 'LONG_SCRIPT_EXECUTION' => 'Please note that this can take a while... Please do not stop the script.',
  609. 'CHANGE_CLEAN_NAMES' => 'The method used to make sure a username is not used by multiple users has been changed. There are some users which have the same name when compared with the new method. You have to delete or rename these users to make sure that each name is only used by one user before you can proceed.',
  610. 'USER_ACTIVE' => 'Active user',
  611. 'USER_INACTIVE' => 'Inactive user',
  612. 'BOT' => 'Spider/Robot',
  613. 'UPDATE_REQUIRES_FILE' => 'The updater requires that the following file is present: %s',
  614. 'DELETE_USER_REMOVE' => 'Delete user and remove posts',
  615. 'DELETE_USER_RETAIN' => 'Delete user but keep posts',
  616. 'EDIT_USERNAME' => 'Edit username',
  617. 'KEEP_OLD_NAME' => 'Keep username',
  618. 'NEW_USERNAME' => 'New username',
  619. ));
  620. }
  621. ?>
  622. <br /><br />
  623. <h1><?php echo $lang['CLEANING_USERNAMES']; ?></h1>
  624. <br />
  625. <?php
  626. flush();
  627. $submit = (isset($_POST['resolve_conflicts'])) ? true : false;
  628. $modify_users = request_var('modify_users', array(0 => ''));
  629. $new_usernames = request_var('new_usernames', array(0 => ''), true);
  630. // We need this file if someone wants to edit usernames.
  631. include($phpbb_root_path . 'includes/utf/utf_normalizer.' . $phpEx);
  632. if (!class_exists('utf_new_normalizer'))
  633. {
  634. if (!file_exists($phpbb_root_path . 'install/data/new_normalizer.' . $phpEx))
  635. {
  636. global $lang;
  637. trigger_error(sprintf($lang['UPDATE_REQUIRES_FILE'], $phpbb_root_path . 'install/data/new_normalizer.' . $phpEx), E_USER_ERROR);
  638. }
  639. include($phpbb_root_path . 'install/data/new_normalizer.' . $phpEx);
  640. }
  641. // the admin decided to change some usernames
  642. if (sizeof($modify_users) && $submit)
  643. {
  644. $sql = 'SELECT user_id, username, user_type
  645. FROM ' . USERS_TABLE . '
  646. WHERE ' . $db->sql_in_set('user_id', array_keys($modify_users));
  647. $result = $db->sql_query($sql);
  648. $users = 0;
  649. while ($row = $db->sql_fetchrow($result))
  650. {
  651. $users++;
  652. $user_id = (int) $row['user_id'];
  653. if (isset($modify_users[$user_id]))
  654. {
  655. $row['action'] = $modify_users[$user_id];
  656. $modify_users[$user_id] = $row;
  657. }
  658. }
  659. $db->sql_freeresult($result);
  660. // only if all ids really existed
  661. if (sizeof($modify_users) == $users)
  662. {
  663. $user->data['user_id'] = ANONYMOUS;
  664. include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
  665. foreach ($modify_users as $user_id => $row)
  666. {
  667. switch ($row['action'])
  668. {
  669. case 'edit':
  670. if (isset($new_usernames[$user_id]))
  671. {
  672. $data = array('username' => utf8_new_normalize_nfc($new_usernames[$user_id]));
  673. // Need to update config, forum, topic, posting, messages, etc.
  674. if ($data['username'] != $row['username'])
  675. {
  676. $check_ary = array('username' => array(
  677. array('string', false, $config['min_name_chars'], $config['max_name_chars']),
  678. array('username'),
  679. ));
  680. // need a little trick for this to work properly
  681. $user->data['username_clean'] = utf8_clean_string($data['username']) . 'a';
  682. $errors = validate_data($data, $check_ary);
  683. if ($errors)
  684. {
  685. include($phpbb_root_path . 'language/' . $language . '/ucp.' . $phpEx);
  686. echo '<div class="errorbox">';
  687. foreach ($errors as $error)
  688. {
  689. echo '<p>' . $lang[$error] . '</p>';
  690. }
  691. echo '</div>';
  692. }
  693. if (!$errors)
  694. {
  695. $sql = 'UPDATE ' . USERS_TABLE . '
  696. SET ' . $db->sql_build_array('UPDATE', array(
  697. 'username' => $data['username'],
  698. 'username_clean' => utf8_clean_string($data['username'])
  699. )) . '
  700. WHERE user_id = ' . $user_id;
  701. $db->sql_query($sql);
  702. add_log('user', $user_id, 'LOG_USER_UPDATE_NAME', $row['username'], $data['username']);
  703. user_update_name($row['username'], $data['username']);
  704. }
  705. }
  706. }
  707. break;
  708. case 'delete_retain':
  709. case 'delete_remove':
  710. if ($user_id != ANONYMOUS && $row['user_type'] != USER_FOUNDER)
  711. {
  712. user_delete(substr($row['action'], 7), $user_id, $row['username']);
  713. add_log('admin', 'LOG_USER_DELETED', $row['username']);
  714. }
  715. break;
  716. }
  717. }
  718. }
  719. }
  720. ?>
  721. <p><?php echo $lang['LONG_SCRIPT_EXECUTION']; ?></p>
  722. <p><?php echo $lang['PROGRESS']; ?> :: <strong>
  723. <?php
  724. flush();
  725. // after RC3 a different utf8_clean_string function is used, this requires that
  726. // the unique column username_clean is recalculated, during this recalculation
  727. // duplicates might be created. Since the column has to be unique such usernames
  728. // must not exist. We need identify them and let the admin decide what to do
  729. // about them.
  730. // After RC8 this was changed again, but this time only usernames containing spaces
  731. // are affected.
  732. $sql_where = (version_compare($current_version, '3.0.RC4', '<=')) ? '' : "WHERE username_clean LIKE '% %'";
  733. $sql = 'SELECT user_id, username, username_clean
  734. FROM ' . USERS_TABLE . "
  735. $sql_where
  736. ORDER BY user_id ASC";
  737. $result = $db->sql_query($sql);
  738. $colliding_users = $found_names = array();
  739. $echos = 0;
  740. while ($row = $db->sql_fetchrow($result))
  741. {
  742. // Calculate the new clean name. If it differs from the old one we need
  743. // to make sure there is no collision
  744. $clean_name = utf8_new_clean_string($row['username']);
  745. if ($clean_name != $row['username_clean'])
  746. {
  747. // Check if there would be a collission, if not put it up for changing
  748. $user_id = (int) $row['user_id'];
  749. // If this clean name was not the result of another user already ...
  750. if (!isset($found_names[$clean_name]))
  751. {
  752. // then we need to figure out whether there are any other users
  753. // who already had this clean name with the old version
  754. $sql = 'SELECT user_id, username
  755. FROM ' . USERS_TABLE . '
  756. WHERE username_clean = \'' . $db->sql_escape($clean_name) . '\'';
  757. $result2 = $db->sql_query($sql);
  758. $user_ids = array($user_id);
  759. while ($row = $db->sql_fetchrow($result2))
  760. {
  761. // For not trimmed entries this could happen, yes. ;)
  762. if ($row['user_id'] == $user_id)
  763. {
  764. continue;
  765. }
  766. // Make sure this clean name will still be the same with the
  767. // new function. If it is, then we have to add it to the list
  768. // of user ids for this clean name
  769. if (utf8_new_clean_string($row['username']) == $clean_name)
  770. {
  771. $user_ids[] = (int) $row['user_id'];
  772. }
  773. }
  774. $db->sql_freeresult($result2);
  775. // if we already found a collision save it
  776. if (sizeof($user_ids) > 1)
  777. {
  778. $colliding_users[$clean_name] = $user_ids;
  779. $found_names[$clean_name] = true;
  780. }
  781. else
  782. {
  783. // otherwise just mark this name as found
  784. $found_names[$clean_name] = $user_id;
  785. }
  786. }
  787. // Else, if we already found the username
  788. else
  789. {
  790. // If the value in the found_names lookup table is only true ...
  791. if ($found_names[$clean_name] === true)
  792. {
  793. // then the actual data was already added to $colliding_users
  794. // and we only need to append the user_id
  795. $colliding_users[$clean_name][] = $user_id;
  796. }
  797. else
  798. {
  799. // otherwise it still keeps the first user_id for this name
  800. // and we need to move the data to $colliding_users, and set
  801. // the value in the found_names lookup table to true, so
  802. // following users will directly be appended to $colliding_users
  803. $colliding_users[$clean_name] = array($found_names[$clean_name], $user_id);
  804. $found_names[$clean_name] = true;
  805. }
  806. }
  807. }
  808. if (($echos % 1000) == 0)
  809. {
  810. echo '.';
  811. flush();
  812. }
  813. $echos++;
  814. }
  815. $db->sql_freeresult($result);
  816. _write_result(false, $errored, $error_ary);
  817. // now retrieve all information about the users and let the admin decide what to do
  818. if (sizeof($colliding_users))
  819. {
  820. $exit = true;
  821. include($phpbb_root_path . 'includes/functions_display.' . $phpEx);
  822. include($phpbb_root_path . 'language/' . $language . '/memberlist.' . $phpEx);
  823. include($phpbb_root_path . 'language/' . $language . '/acp/users.' . $phpEx);
  824. // link a few things to the correct place so we don't get any problems
  825. $user->lang = &$lang;
  826. $user->data['user_id'] = ANONYMOUS;
  827. $user->date_format = $config['default_dateformat'];
  828. // a little trick to get all user_ids
  829. $user_ids = call_user_func_array('array_merge', array_values($colliding_users));
  830. $sql = 'SELECT session_user_id, MAX(session_time) AS session_time
  831. FROM ' . SESSIONS_TABLE . '
  832. WHERE session_time >= ' . (time() - $config['session_length']) . '
  833. AND ' . $db->sql_in_set('session_user_id', $user_ids) . '
  834. GROUP BY session_user_id';
  835. $result = $db->sql_query($sql);
  836. $session_times = array();
  837. while ($row = $db->sql_fetchrow($result))
  838. {
  839. $session_times[$row['session_user_id']] = $row['session_time'];
  840. }
  841. $db->sql_freeresult($result);
  842. $sql = 'SELECT *
  843. FROM ' . USERS_TABLE . '
  844. WHERE ' . $db->sql_in_set('user_id', $user_ids);
  845. $result = $db->sql_query($sql);
  846. $users = array();
  847. while ($row = $db->sql_fetchrow($result))
  848. {
  849. if (isset($session_times[$row['user_id']]))
  850. {
  851. $row['session_time'] = $session_times[$row['user_id']];
  852. }
  853. else
  854. {
  855. $row['session_time'] = 0;
  856. }
  857. $users[(int) $row['user_id']] = $row;
  858. }
  859. $db->sql_freeresult($result);
  860. unset($session_times);
  861. // now display a table with all users, some information about them and options
  862. // for the admin: keep name, change name (with text input) or delete user
  863. $u_action = "database_update.$phpEx?language=$language&amp;type=$inline_update";
  864. ?>
  865. <br /><br />
  866. <p><?php echo $lang['CHANGE_CLEAN_NAMES']; ?></p>
  867. <form id="change_clean_names" method="post" action="<?php echo $u_action; ?>">
  868. <?php
  869. foreach ($colliding_users as $clean_name => $user_ids)
  870. {
  871. ?>
  872. <fieldset class="tabulated">
  873. <table>
  874. <caption><?php echo sprintf($lang['COLLIDING_CLEAN_USERNAME'], $clean_name); ?></caption>
  875. <thead>
  876. <tr>
  877. <th><?php echo $lang['RANK']; ?> <?php echo $lang['USERNAME']; ?></th>
  878. <th><?php echo $lang['POSTS']; ?></th>
  879. <th><?php echo $lang['INFORMATION']; ?></th>
  880. <th><?php echo $lang['JOINED']; ?></th>
  881. <th><?php echo $lang['LAST_ACTIVE']; ?></th>
  882. <th><?php echo $lang['ACTION']; ?></th>
  883. <th><?php echo $lang['NEW_USERNAME']; ?></th>
  884. </tr>
  885. </thead>
  886. <tbody>
  887. <?php
  888. foreach ($user_ids as $i => $user_id)
  889. {
  890. $row = $users[$user_id];
  891. $rank_title = $rank_img = '';
  892. get_user_rank($row['user_rank'], $row['user_posts'], $rank_title, $rank_img, $rank_img_src);
  893. $last_visit = (!empty($row['session_time'])) ? $row['session_time'] : $row['user_lastvisit'];
  894. $info = '';
  895. switch ($row['user_type'])
  896. {
  897. case USER_INACTIVE:
  898. $info .= $lang['USER_INACTIVE'];
  899. break;
  900. case USER_IGNORE:
  901. $info .= $lang['BOT'];
  902. break;
  903. case USER_FOUNDER:
  904. $info .= $lang['FOUNDER'];
  905. break;
  906. default:
  907. $info .= $lang['USER_ACTIVE'];
  908. }
  909. if ($user_id == ANONYMOUS)
  910. {
  911. $info = $lang['GUEST'];
  912. }
  913. ?>
  914. <tr class="bg<?php echo ($i % 2) + 1; ?>">
  915. <td>
  916. <span class="rank-img"><?php echo ($rank_img) ? $rank_img : $rank_title; ?></span><br />
  917. <?php echo get_username_string('full', $row['user_id'], $row['username'], $row['user_colour']); ?>
  918. </td>
  919. <td class="posts"><?php echo $row['user_posts']; ?></td>
  920. <td class="info"><?php echo $info; ?></td>
  921. <td><?php echo $user->format_date($row['user_regdate']) ?></td>
  922. <td><?php echo (empty($last_visit)) ? ' - ' : $user->format_date($last_visit); ?>&nbsp;</td>
  923. <td>
  924. <label><input type="radio" class="radio" id="keep_user_<?php echo $user_id; ?>" name="modify_users[<?php echo $user_id; ?>]" value="keep" checked="checked" /> <?php echo $lang['KEEP_OLD_NAME']; ?></label><br />
  925. <label><input type="radio" class="radio" id="edit_user_<?php echo $user_id; ?>" name="modify_users[<?php echo $user_id; ?>]" value="edit" /> <?php echo $lang['EDIT_USERNAME']; ?></label><br />
  926. <?php
  927. // some users must not be deleted
  928. if ($user_id != ANONYMOUS && $row['user_type'] != USER_FOUNDER)
  929. {
  930. ?>
  931. <label><input type="radio" class="radio" id="delete_user_retain_<?php echo $user_id; ?>" name="modify_users[<?php echo $user_id; ?>]" value="delete_retain" /> <?php echo $lang['DELETE_USER_RETAIN']; ?></label><br />
  932. <label><input type="radio" class="radio" id="delete_user_remove_<?php echo $user_id; ?>" name="modify_users[<?php echo $user_id; ?>]" value="delete_remove" /> <?php echo $lang['DELETE_USER_REMOVE']; ?></label>
  933. <?php
  934. }
  935. ?>
  936. </td>
  937. <td>
  938. <input id="new_username_<?php echo $user_id; ?>" type="text" name="new_usernames[<?php echo $user_id; ?>]" value="<?php echo $row['username']; ?>" />
  939. </td>
  940. </tr>
  941. <?php
  942. }
  943. ?>
  944. </tbody>
  945. </table>
  946. </fieldset>
  947. <?php
  948. }
  949. ?>
  950. <p class="quick">
  951. <input class="button2" id="resolve_conflicts" type="submit" name="resolve_conflicts" value="<?php echo $lang['SUBMIT']; ?>" />
  952. </p>
  953. </form>
  954. <?php
  955. }
  956. else if (sizeof($found_names))
  957. {
  958. $sql = 'SELECT user_id, username, username_clean
  959. FROM ' . USERS_TABLE . '
  960. WHERE ' . $db->sql_in_set('user_id', array_values($found_names));
  961. $result = $db->sql_query($sql);
  962. $found_names = array();
  963. while ($row = $db->sql_fetchrow($result))
  964. {
  965. $clean_name = utf8_new_clean_string($row['username']);
  966. if ($clean_name != $row['username_clean'])
  967. {
  968. $user_id = (int) $row['user_id'];
  969. $found_names[$user_id] = $clean_name;
  970. // impossible unique clean name
  971. $sql = 'UPDATE ' . USERS_TABLE . "
  972. SET username_clean = ' {$user_id}'
  973. WHERE user_id = {$user_id}";
  974. $db->sql_query($sql);
  975. }
  976. }
  977. $db->sql_freeresult($result);
  978. foreach ($found_names as $user_id => $clean_name)
  979. {
  980. $sql = 'UPDATE ' . USERS_TABLE . '
  981. SET username_clean = \'' . $db->sql_escape($clean_name) . '\'
  982. WHERE user_id = ' . $user_id;
  983. $db->sql_query($sql);
  984. }
  985. }
  986. unset($found_names);
  987. unset($colliding_users);
  988. }
  989. if ($exit)
  990. {
  991. ?>
  992. </div>
  993. </div>
  994. <span class="corners-bottom"><span></span></span>
  995. </div>
  996. </div>
  997. </div>
  998. <div id="page-footer">
  999. Powered by <a href="http://www.phpbb.com/">phpBB</a> &copy; 2000, 2002, 2005, 2007 phpBB Group
  1000. </div>
  1001. </div>
  1002. </body>
  1003. </html>
  1004. <?php
  1005. if (function_exists('exit_handler'))
  1006. {
  1007. exit_handler();
  1008. }
  1009. }
  1010. // Schema updates
  1011. ?>
  1012. <br /><br />
  1013. <h1><?php echo $lang['UPDATE_DATABASE_SCHEMA']; ?></h1>
  1014. <br />
  1015. <p><?php echo $lang['PROGRESS']; ?> :: <strong>
  1016. <?php
  1017. flush();
  1018. // We go through the schema changes from the lowest to the highest version
  1019. // We try to also include versions 'in-between'...
  1020. $no_updates = true;
  1021. $versions = array_keys($database_update_info);
  1022. for ($i = 0; $i < sizeof($versions); $i++)
  1023. {
  1024. $version = $versions[$i];
  1025. $schema_changes = $database_update_info[$version];
  1026. $next_version = (isset($versions[$i + 1])) ? $versions[$i + 1] : $updates_to_version;
  1027. // If the installed version to be updated to is < than the current version, and if the current version is >= as the version to be updated to next, we will skip the process
  1028. if (version_compare($version, $current_version, '<') && version_compare($current_version, $next_version, '>='))
  1029. {
  1030. continue;
  1031. }
  1032. /* if ($debug_from_version !== false)
  1033. {
  1034. // Applying update schema for version array with key '$version'
  1035. // for version '$version' to '$next_version'
  1036. continue;
  1037. }*/
  1038. if (!sizeof($schema_changes))
  1039. {
  1040. continue;
  1041. }
  1042. $no_updates = false;
  1043. // Change columns?
  1044. if (!empty($schema_changes['change_columns']))
  1045. {
  1046. foreach ($schema_changes['change_columns'] as $table => $columns)
  1047. {
  1048. foreach ($columns as $column_name => $column_data)
  1049. {
  1050. sql_column_change($map_dbms, $table, $column_name, $column_data);
  1051. }
  1052. }
  1053. }
  1054. // Add columns?
  1055. if (!empty($schema_changes['add_columns']))
  1056. {
  1057. foreach ($schema_changes['add_columns'] as $table => $columns)
  1058. {
  1059. foreach ($columns as $column_name => $column_data)
  1060. {
  1061. // Only add the column if it does not exist yet
  1062. if (!column_exists($map_dbms, $table, $column_name))
  1063. {
  1064. sql_column_add($map_dbms, $table, $column_name, $column_data);
  1065. }
  1066. }
  1067. }
  1068. }
  1069. // Remove keys?
  1070. if (!empty($schema_changes['drop_keys']))
  1071. {
  1072. foreach ($schema_changes['drop_keys'] as $table => $indexes)
  1073. {
  1074. foreach ($indexes as $index_name)
  1075. {
  1076. sql_index_drop($map_dbms, $index_name, $table);
  1077. }
  1078. }
  1079. }
  1080. // Drop columns?
  1081. if (!empty($schema_changes['drop_columns']))
  1082. {
  1083. foreach ($schema_changes['drop_columns'] as $table => $columns)
  1084. {
  1085. foreach ($columns as $column)
  1086. {
  1087. sql_column_remove($map_dbms, $table, $column);
  1088. }
  1089. }
  1090. }
  1091. // Add primary keys?
  1092. if (!empty($schema_changes['add_primary_keys']))
  1093. {
  1094. foreach ($schema_changes['add_primary_keys'] as $table => $columns)
  1095. {
  1096. sql_create_primary_key($map_dbms, $table, $columns);
  1097. }
  1098. }
  1099. // Add unqiue indexes?
  1100. if (!empty($schema_changes['add_unique_index']))
  1101. {
  1102. foreach ($schema_changes['add_unique_index'] as $table => $index_array)
  1103. {
  1104. foreach ($index_array as $index_name => $column)
  1105. {
  1106. sql_create_unique_index($map_dbms, $index_name, $table, $column);
  1107. }
  1108. }
  1109. }
  1110. // Add indexes?
  1111. if (!empty($schema_changes['add_index']))
  1112. {
  1113. foreach ($schema_changes['add_index'] as $table => $index_array)
  1114. {
  1115. foreach ($index_array as $index_name => $column)
  1116. {
  1117. sql_create_index($map_dbms, $index_name, $table, $column);
  1118. }
  1119. }
  1120. }
  1121. }
  1122. _write_result($no_updates, $errored, $error_ary);
  1123. // Data updates
  1124. $error_ary = array();
  1125. $errored = $no_updates = false;
  1126. ?>
  1127. <br /><br />
  1128. <h1><?php echo $lang['UPDATING_DATA']; ?></h1>
  1129. <br />
  1130. <p><?php echo $lang['PROGRESS']; ?> :: <strong>
  1131. <?php
  1132. flush();
  1133. $no_updates = true;
  1134. $versions = array_keys($database_update_info);
  1135. // some code magic
  1136. for ($i = 0; $i < sizeof($versions); $i++)
  1137. {
  1138. $version = $versions[$i];
  1139. $next_version = (isset($versions[$i + 1])) ? $versions[$i + 1] : $updates_to_version;
  1140. // If the installed version to be updated to is < than the current version, and if the current version is >= as the version to be updated to next, we will skip the process
  1141. if (version_compare($version, $current_version, '<') && version_compare($current_version, $next_version, '>='))
  1142. {
  1143. continue;
  1144. }
  1145. /* if ($debug_from_version !== false)
  1146. {
  1147. // Applying update schema for version array with key '$version'
  1148. // for version '$version' to '$next_version'
  1149. continue;
  1150. }*/
  1151. change_database_data($no_updates, $version);
  1152. }
  1153. _write_result($no_updates, $errored, $error_ary);
  1154. $error_ary = array();
  1155. $errored = $no_updates = false;
  1156. ?>
  1157. <br /><br />
  1158. <h1><?php echo $lang['UPDATE_VERSION_OPTIMIZE']; ?></h1>
  1159. <br />
  1160. <p><?php echo $lang['PROGRESS']; ?> :: <strong>
  1161. <?php
  1162. flush();
  1163. //if ($debug_from_version === false)
  1164. // {
  1165. // update the version
  1166. $sql = "UPDATE " . CONFIG_TABLE . "
  1167. SET config_value = '$updates_to_version'
  1168. WHERE config_name = 'version'";
  1169. _sql($sql, $errored, $error_ary);
  1170. // Reset permissions
  1171. $sql = 'UPDATE ' . USERS_TABLE . "
  1172. SET user_permissions = '',
  1173. user_perm_from = 0";
  1174. _sql($sql, $errored, $error_ary);
  1175. // }
  1176. /* Optimize/vacuum analyze the tables where appropriate
  1177. // this should be done for each version in future along with
  1178. // the version number update
  1179. switch ($db->sql_layer)
  1180. {
  1181. case 'mysql':
  1182. case 'mysqli':
  1183. case 'mysql4':
  1184. $sql = 'OPTIMIZE TABLE ' . $table_prefix . 'auth_access, ' . $table_prefix . 'banlist, ' . $table_prefix . 'categories, ' . $table_prefix . 'config, ' . $table_prefix . 'disallow, ' . $table_prefix . 'forum_prune, ' . $table_prefix . 'forums, ' . $table_prefix . 'groups, ' . $table_prefix . 'posts, ' . $table_prefix . 'posts_text, ' . $table_prefix . 'privmsgs, ' . $table_prefix . 'privmsgs_text, ' . $table_prefix . 'ranks, ' . $table_prefix . 'search_results, ' . $table_prefix . 'search_wordlist, ' . $table_prefix . 'search_wordmatch, ' . $table_prefix . 'sessions_keys' . $table_prefix . 'smilies, ' . $table_prefix . 'themes, ' . $table_prefix . 'themes_name, ' . $table_prefix . 'topics, ' . $table_prefix . 'topics_watch, ' . $table_prefix . 'user_group, ' . $table_prefix . 'users, ' . $table_prefix . 'vote_desc, ' . $table_prefix . 'vote_results, ' . $table_prefix . 'vote_voters, ' . $table_prefix . 'words';
  1185. _sql($sql, $errored, $error_ary);
  1186. break;
  1187. case 'postgresql':
  1188. _sql("VACUUM ANALYZE", $errored, $error_ary);
  1189. break;
  1190. }
  1191. */
  1192. _write_result($no_updates, $errored, $error_ary);
  1193. ?>
  1194. <br />
  1195. <h1><?php echo $lang['UPDATE_COMPLETED']; ?></h1>
  1196. <br />
  1197. <?php
  1198. if (!$inline_update)
  1199. {
  1200. // Purge the cache...
  1201. $cache->purge();
  1202. ?>
  1203. <p style="color:red"><?php echo $lang['UPDATE_FILES_NOTICE']; ?></p>
  1204. <p><?php echo $lang['COMPLETE_LOGIN_TO_BOARD']; ?></p>
  1205. <?php
  1206. }
  1207. else
  1208. {
  1209. ?>
  1210. <p><?php echo ((isset($lang['INLINE_UPDATE_SUCCESSFUL'])) ? $lang['INLINE_UPDATE_SUCCESSFUL'] : 'The database update was successful. Now you need to continue the update process.'); ?></p>
  1211. <p><a href="<?php echo append_sid("{$phpbb_root_path}install/index.{$phpEx}", "mode=update&amp;sub=file_check&amp;lang=$language"); ?>" class="button1"><?php echo (isset($lang['CONTINUE_UPDATE_NOW'])) ? $lang['CONTINUE_UPDATE_NOW'] : 'Continue the update process now'; ?></a></p>
  1212. <?php
  1213. }
  1214. // Add database update to log
  1215. add_log('admin', 'LOG_UPDATE_DATABASE', $orig_version, $updates_to_version);
  1216. // Now we purge the session table as well as all cache files
  1217. $cache->purge();
  1218. ?>
  1219. </div>
  1220. </div>
  1221. <span class="corners-bottom"><span></span></span>
  1222. </div>
  1223. </div>
  1224. </div>
  1225. <div id="page-footer">
  1226. Powered by phpBB &copy; 2000, 2002, 2005, 2007 <a href="http://www.phpbb.com/">phpBB Group</a>
  1227. </div>
  1228. </div>
  1229. </body>
  1230. </html>
  1231. <?php
  1232. garbage_collection();
  1233. if (function_exists('exit_handler'))
  1234. {
  1235. exit_handler();
  1236. }
  1237. /**
  1238. * Function where all data changes are executed
  1239. */
  1240. function change_database_data(&$no_updates, $version)
  1241. {
  1242. global $db, $map_dbms, $errored, $error_ary, $config, $phpbb_root_path, $phpEx;
  1243. switch ($version)
  1244. {
  1245. case '3.0.RC2':
  1246. $smileys = array();
  1247. $sql = 'SELECT smiley_id, code
  1248. FROM ' . SMILIES_TABLE;
  1249. $result = $db->sql_query($sql);
  1250. while ($row = $db->sql_fetchrow($result))
  1251. {
  1252. $smileys[$row['smiley_id']] = $row['code'];
  1253. }
  1254. $db->sql_freeresult($result);
  1255. foreach ($smileys as $id => $code)
  1256. {
  1257. // 2.0 only entitized lt and gt; We need to do something about double quotes.
  1258. if (strchr($code, '"') === false)
  1259. {
  1260. continue;
  1261. }
  1262. $new_code = str_replace('&amp;', '&', $code);
  1263. $new_code = str_replace('&lt;', '<', $new_code);
  1264. $new_code = str_replace('&gt;', '>', $new_code);
  1265. $new_code = utf8_htmlspecialchars($new_code);
  1266. $sql = 'UPDATE ' . SMILIES_TABLE . '
  1267. SET code = \'' . $db->sql_escape($new_code) . '\'
  1268. WHERE smiley_id = ' . (int) $id;
  1269. $db->sql_query($sql);
  1270. }
  1271. $index_list = sql_list_index($map_dbms, ACL_ROLES_DATA_TABLE);
  1272. if (in_array('ath_opt_id', $index_list))
  1273. {
  1274. sql_index_drop($map_dbms, 'ath_opt_id', ACL_ROLES_DATA_TABLE);
  1275. sql_create_index($map_dbms, 'ath_op_id', ACL_ROLES_DATA_TABLE, array('auth_option_id'));
  1276. }
  1277. $no_updates = false;
  1278. break;
  1279. case '3.0.RC3':
  1280. if ($map_dbms === 'postgres')
  1281. {
  1282. $sql = "SELECT SETVAL('" . FORUMS_TABLE . "_seq',(select case when max(forum_id)>0 then max(forum_id)+1 else 1 end from " . FORUMS_TABLE . '));';
  1283. _sql($sql, $errored, $error_ary);
  1284. }
  1285. // we check for:
  1286. // ath_opt_id
  1287. // ath_op_id
  1288. // ACL_ROLES_DATA_TABLE_ath_opt_id
  1289. // we want ACL_ROLES_DATA_TABLE_ath_op_id
  1290. $table_index_fix = array(
  1291. ACL_ROLES_DATA_TABLE => array(
  1292. 'ath_opt_id' => 'ath_op_id',
  1293. 'ath_op_id' => 'ath_op_id',
  1294. ACL_ROLES_DATA_TABLE . '_ath_opt_id' => 'ath_op_id'
  1295. ),
  1296. STYLES_IMAGESET_DATA_TABLE => array(
  1297. 'i_id' => 'i_d',
  1298. 'i_d' => 'i_d',
  1299. STYLES_IMAGESET_DATA_TABLE . '_i_id' => 'i_d'
  1300. )
  1301. );
  1302. // we need to create some indicies...
  1303. $needed_creation = array();
  1304. foreach ($table_index_fix as $table_name => $index_info)
  1305. {
  1306. $index_list = sql_list_fake($map_dbms, $table_name);
  1307. foreach ($index_info as $bad_index => $good_index)
  1308. {
  1309. if (in_array($bad_index, $index_list))
  1310. {
  1311. // mysql is actually OK, it won't get a hand in this crud
  1312. switch ($map_dbms)
  1313. {
  1314. // last version, mssql had issues with index removal
  1315. case 'mssql':
  1316. $sql = 'DROP INDEX ' . $table_name . '.' . $bad_index;
  1317. _sql($sql, $errored, $error_ary);
  1318. break;
  1319. // last version, firebird, oracle, postgresql and sqlite all got bad index names
  1320. // we got kinda lucky, tho: they all support the same syntax
  1321. case 'firebird':
  1322. case 'oracle':
  1323. case 'postgres':
  1324. case 'sqlite':
  1325. $sql = 'DROP INDEX ' . $bad_index;
  1326. _sql($sql, $errored, $error_ary);
  1327. break;
  1328. }
  1329. // If the good index already exist we do not need to create it again...
  1330. if (($map_dbms == 'mysql_40' || $map_dbms == 'mysql_41') && $bad_index == $good_index)
  1331. {
  1332. }
  1333. else
  1334. {
  1335. $needed_creation[$table_name][$good_index] = 1;
  1336. }
  1337. }
  1338. }
  1339. }
  1340. $new_index_defs = array('ath_op_id' => array('auth_option_id'), 'i_d' => array('imageset_id'));
  1341. foreach ($needed_creation as $bad_table => $index_repair_list)
  1342. {
  1343. foreach ($index_repair_list as $new_index => $garbage)
  1344. {
  1345. sql_create_index($map_dbms, $new_index, $bad_table, $new_index_defs[$new_index]);
  1346. }
  1347. }
  1348. // Make sure empty smiley codes do not exist
  1349. $sql = 'DELETE FROM ' . SMILIES_TABLE . "
  1350. WHERE code = ''";
  1351. _sql($sql, $errored, $error_ary);
  1352. set_config('allow_birthdays', '1');
  1353. set_config('cron_lock', '0', true);
  1354. $no_updates = false;
  1355. break;
  1356. case '3.0.RC4':
  1357. $update_auto_increment = array(
  1358. STYLES_TABLE => 'style_id',
  1359. STYLES_TEMPLATE_TABLE => 'template_id',
  1360. STYLES_THEME_TABLE => 'theme_id',
  1361. STYLES_IMAGESET_TABLE => 'imageset_id'
  1362. );
  1363. $sql = 'SELECT *
  1364. FROM ' . STYLES_TABLE . '
  1365. WHERE style_id = 0';
  1366. $result = _sql($sql, $errored, $error_ary);
  1367. $bad_style_row = $db->sql_fetchrow($result);
  1368. $db->sql_freeresult($result);
  1369. if ($bad_style_row)
  1370. {
  1371. $sql = 'SELECT MAX(style_id) as max_id
  1372. FROM ' . STYLES_TABLE;
  1373. $result = _sql($sql, $errored, $error_ary);
  1374. $row = $db->sql_fetchrow($result);
  1375. $db->sql_freeresult($result);
  1376. $proper_id = $row['max_id'] + 1;
  1377. _sql('UPDATE ' . STYLES_TABLE . " SET style_id = $proper_id WHERE style_id = 0", $errored, $error_ary);
  1378. _sql('UPDATE ' . FORUMS_TABLE . " SET forum_style = $proper_id WHERE forum_style = 0", $errored, $error_ary);
  1379. _sql('UPDATE ' . USERS_TABLE . " SET user_style = $proper_id WHERE user_style = 0", $errored, $error_ary);
  1380. $sql = 'SELECT config_value
  1381. FROM ' . CONFIG_TABLE . "
  1382. WHERE config_name = 'default_style'";
  1383. $result = _sql($sql, $errored, $error_ary);
  1384. $style_config = $db->sql_fetchrow($result);
  1385. $db->sql_freeresult($result);
  1386. if ($style_config['config_value'] === '0')
  1387. {
  1388. set_config('default_style', (string) $proper_id);
  1389. }
  1390. }
  1391. $sql = 'SELECT *
  1392. FROM ' . STYLES_TEMPLATE_TABLE . '
  1393. WHERE template_id = 0';
  1394. $result = _sql($sql, $errored, $error_ary);
  1395. $bad_style_row = $db->sql_fetchrow($result);
  1396. $db->sql_freeresult($result);
  1397. if ($bad_style_row)
  1398. {
  1399. $sql = 'SELECT MAX(template_id) as max_id
  1400. FROM ' . STYLES_TEMPLATE_TABLE;
  1401. $result = _sql($sql, $errored, $error_ary);
  1402. $row = $db->sql_fetchrow($result);
  1403. $db->sql_freeresult($result);
  1404. $proper_id = $row['max_id'] + 1;
  1405. _sql('UPDATE ' . STYLES_TABLE . " SET template_id = $proper_id WHERE template_id = 0", $errored, $error_ary);
  1406. }
  1407. $sql = 'SELECT *
  1408. FROM ' . STYLES_THEME_TABLE . '
  1409. WHERE theme_id = 0';
  1410. $result = _sql($sql, $errored, $error_ary);
  1411. $bad_style_row = $db->sql_fetchrow($result);
  1412. $db->sql_freeresult($result);
  1413. if ($bad_style_row)
  1414. {
  1415. $sql = 'SELECT MAX(theme_id) as max_id
  1416. FROM ' . STYLES_THEME_TABLE;
  1417. $result = _sql($sql, $errored, $error_ary);
  1418. $row = $db->sql_fetchrow($result);
  1419. $db->sql_freeresult($result);
  1420. $proper_id = $row['max_id'] + 1;
  1421. _sql('UPDATE ' . STYLES_TABLE . " SET theme_id = $proper_id WHERE theme_id = 0", $errored, $error_ary);
  1422. }
  1423. $sql = 'SELECT *
  1424. FROM ' . STYLES_IMAGESET_TABLE . '
  1425. WHERE imageset_id = 0';
  1426. $result = _sql($sql, $errored, $error_ary);
  1427. $bad_style_row = $db->sql_fetchrow($result);
  1428. $db->sql_freeresult($result);
  1429. if ($bad_style_row)
  1430. {
  1431. $sql = 'SELECT MAX(imageset_id) as max_id
  1432. FROM ' . STYLES_IMAGESET_TABLE;
  1433. $result = _sql($sql, $errored, $error_ary);
  1434. $row = $db->sql_fetchrow($result);
  1435. $db->sql_freeresult($result);
  1436. $proper_id = $row['max_id'] + 1;
  1437. _sql('UPDATE ' . STYLES_TABLE . " SET imageset_id = $proper_id WHERE imageset_id = 0", $errored, $error_ary);
  1438. _sql('UPDATE ' . STYLES_IMAGESET_DATA_TABLE . " SET imageset_id = $proper_id WHERE imageset_id = 0", $errored, $error_ary);
  1439. }
  1440. if ($map_dbms == 'mysql_40' || $map_dbms == 'mysql_41')
  1441. {
  1442. foreach ($update_auto_increment as $auto_table_name => $auto_column_name)
  1443. {
  1444. $sql = "SELECT MAX({$auto_column_name}) as max_id
  1445. FROM {$auto_table_name}";
  1446. $result = _sql($sql, $errored, $error_ary);
  1447. $row = $db->sql_fetchrow($result);
  1448. $db->sql_freeresult($result);
  1449. $max_id = ((int) $row['max_id']) + 1;
  1450. _sql("ALTER TABLE {$auto_table_name} AUTO_INCREMENT = {$max_id}", $errored, $error_ary);
  1451. }
  1452. }
  1453. else if ($map_dbms == 'postgres')
  1454. {
  1455. foreach ($update_auto_increment as $auto_table_name => $auto_column_name)
  1456. {
  1457. $sql = "SELECT SETVAL('" . $auto_table_name . "_seq',(select case when max({$auto_column_name})>0 then max({$auto_column_name})+1 else 1 end from " . $auto_table_name . '));';
  1458. _sql($sql, $errored, $error_ary);
  1459. }
  1460. $sql = 'DROP SEQUENCE ' . STYLES_TEMPLATE_DATA_TABLE . '_seq';
  1461. _sql($sql, $errored, $error_ary);
  1462. }
  1463. else if ($map_dbms == 'firebird')
  1464. {
  1465. $sql = 'DROP TRIGGER t_' . STYLES_TEMPLATE_DATA_TABLE;
  1466. _sql($sql, $errored, $error_ary);
  1467. $sql = 'DROP GENERATOR ' . STYLES_TEMPLATE_DATA_TABLE . '_gen';
  1468. _sql($sql, $errored, $error_ary);
  1469. }
  1470. else if ($map_dbms == 'oracle')
  1471. {
  1472. $sql = 'DROP TRIGGER t_' . STYLES_TEMPLATE_DATA_TABLE;
  1473. _sql($sql, $errored, $error_ary);
  1474. $sql = 'DROP SEQUENCE ' . STYLES_TEMPLATE_DATA_TABLE . '_seq';
  1475. _sql($sql, $errored, $error_ary);
  1476. }
  1477. else if ($map_dbms == 'mssql')
  1478. {
  1479. // we use transactions because we need to have a working DB at the end of all of this
  1480. $db->sql_transaction('begin');
  1481. $sql = 'SELECT *
  1482. FROM ' . STYLES_TEMPLATE_DATA_TABLE;
  1483. $result = _sql($sql, $errored, $error_ary);
  1484. $old_style_rows = array();
  1485. while ($row = $db->sql_fetchrow($result))
  1486. {
  1487. $old_style_rows[] = $row;
  1488. }
  1489. $db->sql_freeresult($result);
  1490. // death to the table, it is evil!
  1491. $sql = 'DROP TABLE ' . STYLES_TEMPLATE_DATA_TABLE;
  1492. _sql($sql, $errored, $error_ary);
  1493. // the table of awesomeness, praise be to it (or something)
  1494. $sql = 'CREATE TABLE [' . STYLES_TEMPLATE_DATA_TABLE . "] (
  1495. [template_id] [int] DEFAULT (0) NOT NULL ,
  1496. [template_filename] [varchar] (100) DEFAULT ('') NOT NULL ,
  1497. [template_included] [varchar] (8000) DEFAULT ('') NOT NULL ,
  1498. [template_mtime] [int] DEFAULT (0) NOT NULL ,
  1499. [template_data] [text] DEFAULT ('') NOT NULL
  1500. ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]";
  1501. _sql($sql, $errored, $error_ary);
  1502. // index? index
  1503. $sql = 'CREATE INDEX [tid] ON [' . STYLES_TEMPLATE_DATA_TABLE . ']([template_id]) ON [PRIMARY]';
  1504. _sql($sql, $errored, $error_ary);
  1505. // yet another index
  1506. $sql = 'CREATE INDEX [tfn] ON [' . STYLES_TEMPLATE_DATA_TABLE . ']([template_filename]) ON [PRIMARY]';
  1507. _sql($sql, $errored, $error_ary);
  1508. foreach ($old_style_rows as $return_row)
  1509. {
  1510. _sql('INSERT INTO ' . STYLES_TEMPLATE_DATA_TABLE . ' ' . $db->sql_build_array('INSERT', $return_row), $errored, $error_ary);
  1511. }
  1512. $db->sql_transaction('commit');
  1513. }
  1514. // Setting this here again because new installations may not have it...
  1515. set_config('cron_lock', '0', true);
  1516. set_config('ldap_port', '');
  1517. set_config('ldap_user_filter', '');
  1518. $no_updates = false;
  1519. break;
  1520. case '3.0.RC5':
  1521. // In case the user is having the bot mediapartner google "as is", adjust it.
  1522. $sql = 'UPDATE ' . BOTS_TABLE . "
  1523. SET bot_agent = '" . $db->sql_escape('Mediapartners-Google') . "'
  1524. WHERE bot_agent = '" . $db->sql_escape('Mediapartners-Google/') . "'";
  1525. _sql($sql, $errored, $error_ary);
  1526. set_config('form_token_lifetime', '7200');
  1527. set_config('form_token_mintime', '0');
  1528. set_config('min_time_reg', '5');
  1529. set_config('min_time_terms', '2');
  1530. set_config('form_token_sid_guests', '1');
  1531. $db->sql_transaction('begin');
  1532. $sql = 'SELECT forum_id, forum_password
  1533. FROM ' . FORUMS_TABLE;
  1534. $result = _sql($sql, $errored, $error_ary);
  1535. while ($row = $db->sql_fetchrow($result))
  1536. {
  1537. if (!empty($row['forum_password']))
  1538. {
  1539. _sql('UPDATE ' . FORUMS_TABLE . " SET forum_password = '" . md5($row['forum_password']) . "' WHERE forum_id = {$row['forum_id']}", $errored, $error_ary);
  1540. }
  1541. }
  1542. $db->sql_freeresult($result);
  1543. $db->sql_transaction('commit');
  1544. $no_updates = false;
  1545. break;
  1546. case '3.0.0':
  1547. $sql = 'UPDATE ' . TOPICS_TABLE . "
  1548. SET topic_last_view_time = topic_last_post_time
  1549. WHERE topic_last_view_time = 0";
  1550. _sql($sql, $errored, $error_ary);
  1551. // Update smiley sizes
  1552. $smileys = array('icon_e_surprised.gif', 'icon_eek.gif', 'icon_cool.gif', 'icon_lol.gif', 'icon_mad.gif', 'icon_razz.gif', 'icon_redface.gif', 'icon_cry.gif', 'icon_evil.gif', 'icon_twisted.gif', 'icon_rolleyes.gif', 'icon_exclaim.gif', 'icon_question.gif', 'icon_idea.gif', 'icon_arrow.gif', 'icon_neutral.gif', 'icon_mrgreen.gif', 'icon_e_ugeek.gif');
  1553. foreach ($smileys as $smiley)
  1554. {
  1555. if (file_exists($phpbb_root_path . 'images/smilies/' . $smiley))
  1556. {
  1557. list($width, $height) = getimagesize($phpbb_root_path . 'images/smilies/' . $smiley);
  1558. $sql = 'UPDATE ' . SMILIES_TABLE . '
  1559. SET smiley_width = ' . $width . ', smiley_height = ' . $height . "
  1560. WHERE smiley_url = '" . $db->sql_escape($smiley) . "'";
  1561. _sql($sql, $errored, $error_ary);
  1562. }
  1563. }
  1564. $no_updates = false;
  1565. break;
  1566. // No changes from 3.0.1-RC1 to 3.0.1
  1567. case '3.0.1-RC1':
  1568. break;
  1569. // changes from 3.0.1 to 3.0.2-RC1
  1570. case '3.0.1':
  1571. set_config('referer_validation', '1');
  1572. set_config('check_attachment_content', '1');
  1573. set_config('mime_triggers', 'body|head|html|img|plaintext|a href|pre|script|table|title');
  1574. $no_updates = false;
  1575. break;
  1576. // No changes from 3.0.2-RC1 to 3.0.2-RC2
  1577. case '3.0.2-RC1':
  1578. break;
  1579. // No changes from 3.0.2-RC2 to 3.0.2
  1580. case '3.0.2-RC2':
  1581. break;
  1582. // Changes from 3.0.2 to 3.0.3-RC1
  1583. case '3.0.2':
  1584. set_config('enable_queue_trigger', '0');
  1585. set_config('queue_trigger_posts', '3');
  1586. set_config('pm_max_recipients', '0');
  1587. // Set maximum number of recipients for the registered users, bots, guests group
  1588. $sql = 'UPDATE ' . GROUPS_TABLE . ' SET group_max_recipients = 5
  1589. WHERE ' . $db->sql_in_set('group_name', array('GUESTS', 'REGISTERED', 'REGISTERED_COPPA', 'BOTS'));
  1590. _sql($sql, $errored, $error_ary);
  1591. // Not prefilling yet
  1592. set_config('dbms_version', '');
  1593. // Add new permission u_masspm_group and duplicate settings from u_masspm
  1594. include_once($phpbb_root_path . 'includes/acp/auth.' . $phpEx);
  1595. $auth_admin = new auth_admin();
  1596. // Only add the new permission if it does not already exist
  1597. if (empty($auth_admin->acl_options['id']['u_masspm_group']))
  1598. {
  1599. $auth_admin->acl_add_option(array('global' => array('u_masspm_group')));
  1600. // Now the tricky part, filling the permission
  1601. $old_id = $auth_admin->acl_options['id']['u_masspm'];
  1602. $new_id = $auth_admin->acl_options['id']['u_masspm_group'];
  1603. $tables = array(ACL_GROUPS_TABLE, ACL_ROLES_DATA_TABLE, ACL_USERS_TABLE);
  1604. foreach ($tables as $table)
  1605. {
  1606. $sql = 'SELECT *
  1607. FROM ' . $table . '
  1608. WHERE auth_option_id = ' . $old_id;
  1609. $result = _sql($sql, $errored, $error_ary);
  1610. $sql_ary = array();
  1611. while ($row = $db->sql_fetchrow($result))
  1612. {
  1613. $row['auth_option_id'] = $new_id;
  1614. $sql_ary[] = $row;
  1615. }
  1616. $db->sql_freeresult($result);
  1617. if (sizeof($sql_ary))
  1618. {
  1619. $db->sql_multi_insert($table, $sql_ary);
  1620. }
  1621. }
  1622. // Remove any old permission entries
  1623. $auth_admin->acl_clear_prefetch();
  1624. }
  1625. /**
  1626. * Do not resync post counts here. An admin may do this later from the ACP
  1627. $start = 0;
  1628. $step = ($config['num_posts']) ? (max((int) ($config['num_posts'] / 5), 20000)) : 20000;
  1629. $sql = 'UPDATE ' . USERS_TABLE . ' SET user_posts = 0';
  1630. _sql($sql, $errored, $error_ary);
  1631. do
  1632. {
  1633. $sql = 'SELECT COUNT(post_id) AS num_posts, poster_id
  1634. FROM ' . POSTS_TABLE . '
  1635. WHERE post_id BETWEEN ' . ($start + 1) . ' AND ' . ($start + $step) . '
  1636. AND post_postcount = 1 AND post_approved = 1
  1637. GROUP BY poster_id';
  1638. $result = _sql($sql, $errored, $error_ary);
  1639. if ($row = $db->sql_fetchrow($result))
  1640. {
  1641. do
  1642. {
  1643. $sql = 'UPDATE ' . USERS_TABLE . " SET user_posts = user_posts + {$row['num_posts']} WHERE user_id = {$row['poster_id']}";
  1644. _sql($sql, $errored, $error_ary);
  1645. }
  1646. while ($row = $db->sql_fetchrow($result));
  1647. $start += $step;
  1648. }
  1649. else
  1650. {
  1651. $start = 0;
  1652. }
  1653. $db->sql_freeresult($result);
  1654. }
  1655. while ($start);
  1656. */
  1657. $sql = 'UPDATE ' . MODULES_TABLE . '
  1658. SET module_auth = \'acl_a_email && cfg_email_enable\'
  1659. WHERE module_class = \'acp\'
  1660. AND module_basename = \'email\'';
  1661. _sql($sql, $errored, $error_ary);
  1662. $no_updates = false;
  1663. break;
  1664. // Changes from 3.0.3-RC1 to 3.0.3
  1665. case '3.0.3-RC1':
  1666. $sql = 'UPDATE ' . LOG_TABLE . "
  1667. SET log_operation = 'LOG_DELETE_TOPIC'
  1668. WHERE log_operation = 'LOG_TOPIC_DELETED'";
  1669. _sql($sql, $errored, $error_ary);
  1670. $no_updates = false;
  1671. break;
  1672. }
  1673. }
  1674. /**
  1675. * Function for triggering an sql statement
  1676. */
  1677. function _sql($sql, &$errored, &$error_ary, $echo_dot = true)
  1678. {
  1679. global $db;
  1680. if (defined('DEBUG_EXTRA'))
  1681. {
  1682. echo "<br />\n{$sql}\n<br />";
  1683. }
  1684. $db->sql_return_on_error(true);
  1685. $result = $db->sql_query($sql);
  1686. if ($db->sql_error_triggered)
  1687. {
  1688. $errored = true;
  1689. $error_ary['sql'][] = $db->sql_error_sql;
  1690. $error_ary['error_code'][] = $db->_sql_error();
  1691. }
  1692. $db->sql_return_on_error(false);
  1693. if ($echo_dot)
  1694. {
  1695. echo ". \n";
  1696. flush();
  1697. }
  1698. return $result;
  1699. }
  1700. function _write_result($no_updates, $errored, $error_ary)
  1701. {
  1702. global $lang;
  1703. if ($no_updates)
  1704. {
  1705. echo ' ' . $lang['NO_UPDATES_REQUIRED'] . '</strong></p>';
  1706. }
  1707. else
  1708. {
  1709. echo ' <span class="success">' . $lang['DONE'] . '</span></strong><br />' . $lang['RESULT'] . ' :: ';
  1710. if ($errored)
  1711. {
  1712. echo ' <strong>' . $lang['SOME_QUERIES_FAILED'] . '</strong> <ul>';
  1713. for ($i = 0; $i < sizeof($error_ary['sql']); $i++)
  1714. {
  1715. echo '<li>' . $lang['ERROR'] . ' :: <strong>' . htmlspecialchars($error_ary['error_code'][$i]['message']) . '</strong><br />';
  1716. echo $lang['SQL'] . ' :: <strong>' . htmlspecialchars($error_ary['sql'][$i]) . '</strong><br /><br /></li>';
  1717. }
  1718. echo '</ul> <br /><br />' . $lang['SQL_FAILURE_EXPLAIN'] . '</p>';
  1719. }
  1720. else
  1721. {
  1722. echo '<strong>' . $lang['NO_ERRORS'] . '</strong></p>';
  1723. }
  1724. }
  1725. }
  1726. /**
  1727. * Check if a specified column exist
  1728. */
  1729. function column_exists($dbms, $table, $column_name)
  1730. {
  1731. global $db;
  1732. switch ($dbms)
  1733. {
  1734. case 'mysql_40':
  1735. case 'mysql_41':
  1736. $sql = "SHOW COLUMNS
  1737. FROM $table";
  1738. $result = $db->sql_query($sql);
  1739. while ($row = $db->sql_fetchrow($result))
  1740. {
  1741. // lower case just in case
  1742. if (strtolower($row['Field']) == $column_name)
  1743. {
  1744. $db->sql_freeresult($result);
  1745. return true;
  1746. }
  1747. }
  1748. $db->sql_freeresult($result);
  1749. return false;
  1750. break;
  1751. // PostgreSQL has a way of doing this in a much simpler way but would
  1752. // not allow us to support all versions of PostgreSQL
  1753. case 'postgres':
  1754. $sql = "SELECT a.attname
  1755. FROM pg_class c, pg_attribute a
  1756. WHERE c.relname = '{$table}'
  1757. AND a.attnum > 0
  1758. AND a.attrelid = c.oid";
  1759. $result = $db->sql_query($sql);
  1760. while ($row = $db->sql_fetchrow($result))
  1761. {
  1762. // lower case just in case
  1763. if (strtolower($row['attname']) == $column_name)
  1764. {
  1765. $db->sql_freeresult($result);
  1766. return true;
  1767. }
  1768. }
  1769. $db->sql_freeresult($result);
  1770. return false;
  1771. break;
  1772. // same deal with PostgreSQL, we must perform more complex operations than
  1773. // we technically could
  1774. case 'mssql':
  1775. $sql = "SELECT c.name
  1776. FROM syscolumns c
  1777. LEFT JOIN sysobjects o ON c.id = o.id
  1778. WHERE o.name = '{$table}'";
  1779. $result = $db->sql_query($sql);
  1780. while ($row = $db->sql_fetchrow($result))
  1781. {
  1782. // lower case just in case
  1783. if (strtolower($row['name']) == $column_name)
  1784. {
  1785. $db->sql_freeresult($result);
  1786. return true;
  1787. }
  1788. }
  1789. $db->sql_freeresult($result);
  1790. return false;
  1791. break;
  1792. case 'oracle':
  1793. $sql = "SELECT column_name
  1794. FROM user_tab_columns
  1795. WHERE table_name = '{$table}'";
  1796. $result = $db->sql_query($sql);
  1797. while ($row = $db->sql_fetchrow($result))
  1798. {
  1799. // lower case just in case
  1800. if (strtolower($row['column_name']) == $column_name)
  1801. {
  1802. $db->sql_freeresult($result);
  1803. return true;
  1804. }
  1805. }
  1806. $db->sql_freeresult($result);
  1807. return false;
  1808. break;
  1809. case 'firebird':
  1810. $sql = "SELECT RDB\$FIELD_NAME as FNAME
  1811. FROM RDB\$RELATION_FIELDS
  1812. WHERE RDB\$RELATION_NAME = '{$table}'";
  1813. $result = $db->sql_query($sql);
  1814. while ($row = $db->sql_fetchrow($result))
  1815. {
  1816. // lower case just in case
  1817. if (strtolower($row['fname']) == $column_name)
  1818. {
  1819. $db->sql_freeresult($result);
  1820. return true;
  1821. }
  1822. }
  1823. $db->sql_freeresult($result);
  1824. return false;
  1825. break;
  1826. // ugh, SQLite
  1827. case 'sqlite':
  1828. $sql = "SELECT sql
  1829. FROM sqlite_master
  1830. WHERE type = 'table'
  1831. AND name = '{$table}'";
  1832. $result = $db->sql_query($sql);
  1833. if (!$result)
  1834. {
  1835. return false;
  1836. }
  1837. $row = $db->sql_fetchrow($result);
  1838. $db->sql_freeresult($result);
  1839. preg_match('#\((.*)\)#s', $row['sql'], $matches);
  1840. $cols = trim($matches[1]);
  1841. $col_array = preg_split('/,(?![\s\w]+\))/m', $cols);
  1842. foreach ($col_array as $declaration)
  1843. {
  1844. $entities = preg_split('#\s+#', trim($declaration));
  1845. if ($entities[0] == 'PRIMARY')
  1846. {
  1847. continue;
  1848. }
  1849. if (strtolower($entities[0]) == $column_name)
  1850. {
  1851. return true;
  1852. }
  1853. }
  1854. return false;
  1855. break;
  1856. }
  1857. }
  1858. /**
  1859. * Function to prepare some column information for better usage
  1860. */
  1861. function prepare_column_data($dbms, $column_data, $table_name, $column_name)
  1862. {
  1863. global $dbms_type_map, $unsigned_types;
  1864. // Get type
  1865. if (strpos($column_data[0], ':') !== false)
  1866. {
  1867. list($orig_column_type, $column_length) = explode(':', $column_data[0]);
  1868. if (!is_array($dbms_type_map[$dbms][$orig_column_type . ':']))
  1869. {
  1870. $column_type = sprintf($dbms_type_map[$dbms][$orig_column_type . ':'], $column_length);
  1871. }
  1872. else
  1873. {
  1874. if (isset($dbms_type_map[$dbms][$orig_column_type . ':']['rule']))
  1875. {
  1876. switch ($dbms_type_map[$dbms][$orig_column_type . ':']['rule'][0])
  1877. {
  1878. case 'div':
  1879. $column_length /= $dbms_type_map[$dbms][$orig_column_type . ':']['rule'][1];
  1880. $column_length = ceil($column_length);
  1881. $column_type = sprintf($dbms_type_map[$dbms][$orig_column_type . ':'][0], $column_length);
  1882. break;
  1883. }
  1884. }
  1885. if (isset($dbms_type_map[$dbms][$orig_column_type . ':']['limit']))
  1886. {
  1887. switch ($dbms_type_map[$dbms][$orig_column_type . ':']['limit'][0])
  1888. {
  1889. case 'mult':
  1890. $column_length *= $dbms_type_map[$dbms][$orig_column_type . ':']['limit'][1];
  1891. if ($column_length > $dbms_type_map[$dbms][$orig_column_type . ':']['limit'][2])
  1892. {
  1893. $column_type = $dbms_type_map[$dbms][$orig_column_type . ':']['limit'][3];
  1894. }
  1895. else
  1896. {
  1897. $column_type = sprintf($dbms_type_map[$dbms][$orig_column_type . ':'][0], $column_length);
  1898. }
  1899. break;
  1900. }
  1901. }
  1902. }
  1903. $orig_column_type .= ':';
  1904. }
  1905. else
  1906. {
  1907. $orig_column_type = $column_data[0];
  1908. $column_type = $dbms_type_map[$dbms][$column_data[0]];
  1909. }
  1910. // Adjust default value if db-dependant specified
  1911. if (is_array($column_data[1]))
  1912. {
  1913. $column_data[1] = (isset($column_data[1][$dbms])) ? $column_data[1][$dbms] : $column_data[1]['default'];
  1914. }
  1915. $sql = '';
  1916. $return_array = array();
  1917. switch ($dbms)
  1918. {
  1919. case 'firebird':
  1920. $sql .= " {$column_type} ";
  1921. if (!is_null($column_data[1]))
  1922. {
  1923. $sql .= 'DEFAULT ' . ((is_numeric($column_data[1])) ? $column_data[1] : "'{$column_data[1]}'") . ' ';
  1924. }
  1925. $sql .= 'NOT NULL';
  1926. // This is a UNICODE column and thus should be given it's fair share
  1927. if (preg_match('/^X?STEXT_UNI|VCHAR_(CI|UNI:?)/', $column_data[0]))
  1928. {
  1929. $sql .= ' COLLATE UNICODE';
  1930. }
  1931. break;
  1932. case 'mssql':
  1933. $sql .= " {$column_type} ";
  1934. $sql_default = " {$column_type} ";
  1935. // For adding columns we need the default definition
  1936. if (!is_null($column_data[1]))
  1937. {
  1938. // For hexadecimal values do not use single quotes
  1939. if (strpos($column_data[1], '0x') === 0)
  1940. {
  1941. $sql_default .= 'DEFAULT (' . $column_data[1] . ') ';
  1942. }
  1943. else
  1944. {
  1945. $sql_default .= 'DEFAULT (' . ((is_numeric($column_data[1])) ? $column_data[1] : "'{$column_data[1]}'") . ') ';
  1946. }
  1947. }
  1948. $sql .= 'NOT NULL';
  1949. $sql_default .= 'NOT NULL';
  1950. $return_array['column_type_sql_default'] = $sql_default;
  1951. break;
  1952. case 'mysql_40':
  1953. case 'mysql_41':
  1954. $sql .= " {$column_type} ";
  1955. // For hexadecimal values do not use single quotes
  1956. if (!is_null($column_data[1]) && substr($column_type, -4) !== 'text' && substr($column_type, -4) !== 'blob')
  1957. {
  1958. $sql .= (strpos($column_data[1], '0x') === 0) ? "DEFAULT {$column_data[1]} " : "DEFAULT '{$column_data[1]}' ";
  1959. }
  1960. $sql .= 'NOT NULL';
  1961. if (isset($column_data[2]))
  1962. {
  1963. if ($column_data[2] == 'auto_increment')
  1964. {
  1965. $sql .= ' auto_increment';
  1966. }
  1967. else if ($dbms === 'mysql_41' && $column_data[2] == 'true_sort')
  1968. {
  1969. $sql .= ' COLLATE utf8_unicode_ci';
  1970. }
  1971. }
  1972. break;
  1973. case 'oracle':
  1974. $sql .= " {$column_type} ";
  1975. $sql .= (!is_null($column_data[1])) ? "DEFAULT '{$column_data[1]}' " : '';
  1976. // In Oracle empty strings ('') are treated as NULL.
  1977. // Therefore in oracle we allow NULL's for all DEFAULT '' entries
  1978. // Oracle does not like setting NOT NULL on a column that is already NOT NULL (this happens only on number fields)
  1979. if (preg_match('/number/i', $column_type))
  1980. {
  1981. $sql .= ($column_data[1] === '') ? '' : 'NOT NULL';
  1982. }
  1983. break;
  1984. case 'postgres':
  1985. $return_array['column_type'] = $column_type;
  1986. $sql .= " {$column_type} ";
  1987. if (isset($column_data[2]) && $column_data[2] == 'auto_increment')
  1988. {
  1989. $default_val = "nextval('{$table_name}_seq')";
  1990. }
  1991. else if (!is_null($column_data[1]))
  1992. {
  1993. $default_val = "'" . $column_data[1] . "'";
  1994. $return_array['null'] = 'NOT NULL';
  1995. $sql .= 'NOT NULL ';
  1996. }
  1997. $return_array['default'] = $default_val;
  1998. $sql .= "DEFAULT {$default_val}";
  1999. // Unsigned? Then add a CHECK contraint
  2000. if (in_array($orig_column_type, $unsigned_types))
  2001. {
  2002. $return_array['constraint'] = "CHECK ({$column_name} >= 0)";
  2003. $sql .= " CHECK ({$column_name} >= 0)";
  2004. }
  2005. break;
  2006. case 'sqlite':
  2007. if (isset($column_data[2]) && $column_data[2] == 'auto_increment')
  2008. {
  2009. $sql .= ' INTEGER PRIMARY KEY';
  2010. }
  2011. else
  2012. {
  2013. $sql .= ' ' . $column_type;
  2014. }
  2015. $sql .= ' NOT NULL ';
  2016. $sql .= (!is_null($column_data[1])) ? "DEFAULT '{$column_data[1]}'" : '';
  2017. break;
  2018. }
  2019. $return_array['column_type_sql'] = $sql;
  2020. return $return_array;
  2021. }
  2022. /**
  2023. * Add new column
  2024. */
  2025. function sql_column_add($dbms, $table_name, $column_name, $column_data)
  2026. {
  2027. global $errored, $error_ary;
  2028. $column_data = prepare_column_data($dbms, $column_data, $table_name, $column_name);
  2029. switch ($dbms)
  2030. {
  2031. case 'firebird':
  2032. $sql = 'ALTER TABLE "' . $table_name . '" ADD "' . $column_name . '" ' . $column_data['column_type_sql'];
  2033. _sql($sql, $errored, $error_ary);
  2034. break;
  2035. case 'mssql':
  2036. $sql = 'ALTER TABLE [' . $table_name . '] ADD [' . $column_name . '] ' . $column_data['column_type_sql_default'];
  2037. _sql($sql, $errored, $error_ary);
  2038. break;
  2039. case 'mysql_40':
  2040. case 'mysql_41':
  2041. $sql = 'ALTER TABLE `' . $table_name . '` ADD COLUMN `' . $column_name . '` ' . $column_data['column_type_sql'];
  2042. _sql($sql, $errored, $error_ary);
  2043. break;
  2044. case 'oracle':
  2045. $sql = 'ALTER TABLE ' . $table_name . ' ADD ' . $column_name . ' ' . $column_data['column_type_sql'];
  2046. _sql($sql, $errored, $error_ary);
  2047. break;
  2048. case 'postgres':
  2049. $sql = 'ALTER TABLE ' . $table_name . ' ADD COLUMN "' . $column_name . '" ' . $column_data['column_type_sql'];
  2050. _sql($sql, $errored, $error_ary);
  2051. break;
  2052. case 'sqlite':
  2053. if (version_compare(sqlite_libversion(), '3.0') == -1)
  2054. {
  2055. global $db;
  2056. $sql = "SELECT sql
  2057. FROM sqlite_master
  2058. WHERE type = 'table'
  2059. AND name = '{$table_name}'
  2060. ORDER BY type DESC, name;";
  2061. $result = $db->sql_query($sql);
  2062. if (!$result)
  2063. {
  2064. break;
  2065. }
  2066. $row = $db->sql_fetchrow($result);
  2067. $db->sql_freeresult($result);
  2068. $db->sql_transaction('begin');
  2069. // Create a backup table and populate it, destroy the existing one
  2070. $db->sql_query(preg_replace('#CREATE\s+TABLE\s+"?' . $table_name . '"?#i', 'CREATE TEMPORARY TABLE ' . $table_name . '_temp', $row['sql']));
  2071. $db->sql_query('INSERT INTO ' . $table_name . '_temp SELECT * FROM ' . $table_name);
  2072. $db->sql_query('DROP TABLE ' . $table_name);
  2073. preg_match('#\((.*)\)#s', $row['sql'], $matches);
  2074. $new_table_cols = trim($matches[1]);
  2075. $old_table_cols = preg_split('/,(?![\s\w]+\))/m', $new_table_cols);
  2076. $column_list = array();
  2077. foreach ($old_table_cols as $declaration)
  2078. {
  2079. $entities = preg_split('#\s+#', trim($declaration));
  2080. if ($entities[0] == 'PRIMARY')
  2081. {
  2082. continue;
  2083. }
  2084. $column_list[] = $entities[0];
  2085. }
  2086. $columns = implode(',', $column_list);
  2087. $new_table_cols = $column_name . ' ' . $column_data['column_type_sql'] . ',' . $new_table_cols;
  2088. // create a new table and fill it up. destroy the temp one
  2089. $db->sql_query('CREATE TABLE ' . $table_name . ' (' . $new_table_cols . ');');
  2090. $db->sql_query('INSERT INTO ' . $table_name . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . $table_name . '_temp;');
  2091. $db->sql_query('DROP TABLE ' . $table_name . '_temp');
  2092. $db->sql_transaction('commit');
  2093. }
  2094. else
  2095. {
  2096. $sql = 'ALTER TABLE ' . $table_name . ' ADD ' . $column_name . ' [' . $column_data['column_type_sql'] . ']';
  2097. _sql($sql, $errored, $error_ary);
  2098. }
  2099. break;
  2100. }
  2101. }
  2102. /**
  2103. * Drop column
  2104. */
  2105. function sql_column_remove($dbms, $table_name, $column_name)
  2106. {
  2107. global $errored, $error_ary;
  2108. switch ($dbms)
  2109. {
  2110. case 'firebird':
  2111. $sql = 'ALTER TABLE "' . $table_name . '" DROP "' . $column_name . '"';
  2112. _sql($sql, $errored, $error_ary);
  2113. break;
  2114. case 'mssql':
  2115. $sql = 'ALTER TABLE [' . $table_name . '] DROP COLUMN [' . $column_name . ']';
  2116. _sql($sql, $errored, $error_ary);
  2117. break;
  2118. case 'mysql_40':
  2119. case 'mysql_41':
  2120. $sql = 'ALTER TABLE `' . $table_name . '` DROP COLUMN `' . $column_name . '`';
  2121. _sql($sql, $errored, $error_ary);
  2122. break;
  2123. case 'oracle':
  2124. $sql = 'ALTER TABLE ' . $table_name . ' DROP ' . $column_name;
  2125. _sql($sql, $errored, $error_ary);
  2126. break;
  2127. case 'postgres':
  2128. $sql = 'ALTER TABLE ' . $table_name . ' DROP COLUMN "' . $column_name . '"';
  2129. _sql($sql, $errored, $error_ary);
  2130. break;
  2131. case 'sqlite':
  2132. if (version_compare(sqlite_libversion(), '3.0') == -1)
  2133. {
  2134. global $db;
  2135. $sql = "SELECT sql
  2136. FROM sqlite_master
  2137. WHERE type = 'table'
  2138. AND name = '{$table_name}'
  2139. ORDER BY type DESC, name;";
  2140. $result = $db->sql_query($sql);
  2141. if (!$result)
  2142. {
  2143. break;
  2144. }
  2145. $row = $db->sql_fetchrow($result);
  2146. $db->sql_freeresult($result);
  2147. $db->sql_transaction('begin');
  2148. // Create a backup table and populate it, destroy the existing one
  2149. $db->sql_query(preg_replace('#CREATE\s+TABLE\s+"?' . $table_name . '"?#i', 'CREATE TEMPORARY TABLE ' . $table_name . '_temp', $row['sql']));
  2150. $db->sql_query('INSERT INTO ' . $table_name . '_temp SELECT * FROM ' . $table_name);
  2151. $db->sql_query('DROP TABLE ' . $table_name);
  2152. preg_match('#\((.*)\)#s', $row['sql'], $matches);
  2153. $new_table_cols = trim($matches[1]);
  2154. $old_table_cols = preg_split('/,(?![\s\w]+\))/m', $new_table_cols);
  2155. $column_list = array();
  2156. foreach ($old_table_cols as $declaration)
  2157. {
  2158. $entities = preg_split('#\s+#', trim($declaration));
  2159. if ($entities[0] == 'PRIMARY' || $entities[0] === $column_name)
  2160. {
  2161. continue;
  2162. }
  2163. $column_list[] = $entities[0];
  2164. }
  2165. $columns = implode(',', $column_list);
  2166. $new_table_cols = $new_table_cols = preg_replace('/' . $column_name . '[^,]+(?:,|$)/m', '', $new_table_cols);
  2167. // create a new table and fill it up. destroy the temp one
  2168. $db->sql_query('CREATE TABLE ' . $table_name . ' (' . $new_table_cols . ');');
  2169. $db->sql_query('INSERT INTO ' . $table_name . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . $table_name . '_temp;');
  2170. $db->sql_query('DROP TABLE ' . $table_name . '_temp');
  2171. $db->sql_transaction('commit');
  2172. }
  2173. else
  2174. {
  2175. $sql = 'ALTER TABLE ' . $table_name . ' DROP COLUMN ' . $column_name;
  2176. _sql($sql, $errored, $error_ary);
  2177. }
  2178. break;
  2179. }
  2180. }
  2181. function sql_index_drop($dbms, $index_name, $table_name)
  2182. {
  2183. global $dbms_type_map, $db;
  2184. global $errored, $error_ary;
  2185. switch ($dbms)
  2186. {
  2187. case 'mssql':
  2188. $sql = 'DROP INDEX ' . $table_name . '.' . $index_name;
  2189. _sql($sql, $errored, $error_ary);
  2190. break;
  2191. case 'mysql_40':
  2192. case 'mysql_41':
  2193. $sql = 'DROP INDEX ' . $index_name . ' ON ' . $table_name;
  2194. _sql($sql, $errored, $error_ary);
  2195. break;
  2196. case 'firebird':
  2197. case 'oracle':
  2198. case 'postgres':
  2199. case 'sqlite':
  2200. $sql = 'DROP INDEX ' . $table_name . '_' . $index_name;
  2201. _sql($sql, $errored, $error_ary);
  2202. break;
  2203. }
  2204. }
  2205. function sql_create_primary_key($dbms, $table_name, $column)
  2206. {
  2207. global $dbms_type_map, $db;
  2208. global $errored, $error_ary;
  2209. switch ($dbms)
  2210. {
  2211. case 'firebird':
  2212. case 'postgres':
  2213. $sql = 'ALTER TABLE ' . $table_name . ' ADD PRIMARY KEY (' . implode(', ', $column) . ')';
  2214. _sql($sql, $errored, $error_ary);
  2215. break;
  2216. case 'mssql':
  2217. $sql = "ALTER TABLE [{$table_name}] WITH NOCHECK ADD ";
  2218. $sql .= "CONSTRAINT [PK_{$table_name}] PRIMARY KEY CLUSTERED (";
  2219. $sql .= '[' . implode("],\n\t\t[", $column) . ']';
  2220. $sql .= ') ON [PRIMARY]';
  2221. _sql($sql, $errored, $error_ary);
  2222. break;
  2223. case 'mysql_40':
  2224. case 'mysql_41':
  2225. $sql = 'ALTER TABLE ' . $table_name . ' ADD PRIMARY KEY (' . implode(', ', $column) . ')';
  2226. _sql($sql, $errored, $error_ary);
  2227. break;
  2228. case 'oracle':
  2229. $sql = 'ALTER TABLE ' . $table_name . 'add CONSTRAINT pk_' . $table_name . ' PRIMARY KEY (' . implode(', ', $column) . ')';
  2230. _sql($sql, $errored, $error_ary);
  2231. break;
  2232. case 'sqlite':
  2233. $sql = "SELECT sql
  2234. FROM sqlite_master
  2235. WHERE type = 'table'
  2236. AND name = '{$table_name}'
  2237. ORDER BY type DESC, name;";
  2238. $result = _sql($sql, $errored, $error_ary);
  2239. if (!$result)
  2240. {
  2241. break;
  2242. }
  2243. $row = $db->sql_fetchrow($result);
  2244. $db->sql_freeresult($result);
  2245. $db->sql_transaction('begin');
  2246. // Create a backup table and populate it, destroy the existing one
  2247. $db->sql_query(preg_replace('#CREATE\s+TABLE\s+"?' . $table_name . '"?#i', 'CREATE TEMPORARY TABLE ' . $table_name . '_temp', $row['sql']));
  2248. $db->sql_query('INSERT INTO ' . $table_name . '_temp SELECT * FROM ' . $table_name);
  2249. $db->sql_query('DROP TABLE ' . $table_name);
  2250. preg_match('#\((.*)\)#s', $row['sql'], $matches);
  2251. $new_table_cols = trim($matches[1]);
  2252. $old_table_cols = preg_split('/,(?![\s\w]+\))/m', $new_table_cols);
  2253. $column_list = array();
  2254. foreach ($old_table_cols as $declaration)
  2255. {
  2256. $entities = preg_split('#\s+#', trim($declaration));
  2257. if ($entities[0] == 'PRIMARY')
  2258. {
  2259. continue;
  2260. }
  2261. $column_list[] = $entities[0];
  2262. }
  2263. $columns = implode(',', $column_list);
  2264. // create a new table and fill it up. destroy the temp one
  2265. $db->sql_query('CREATE TABLE ' . $table_name . ' (' . $new_table_cols . ', PRIMARY KEY (' . implode(', ', $column) . '));');
  2266. $db->sql_query('INSERT INTO ' . $table_name . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . $table_name . '_temp;');
  2267. $db->sql_query('DROP TABLE ' . $table_name . '_temp');
  2268. $db->sql_transaction('commit');
  2269. break;
  2270. }
  2271. }
  2272. function sql_create_unique_index($dbms, $index_name, $table_name, $column)
  2273. {
  2274. global $dbms_type_map, $db;
  2275. global $errored, $error_ary;
  2276. switch ($dbms)
  2277. {
  2278. case 'firebird':
  2279. case 'postgres':
  2280. case 'oracle':
  2281. case 'sqlite':
  2282. $sql = 'CREATE UNIQUE INDEX ' . $table_name . '_' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')';
  2283. _sql($sql, $errored, $error_ary);
  2284. break;
  2285. case 'mysql_40':
  2286. case 'mysql_41':
  2287. $sql = 'CREATE UNIQUE INDEX ' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')';
  2288. _sql($sql, $errored, $error_ary);
  2289. break;
  2290. case 'mssql':
  2291. $sql = 'CREATE UNIQUE INDEX ' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ') ON [PRIMARY]';
  2292. _sql($sql, $errored, $error_ary);
  2293. break;
  2294. }
  2295. }
  2296. function sql_create_index($dbms, $index_name, $table_name, $column)
  2297. {
  2298. global $dbms_type_map, $db;
  2299. global $errored, $error_ary;
  2300. switch ($dbms)
  2301. {
  2302. case 'firebird':
  2303. case 'postgres':
  2304. case 'oracle':
  2305. case 'sqlite':
  2306. $sql = 'CREATE INDEX ' . $table_name . '_' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')';
  2307. _sql($sql, $errored, $error_ary);
  2308. break;
  2309. case 'mysql_40':
  2310. case 'mysql_41':
  2311. $sql = 'CREATE INDEX ' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')';
  2312. _sql($sql, $errored, $error_ary);
  2313. break;
  2314. case 'mssql':
  2315. $sql = 'CREATE INDEX ' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ') ON [PRIMARY]';
  2316. _sql($sql, $errored, $error_ary);
  2317. break;
  2318. }
  2319. }
  2320. // List all of the indices that belong to a table,
  2321. // does not count:
  2322. // * UNIQUE indices
  2323. // * PRIMARY keys
  2324. function sql_list_index($dbms, $table_name)
  2325. {
  2326. global $dbms_type_map, $db;
  2327. global $errored, $error_ary;
  2328. $index_array = array();
  2329. if ($dbms == 'mssql')
  2330. {
  2331. $sql = "EXEC sp_statistics '$table_name'";
  2332. $result = $db->sql_query($sql);
  2333. while ($row = $db->sql_fetchrow($result))
  2334. {
  2335. if ($row['TYPE'] == 3)
  2336. {
  2337. $index_array[] = $row['INDEX_NAME'];
  2338. }
  2339. }
  2340. $db->sql_freeresult($result);
  2341. }
  2342. else
  2343. {
  2344. switch ($dbms)
  2345. {
  2346. case 'firebird':
  2347. $sql = "SELECT LOWER(RDB\$INDEX_NAME) as index_name
  2348. FROM RDB\$INDICES
  2349. WHERE RDB\$RELATION_NAME = " . strtoupper($table_name) . "
  2350. AND RDB\$UNIQUE_FLAG IS NULL
  2351. AND RDB\$FOREIGN_KEY IS NULL";
  2352. $col = 'index_name';
  2353. break;
  2354. case 'postgres':
  2355. $sql = "SELECT ic.relname as index_name
  2356. FROM pg_class bc, pg_class ic, pg_index i
  2357. WHERE (bc.oid = i.indrelid)
  2358. AND (ic.oid = i.indexrelid)
  2359. AND (bc.relname = '" . $table_name . "')
  2360. AND (i.indisunique != 't')
  2361. AND (i.indisprimary != 't')";
  2362. $col = 'index_name';
  2363. break;
  2364. case 'mysql_40':
  2365. case 'mysql_41':
  2366. $sql = 'SHOW KEYS
  2367. FROM ' . $table_name;
  2368. $col = 'Key_name';
  2369. break;
  2370. case 'oracle':
  2371. $sql = "SELECT index_name
  2372. FROM user_indexes
  2373. WHERE table_name = '" . $table_name . "'
  2374. AND generated = 'N'";
  2375. break;
  2376. case 'sqlite':
  2377. $sql = "PRAGMA index_info('" . $table_name . "');";
  2378. $col = 'name';
  2379. break;
  2380. }
  2381. $result = $db->sql_query($sql);
  2382. while ($row = $db->sql_fetchrow($result))
  2383. {
  2384. if (($dbms == 'mysql_40' || $dbms == 'mysql_41') && !$row['Non_unique'])
  2385. {
  2386. continue;
  2387. }
  2388. switch ($dbms)
  2389. {
  2390. case 'firebird':
  2391. case 'oracle':
  2392. case 'postgres':
  2393. case 'sqlite':
  2394. $row[$col] = substr($row[$col], strlen($table_name) + 1);
  2395. break;
  2396. }
  2397. $index_array[] = $row[$col];
  2398. }
  2399. $db->sql_freeresult($result);
  2400. }
  2401. return array_map('strtolower', $index_array);
  2402. }
  2403. // This is totally fake, never use it
  2404. // it exists only to mend bad update functions introduced
  2405. // * UNIQUE indices
  2406. // * PRIMARY keys
  2407. function sql_list_fake($dbms, $table_name)
  2408. {
  2409. global $dbms_type_map, $db;
  2410. global $errored, $error_ary;
  2411. $index_array = array();
  2412. if ($dbms == 'mssql')
  2413. {
  2414. $sql = "EXEC sp_statistics '$table_name'";
  2415. $result = $db->sql_query($sql);
  2416. while ($row = $db->sql_fetchrow($result))
  2417. {
  2418. if ($row['TYPE'] == 3)
  2419. {
  2420. $index_array[] = $row['INDEX_NAME'];
  2421. }
  2422. }
  2423. $db->sql_freeresult($result);
  2424. }
  2425. else
  2426. {
  2427. switch ($dbms)
  2428. {
  2429. case 'firebird':
  2430. $sql = "SELECT LOWER(RDB\$INDEX_NAME) as index_name
  2431. FROM RDB\$INDICES
  2432. WHERE RDB\$RELATION_NAME = " . strtoupper($table_name) . "
  2433. AND RDB\$UNIQUE_FLAG IS NULL
  2434. AND RDB\$FOREIGN_KEY IS NULL";
  2435. $col = 'index_name';
  2436. break;
  2437. case 'postgres':
  2438. $sql = "SELECT ic.relname as index_name
  2439. FROM pg_class bc, pg_class ic, pg_index i
  2440. WHERE (bc.oid = i.indrelid)
  2441. AND (ic.oid = i.indexrelid)
  2442. AND (bc.relname = '" . $table_name . "')
  2443. AND (i.indisunique != 't')
  2444. AND (i.indisprimary != 't')";
  2445. $col = 'index_name';
  2446. break;
  2447. case 'mysql_40':
  2448. case 'mysql_41':
  2449. $sql = 'SHOW KEYS
  2450. FROM ' . $table_name;
  2451. $col = 'Key_name';
  2452. break;
  2453. case 'oracle':
  2454. $sql = "SELECT index_name
  2455. FROM user_indexes
  2456. WHERE table_name = '" . $table_name . "'
  2457. AND generated = 'N'";
  2458. break;
  2459. case 'sqlite':
  2460. $sql = "PRAGMA index_info('" . $table_name . "');";
  2461. $col = 'name';
  2462. break;
  2463. }
  2464. $result = $db->sql_query($sql);
  2465. while ($row = $db->sql_fetchrow($result))
  2466. {
  2467. if (($dbms == 'mysql_40' || $dbms == 'mysql_41') && !$row['Non_unique'])
  2468. {
  2469. continue;
  2470. }
  2471. $index_array[] = $row[$col];
  2472. }
  2473. $db->sql_freeresult($result);
  2474. }
  2475. return array_map('strtolower', $index_array);
  2476. }
  2477. /**
  2478. * Change column type (not name!)
  2479. */
  2480. function sql_column_change($dbms, $table_name, $column_name, $column_data)
  2481. {
  2482. global $dbms_type_map, $db;
  2483. global $errored, $error_ary;
  2484. $column_data = prepare_column_data($dbms, $column_data, $table_name, $column_name);
  2485. switch ($dbms)
  2486. {
  2487. case 'firebird':
  2488. // Change type...
  2489. $sql = 'ALTER TABLE "' . $table_name . '" ALTER COLUMN "' . $column_name . '" TYPE ' . ' ' . $column_data['column_type_sql'];
  2490. _sql($sql, $errored, $error_ary);
  2491. break;
  2492. case 'mssql':
  2493. $sql = 'ALTER TABLE [' . $table_name . '] ALTER COLUMN [' . $column_name . '] ' . $column_data['column_type_sql'];
  2494. _sql($sql, $errored, $error_ary);
  2495. break;
  2496. case 'mysql_40':
  2497. case 'mysql_41':
  2498. $sql = 'ALTER TABLE `' . $table_name . '` CHANGE `' . $column_name . '` `' . $column_name . '` ' . $column_data['column_type_sql'];
  2499. _sql($sql, $errored, $error_ary);
  2500. break;
  2501. case 'oracle':
  2502. $sql = 'ALTER TABLE ' . $table_name . ' MODIFY ' . $column_name . ' ' . $column_data['column_type_sql'];
  2503. _sql($sql, $errored, $error_ary);
  2504. break;
  2505. case 'postgres':
  2506. $sql = 'ALTER TABLE ' . $table_name . ' ';
  2507. $sql_array = array();
  2508. $sql_array[] = 'ALTER COLUMN ' . $column_name . ' TYPE ' . $column_data['column_type'];
  2509. if (isset($column_data['null']))
  2510. {
  2511. if ($column_data['null'] == 'NOT NULL')
  2512. {
  2513. $sql_array[] = 'ALTER COLUMN ' . $column_name . ' SET NOT NULL';
  2514. }
  2515. else if ($column_data['null'] == 'NULL')
  2516. {
  2517. $sql_array[] = 'ALTER COLUMN ' . $column_name . ' DROP NOT NULL';
  2518. }
  2519. }
  2520. if (isset($column_data['default']))
  2521. {
  2522. $sql_array[] = 'ALTER COLUMN ' . $column_name . ' SET DEFAULT ' . $column_data['default'];
  2523. }
  2524. // we don't want to double up on constraints if we change different number data types
  2525. if (isset($column_data['constraint']))
  2526. {
  2527. $constraint_sql = "SELECT consrc as constraint_data
  2528. FROM pg_constraint, pg_class bc
  2529. WHERE conrelid = bc.oid
  2530. AND bc.relname = '{$table_name}'
  2531. AND NOT EXISTS (
  2532. SELECT *
  2533. FROM pg_constraint as c, pg_inherits as i
  2534. WHERE i.inhrelid = pg_constraint.conrelid
  2535. AND c.conname = pg_constraint.conname
  2536. AND c.consrc = pg_constraint.consrc
  2537. AND c.conrelid = i.inhparent
  2538. )";
  2539. $constraint_exists = false;
  2540. $result = $db->sql_query($constraint_sql);
  2541. while ($row = $db->sql_fetchrow($result))
  2542. {
  2543. if (trim($row['constraint_data']) == trim($column_data['constraint']))
  2544. {
  2545. $constraint_exists = true;
  2546. break;
  2547. }
  2548. }
  2549. $db->sql_freeresult($result);
  2550. if (!$constraint_exists)
  2551. {
  2552. $sql_array[] = 'ADD ' . $column_data['constraint'];
  2553. }
  2554. }
  2555. $sql .= implode(', ', $sql_array);
  2556. _sql($sql, $errored, $error_ary);
  2557. break;
  2558. case 'sqlite':
  2559. $sql = "SELECT sql
  2560. FROM sqlite_master
  2561. WHERE type = 'table'
  2562. AND name = '{$table_name}'
  2563. ORDER BY type DESC, name;";
  2564. $result = _sql($sql, $errored, $error_ary);
  2565. if (!$result)
  2566. {
  2567. break;
  2568. }
  2569. $row = $db->sql_fetchrow($result);
  2570. $db->sql_freeresult($result);
  2571. $db->sql_transaction('begin');
  2572. // Create a temp table and populate it, destroy the existing one
  2573. $db->sql_query(preg_replace('#CREATE\s+TABLE\s+"?' . $table_name . '"?#i', 'CREATE TEMPORARY TABLE ' . $table_name . '_temp', $row['sql']));
  2574. $db->sql_query('INSERT INTO ' . $table_name . '_temp SELECT * FROM ' . $table_name);
  2575. $db->sql_query('DROP TABLE ' . $table_name);
  2576. preg_match('#\((.*)\)#s', $row['sql'], $matches);
  2577. $new_table_cols = trim($matches[1]);
  2578. $old_table_cols = preg_split('/,(?![\s\w]+\))/m', $new_table_cols);
  2579. $column_list = array();
  2580. foreach ($old_table_cols as $key => $declaration)
  2581. {
  2582. $entities = preg_split('#\s+#', trim($declaration));
  2583. $column_list[] = $entities[0];
  2584. if ($entities[0] == $column_name)
  2585. {
  2586. $old_table_cols[$key] = $column_name . ' ' . $column_data['column_type_sql'];
  2587. }
  2588. }
  2589. $columns = implode(',', $column_list);
  2590. // create a new table and fill it up. destroy the temp one
  2591. $db->sql_query('CREATE TABLE ' . $table_name . ' (' . implode(',', $old_table_cols) . ');');
  2592. $db->sql_query('INSERT INTO ' . $table_name . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . $table_name . '_temp;');
  2593. $db->sql_query('DROP TABLE ' . $table_name . '_temp');
  2594. $db->sql_transaction('commit');
  2595. break;
  2596. }
  2597. }
  2598. function utf8_new_clean_string($text)
  2599. {
  2600. static $homographs = array();
  2601. static $utf8_case_fold_nfkc = '';
  2602. if (empty($homographs))
  2603. {
  2604. global $phpbb_root_path, $phpEx;
  2605. if (!function_exists('utf8_case_fold_nfkc') || !file_exists($phpbb_root_path . 'includes/utf/data/confusables.' . $phpEx))
  2606. {
  2607. if (!file_exists($phpbb_root_path . 'install/data/confusables.' . $phpEx))
  2608. {
  2609. global $lang;
  2610. trigger_error(sprintf($lang['UPDATE_REQUIRES_FILE'], $phpbb_root_path . 'install/data/confusables.' . $phpEx), E_USER_ERROR);
  2611. }
  2612. $homographs = include($phpbb_root_path . 'install/data/confusables.' . $phpEx);
  2613. $utf8_case_fold_nfkc = 'utf8_new_case_fold_nfkc';
  2614. }
  2615. else
  2616. {
  2617. $homographs = include($phpbb_root_path . 'includes/utf/data/confusables.' . $phpEx);
  2618. $utf8_case_fold_nfkc = 'utf8_case_fold_nfkc';
  2619. }
  2620. }
  2621. $text = $utf8_case_fold_nfkc($text);
  2622. $text = strtr($text, $homographs);
  2623. // Other control characters
  2624. $text = preg_replace('#(?:[\x00-\x1F\x7F]+|(?:\xC2[\x80-\x9F])+)#', '', $text);
  2625. $text = preg_replace('# {2,}#', ' ', $text);
  2626. // we can use trim here as all the other space characters should have been turned
  2627. // into normal ASCII spaces by now
  2628. return trim($text);
  2629. }
  2630. ?>