PageRenderTime 53ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/phpBB/includes/functions_install.php

http://github.com/phpbb/phpbb
PHP | 545 lines | 453 code | 31 blank | 61 comment | 26 complexity | c82f74a29e6ae923f6c03cac1f316f6e MD5 | raw file
Possible License(s): GPL-3.0, AGPL-1.0
  1. <?php
  2. /**
  3. *
  4. * This file is part of the phpBB Forum Software package.
  5. *
  6. * @copyright (c) phpBB Limited <https://www.phpbb.com>
  7. * @license GNU General Public License, version 2 (GPL-2.0)
  8. *
  9. * For full copyright and license information, please see
  10. * the docs/CREDITS.txt file.
  11. *
  12. */
  13. /**
  14. * @ignore
  15. */
  16. if (!defined('IN_PHPBB'))
  17. {
  18. exit;
  19. }
  20. /**
  21. * Returns an array of available DBMS with some data, if a DBMS is specified it will only
  22. * return data for that DBMS and will load its extension if necessary.
  23. */
  24. function get_available_dbms($dbms = false, $return_unavailable = false, $only_20x_options = false)
  25. {
  26. global $lang;
  27. $available_dbms = array(
  28. // Note: php 5.5 alpha 2 deprecated mysql.
  29. // Keep mysqli before mysql in this list.
  30. 'mysqli' => array(
  31. 'LABEL' => 'MySQL with MySQLi Extension',
  32. 'SCHEMA' => 'mysql_41',
  33. 'MODULE' => 'mysqli',
  34. 'DELIM' => ';',
  35. 'DRIVER' => 'phpbb\db\driver\mysqli',
  36. 'AVAILABLE' => true,
  37. '2.0.x' => true,
  38. ),
  39. 'mysql' => array(
  40. 'LABEL' => 'MySQL',
  41. 'SCHEMA' => 'mysql',
  42. 'MODULE' => 'mysql',
  43. 'DELIM' => ';',
  44. 'DRIVER' => 'phpbb\db\driver\mysql',
  45. 'AVAILABLE' => true,
  46. '2.0.x' => true,
  47. ),
  48. 'mssql' => array(
  49. 'LABEL' => 'MS SQL Server 2000+',
  50. 'SCHEMA' => 'mssql',
  51. 'MODULE' => 'mssql',
  52. 'DELIM' => 'GO',
  53. 'DRIVER' => 'phpbb\db\driver\mssql',
  54. 'AVAILABLE' => true,
  55. '2.0.x' => true,
  56. ),
  57. 'mssql_odbc'=> array(
  58. 'LABEL' => 'MS SQL Server [ ODBC ]',
  59. 'SCHEMA' => 'mssql',
  60. 'MODULE' => 'odbc',
  61. 'DELIM' => 'GO',
  62. 'DRIVER' => 'phpbb\db\driver\mssql_odbc',
  63. 'AVAILABLE' => true,
  64. '2.0.x' => true,
  65. ),
  66. 'mssqlnative' => array(
  67. 'LABEL' => 'MS SQL Server 2005+ [ Native ]',
  68. 'SCHEMA' => 'mssql',
  69. 'MODULE' => 'sqlsrv',
  70. 'DELIM' => 'GO',
  71. 'DRIVER' => 'phpbb\db\driver\mssqlnative',
  72. 'AVAILABLE' => true,
  73. '2.0.x' => false,
  74. ),
  75. 'oracle' => array(
  76. 'LABEL' => 'Oracle',
  77. 'SCHEMA' => 'oracle',
  78. 'MODULE' => 'oci8',
  79. 'DELIM' => '/',
  80. 'DRIVER' => 'phpbb\db\driver\oracle',
  81. 'AVAILABLE' => true,
  82. '2.0.x' => false,
  83. ),
  84. 'postgres' => array(
  85. 'LABEL' => 'PostgreSQL 8.3+',
  86. 'SCHEMA' => 'postgres',
  87. 'MODULE' => 'pgsql',
  88. 'DELIM' => ';',
  89. 'DRIVER' => 'phpbb\db\driver\postgres',
  90. 'AVAILABLE' => true,
  91. '2.0.x' => true,
  92. ),
  93. 'sqlite' => array(
  94. 'LABEL' => 'SQLite',
  95. 'SCHEMA' => 'sqlite',
  96. 'MODULE' => 'sqlite',
  97. 'DELIM' => ';',
  98. 'DRIVER' => 'phpbb\db\driver\sqlite',
  99. 'AVAILABLE' => true,
  100. '2.0.x' => false,
  101. ),
  102. 'sqlite3' => array(
  103. 'LABEL' => 'SQLite3',
  104. 'SCHEMA' => 'sqlite',
  105. 'MODULE' => 'sqlite3',
  106. 'DELIM' => ';',
  107. 'DRIVER' => 'phpbb\db\driver\sqlite3',
  108. 'AVAILABLE' => true,
  109. '2.0.x' => false,
  110. ),
  111. );
  112. if ($dbms)
  113. {
  114. if (isset($available_dbms[$dbms]))
  115. {
  116. $available_dbms = array($dbms => $available_dbms[$dbms]);
  117. }
  118. else
  119. {
  120. return array();
  121. }
  122. }
  123. // now perform some checks whether they are really available
  124. foreach ($available_dbms as $db_name => $db_ary)
  125. {
  126. if ($only_20x_options && !$db_ary['2.0.x'])
  127. {
  128. if ($return_unavailable)
  129. {
  130. $available_dbms[$db_name]['AVAILABLE'] = false;
  131. }
  132. else
  133. {
  134. unset($available_dbms[$db_name]);
  135. }
  136. continue;
  137. }
  138. $dll = $db_ary['MODULE'];
  139. if (!@extension_loaded($dll))
  140. {
  141. if ($return_unavailable)
  142. {
  143. $available_dbms[$db_name]['AVAILABLE'] = false;
  144. }
  145. else
  146. {
  147. unset($available_dbms[$db_name]);
  148. }
  149. continue;
  150. }
  151. $any_db_support = true;
  152. }
  153. if ($return_unavailable)
  154. {
  155. $available_dbms['ANY_DB_SUPPORT'] = $any_db_support;
  156. }
  157. return $available_dbms;
  158. }
  159. /**
  160. * Generate the drop down of available database options
  161. */
  162. function dbms_select($default = '', $only_20x_options = false)
  163. {
  164. global $lang;
  165. $available_dbms = get_available_dbms(false, false, $only_20x_options);
  166. $dbms_options = '';
  167. foreach ($available_dbms as $dbms_name => $details)
  168. {
  169. $selected = ($dbms_name == $default) ? ' selected="selected"' : '';
  170. $dbms_options .= '<option value="' . $dbms_name . '"' . $selected .'>' . $lang['DLL_' . strtoupper($dbms_name)] . '</option>';
  171. }
  172. return $dbms_options;
  173. }
  174. /**
  175. * Get tables of a database
  176. *
  177. * @deprecated
  178. */
  179. function get_tables(&$db)
  180. {
  181. $db_tools = new \phpbb\db\tools($db);
  182. return $db_tools->sql_list_tables();
  183. }
  184. /**
  185. * Used to test whether we are able to connect to the database the user has specified
  186. * and identify any problems (eg there are already tables with the names we want to use
  187. * @param array $dbms should be of the format of an element of the array returned by {@link get_available_dbms get_available_dbms()}
  188. * necessary extensions should be loaded already
  189. */
  190. function connect_check_db($error_connect, &$error, $dbms_details, $table_prefix, $dbhost, $dbuser, $dbpasswd, $dbname, $dbport, $prefix_may_exist = false, $load_dbal = true, $unicode_check = true)
  191. {
  192. global $phpbb_root_path, $phpEx, $config, $lang;
  193. $dbms = $dbms_details['DRIVER'];
  194. // Instantiate it and set return on error true
  195. $db = new $dbms();
  196. $db->sql_return_on_error(true);
  197. // Check that we actually have a database name before going any further.....
  198. if ($dbms_details['DRIVER'] != 'phpbb\db\driver\sqlite' && $dbms_details['DRIVER'] != 'phpbb\db\driver\sqlite3' && $dbms_details['DRIVER'] != 'phpbb\db\driver\oracle' && $dbname === '')
  199. {
  200. $error[] = $lang['INST_ERR_DB_NO_NAME'];
  201. return false;
  202. }
  203. // Make sure we don't have a daft user who thinks having the SQLite database in the forum directory is a good idea
  204. if (($dbms_details['DRIVER'] == 'phpbb\db\driver\sqlite' || $dbms_details['DRIVER'] == 'phpbb\db\driver\sqlite3') && stripos(phpbb_realpath($dbhost), phpbb_realpath('../')) === 0)
  205. {
  206. $error[] = $lang['INST_ERR_DB_FORUM_PATH'];
  207. return false;
  208. }
  209. // Check the prefix length to ensure that index names are not too long and does not contain invalid characters
  210. switch ($dbms_details['DRIVER'])
  211. {
  212. case 'phpbb\db\driver\mysql':
  213. case 'phpbb\db\driver\mysqli':
  214. if (strspn($table_prefix, '-./\\') !== 0)
  215. {
  216. $error[] = $lang['INST_ERR_PREFIX_INVALID'];
  217. return false;
  218. }
  219. // no break;
  220. case 'phpbb\db\driver\postgres':
  221. $prefix_length = 36;
  222. break;
  223. case 'phpbb\db\driver\mssql':
  224. case 'phpbb\db\driver\mssql_odbc':
  225. case 'phpbb\db\driver\mssqlnative':
  226. $prefix_length = 90;
  227. break;
  228. case 'phpbb\db\driver\sqlite':
  229. case 'phpbb\db\driver\sqlite3':
  230. $prefix_length = 200;
  231. break;
  232. case 'phpbb\db\driver\oracle':
  233. $prefix_length = 6;
  234. break;
  235. }
  236. if (strlen($table_prefix) > $prefix_length)
  237. {
  238. $error[] = sprintf($lang['INST_ERR_PREFIX_TOO_LONG'], $prefix_length);
  239. return false;
  240. }
  241. // Try and connect ...
  242. if (is_array($db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, true)))
  243. {
  244. $db_error = $db->sql_error();
  245. $error[] = $lang['INST_ERR_DB_CONNECT'] . '<br />' . (($db_error['message']) ? utf8_convert_message($db_error['message']) : $lang['INST_ERR_DB_NO_ERROR']);
  246. }
  247. else
  248. {
  249. // Likely matches for an existing phpBB installation
  250. if (!$prefix_may_exist)
  251. {
  252. $temp_prefix = strtolower($table_prefix);
  253. $table_ary = array($temp_prefix . 'attachments', $temp_prefix . 'config', $temp_prefix . 'sessions', $temp_prefix . 'topics', $temp_prefix . 'users');
  254. $tables = get_tables($db);
  255. $tables = array_map('strtolower', $tables);
  256. $table_intersect = array_intersect($tables, $table_ary);
  257. if (sizeof($table_intersect))
  258. {
  259. $error[] = $lang['INST_ERR_PREFIX'];
  260. }
  261. }
  262. // Make sure that the user has selected a sensible DBAL for the DBMS actually installed
  263. switch ($dbms_details['DRIVER'])
  264. {
  265. case 'phpbb\db\driver\mysqli':
  266. if (version_compare(mysqli_get_server_info($db->get_db_connect_id()), '4.1.3', '<'))
  267. {
  268. $error[] = $lang['INST_ERR_DB_NO_MYSQLI'];
  269. }
  270. break;
  271. case 'phpbb\db\driver\sqlite':
  272. if (version_compare(sqlite_libversion(), '2.8.2', '<'))
  273. {
  274. $error[] = $lang['INST_ERR_DB_NO_SQLITE'];
  275. }
  276. break;
  277. case 'phpbb\db\driver\sqlite3':
  278. $version = \SQLite3::version();
  279. if (version_compare($version['versionString'], '3.6.15', '<'))
  280. {
  281. $error[] = $lang['INST_ERR_DB_NO_SQLITE3'];
  282. }
  283. break;
  284. case 'phpbb\db\driver\oracle':
  285. if ($unicode_check)
  286. {
  287. $sql = "SELECT *
  288. FROM NLS_DATABASE_PARAMETERS
  289. WHERE PARAMETER = 'NLS_RDBMS_VERSION'
  290. OR PARAMETER = 'NLS_CHARACTERSET'";
  291. $result = $db->sql_query($sql);
  292. while ($row = $db->sql_fetchrow($result))
  293. {
  294. $stats[$row['parameter']] = $row['value'];
  295. }
  296. $db->sql_freeresult($result);
  297. if (version_compare($stats['NLS_RDBMS_VERSION'], '9.2', '<') && $stats['NLS_CHARACTERSET'] !== 'UTF8')
  298. {
  299. $error[] = $lang['INST_ERR_DB_NO_ORACLE'];
  300. }
  301. }
  302. break;
  303. case 'phpbb\db\driver\postgres':
  304. if ($unicode_check)
  305. {
  306. $sql = "SHOW server_encoding;";
  307. $result = $db->sql_query($sql);
  308. $row = $db->sql_fetchrow($result);
  309. $db->sql_freeresult($result);
  310. if ($row['server_encoding'] !== 'UNICODE' && $row['server_encoding'] !== 'UTF8')
  311. {
  312. $error[] = $lang['INST_ERR_DB_NO_POSTGRES'];
  313. }
  314. }
  315. break;
  316. }
  317. }
  318. if ($error_connect && (!isset($error) || !sizeof($error)))
  319. {
  320. return true;
  321. }
  322. return false;
  323. }
  324. /**
  325. * Removes "/* style" as well as "# style" comments from $input.
  326. *
  327. * @param string $input Input string
  328. *
  329. * @return string Input string with comments removed
  330. */
  331. function phpbb_remove_comments($input)
  332. {
  333. // Remove /* */ comments (http://ostermiller.org/findcomment.html)
  334. $input = preg_replace('#/\*(.|[\r\n])*?\*/#', "\n", $input);
  335. // Remove # style comments
  336. $input = preg_replace('/\n{2,}/', "\n", preg_replace('/^#.*$/m', "\n", $input));
  337. return $input;
  338. }
  339. /**
  340. * split_sql_file will split an uploaded sql file into single sql statements.
  341. * Note: expects trim() to have already been run on $sql.
  342. */
  343. function split_sql_file($sql, $delimiter)
  344. {
  345. $sql = str_replace("\r" , '', $sql);
  346. $data = preg_split('/' . preg_quote($delimiter, '/') . '$/m', $sql);
  347. $data = array_map('trim', $data);
  348. // The empty case
  349. $end_data = end($data);
  350. if (empty($end_data))
  351. {
  352. unset($data[key($data)]);
  353. }
  354. return $data;
  355. }
  356. /**
  357. * For replacing {L_*} strings with preg_replace_callback
  358. */
  359. function adjust_language_keys_callback($matches)
  360. {
  361. if (!empty($matches[1]))
  362. {
  363. global $lang, $db;
  364. return (!empty($lang[$matches[1]])) ? $db->sql_escape($lang[$matches[1]]) : $db->sql_escape($matches[1]);
  365. }
  366. }
  367. /**
  368. * Creates the output to be stored in a phpBB config.php file
  369. *
  370. * @param array $data Array containing the database connection information
  371. * @param string $dbms The name of the DBAL class to use
  372. * @param bool $debug If the debug constants should be enabled by default or not
  373. * @param bool $debug_container If the container should be compiled on
  374. * every page load or not
  375. * @param bool $debug_test If the DEBUG_TEST constant should be added
  376. * NOTE: Only for use within the testing framework
  377. *
  378. * @return string The output to write to the file
  379. */
  380. function phpbb_create_config_file_data($data, $dbms, $debug = false, $debug_container = false, $debug_test = false)
  381. {
  382. $config_data = "<?php\n";
  383. $config_data .= "// phpBB 3.1.x auto-generated configuration file\n// Do not change anything in this file!\n";
  384. $config_data_array = array(
  385. 'dbms' => $dbms,
  386. 'dbhost' => $data['dbhost'],
  387. 'dbport' => $data['dbport'],
  388. 'dbname' => $data['dbname'],
  389. 'dbuser' => $data['dbuser'],
  390. 'dbpasswd' => htmlspecialchars_decode($data['dbpasswd']),
  391. 'table_prefix' => $data['table_prefix'],
  392. 'phpbb_adm_relative_path' => 'adm/',
  393. 'acm_type' => 'phpbb\cache\driver\file',
  394. );
  395. foreach ($config_data_array as $key => $value)
  396. {
  397. $config_data .= "\${$key} = '" . str_replace("'", "\\'", str_replace('\\', '\\\\', $value)) . "';\n";
  398. }
  399. $config_data .= "\n@define('PHPBB_INSTALLED', true);\n";
  400. $config_data .= "// @define('PHPBB_DISPLAY_LOAD_TIME', true);\n";
  401. if ($debug)
  402. {
  403. $config_data .= "@define('DEBUG', true);\n";
  404. }
  405. else
  406. {
  407. $config_data .= "// @define('DEBUG', true);\n";
  408. }
  409. if ($debug_container)
  410. {
  411. $config_data .= "@define('DEBUG_CONTAINER', true);\n";
  412. }
  413. else
  414. {
  415. $config_data .= "// @define('DEBUG_CONTAINER', true);\n";
  416. }
  417. if ($debug_test)
  418. {
  419. $config_data .= "@define('DEBUG_TEST', true);\n";
  420. }
  421. return $config_data;
  422. }
  423. /**
  424. * Check whether a file should be ignored on update
  425. *
  426. * We ignore new files in some circumstances:
  427. * 1. The file is a language file, but the language is not installed
  428. * 2. The file is a style file, but the style is not installed
  429. * 3. The file is a style language file, but the language is not installed
  430. *
  431. * @param string $phpbb_root_path phpBB root path
  432. * @param string $file File including path from phpbb root
  433. * @return bool Should we ignore the new file or add it to the board?
  434. */
  435. function phpbb_ignore_new_file_on_update($phpbb_root_path, $file)
  436. {
  437. $ignore_new_file = false;
  438. // We ignore new files in some circumstances:
  439. // 1. The file is a language file, but the language is not installed
  440. if (!$ignore_new_file && strpos($file, 'language/') === 0)
  441. {
  442. list($language_dir, $language_iso) = explode('/', $file);
  443. $ignore_new_file = !file_exists($phpbb_root_path . $language_dir . '/' . $language_iso);
  444. }
  445. // 2. The file is a style file, but the style is not installed
  446. if (!$ignore_new_file && strpos($file, 'styles/') === 0)
  447. {
  448. list($styles_dir, $style_name) = explode('/', $file);
  449. $ignore_new_file = !file_exists($phpbb_root_path . $styles_dir . '/' . $style_name);
  450. }
  451. // 3. The file is a style language file, but the language is not installed
  452. if (!$ignore_new_file && strpos($file, 'styles/') === 0)
  453. {
  454. $dirs = explode('/', $file);
  455. if (sizeof($dirs) >= 5)
  456. {
  457. list($styles_dir, $style_name, $template_component, $language_iso) = explode('/', $file);
  458. if ($template_component == 'theme' && $language_iso !== 'images')
  459. {
  460. $ignore_new_file = !file_exists($phpbb_root_path . 'language/' . $language_iso);
  461. }
  462. }
  463. }
  464. return $ignore_new_file;
  465. }
  466. /**
  467. * Check whether phpBB is installed.
  468. *
  469. * @param string $phpbb_root_path Path to the phpBB board root.
  470. * @param string $php_ext PHP file extension.
  471. *
  472. * @return bool Returns true if phpBB is installed.
  473. */
  474. function phpbb_check_installation_exists($phpbb_root_path, $php_ext)
  475. {
  476. // Try opening config file
  477. if (file_exists($phpbb_root_path . 'config.' . $php_ext))
  478. {
  479. include($phpbb_root_path . 'config.' . $php_ext);
  480. }
  481. return defined('PHPBB_INSTALLED');
  482. }