[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/includes/ -> functions_install.php (source)

   1  <?php
   2  /**
   3  *
   4  * @package install
   5  * @version $Id$
   6  * @copyright (c) 2006 phpBB Group
   7  * @license http://opensource.org/licenses/gpl-license.php GNU Public License
   8  *
   9  */
  10  
  11  /**
  12  * @ignore
  13  */
  14  if (!defined('IN_PHPBB'))
  15  {
  16      exit;
  17  }
  18  
  19  /**
  20  * Determine if we are able to load a specified PHP module and do so if possible
  21  */
  22  function can_load_dll($dll)
  23  {
  24      // SQLite2 is a tricky thing, from 5.0.0 it requires PDO; if PDO is not loaded we must state that SQLite is unavailable
  25      // as the installer doesn't understand that the extension has a prerequisite.
  26      //
  27      // On top of this sometimes the SQLite extension is compiled for a different version of PDO
  28      // by some Linux distributions which causes phpBB to bomb out with a blank page.
  29      //
  30      // Net result we'll disable automatic inclusion of SQLite support
  31      //
  32      // See: r9618 and #56105
  33      if ($dll == 'sqlite')
  34      {
  35          return false;
  36      }
  37      return ((@ini_get('enable_dl') || strtolower(@ini_get('enable_dl')) == 'on') && (!@ini_get('safe_mode') || strtolower(@ini_get('safe_mode')) == 'off') && function_exists('dl') && @dl($dll . '.' . PHP_SHLIB_SUFFIX)) ? true : false;
  38  }
  39  
  40  /**
  41  * Returns an array of available DBMS with some data, if a DBMS is specified it will only
  42  * return data for that DBMS and will load its extension if necessary.
  43  */
  44  function get_available_dbms($dbms = false, $return_unavailable = false, $only_20x_options = false)
  45  {
  46      global $lang;
  47      $available_dbms = array(
  48          'firebird'    => array(
  49              'LABEL'            => 'FireBird',
  50              'SCHEMA'        => 'firebird',
  51              'MODULE'        => 'interbase',
  52              'DELIM'            => ';;',
  53              'COMMENTS'        => 'remove_remarks',
  54              'DRIVER'        => 'firebird',
  55              'AVAILABLE'        => true,
  56              '2.0.x'            => false,
  57          ),
  58          // Note: php 5.5 alpha 2 deprecated mysql.
  59          // Keep mysqli before mysql in this list.
  60          'mysqli'    => array(
  61              'LABEL'            => 'MySQL with MySQLi Extension',
  62              'SCHEMA'        => 'mysql_41',
  63              'MODULE'        => 'mysqli',
  64              'DELIM'            => ';',
  65              'COMMENTS'        => 'remove_remarks',
  66              'DRIVER'        => 'mysqli',
  67              'AVAILABLE'        => true,
  68              '2.0.x'            => true,
  69          ),
  70          'mysql'        => array(
  71              'LABEL'            => 'MySQL',
  72              'SCHEMA'        => 'mysql',
  73              'MODULE'        => 'mysql',
  74              'DELIM'            => ';',
  75              'COMMENTS'        => 'remove_remarks',
  76              'DRIVER'        => 'mysql',
  77              'AVAILABLE'        => true,
  78              '2.0.x'            => true,
  79          ),
  80          'mssql'        => array(
  81              'LABEL'            => 'MS SQL Server 2000+',
  82              'SCHEMA'        => 'mssql',
  83              'MODULE'        => 'mssql',
  84              'DELIM'            => 'GO',
  85              'COMMENTS'        => 'remove_comments',
  86              'DRIVER'        => 'mssql',
  87              'AVAILABLE'        => true,
  88              '2.0.x'            => true,
  89          ),
  90          'mssql_odbc'=>    array(
  91              'LABEL'            => 'MS SQL Server [ ODBC ]',
  92              'SCHEMA'        => 'mssql',
  93              'MODULE'        => 'odbc',
  94              'DELIM'            => 'GO',
  95              'COMMENTS'        => 'remove_comments',
  96              'DRIVER'        => 'mssql_odbc',
  97              'AVAILABLE'        => true,
  98              '2.0.x'            => true,
  99          ),
 100          'mssqlnative'        => array(
 101              'LABEL'            => 'MS SQL Server 2005+ [ Native ]',
 102              'SCHEMA'        => 'mssql',
 103              'MODULE'        => 'sqlsrv',
 104              'DELIM'            => 'GO',
 105              'COMMENTS'        => 'remove_comments',
 106              'DRIVER'        => 'mssqlnative',
 107              'AVAILABLE'        => true,
 108              '2.0.x'            => false,
 109          ),            
 110          'oracle'    =>    array(
 111              'LABEL'            => 'Oracle',
 112              'SCHEMA'        => 'oracle',
 113              'MODULE'        => 'oci8',
 114              'DELIM'            => '/',
 115              'COMMENTS'        => 'remove_comments',
 116              'DRIVER'        => 'oracle',
 117              'AVAILABLE'        => true,
 118              '2.0.x'            => false,
 119          ),
 120          'postgres' => array(
 121              'LABEL'            => 'PostgreSQL 7.x/8.x',
 122              'SCHEMA'        => 'postgres',
 123              'MODULE'        => 'pgsql',
 124              'DELIM'            => ';',
 125              'COMMENTS'        => 'remove_comments',
 126              'DRIVER'        => 'postgres',
 127              'AVAILABLE'        => true,
 128              '2.0.x'            => true,
 129          ),
 130          'sqlite'        => array(
 131              'LABEL'            => 'SQLite',
 132              'SCHEMA'        => 'sqlite',
 133              'MODULE'        => 'sqlite',
 134              'DELIM'            => ';',
 135              'COMMENTS'        => 'remove_remarks',
 136              'DRIVER'        => 'sqlite',
 137              'AVAILABLE'        => true,
 138              '2.0.x'            => false,
 139          ),
 140      );
 141  
 142      if ($dbms)
 143      {
 144          if (isset($available_dbms[$dbms]))
 145          {
 146              $available_dbms = array($dbms => $available_dbms[$dbms]);
 147          }
 148          else
 149          {
 150              return array();
 151          }
 152      }
 153  
 154      // now perform some checks whether they are really available
 155      foreach ($available_dbms as $db_name => $db_ary)
 156      {
 157          if ($only_20x_options && !$db_ary['2.0.x'])
 158          {
 159              if ($return_unavailable)
 160              {
 161                  $available_dbms[$db_name]['AVAILABLE'] = false;
 162              }
 163              else
 164              {
 165                  unset($available_dbms[$db_name]);
 166              }
 167              continue;
 168          }
 169  
 170          $dll = $db_ary['MODULE'];
 171  
 172          if (!@extension_loaded($dll))
 173          {
 174              if (!can_load_dll($dll))
 175              {
 176                  if ($return_unavailable)
 177                  {
 178                      $available_dbms[$db_name]['AVAILABLE'] = false;
 179                  }
 180                  else
 181                  {
 182                      unset($available_dbms[$db_name]);
 183                  }
 184                  continue;
 185              }
 186          }
 187          $any_db_support = true;
 188      }
 189  
 190      if ($return_unavailable)
 191      {
 192          $available_dbms['ANY_DB_SUPPORT'] = $any_db_support;
 193      }
 194      return $available_dbms;
 195  }
 196  
 197  /**
 198  * Generate the drop down of available database options
 199  */
 200  function dbms_select($default = '', $only_20x_options = false)
 201  {
 202      global $lang;
 203  
 204      $available_dbms = get_available_dbms(false, false, $only_20x_options);
 205      $dbms_options = '';
 206      foreach ($available_dbms as $dbms_name => $details)
 207      {
 208          $selected = ($dbms_name == $default) ? ' selected="selected"' : '';
 209          $dbms_options .= '<option value="' . $dbms_name . '"' . $selected .'>' . $lang['DLL_' . strtoupper($dbms_name)] . '</option>';
 210      }
 211      return $dbms_options;
 212  }
 213  
 214  /**
 215  * Get tables of a database
 216  *
 217  * @deprecated
 218  */
 219  function get_tables(&$db)
 220  {
 221      if (!class_exists('phpbb_db_tools'))
 222      {
 223          global $phpbb_root_path, $phpEx;
 224          require($phpbb_root_path . 'includes/db/db_tools.' . $phpEx);
 225      }
 226  
 227      $db_tools = new phpbb_db_tools($db);
 228  
 229      return $db_tools->sql_list_tables();
 230  }
 231  
 232  /**
 233  * Used to test whether we are able to connect to the database the user has specified
 234  * and identify any problems (eg there are already tables with the names we want to use
 235  * @param    array    $dbms should be of the format of an element of the array returned by {@link get_available_dbms get_available_dbms()}
 236  *                    necessary extensions should be loaded already
 237  */
 238  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)
 239  {
 240      global $phpbb_root_path, $phpEx, $config, $lang;
 241  
 242      $dbms = $dbms_details['DRIVER'];
 243  
 244      if ($load_dbal)
 245      {
 246          // Include the DB layer
 247          include($phpbb_root_path . 'includes/db/' . $dbms . '.' . $phpEx);
 248      }
 249  
 250      // Instantiate it and set return on error true
 251      $sql_db = 'dbal_' . $dbms;
 252      $db = new $sql_db();
 253      $db->sql_return_on_error(true);
 254  
 255      // Check that we actually have a database name before going any further.....
 256      if ($dbms_details['DRIVER'] != 'sqlite' && $dbms_details['DRIVER'] != 'oracle' && $dbname === '')
 257      {
 258          $error[] = $lang['INST_ERR_DB_NO_NAME'];
 259          return false;
 260      }
 261  
 262      // Make sure we don't have a daft user who thinks having the SQLite database in the forum directory is a good idea
 263      if ($dbms_details['DRIVER'] == 'sqlite' && stripos(phpbb_realpath($dbhost), phpbb_realpath('../')) === 0)
 264      {
 265          $error[] = $lang['INST_ERR_DB_FORUM_PATH'];
 266          return false;
 267      }
 268  
 269      // Check the prefix length to ensure that index names are not too long and does not contain invalid characters
 270      switch ($dbms_details['DRIVER'])
 271      {
 272          case 'mysql':
 273          case 'mysqli':
 274              if (strspn($table_prefix, '-./\\') !== 0)
 275              {
 276                  $error[] = $lang['INST_ERR_PREFIX_INVALID'];
 277                  return false;
 278              }
 279  
 280          // no break;
 281  
 282          case 'postgres':
 283              $prefix_length = 36;
 284          break;
 285  
 286          case 'mssql':
 287          case 'mssql_odbc':
 288          case 'mssqlnative':
 289              $prefix_length = 90;
 290          break;
 291  
 292          case 'sqlite':
 293              $prefix_length = 200;
 294          break;
 295  
 296          case 'firebird':
 297          case 'oracle':
 298              $prefix_length = 6;
 299          break;
 300      }
 301  
 302      if (strlen($table_prefix) > $prefix_length)
 303      {
 304          $error[] = sprintf($lang['INST_ERR_PREFIX_TOO_LONG'], $prefix_length);
 305          return false;
 306      }
 307  
 308      // Try and connect ...
 309      if (is_array($db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, true)))
 310      {
 311          $db_error = $db->sql_error();
 312          $error[] = $lang['INST_ERR_DB_CONNECT'] . '<br />' . (($db_error['message']) ? $db_error['message'] : $lang['INST_ERR_DB_NO_ERROR']);
 313      }
 314      else
 315      {
 316          // Likely matches for an existing phpBB installation
 317          if (!$prefix_may_exist)
 318          {
 319              $temp_prefix = strtolower($table_prefix);
 320              $table_ary = array($temp_prefix . 'attachments', $temp_prefix . 'config', $temp_prefix . 'sessions', $temp_prefix . 'topics', $temp_prefix . 'users');
 321  
 322              $tables = get_tables($db);
 323              $tables = array_map('strtolower', $tables);
 324              $table_intersect = array_intersect($tables, $table_ary);
 325  
 326              if (sizeof($table_intersect))
 327              {
 328                  $error[] = $lang['INST_ERR_PREFIX'];
 329              }
 330          }
 331  
 332          // Make sure that the user has selected a sensible DBAL for the DBMS actually installed
 333          switch ($dbms_details['DRIVER'])
 334          {
 335              case 'mysqli':
 336                  if (version_compare(mysqli_get_server_info($db->db_connect_id), '4.1.3', '<'))
 337                  {
 338                      $error[] = $lang['INST_ERR_DB_NO_MYSQLI'];
 339                  }
 340              break;
 341  
 342              case 'sqlite':
 343                  if (version_compare(sqlite_libversion(), '2.8.2', '<'))
 344                  {
 345                      $error[] = $lang['INST_ERR_DB_NO_SQLITE'];
 346                  }
 347              break;
 348  
 349              case 'firebird':
 350                  // check the version of FB, use some hackery if we can't get access to the server info
 351                  if ($db->service_handle !== false && function_exists('ibase_server_info'))
 352                  {
 353                      $val = @ibase_server_info($db->service_handle, IBASE_SVC_SERVER_VERSION);
 354                      preg_match('#V([\d.]+)#', $val, $match);
 355                      if ($match[1] < 2)
 356                      {
 357                          $error[] = $lang['INST_ERR_DB_NO_FIREBIRD'];
 358                      }
 359                      $db_info = @ibase_db_info($db->service_handle, $dbname, IBASE_STS_HDR_PAGES);
 360  
 361                      preg_match('/^\\s*Page size\\s*(\\d+)/m', $db_info, $regs);
 362                      $page_size = intval($regs[1]);
 363                      if ($page_size < 8192)
 364                      {
 365                          $error[] = $lang['INST_ERR_DB_NO_FIREBIRD_PS'];
 366                      }
 367                  }
 368                  else
 369                  {
 370                      $sql = "SELECT *
 371                          FROM RDB$FUNCTIONS
 372                          WHERE RDB$SYSTEM_FLAG IS NULL
 373                              AND RDB$FUNCTION_NAME = 'CHAR_LENGTH'";
 374                      $result = $db->sql_query($sql);
 375                      $row = $db->sql_fetchrow($result);
 376                      $db->sql_freeresult($result);
 377  
 378                      // if its a UDF, its too old
 379                      if ($row)
 380                      {
 381                          $error[] = $lang['INST_ERR_DB_NO_FIREBIRD'];
 382                      }
 383                      else
 384                      {
 385                          $sql = 'SELECT 1 FROM RDB$DATABASE
 386                              WHERE BIN_AND(10, 1) = 0';
 387                          $result = $db->sql_query($sql);
 388                          if (!$result) // This can only fail if BIN_AND is not defined
 389                          {
 390                              $error[] = $lang['INST_ERR_DB_NO_FIREBIRD'];
 391                          }
 392                          $db->sql_freeresult($result);
 393                      }
 394  
 395                      // Setup the stuff for our random table
 396                      $char_array = array_merge(range('A', 'Z'), range('0', '9'));
 397                      $char_len = mt_rand(7, 9);
 398                      $char_array_len = sizeof($char_array) - 1;
 399  
 400                      $final = '';
 401  
 402                      for ($i = 0; $i < $char_len; $i++)
 403                      {
 404                          $final .= $char_array[mt_rand(0, $char_array_len)];
 405                      }
 406  
 407                      // Create some random table
 408                      $sql = 'CREATE TABLE ' . $final . " (
 409                          FIELD1 VARCHAR(255) CHARACTER SET UTF8 DEFAULT '' NOT NULL COLLATE UNICODE,
 410                          FIELD2 INTEGER DEFAULT 0 NOT NULL);";
 411                      $db->sql_query($sql);
 412  
 413                      // Create an index that should fail if the page size is less than 8192
 414                      $sql = 'CREATE INDEX ' . $final . ' ON ' . $final . '(FIELD1, FIELD2);';
 415                      $db->sql_query($sql);
 416  
 417                      if (ibase_errmsg() !== false)
 418                      {
 419                          $error[] = $lang['INST_ERR_DB_NO_FIREBIRD_PS'];
 420                      }
 421                      else
 422                      {
 423                          // Kill the old table
 424                          $db->sql_query('DROP TABLE ' . $final . ';');
 425                      }
 426                      unset($final);
 427                  }
 428              break;
 429  
 430              case 'oracle':
 431                  if ($unicode_check)
 432                  {
 433                      $sql = "SELECT *
 434                          FROM NLS_DATABASE_PARAMETERS
 435                          WHERE PARAMETER = 'NLS_RDBMS_VERSION'
 436                              OR PARAMETER = 'NLS_CHARACTERSET'";
 437                      $result = $db->sql_query($sql);
 438  
 439                      while ($row = $db->sql_fetchrow($result))
 440                      {
 441                          $stats[$row['parameter']] = $row['value'];
 442                      }
 443                      $db->sql_freeresult($result);
 444  
 445                      if (version_compare($stats['NLS_RDBMS_VERSION'], '9.2', '<') && $stats['NLS_CHARACTERSET'] !== 'UTF8')
 446                      {
 447                          $error[] = $lang['INST_ERR_DB_NO_ORACLE'];
 448                      }
 449                  }
 450              break;
 451  
 452              case 'postgres':
 453                  if ($unicode_check)
 454                  {
 455                      $sql = "SHOW server_encoding;";
 456                      $result = $db->sql_query($sql);
 457                      $row = $db->sql_fetchrow($result);
 458                      $db->sql_freeresult($result);
 459  
 460                      if ($row['server_encoding'] !== 'UNICODE' && $row['server_encoding'] !== 'UTF8')
 461                      {
 462                          $error[] = $lang['INST_ERR_DB_NO_POSTGRES'];
 463                      }
 464                  }
 465              break;
 466          }
 467  
 468      }
 469  
 470      if ($error_connect && (!isset($error) || !sizeof($error)))
 471      {
 472          return true;
 473      }
 474      return false;
 475  }
 476  
 477  /**
 478  * Removes comments from schema files
 479  *
 480  * @deprecated        Use phpbb_remove_comments() instead.
 481  */
 482  function remove_remarks(&$sql)
 483  {
 484      // Remove # style comments
 485      $sql = preg_replace('/\n{2,}/', "\n", preg_replace('/^#.*$/m', "\n", $sql));
 486  
 487      // Return by reference
 488  }
 489  
 490  /**
 491  * Removes "/* style" as well as "# style" comments from $input.
 492  *
 493  * @param string $input        Input string
 494  *
 495  * @return string            Input string with comments removed
 496  */
 497  function phpbb_remove_comments($input)
 498  {
 499      if (!function_exists('remove_comments'))
 500      {
 501          global $phpbb_root_path, $phpEx;
 502          require($phpbb_root_path . 'includes/functions_admin.' . $phpEx);
 503      }
 504  
 505      // Remove /* */ comments
 506      remove_comments($input);
 507  
 508      // Remove # style comments
 509      remove_remarks($input);
 510  
 511      return $input;
 512  }
 513  
 514  /**
 515  * split_sql_file will split an uploaded sql file into single sql statements.
 516  * Note: expects trim() to have already been run on $sql.
 517  */
 518  function split_sql_file($sql, $delimiter)
 519  {
 520      $sql = str_replace("\r" , '', $sql);
 521      $data = preg_split('/' . preg_quote($delimiter, '/') . '$/m', $sql);
 522  
 523      $data = array_map('trim', $data);
 524  
 525      // The empty case
 526      $end_data = end($data);
 527  
 528      if (empty($end_data))
 529      {
 530          unset($data[key($data)]);
 531      }
 532  
 533      return $data;
 534  }
 535  
 536  /**
 537  * For replacing {L_*} strings with preg_replace_callback
 538  */
 539  function adjust_language_keys_callback($matches)
 540  {
 541      if (!empty($matches[1]))
 542      {
 543          global $lang, $db;
 544  
 545          return (!empty($lang[$matches[1]])) ? $db->sql_escape($lang[$matches[1]]) : $db->sql_escape($matches[1]);
 546      }
 547  }
 548  
 549  /**
 550  * Creates the output to be stored in a phpBB config.php file
 551  *
 552  * @param    array    $data Array containing the database connection information
 553  * @param    string    $dbms The name of the DBAL class to use
 554  * @param    array    $load_extensions Array of additional extensions that should be loaded
 555  * @param    bool    $debug If the debug constants should be enabled by default or not
 556  * @param    bool    $debug_test If the DEBUG_TEST constant should be added
 557  *                    NOTE: Only for use within the testing framework
 558  *
 559  * @return    string    The output to write to the file
 560  */
 561  function phpbb_create_config_file_data($data, $dbms, $load_extensions, $debug = false, $debug_test = false)
 562  {
 563      $load_extensions = implode(',', $load_extensions);
 564  
 565      $config_data = "<?php\n";
 566      $config_data .= "// phpBB 3.0.x auto-generated configuration file\n// Do not change anything in this file!\n";
 567  
 568      $config_data_array = array(
 569          'dbms'            => $dbms,
 570          'dbhost'        => $data['dbhost'],
 571          'dbport'        => $data['dbport'],
 572          'dbname'        => $data['dbname'],
 573          'dbuser'        => $data['dbuser'],
 574          'dbpasswd'        => htmlspecialchars_decode($data['dbpasswd']),
 575          'table_prefix'    => $data['table_prefix'],
 576          'acm_type'        => 'file',
 577          'load_extensions'    => $load_extensions,
 578      );
 579  
 580      foreach ($config_data_array as $key => $value)
 581      {
 582          $config_data .= "\${$key} = '" . str_replace("'", "\\'", str_replace('\\', '\\\\', $value)) . "';\n";
 583      }
 584  
 585      $config_data .= "\n@define('PHPBB_INSTALLED', true);\n";
 586  
 587      if ($debug)
 588      {
 589          $config_data .= "@define('DEBUG', true);\n";
 590          $config_data .= "@define('DEBUG_EXTRA', true);\n";
 591      }
 592      else
 593      {
 594          $config_data .= "// @define('DEBUG', true);\n";
 595          $config_data .= "// @define('DEBUG_EXTRA', true);\n";
 596      }
 597  
 598      if ($debug_test)
 599      {
 600          $config_data .= "@define('DEBUG_TEST', true);\n";
 601      }
 602  
 603      return $config_data;
 604  }
 605  
 606  ?>


Generated: Wed Oct 2 15:03:47 2013 Cross-referenced by PHPXref 0.7.1