Verzeichnisstruktur phpBB-3.2.0
- Veröffentlicht
- 06.01.2017
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. |
|
(Beispiel Datei-Icons)
|
Auf das Icon klicken um den Quellcode anzuzeigen |
database.php
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 'mysql' => array(
049 'LABEL' => 'MySQL',
050 'SCHEMA' => 'mysql',
051 'MODULE' => 'mysql',
052 'DELIM' => ';',
053 'DRIVER' => 'phpbb\db\driver\mysql',
054 'AVAILABLE' => true,
055 '2.0.x' => true,
056 ),
057 'mssql_odbc'=> array(
058 'LABEL' => 'MS SQL Server [ ODBC ]',
059 'SCHEMA' => 'mssql',
060 'MODULE' => 'odbc',
061 'DELIM' => ';',
062 'DRIVER' => 'phpbb\db\driver\mssql_odbc',
063 'AVAILABLE' => true,
064 '2.0.x' => true,
065 ),
066 'mssqlnative' => array(
067 'LABEL' => 'MS SQL Server 2005+ [ Native ]',
068 'SCHEMA' => 'mssql',
069 'MODULE' => 'sqlsrv',
070 'DELIM' => ';',
071 'DRIVER' => 'phpbb\db\driver\mssqlnative',
072 'AVAILABLE' => true,
073 '2.0.x' => false,
074 ),
075 'oracle' => array(
076 'LABEL' => 'Oracle',
077 'SCHEMA' => 'oracle',
078 'MODULE' => 'oci8',
079 'DELIM' => '/',
080 'DRIVER' => 'phpbb\db\driver\oracle',
081 'AVAILABLE' => true,
082 '2.0.x' => false,
083 ),
084 'postgres' => array(
085 'LABEL' => 'PostgreSQL 8.3+',
086 'SCHEMA' => 'postgres',
087 'MODULE' => 'pgsql',
088 'DELIM' => ';',
089 'DRIVER' => 'phpbb\db\driver\postgres',
090 'AVAILABLE' => true,
091 '2.0.x' => true,
092 ),
093 'sqlite3' => array(
094 'LABEL' => 'SQLite3',
095 'SCHEMA' => 'sqlite',
096 'MODULE' => 'sqlite3',
097 'DELIM' => ';',
098 'DRIVER' => 'phpbb\db\driver\sqlite3',
099 'AVAILABLE' => true,
100 '2.0.x' => false,
101 ),
102 );
103
104 /**
105 * Constructor
106 *
107 * @param \phpbb\filesystem\filesystem_interface $filesystem Filesystem interface
108 * @param string $phpbb_root_path Path to phpBB's root
109 */
110 public function __construct(\phpbb\filesystem\filesystem_interface $filesystem, $phpbb_root_path)
111 {
112 $this->filesystem = $filesystem;
113 $this->phpbb_root_path = $phpbb_root_path;
114 }
115
116 /**
117 * Returns an array of available DBMS supported by phpBB
118 *
119 * If a DBMS is specified it will only return data for that DBMS
120 * and will load its extension if necessary.
121 *
122 * @param mixed $dbms name of the DBMS that's info is required or false for all DBMS info
123 * @param bool $return_unavailable set it to true if you expect unavailable but supported DBMS
124 * returned as well
125 * @param bool $only_20x_options set it to true if you only want to recover 2.0.x options
126 *
127 * @return array Array of available and supported DBMS
128 */
129 public function get_available_dbms($dbms = false, $return_unavailable = false, $only_20x_options = false)
130 {
131 $available_dbms = $this->supported_dbms;
132
133 if ($dbms)
134 {
135 if (isset($this->supported_dbms[$dbms]))
136 {
137 $available_dbms = array($dbms => $this->supported_dbms[$dbms]);
138 }
139 else
140 {
141 return array();
142 }
143 }
144
145 $any_dbms_available = false;
146 foreach ($available_dbms as $db_name => $db_array)
147 {
148 if ($only_20x_options && !$db_array['2.0.x'])
149 {
150 if ($return_unavailable)
151 {
152 $available_dbms[$db_name]['AVAILABLE'] = false;
153 }
154 else
155 {
156 unset($available_dbms[$db_name]);
157 }
158
159 continue;
160 }
161
162 $dll = $db_array['MODULE'];
163 if (!@extension_loaded($dll))
164 {
165 if ($return_unavailable)
166 {
167 $available_dbms[$db_name]['AVAILABLE'] = false;
168 }
169 else
170 {
171 unset($available_dbms[$db_name]);
172 }
173
174 continue;
175 }
176
177 $any_dbms_available = true;
178 }
179
180 if ($return_unavailable)
181 {
182 $available_dbms['ANY_DB_SUPPORT'] = $any_dbms_available;
183 }
184
185 return $available_dbms;
186 }
187
188 /**
189 * Removes "/* style" as well as "# style" comments from $input.
190 *
191 * @param string $sql_query Input string
192 *
193 * @return string Input string with comments removed
194 */
195 public function remove_comments($sql_query)
196 {
197 // Remove /* */ comments (http://ostermiller.org/findcomment.html)
198 $sql_query = preg_replace('#/\*(.|[\r\n])*?\*/#', "\n", $sql_query);
199
200 // Remove # style comments
201 $sql_query = preg_replace('/\n{2,}/', "\n", preg_replace('/^#.*$/m', "\n", $sql_query));
202
203 return $sql_query;
204 }
205
206 /**
207 * split_sql_file() will split an uploaded sql file into single sql statements.
208 *
209 * Note: expects trim() to have already been run on $sql.
210 *
211 * @param string $sql SQL statements
212 * @param string $delimiter Delimiter between sql statements
213 *
214 * @return array Array of sql statements
215 */
216 public function split_sql_file($sql, $delimiter)
217 {
218 $sql = str_replace("\r" , '', $sql);
219 $data = preg_split('/' . preg_quote($delimiter, '/') . '$/m', $sql);
220
221 $data = array_map('trim', $data);
222
223 // The empty case
224 $end_data = end($data);
225
226 if (empty($end_data))
227 {
228 unset($data[key($data)]);
229 }
230
231 return $data;
232 }
233
234 /**
235 * Validates table prefix
236 *
237 * @param string $dbms The selected dbms
238 * @param string $table_prefix The table prefix to validate
239 *
240 * @return bool|array true if table prefix is valid, array of errors otherwise
241 *
242 * @throws \phpbb\install\exception\invalid_dbms_exception When $dbms is not a valid
243 */
244 public function validate_table_prefix($dbms, $table_prefix)
245 {
246 $errors = array();
247
248 if (!preg_match('#^[a-zA-Z][a-zA-Z0-9_]*$#', $table_prefix))
249 {
250 $errors[] = array(
251 'title' => 'INST_ERR_DB_INVALID_PREFIX',
252 );
253 }
254
255 // Do dbms specific checks
256 $dbms_info = $this->get_available_dbms($dbms);
257 switch ($dbms_info[$dbms]['SCHEMA'])
258 {
259 case 'mysql':
260 case 'mysql_41':
261 $prefix_length = 36;
262 break;
263 case 'mssql':
264 $prefix_length = 90;
265 break;
266 case 'oracle':
267 $prefix_length = 6;
268 break;
269 case 'postgres':
270 $prefix_length = 36;
271 break;
272 case 'sqlite':
273 $prefix_length = 200;
274 break;
275 default:
276 throw new invalid_dbms_exception();
277 break;
278 }
279
280 // Check the prefix length to ensure that index names are not too long
281 if (strlen($table_prefix) > $prefix_length)
282 {
283 $errors[] = array(
284 'title' => array('INST_ERR_PREFIX_TOO_LONG', $prefix_length),
285 );
286 }
287
288 return (empty($errors)) ? true : $errors;
289 }
290
291 /**
292 * Check if the user provided database parameters are correct
293 *
294 * This function checks the database connection data and also checks for
295 * any other problems that could cause an error during the installation
296 * such as if there is any database table names conflicting.
297 *
298 * Note: The function assumes that $table_prefix has been already validated
299 * with validate_table_prefix().
300 *
301 * @param string $dbms Selected database type
302 * @param string $dbhost Database host address
303 * @param int $dbport Database port number
304 * @param string $dbuser Database username
305 * @param string $dbpass Database password
306 * @param string $dbname Database name
307 * @param string $table_prefix Database table prefix
308 *
309 * @return array|bool Returns true if test is successful, array of errors otherwise
310 */
311 public function check_database_connection($dbms, $dbhost, $dbport, $dbuser, $dbpass, $dbname, $table_prefix)
312 {
313 $dbms_info = $this->get_available_dbms($dbms);
314 $dbms_info = $dbms_info[$dbms];
315 $errors = array();
316
317 // Instantiate it and set return on error true
318 /** @var \phpbb\db\driver\driver_interface $db */
319 $db = new $dbms_info['DRIVER'];
320 $db->sql_return_on_error(true);
321
322 // Check that we actually have a database name before going any further
323 if (!in_array($dbms_info['SCHEMA'], array('sqlite', 'oracle'), true) && $dbname === '')
324 {
325 $errors[] = array(
326 'title' => 'INST_ERR_DB_NO_NAME',
327 );
328 }
329
330 // Make sure we don't have a daft user who thinks having the SQLite database in the forum directory is a good idea
331 if ($dbms_info['SCHEMA'] === 'sqlite'
332 && stripos($this->filesystem->realpath($dbhost), $this->filesystem->realpath($this->phpbb_root_path) === 0))
333 {
334 $errors[] = array(
335 'title' =>'INST_ERR_DB_FORUM_PATH',
336 );
337 }
338
339 // Try to connect to db
340 if (is_array($db->sql_connect($dbhost, $dbuser, $dbpass, $dbname, $dbport, false, true)))
341 {
342 $db_error = $db->sql_error();
343 $errors[] = array(
344 'title' => 'INST_ERR_DB_CONNECT',
345 'description' => ($db_error['message']) ? utf8_convert_message($db_error['message']) : 'INST_ERR_DB_NO_ERROR',
346 );
347 }
348 else
349 {
350 // Check if there is any table name collisions
351 $temp_prefix = strtolower($table_prefix);
352 $table_ary = array(
353 $temp_prefix . 'attachments',
354 $temp_prefix . 'config',
355 $temp_prefix . 'sessions',
356 $temp_prefix . 'topics',
357 $temp_prefix . 'users',
358 );
359
360 $db_tools_factory = new \phpbb\db\tools\factory();
361 $db_tools = $db_tools_factory->get($db);
362 $tables = $db_tools->sql_list_tables();
363 $tables = array_map('strtolower', $tables);
364 $table_intersect = array_intersect($tables, $table_ary);
365
366 if (sizeof($table_intersect))
367 {
368 $errors[] = array(
369 'title' => 'INST_ERR_PREFIX',
370 );
371 }
372
373 // Check if database version is supported
374 switch ($dbms)
375 {
376 case 'mysqli':
377 if (version_compare($db->sql_server_info(true), '4.1.3', '<'))
378 {
379 $errors[] = array(
380 'title' => 'INST_ERR_DB_NO_MYSQLI',
381 );
382 }
383 break;
384 case 'sqlite3':
385 if (version_compare($db->sql_server_info(true), '3.6.15', '<'))
386 {
387 $errors[] = array(
388 'title' => 'INST_ERR_DB_NO_SQLITE3',
389 );
390 }
391 break;
392 case 'oracle':
393 $sql = "SELECT *
394 FROM NLS_DATABASE_PARAMETERS
395 WHERE PARAMETER = 'NLS_RDBMS_VERSION'
396 OR PARAMETER = 'NLS_CHARACTERSET'";
397 $result = $db->sql_query($sql);
398
399 while ($row = $db->sql_fetchrow($result))
400 {
401 $stats[$row['parameter']] = $row['value'];
402 }
403 $db->sql_freeresult($result);
404
405 if (version_compare($stats['NLS_RDBMS_VERSION'], '9.2', '<') && $stats['NLS_CHARACTERSET'] !== 'UTF8')
406 {
407 $errors[] = array(
408 'title' => 'INST_ERR_DB_NO_ORACLE',
409 );
410 }
411 break;
412 case 'postgres':
413 $sql = "SHOW server_encoding;";
414 $result = $db->sql_query($sql);
415 $row = $db->sql_fetchrow($result);
416 $db->sql_freeresult($result);
417
418 if ($row['server_encoding'] !== 'UNICODE' && $row['server_encoding'] !== 'UTF8')
419 {
420 $errors[] = array(
421 'title' => 'INST_ERR_DB_NO_POSTGRES',
422 );
423 }
424 break;
425 }
426 }
427
428 return (empty($errors)) ? true : $errors;
429 }
430 }
431