Verzeichnisstruktur phpBB-3.3.15


Veröffentlicht
28.08.2024

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

(Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

database.php

Zuletzt modifiziert: 02.04.2025, 15:02 - Dateigröße: 10.61 KiB


001  <?php
002  /**
003   *
004   * This file is part of the phpBB Forum Software package.
005   *
006   * @copyright (c) phpBB Limited <https://www.phpbb.com>
007   * @license GNU General Public License, version 2 (GPL-2.0)
008   *
009   * For full copyright and license information, please see
010   * the docs/CREDITS.txt file.
011   *
012   */
013   
014  namespace phpbb\install\helper;
015   
016  use phpbb\install\exception\invalid_dbms_exception;
017   
018  /**
019   * Database related general functionality for installer
020   */
021  class database
022  {
023      /**
024       * @var \phpbb\filesystem\filesystem_interface
025       */
026      protected $filesystem;
027   
028      /**
029       * @var string
030       */
031      protected $phpbb_root_path;
032   
033      /**
034       * @var array
035       */
036      protected $supported_dbms = array(
037          // Note: php 5.5 alpha 2 deprecated mysql.
038          // Keep mysqli before mysql in this list.
039          'mysqli'    => array(
040              'LABEL'            => 'MySQL with MySQLi Extension',
041              'SCHEMA'        => 'mysql_41',
042              'MODULE'        => 'mysqli',
043              'DELIM'            => ';',
044              'DRIVER'        => 'phpbb\db\driver\mysqli',
045              'AVAILABLE'        => true,
046              '2.0.x'            => true,
047          ),
048          'mssql_odbc'=>    array(
049              'LABEL'            => 'MS SQL Server [ ODBC ]',
050              'SCHEMA'        => 'mssql',
051              'MODULE'        => 'odbc',
052              'DELIM'            => ';',
053              'DRIVER'        => 'phpbb\db\driver\mssql_odbc',
054              'AVAILABLE'        => true,
055              '2.0.x'            => true,
056          ),
057          'mssqlnative'        => array(
058              'LABEL'            => 'MS SQL Server 2005+ [ Native ]',
059              'SCHEMA'        => 'mssql',
060              'MODULE'        => 'sqlsrv',
061              'DELIM'            => ';',
062              'DRIVER'        => 'phpbb\db\driver\mssqlnative',
063              'AVAILABLE'        => true,
064              '2.0.x'            => false,
065          ),
066          'oracle'    =>    array(
067              'LABEL'            => 'Oracle',
068              'SCHEMA'        => 'oracle',
069              'MODULE'        => 'oci8',
070              'DELIM'            => ';',
071              'DRIVER'        => 'phpbb\db\driver\oracle',
072              'AVAILABLE'        => true,
073              '2.0.x'            => false,
074          ),
075          'postgres' => array(
076              'LABEL'            => 'PostgreSQL 8.3+',
077              'SCHEMA'        => 'postgres',
078              'MODULE'        => 'pgsql',
079              'DELIM'            => ';',
080              'DRIVER'        => 'phpbb\db\driver\postgres',
081              'AVAILABLE'        => true,
082              '2.0.x'            => true,
083          ),
084          'sqlite3'        => array(
085              'LABEL'            => 'SQLite3',
086              'SCHEMA'        => 'sqlite',
087              'MODULE'        => 'sqlite3',
088              'DELIM'            => ';',
089              'DRIVER'        => 'phpbb\db\driver\sqlite3',
090              'AVAILABLE'        => true,
091              '2.0.x'            => false,
092          ),
093      );
094   
095      /**
096       * Constructor
097       *
098       * @param \phpbb\filesystem\filesystem_interface    $filesystem            Filesystem interface
099       * @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  }
422