[ Index ]

PHP Cross Reference of phpBB-3.3.14-deutsch

title

Body

[close]

/phpbb/install/helper/ -> database.php (source)

   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  namespace phpbb\install\helper;
  15  
  16  use phpbb\install\exception\invalid_dbms_exception;
  17  
  18  /**
  19   * Database related general functionality for installer
  20   */
  21  class database
  22  {
  23      /**
  24       * @var \phpbb\filesystem\filesystem_interface
  25       */
  26      protected $filesystem;
  27  
  28      /**
  29       * @var string
  30       */
  31      protected $phpbb_root_path;
  32  
  33      /**
  34       * @var array
  35       */
  36      protected $supported_dbms = array(
  37          // Note: php 5.5 alpha 2 deprecated mysql.
  38          // Keep mysqli before mysql in this list.
  39          'mysqli'    => array(
  40              'LABEL'            => 'MySQL with MySQLi Extension',
  41              'SCHEMA'        => 'mysql_41',
  42              'MODULE'        => 'mysqli',
  43              'DELIM'            => ';',
  44              'DRIVER'        => 'phpbb\db\driver\mysqli',
  45              'AVAILABLE'        => true,
  46              '2.0.x'            => true,
  47          ),
  48          'mssql_odbc'=>    array(
  49              'LABEL'            => 'MS SQL Server [ ODBC ]',
  50              'SCHEMA'        => 'mssql',
  51              'MODULE'        => 'odbc',
  52              'DELIM'            => ';',
  53              'DRIVER'        => 'phpbb\db\driver\mssql_odbc',
  54              'AVAILABLE'        => true,
  55              '2.0.x'            => true,
  56          ),
  57          'mssqlnative'        => array(
  58              'LABEL'            => 'MS SQL Server 2005+ [ Native ]',
  59              'SCHEMA'        => 'mssql',
  60              'MODULE'        => 'sqlsrv',
  61              'DELIM'            => ';',
  62              'DRIVER'        => 'phpbb\db\driver\mssqlnative',
  63              'AVAILABLE'        => true,
  64              '2.0.x'            => false,
  65          ),
  66          'oracle'    =>    array(
  67              'LABEL'            => 'Oracle',
  68              'SCHEMA'        => 'oracle',
  69              'MODULE'        => 'oci8',
  70              'DELIM'            => ';',
  71              'DRIVER'        => 'phpbb\db\driver\oracle',
  72              'AVAILABLE'        => true,
  73              '2.0.x'            => false,
  74          ),
  75          'postgres' => array(
  76              'LABEL'            => 'PostgreSQL 8.3+',
  77              'SCHEMA'        => 'postgres',
  78              'MODULE'        => 'pgsql',
  79              'DELIM'            => ';',
  80              'DRIVER'        => 'phpbb\db\driver\postgres',
  81              'AVAILABLE'        => true,
  82              '2.0.x'            => true,
  83          ),
  84          'sqlite3'        => array(
  85              'LABEL'            => 'SQLite3',
  86              'SCHEMA'        => 'sqlite',
  87              'MODULE'        => 'sqlite3',
  88              'DELIM'            => ';',
  89              'DRIVER'        => 'phpbb\db\driver\sqlite3',
  90              'AVAILABLE'        => true,
  91              '2.0.x'            => false,
  92          ),
  93      );
  94  
  95      /**
  96       * Constructor
  97       *
  98       * @param \phpbb\filesystem\filesystem_interface    $filesystem            Filesystem interface
  99       * @param string                                    $phpbb_root_path    Path to phpBB's root
 100       */
 101  	public function __construct(\phpbb\filesystem\filesystem_interface $filesystem, $phpbb_root_path)
 102      {
 103          $this->filesystem        = $filesystem;
 104          $this->phpbb_root_path    = $phpbb_root_path;
 105      }
 106  
 107      /**
 108       * Returns an array of available DBMS supported by phpBB
 109       *
 110       * If a DBMS is specified it will only return data for that DBMS
 111       * and will load its extension if necessary.
 112       *
 113       * @param    mixed    $dbms                name of the DBMS that's info is required or false for all DBMS info
 114       * @param    bool    $return_unavailable    set it to true if you expect unavailable but supported DBMS
 115       *                                         returned as well
 116       * @param    bool    $only_20x_options    set it to true if you only want to recover 2.0.x options
 117       *
 118       * @return    array    Array of available and supported DBMS
 119       */
 120  	public function get_available_dbms($dbms = false, $return_unavailable = false, $only_20x_options = false)
 121      {
 122          $available_dbms = $this->supported_dbms;
 123  
 124          if ($dbms)
 125          {
 126              if (isset($this->supported_dbms[$dbms]))
 127              {
 128                  $available_dbms = array($dbms => $this->supported_dbms[$dbms]);
 129              }
 130              else
 131              {
 132                  return array();
 133              }
 134          }
 135  
 136          $any_dbms_available = false;
 137          foreach ($available_dbms as $db_name => $db_array)
 138          {
 139              if ($only_20x_options && !$db_array['2.0.x'])
 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  
 150                  continue;
 151              }
 152  
 153              $dll = $db_array['MODULE'];
 154              if (!@extension_loaded($dll))
 155              {
 156                  if ($return_unavailable)
 157                  {
 158                      $available_dbms[$db_name]['AVAILABLE'] = false;
 159                  }
 160                  else
 161                  {
 162                      unset($available_dbms[$db_name]);
 163                  }
 164  
 165                  continue;
 166              }
 167  
 168              $any_dbms_available = true;
 169          }
 170  
 171          if ($return_unavailable)
 172          {
 173              $available_dbms['ANY_DB_SUPPORT'] = $any_dbms_available;
 174          }
 175  
 176          return $available_dbms;
 177      }
 178  
 179      /**
 180       * Removes "/* style" as well as "# style" comments from $input.
 181       *
 182       * @param string $sql_query    Input string
 183       *
 184       * @return string Input string with comments removed
 185       */
 186  	public function remove_comments($sql_query)
 187      {
 188          // Remove /* */ comments (http://ostermiller.org/findcomment.html)
 189          $sql_query = preg_replace('#/\*(.|[\r\n])*?\*/#', "\n", $sql_query);
 190  
 191          // Remove # style comments
 192          $sql_query = preg_replace('/\n{2,}/', "\n", preg_replace('/^#.*$/m', "\n", $sql_query));
 193  
 194          return $sql_query;
 195      }
 196  
 197      /**
 198       * split_sql_file() will split an uploaded sql file into single sql statements.
 199       *
 200       * Note: expects trim() to have already been run on $sql.
 201       *
 202       * @param    string    $sql        SQL statements
 203       * @param    string    $delimiter    Delimiter between sql statements
 204       *
 205       * @return array Array of sql statements
 206       */
 207  	public function split_sql_file($sql, $delimiter)
 208      {
 209          $sql = str_replace("\r" , '', $sql);
 210          $data = preg_split('/' . preg_quote($delimiter, '/') . '$/m', $sql);
 211  
 212          $data = array_map('trim', $data);
 213  
 214          // The empty case
 215          $end_data = end($data);
 216  
 217          if (empty($end_data))
 218          {
 219              unset($data[key($data)]);
 220          }
 221  
 222          return $data;
 223      }
 224  
 225      /**
 226       * Validates table prefix
 227       *
 228       * @param string    $dbms            The selected dbms
 229       * @param string    $table_prefix    The table prefix to validate
 230       *
 231       * @return bool|array    true if table prefix is valid, array of errors otherwise
 232       *
 233       * @throws invalid_dbms_exception When $dbms is not a valid
 234       */
 235  	public function validate_table_prefix($dbms, $table_prefix)
 236      {
 237          $errors = array();
 238  
 239          if (!preg_match('#^[a-zA-Z][a-zA-Z0-9_]*$#', $table_prefix))
 240          {
 241              $errors[] = array(
 242                  'title' => 'INST_ERR_DB_INVALID_PREFIX',
 243              );
 244          }
 245  
 246          // Do dbms specific checks
 247          $dbms_info = $this->get_available_dbms($dbms);
 248          switch ($dbms_info[$dbms]['SCHEMA'])
 249          {
 250              case 'mysql_41':
 251                  $prefix_length = 36;
 252              break;
 253              case 'mssql':
 254                  $prefix_length = 90;
 255              break;
 256              case 'oracle':
 257                  $prefix_length = 6;
 258              break;
 259              case 'postgres':
 260                  $prefix_length = 36;
 261              break;
 262              case 'sqlite':
 263                  $prefix_length = 200;
 264              break;
 265              default:
 266                  throw new invalid_dbms_exception();
 267              break;
 268          }
 269  
 270          // Check the prefix length to ensure that index names are not too long
 271          if (strlen($table_prefix) > $prefix_length)
 272          {
 273              $errors[] = array(
 274                  'title' => array('INST_ERR_PREFIX_TOO_LONG', $prefix_length),
 275              );
 276          }
 277  
 278          return (empty($errors)) ? true : $errors;
 279      }
 280  
 281      /**
 282       * Check if the user provided database parameters are correct
 283       *
 284       * This function checks the database connection data and also checks for
 285       * any other problems that could cause an error during the installation
 286       * such as if there is any database table names conflicting.
 287       *
 288       * Note: The function assumes that $table_prefix has been already validated
 289       * with validate_table_prefix().
 290       *
 291       * @param string    $dbms            Selected database type
 292       * @param string    $dbhost            Database host address
 293       * @param int        $dbport            Database port number
 294       * @param string    $dbuser            Database username
 295       * @param string    $dbpass            Database password
 296       * @param string    $dbname            Database name
 297       * @param string    $table_prefix    Database table prefix
 298       *
 299       * @return array|bool    Returns true if test is successful, array of errors otherwise
 300       */
 301  	public function check_database_connection($dbms, $dbhost, $dbport, $dbuser, $dbpass, $dbname, $table_prefix)
 302      {
 303          $dbms_info = $this->get_available_dbms($dbms);
 304          $dbms_info = $dbms_info[$dbms];
 305          $errors = array();
 306  
 307          // Instantiate it and set return on error true
 308          /** @var \phpbb\db\driver\driver_interface $db */
 309          $db = new $dbms_info['DRIVER'];
 310          $db->sql_return_on_error(true);
 311  
 312          // Check that we actually have a database name before going any further
 313          if (!in_array($dbms_info['SCHEMA'], array('sqlite', 'oracle'), true) && $dbname === '')
 314          {
 315              $errors[] = array(
 316                  'title' => 'INST_ERR_DB_NO_NAME',
 317              );
 318          }
 319  
 320          // Make sure we don't have a daft user who thinks having the SQLite database in the forum directory is a good idea
 321          if ($dbms_info['SCHEMA'] === 'sqlite'
 322              && stripos($this->filesystem->realpath($dbhost), $this->filesystem->realpath($this->phpbb_root_path) === 0))
 323          {
 324              $errors[] = array(
 325                  'title' =>'INST_ERR_DB_FORUM_PATH',
 326              );
 327          }
 328  
 329          // Check if SQLite database is writable
 330          if ($dbms_info['SCHEMA'] === 'sqlite'
 331              && (($this->filesystem->exists($dbhost) && !$this->filesystem->is_writable($dbhost)) || !$this->filesystem->is_writable(pathinfo($dbhost, PATHINFO_DIRNAME))))
 332          {
 333              $errors[] = array(
 334                  'title' =>'INST_ERR_DB_NO_WRITABLE',
 335              );
 336          }
 337  
 338          // Try to connect to db
 339          if (is_array($db->sql_connect($dbhost, $dbuser, $dbpass, $dbname, $dbport, false, true)))
 340          {
 341              $db_error = $db->sql_error();
 342              $errors[] = array(
 343                  'title' => 'INST_ERR_DB_CONNECT',
 344                  'description' => ($db_error['message']) ? utf8_convert_message($db_error['message']) : 'INST_ERR_DB_NO_ERROR',
 345              );
 346          }
 347          else
 348          {
 349              // Check if there is any table name collisions
 350              $temp_prefix = strtolower($table_prefix);
 351              $table_ary = array(
 352                  $temp_prefix . 'attachments',
 353                  $temp_prefix . 'config',
 354                  $temp_prefix . 'sessions',
 355                  $temp_prefix . 'topics',
 356                  $temp_prefix . 'users',
 357              );
 358  
 359              $db_tools_factory = new \phpbb\db\tools\factory();
 360              $db_tools = $db_tools_factory->get($db);
 361              $tables = $db_tools->sql_list_tables();
 362              $tables = array_map('strtolower', $tables);
 363              $table_intersect = array_intersect($tables, $table_ary);
 364  
 365              if (count($table_intersect))
 366              {
 367                  $errors[] = array(
 368                      'title' => 'INST_ERR_PREFIX',
 369                  );
 370              }
 371  
 372              // Check if database version is supported
 373              switch ($dbms)
 374              {
 375                  case 'sqlite3':
 376                      if (version_compare($db->sql_server_info(true), '3.6.15', '<'))
 377                      {
 378                          $errors[] = array(
 379                              'title' => 'INST_ERR_DB_NO_SQLITE3',
 380                          );
 381                      }
 382                  break;
 383                  case 'oracle':
 384                      $sql = "SELECT *
 385                          FROM NLS_DATABASE_PARAMETERS
 386                          WHERE PARAMETER = 'NLS_RDBMS_VERSION'
 387                              OR PARAMETER = 'NLS_CHARACTERSET'";
 388                      $result = $db->sql_query($sql);
 389  
 390                      while ($row = $db->sql_fetchrow($result))
 391                      {
 392                          $stats[$row['parameter']] = $row['value'];
 393                      }
 394                      $db->sql_freeresult($result);
 395  
 396                      if (version_compare($stats['NLS_RDBMS_VERSION'], '9.2', '<') && $stats['NLS_CHARACTERSET'] !== 'UTF8')
 397                      {
 398                          $errors[] = array(
 399                              'title' => 'INST_ERR_DB_NO_ORACLE',
 400                          );
 401                      }
 402                  break;
 403                  case 'postgres':
 404                      $sql = "SHOW server_encoding;";
 405                      $result = $db->sql_query($sql);
 406                      $row = $db->sql_fetchrow($result);
 407                      $db->sql_freeresult($result);
 408  
 409                      if ($row['server_encoding'] !== 'UNICODE' && $row['server_encoding'] !== 'UTF8')
 410                      {
 411                          $errors[] = array(
 412                              'title' => 'INST_ERR_DB_NO_POSTGRES',
 413                          );
 414                      }
 415                  break;
 416              }
 417          }
 418  
 419          return (empty($errors)) ? true : $errors;
 420      }
 421  }


Generated: Mon Nov 25 19:05:08 2024 Cross-referenced by PHPXref 0.7.1