phpBB
Statistics
| Revision:

root / branches / phpBB-3_0_0 / phpBB / includes / functions_install.php

History | View | Annotate | Download (12.6 kB)

1
<?php
2
/**
3
*
4
* @package install
5
* @version $Id: functions_install.php 11612 2011-12-04 04:15:41Z git-gate $
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
                        'DRIVER'                => 'firebird',
54
                        'AVAILABLE'                => true,
55
                        '2.0.x'                        => false,
56
                ),
57
                'mysqli'        => array(
58
                        'LABEL'                        => 'MySQL with MySQLi Extension',
59
                        'SCHEMA'                => 'mysql_41',
60
                        'MODULE'                => 'mysqli',
61
                        'DELIM'                        => ';',
62
                        'DRIVER'                => 'mysqli',
63
                        'AVAILABLE'                => true,
64
                        '2.0.x'                        => true,
65
                ),
66
                'mysql'                => array(
67
                        'LABEL'                        => 'MySQL',
68
                        'SCHEMA'                => 'mysql',
69
                        'MODULE'                => 'mysql',
70
                        'DELIM'                        => ';',
71
                        'DRIVER'                => 'mysql',
72
                        'AVAILABLE'                => true,
73
                        '2.0.x'                        => true,
74
                ),
75
                'mssql'                => array(
76
                        'LABEL'                        => 'MS SQL Server 2000+',
77
                        'SCHEMA'                => 'mssql',
78
                        'MODULE'                => 'mssql',
79
                        'DELIM'                        => 'GO',
80
                        'DRIVER'                => 'mssql',
81
                        'AVAILABLE'                => true,
82
                        '2.0.x'                        => true,
83
                ),
84
                'mssql_odbc'=>        array(
85
                        'LABEL'                        => 'MS SQL Server [ ODBC ]',
86
                        'SCHEMA'                => 'mssql',
87
                        'MODULE'                => 'odbc',
88
                        'DELIM'                        => 'GO',
89
                        'DRIVER'                => 'mssql_odbc',
90
                        'AVAILABLE'                => true,
91
                        '2.0.x'                        => true,
92
                ),
93
                'mssqlnative'                => array(
94
                        'LABEL'                        => 'MS SQL Server 2005+ [ Native ]',
95
                        'SCHEMA'                => 'mssql',
96
                        'MODULE'                => 'sqlsrv',
97
                        'DELIM'                        => 'GO',
98
                        'DRIVER'                => 'mssqlnative',
99
                        'AVAILABLE'                => true,
100
                        '2.0.x'                        => false,
101
                ),                        
102
                'oracle'        =>        array(
103
                        'LABEL'                        => 'Oracle',
104
                        'SCHEMA'                => 'oracle',
105
                        'MODULE'                => 'oci8',
106
                        'DELIM'                        => '/',
107
                        'DRIVER'                => 'oracle',
108
                        'AVAILABLE'                => true,
109
                        '2.0.x'                        => false,
110
                ),
111
                'postgres' => array(
112
                        'LABEL'                        => 'PostgreSQL 7.x/8.x',
113
                        'SCHEMA'                => 'postgres',
114
                        'MODULE'                => 'pgsql',
115
                        'DELIM'                        => ';',
116
                        'DRIVER'                => 'postgres',
117
                        'AVAILABLE'                => true,
118
                        '2.0.x'                        => true,
119
                ),
120
                'sqlite'                => array(
121
                        'LABEL'                        => 'SQLite',
122
                        'SCHEMA'                => 'sqlite',
123
                        'MODULE'                => 'sqlite',
124
                        'DELIM'                        => ';',
125
                        'DRIVER'                => 'sqlite',
126
                        'AVAILABLE'                => true,
127
                        '2.0.x'                        => false,
128
                ),
129
        );
130
131
        if ($dbms)
132
        {
133
                if (isset($available_dbms[$dbms]))
134
                {
135
                        $available_dbms = array($dbms => $available_dbms[$dbms]);
136
                }
137
                else
138
                {
139
                        return array();
140
                }
141
        }
142
143
        // now perform some checks whether they are really available
144
        foreach ($available_dbms as $db_name => $db_ary)
145
        {
146
                if ($only_20x_options && !$db_ary['2.0.x'])
147
                {
148
                        if ($return_unavailable)
149
                        {
150
                                $available_dbms[$db_name]['AVAILABLE'] = false;
151
                        }
152
                        else
153
                        {
154
                                unset($available_dbms[$db_name]);
155
                        }
156
                        continue;
157
                }
158
159
                $dll = $db_ary['MODULE'];
160
161
                if (!@extension_loaded($dll))
162
                {
163
                        if (!can_load_dll($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
                                continue;
174
                        }
175
                }
176
                $any_db_support = true;
177
        }
178
179
        if ($return_unavailable)
180
        {
181
                $available_dbms['ANY_DB_SUPPORT'] = $any_db_support;
182
        }
183
        return $available_dbms;
184
}
185
186
/**
187
* Generate the drop down of available database options
188
*/
189
function dbms_select($default = '', $only_20x_options = false)
190
{
191
        global $lang;
192
193
        $available_dbms = get_available_dbms(false, false, $only_20x_options);
194
        $dbms_options = '';
195
        foreach ($available_dbms as $dbms_name => $details)
196
        {
197
                $selected = ($dbms_name == $default) ? ' selected="selected"' : '';
198
                $dbms_options .= '<option value="' . $dbms_name . '"' . $selected .'>' . $lang['DLL_' . strtoupper($dbms_name)] . '</option>';
199
        }
200
        return $dbms_options;
201
}
202
203
/**
204
* Get tables of a database
205
*
206
* @deprecated
207
*/
208
function get_tables(&$db)
209
{
210
        if (!class_exists('phpbb_db_tools'))
211
        {
212
                global $phpbb_root_path, $phpEx;
213
                require($phpbb_root_path . 'includes/db/db_tools.' . $phpEx);
214
        }
215
216
        $db_tools = new phpbb_db_tools($db);
217
218
        return $db_tools->sql_list_tables();
219
}
220
221
/**
222
* Used to test whether we are able to connect to the database the user has specified
223
* and identify any problems (eg there are already tables with the names we want to use
224
* @param        array        $dbms should be of the format of an element of the array returned by {@link get_available_dbms get_available_dbms()}
225
*                                        necessary extensions should be loaded already
226
*/
227
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)
228
{
229
        global $phpbb_root_path, $phpEx, $config, $lang;
230
231
        $dbms = $dbms_details['DRIVER'];
232
233
        if ($load_dbal)
234
        {
235
                // Include the DB layer
236
                include($phpbb_root_path . 'includes/db/' . $dbms . '.' . $phpEx);
237
        }
238
239
        // Instantiate it and set return on error true
240
        $sql_db = 'dbal_' . $dbms;
241
        $db = new $sql_db();
242
        $db->sql_return_on_error(true);
243
244
        // Check that we actually have a database name before going any further.....
245
        if ($dbms_details['DRIVER'] != 'sqlite' && $dbms_details['DRIVER'] != 'oracle' && $dbname === '')
246
        {
247
                $error[] = $lang['INST_ERR_DB_NO_NAME'];
248
                return false;
249
        }
250
251
        // Make sure we don't have a daft user who thinks having the SQLite database in the forum directory is a good idea
252
        if ($dbms_details['DRIVER'] == 'sqlite' && stripos(phpbb_realpath($dbhost), phpbb_realpath('../')) === 0)
253
        {
254
                $error[] = $lang['INST_ERR_DB_FORUM_PATH'];
255
                return false;
256
        }
257
258
        // Check the prefix length to ensure that index names are not too long and does not contain invalid characters
259
        switch ($dbms_details['DRIVER'])
260
        {
261
                case 'mysql':
262
                case 'mysqli':
263
                        if (strspn($table_prefix, '-./\\') !== 0)
264
                        {
265
                                $error[] = $lang['INST_ERR_PREFIX_INVALID'];
266
                                return false;
267
                        }
268
269
                // no break;
270
271
                case 'postgres':
272
                        $prefix_length = 36;
273
                break;
274
275
                case 'mssql':
276
                case 'mssql_odbc':
277
                case 'mssqlnative':
278
                        $prefix_length = 90;
279
                break;
280
281
                case 'sqlite':
282
                        $prefix_length = 200;
283
                break;
284
285
                case 'firebird':
286
                case 'oracle':
287
                        $prefix_length = 6;
288
                break;
289
        }
290
291
        if (strlen($table_prefix) > $prefix_length)
292
        {
293
                $error[] = sprintf($lang['INST_ERR_PREFIX_TOO_LONG'], $prefix_length);
294
                return false;
295
        }
296
297
        // Try and connect ...
298
        if (is_array($db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, true)))
299
        {
300
                $db_error = $db->sql_error();
301
                $error[] = $lang['INST_ERR_DB_CONNECT'] . '<br />' . (($db_error['message']) ? $db_error['message'] : $lang['INST_ERR_DB_NO_ERROR']);
302
        }
303
        else
304
        {
305
                // Likely matches for an existing phpBB installation
306
                if (!$prefix_may_exist)
307
                {
308
                        $temp_prefix = strtolower($table_prefix);
309
                        $table_ary = array($temp_prefix . 'attachments', $temp_prefix . 'config', $temp_prefix . 'sessions', $temp_prefix . 'topics', $temp_prefix . 'users');
310
311
                        $tables = get_tables($db);
312
                        $tables = array_map('strtolower', $tables);
313
                        $table_intersect = array_intersect($tables, $table_ary);
314
315
                        if (sizeof($table_intersect))
316
                        {
317
                                $error[] = $lang['INST_ERR_PREFIX'];
318
                        }
319
                }
320
321
                // Make sure that the user has selected a sensible DBAL for the DBMS actually installed
322
                switch ($dbms_details['DRIVER'])
323
                {
324
                        case 'mysqli':
325
                                if (version_compare(mysqli_get_server_info($db->db_connect_id), '4.1.3', '<'))
326
                                {
327
                                        $error[] = $lang['INST_ERR_DB_NO_MYSQLI'];
328
                                }
329
                        break;
330
331
                        case 'sqlite':
332
                                if (version_compare(sqlite_libversion(), '2.8.2', '<'))
333
                                {
334
                                        $error[] = $lang['INST_ERR_DB_NO_SQLITE'];
335
                                }
336
                        break;
337
338
                        case 'firebird':
339
                                // check the version of FB, use some hackery if we can't get access to the server info
340
                                if ($db->service_handle !== false && function_exists('ibase_server_info'))
341
                                {
342
                                        $val = @ibase_server_info($db->service_handle, IBASE_SVC_SERVER_VERSION);
343
                                        preg_match('#V([\d.]+)#', $val, $match);
344
                                        if ($match[1] < 2)
345
                                        {
346
                                                $error[] = $lang['INST_ERR_DB_NO_FIREBIRD'];
347
                                        }
348
                                        $db_info = @ibase_db_info($db->service_handle, $dbname, IBASE_STS_HDR_PAGES);
349
350
                                        preg_match('/^\\s*Page size\\s*(\\d+)/m', $db_info, $regs);
351
                                        $page_size = intval($regs[1]);
352
                                        if ($page_size < 8192)
353
                                        {
354
                                                $error[] = $lang['INST_ERR_DB_NO_FIREBIRD_PS'];
355
                                        }
356
                                }
357
                                else
358
                                {
359
                                        $sql = "SELECT *
360
                                                FROM RDB$FUNCTIONS
361
                                                WHERE RDB$SYSTEM_FLAG IS NULL
362
                                                        AND RDB$FUNCTION_NAME = 'CHAR_LENGTH'";
363
                                        $result = $db->sql_query($sql);
364
                                        $row = $db->sql_fetchrow($result);
365
                                        $db->sql_freeresult($result);
366
367
                                        // if its a UDF, its too old
368
                                        if ($row)
369
                                        {
370
                                                $error[] = $lang['INST_ERR_DB_NO_FIREBIRD'];
371
                                        }
372
                                        else
373
                                        {
374
                                                $sql = 'SELECT 1 FROM RDB$DATABASE
375
                                                        WHERE BIN_AND(10, 1) = 0';
376
                                                $result = $db->sql_query($sql);
377
                                                if (!$result) // This can only fail if BIN_AND is not defined
378
                                                {
379
                                                        $error[] = $lang['INST_ERR_DB_NO_FIREBIRD'];
380
                                                }
381
                                                $db->sql_freeresult($result);
382
                                        }
383
384
                                        // Setup the stuff for our random table
385
                                        $char_array = array_merge(range('A', 'Z'), range('0', '9'));
386
                                        $char_len = mt_rand(7, 9);
387
                                        $char_array_len = sizeof($char_array) - 1;
388
389
                                        $final = '';
390
391
                                        for ($i = 0; $i < $char_len; $i++)
392
                                        {
393
                                                $final .= $char_array[mt_rand(0, $char_array_len)];
394
                                        }
395
396
                                        // Create some random table
397
                                        $sql = 'CREATE TABLE ' . $final . " (
398
                                                FIELD1 VARCHAR(255) CHARACTER SET UTF8 DEFAULT '' NOT NULL COLLATE UNICODE,
399
                                                FIELD2 INTEGER DEFAULT 0 NOT NULL);";
400
                                        $db->sql_query($sql);
401
402
                                        // Create an index that should fail if the page size is less than 8192
403
                                        $sql = 'CREATE INDEX ' . $final . ' ON ' . $final . '(FIELD1, FIELD2);';
404
                                        $db->sql_query($sql);
405
406
                                        if (ibase_errmsg() !== false)
407
                                        {
408
                                                $error[] = $lang['INST_ERR_DB_NO_FIREBIRD_PS'];
409
                                        }
410
                                        else
411
                                        {
412
                                                // Kill the old table
413
                                                $db->sql_query('DROP TABLE ' . $final . ';');
414
                                        }
415
                                        unset($final);
416
                                }
417
                        break;
418
419
                        case 'oracle':
420
                                if ($unicode_check)
421
                                {
422
                                        $sql = "SELECT *
423
                                                FROM NLS_DATABASE_PARAMETERS
424
                                                WHERE PARAMETER = 'NLS_RDBMS_VERSION'
425
                                                        OR PARAMETER = 'NLS_CHARACTERSET'";
426
                                        $result = $db->sql_query($sql);
427
428
                                        while ($row = $db->sql_fetchrow($result))
429
                                        {
430
                                                $stats[$row['parameter']] = $row['value'];
431
                                        }
432
                                        $db->sql_freeresult($result);
433
434
                                        if (version_compare($stats['NLS_RDBMS_VERSION'], '9.2', '<') && $stats['NLS_CHARACTERSET'] !== 'UTF8')
435
                                        {
436
                                                $error[] = $lang['INST_ERR_DB_NO_ORACLE'];
437
                                        }
438
                                }
439
                        break;
440
441
                        case 'postgres':
442
                                if ($unicode_check)
443
                                {
444
                                        $sql = "SHOW server_encoding;";
445
                                        $result = $db->sql_query($sql);
446
                                        $row = $db->sql_fetchrow($result);
447
                                        $db->sql_freeresult($result);
448
449
                                        if ($row['server_encoding'] !== 'UNICODE' && $row['server_encoding'] !== 'UTF8')
450
                                        {
451
                                                $error[] = $lang['INST_ERR_DB_NO_POSTGRES'];
452
                                        }
453
                                }
454
                        break;
455
                }
456
457
        }
458
459
        if ($error_connect && (!isset($error) || !sizeof($error)))
460
        {
461
                return true;
462
        }
463
        return false;
464
}
465
466
/**
467
* Removes comments from schema files
468
*/
469
function remove_comments($sql)
470
{
471
        // Remove /* */ comments (http://ostermiller.org/findcomment.html)
472
        $sql = preg_replace('#/\*(.|[\r\n])*?\*/#', "\n", $sql);
473
474
        // Remove # style comments
475
        $sql = preg_replace('/\n{2,}/', "\n", preg_replace('/^#.*$/m', "\n", $sql));
476
477
        return $sql;
478
}
479
480
/**
481
* split_sql_file will split an uploaded sql file into single sql statements.
482
* Note: expects trim() to have already been run on $sql.
483
*/
484
function split_sql_file($sql, $delimiter)
485
{
486
        $sql = str_replace("\r" , '', $sql);
487
        $data = preg_split('/' . preg_quote($delimiter, '/') . '$/m', $sql);
488
489
        $data = array_map('trim', $data);
490
491
        // The empty case
492
        $end_data = end($data);
493
494
        if (empty($end_data))
495
        {
496
                unset($data[key($data)]);
497
        }
498
499
        return $data;
500
}
501
502
/**
503
* For replacing {L_*} strings with preg_replace_callback
504
*/
505
function adjust_language_keys_callback($matches)
506
{
507
        if (!empty($matches[1]))
508
        {
509
                global $lang, $db;
510
511
                return (!empty($lang[$matches[1]])) ? $db->sql_escape($lang[$matches[1]]) : $db->sql_escape($matches[1]);
512
        }
513
}
514
515
?>