Completed
Push — release-2.1 ( 4c82a0...64d581 )
by Rick
09:29
created

install.php ➔ DatabaseSettings()   F

Complexity

Conditions 36
Paths > 20000

Size

Total Lines 208
Code Lines 108

Duplication

Lines 7
Ratio 3.37 %

Importance

Changes 0
Metric Value
cc 36
eloc 108
nc 156690
nop 0
dl 7
loc 208
rs 2
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * Simple Machines Forum (SMF)
5
 *
6
 * @package SMF
7
 * @author Simple Machines http://www.simplemachines.org
8
 * @copyright 2016 Simple Machines and individual contributors
9
 * @license http://www.simplemachines.org/about/smf/license.php BSD
10
 *
11
 * @version 2.1 Beta 3
12
 */
13
14
$GLOBALS['current_smf_version'] = '2.1 Beta 3';
15
$GLOBALS['db_script_version'] = '2-1';
16
17
$GLOBALS['required_php_version'] = '5.3.8';
18
19
// Don't have PHP support, do you?
20
// ><html dir="ltr"><head><title>Error!</title></head><body>Sorry, this installer requires PHP!<div style="display: none;">
21
22
// Let's pull in useful classes
23
if (!defined('SMF'))
24
	define('SMF', 1);
25
26
require_once('Sources/Class-Package.php');
27
28
// Database info.
29
$databases = array(
30
	'mysqli' => array(
31
		'name' => 'MySQLi',
32
		'version' => '5.0.3',
33
		'version_check' => 'return min(mysqli_get_server_info($db_connection), mysqli_get_client_info());',
34
		'supported' => function_exists('mysqli_connect'),
35
		'default_user' => 'mysql.default_user',
36
		'default_password' => 'mysql.default_password',
37
		'default_host' => 'mysql.default_host',
38
		'default_port' => 'mysql.default_port',
39
		'utf8_support' => true,
40
		'utf8_version' => '5.0.3',
41
		'utf8_version_check' => 'return mysqli_get_server_info($db_connection);',
42
		'utf8_default' => true,
43
		'utf8_required' => true,
44
		'alter_support' => true,
45
		'validate_prefix' => function(&$value) {
46
			$value = preg_replace('~[^A-Za-z0-9_\$]~', '', $value);
47
			return true;
48
		},
49
	),
50
	'mysql' => array(
51
		'name' => 'MySQL',
52
		'version' => '5.0.3',
53
		'version_check' => 'return min(mysql_get_server_info(), mysql_get_client_info());',
54
		'supported' => function_exists('mysql_connect'),
55
		'default_user' => 'mysql.default_user',
56
		'default_password' => 'mysql.default_password',
57
		'default_host' => 'mysql.default_host',
58
		'default_port' => 'mysql.default_port',
59
		'utf8_support' => true,
60
		'utf8_version' => '5.0.3',
61
		'utf8_version_check' => 'return mysql_get_server_info();',
62
		'utf8_default' => true,
63
		'utf8_required' => true,
64
		'alter_support' => true,
65
		'validate_prefix' => function(&$value){
66
			$value = preg_replace('~[^A-Za-z0-9_\$]~', '', $value);
67
			return true;
68
		},
69
	),
70
	'postgresql' => array(
71
		'name' => 'PostgreSQL',
72
		'version' => '9.1',
73
		'function_check' => 'pg_connect',
74
		'version_check' => '$request = pg_query(\'SELECT version()\'); list ($version) = pg_fetch_row($request); list($pgl, $version) = explode(" ", $version); return $version;',
75
		'supported' => function_exists('pg_connect'),
76
		'always_has_db' => true,
77
		'utf8_default' => true,
78
		'utf8_required' => true,
79
		'utf8_support' => true,
80
		'utf8_version' => '8.0',
81
		'utf8_version_check' => '$request = pg_query(\'SELECT version()\'); list ($version) = pg_fetch_row($request); list($pgl, $version) = explode(" ", $version); return $version;',
82
		'validate_prefix' => function(&$value){
83
			$value = preg_replace('~[^A-Za-z0-9_\$]~', '', $value);
84
85
			// Is it reserved?
86
			if ($value == 'pg_')
87
				return $txt['error_db_prefix_reserved'];
0 ignored issues
show
Bug introduced by
The variable $txt does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
88
89
			// Is the prefix numeric?
90
			if (preg_match('~^\d~', $value))
91
				return $txt['error_db_prefix_numeric'];
92
93
			return true;
94
		},
95
	),
96
);
97
98
// Initialize everything and load the language files.
99
initialize_inputs();
100
load_lang_file();
101
102
// This is what we are.
103
$installurl = $_SERVER['PHP_SELF'];
104
// This is where SMF is.
105
$smfsite = 'http://www.simplemachines.org/smf';
106
107
// All the steps in detail.
108
// Number,Name,Function,Progress Weight.
109
$incontext['steps'] = array(
110
	0 => array(1, $txt['install_step_welcome'], 'Welcome', 0),
111
	1 => array(2, $txt['install_step_writable'], 'CheckFilesWritable', 10),
112
	2 => array(3, $txt['install_step_databaseset'], 'DatabaseSettings', 15),
113
	3 => array(4, $txt['install_step_forum'], 'ForumSettings', 40),
114
	4 => array(5, $txt['install_step_databasechange'], 'DatabasePopulation', 15),
115
	5 => array(6, $txt['install_step_admin'], 'AdminAccount', 20),
116
	6 => array(7, $txt['install_step_delete'], 'DeleteInstall', 0),
117
);
118
119
// Default title...
120
$incontext['page_title'] = $txt['smf_installer'];
121
122
// What step are we on?
123
$incontext['current_step'] = isset($_GET['step']) ? (int) $_GET['step'] : 0;
124
125
// Loop through all the steps doing each one as required.
126
$incontext['overall_percent'] = 0;
127
128
foreach ($incontext['steps'] as $num => $step)
129
{
130
	if ($num >= $incontext['current_step'])
131
	{
132
		// The current weight of this step in terms of overall progress.
133
		$incontext['step_weight'] = $step[3];
134
		// Make sure we reset the skip button.
135
		$incontext['skip'] = false;
136
137
		// Call the step and if it returns false that means pause!
138 View Code Duplication
		if (function_exists($step[2]) && $step[2]() === false)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
139
			break;
140
		elseif (function_exists($step[2]))
141
			$incontext['current_step']++;
142
143
		// No warnings pass on.
144
		$incontext['warning'] = '';
145
	}
146
	$incontext['overall_percent'] += $step[3];
147
}
148
149
// Actually do the template stuff.
150
installExit();
151
152
function initialize_inputs()
153
{
154
	global $databases, $incontext;
155
156
	// Just so people using older versions of PHP aren't left in the cold.
157
	if (!isset($_SERVER['PHP_SELF']))
158
		$_SERVER['PHP_SELF'] = isset($GLOBALS['HTTP_SERVER_VARS']['PHP_SELF']) ? $GLOBALS['HTTP_SERVER_VARS']['PHP_SELF'] : 'install.php';
159
160
	// Turn off magic quotes runtime and enable error reporting.
161
	if (function_exists('set_magic_quotes_runtime'))
162
		@set_magic_quotes_runtime(0);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
163
	error_reporting(E_ALL);
164
165
	// Fun.  Low PHP version...
166
	if (!isset($_GET))
167
	{
168
		$GLOBALS['_GET']['step'] = 0;
169
		return;
170
	}
171
172
	if (!isset($_GET['obgz']))
173
	{
174
		ob_start();
175
176
		if (ini_get('session.save_handler') == 'user')
177
			@ini_set('session.save_handler', 'files');
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
178
		if (function_exists('session_start'))
179
			@session_start();
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
180
	}
181
	else
182
	{
183
		ob_start('ob_gzhandler');
184
185
		if (ini_get('session.save_handler') == 'user')
186
			@ini_set('session.save_handler', 'files');
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
187
		session_start();
188
189
		if (!headers_sent())
190
			echo '<!DOCTYPE html>
191
<html>
192
	<head>
193
		<title>', htmlspecialchars($_GET['pass_string']), '</title>
194
	</head>
195
	<body style="background-color: #d4d4d4; margin-top: 16%; text-align: center; font-size: 16pt;">
196
		<strong>', htmlspecialchars($_GET['pass_string']), '</strong>
197
	</body>
198
</html>';
199
		exit;
200
	}
201
202
	// Anybody home?
203 View Code Duplication
	if (!isset($_GET['xml']))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
204
	{
205
		$incontext['remote_files_available'] = false;
206
		$test = @fsockopen('www.simplemachines.org', 80, $errno, $errstr, 1);
207
		if ($test)
208
			$incontext['remote_files_available'] = true;
209
		@fclose($test);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
210
	}
211
212
	// Add slashes, as long as they aren't already being added.
213
	if (!function_exists('get_magic_quotes_gpc') || @get_magic_quotes_gpc() == 0)
214
		foreach ($_POST as $k => $v)
215
			if (strpos($k, 'password') === false && strpos($k, 'db_passwd') === false)
216
				$_POST[$k] = addslashes($v);
217
218
	// This is really quite simple; if ?delete is on the URL, delete the installer...
219
	if (isset($_GET['delete']))
220
	{
221
		if (isset($_SESSION['installer_temp_ftp']))
222
		{
223
			$ftp = new ftp_connection($_SESSION['installer_temp_ftp']['server'], $_SESSION['installer_temp_ftp']['port'], $_SESSION['installer_temp_ftp']['username'], $_SESSION['installer_temp_ftp']['password']);
224
			$ftp->chdir($_SESSION['installer_temp_ftp']['path']);
225
226
			$ftp->unlink('install.php');
227
228
			foreach ($databases as $key => $dummy)
229
			{
230
				$type = ($key == 'mysqli') ? 'mysql' : $key;
231
				$ftp->unlink('install_' . $GLOBALS['db_script_version'] . '_' . $type . '.sql');
232
			}
233
234
			$ftp->close();
235
236
			unset($_SESSION['installer_temp_ftp']);
237
		}
238
		else
239
		{
240
			@unlink(__FILE__);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
241
242
			foreach ($databases as $key => $dummy)
243
			{
244
				$type = ($key == 'mysqli') ? 'mysql' : $key;
245
				@unlink(dirname(__FILE__) . '/install_' . $GLOBALS['db_script_version'] . '_' . $type . '.sql');
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
246
			}
247
		}
248
249
		// Now just redirect to a blank.png...
250
		header('Location: http://' . (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : $_SERVER['SERVER_NAME'] . ':' . $_SERVER['SERVER_PORT']) . dirname($_SERVER['PHP_SELF']) . '/Themes/default/images/blank.png');
251
		exit;
252
	}
253
254
	// PHP 5 might cry if we don't do this now.
255
	if (function_exists('date_default_timezone_set'))
256
	{
257
		$server_offset = @mktime(0, 0, 0, 1, 1, 1970);
258
		date_default_timezone_set('Etc/GMT' . ($server_offset > 0 ? '+' : '') . ($server_offset / 3600));
259
	}
260
261
	// Force an integer step, defaulting to 0.
262
	$_GET['step'] = (int) @$_GET['step'];
263
}
264
265
// Load the list of language files, and the current language file.
266
function load_lang_file()
267
{
268
	global $txt, $incontext;
269
270
	$incontext['detected_languages'] = array();
271
272
	// Make sure the languages directory actually exists.
273
	if (file_exists(dirname(__FILE__) . '/Themes/default/languages'))
274
	{
275
		// Find all the "Install" language files in the directory.
276
		$dir = dir(dirname(__FILE__) . '/Themes/default/languages');
277
		while ($entry = $dir->read())
278
		{
279
			if (substr($entry, 0, 8) == 'Install.' && substr($entry, -4) == '.php')
280
				$incontext['detected_languages'][$entry] = ucfirst(substr($entry, 8, strlen($entry) - 12));
281
		}
282
		$dir->close();
283
	}
284
285
	// Didn't find any, show an error message!
286
	if (empty($incontext['detected_languages']))
287
	{
288
		// Let's not cache this message, eh?
289
		header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
290
		header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
291
		header('Cache-Control: no-cache');
292
293
		echo '<!DOCTYPE html>
294
<html>
295
	<head>
296
		<title>SMF Installer: Error!</title>
297
	</head>
298
	<body style="font-family: sans-serif;"><div style="width: 600px;">
299
		<h1 style="font-size: 14pt;">A critical error has occurred.</h1>
300
301
		<p>This installer was unable to find the installer\'s language file or files.  They should be found under:</p>
302
303
		<div style="margin: 1ex; font-family: monospace; font-weight: bold;">', dirname($_SERVER['PHP_SELF']) != '/' ? dirname($_SERVER['PHP_SELF']) : '', '/Themes/default/languages</div>
304
305
		<p>In some cases, FTP clients do not properly upload files with this many folders.  Please double check to make sure you <span style="font-weight: 600;">have uploaded all the files in the distribution</span>.</p>
306
		<p>If that doesn\'t help, please make sure this install.php file is in the same place as the Themes folder.</p>
307
308
		<p>If you continue to get this error message, feel free to <a href="http://support.simplemachines.org/">look to us for support</a>.</p>
309
	</div></body>
310
</html>';
311
		die;
312
	}
313
314
	// Override the language file?
315
	if (isset($_GET['lang_file']))
316
		$_SESSION['installer_temp_lang'] = $_GET['lang_file'];
317
	elseif (isset($GLOBALS['HTTP_GET_VARS']['lang_file']))
318
		$_SESSION['installer_temp_lang'] = $GLOBALS['HTTP_GET_VARS']['lang_file'];
319
320
	// Make sure it exists, if it doesn't reset it.
321
	if (!isset($_SESSION['installer_temp_lang']) || preg_match('~[^\\w_\\-.]~', $_SESSION['installer_temp_lang']) === 1 || !file_exists(dirname(__FILE__) . '/Themes/default/languages/' . $_SESSION['installer_temp_lang']))
322
	{
323
		// Use the first one...
324
		list ($_SESSION['installer_temp_lang']) = array_keys($incontext['detected_languages']);
325
326
		// If we have english and some other language, use the other language.  We Americans hate english :P.
327
		if ($_SESSION['installer_temp_lang'] == 'Install.english.php' && count($incontext['detected_languages']) > 1)
328
			list (, $_SESSION['installer_temp_lang']) = array_keys($incontext['detected_languages']);
329
	}
330
331
	// And now include the actual language file itself.
332
	require_once(dirname(__FILE__) . '/Themes/default/languages/' . $_SESSION['installer_temp_lang']);
333
}
334
335
// This handy function loads some settings and the like.
336
function load_database()
337
{
338
	global $db_prefix, $db_connection, $sourcedir;
339
	global $smcFunc, $modSettings, $db_type, $db_name, $db_user, $db_persist;
340
341
	if (empty($sourcedir))
342
		$sourcedir = dirname(__FILE__) . '/Sources';
343
344
	// Need this to check whether we need the database password.
345
	require(dirname(__FILE__) . '/Settings.php');
346
	if (!defined('SMF'))
347
		define('SMF', 1);
348
	if (empty($smcFunc))
349
		$smcFunc = array();
350
351
	$modSettings['disableQueryCheck'] = true;
352
353
	// Connect the database.
354
	if (!$db_connection)
355
	{
356
		require_once($sourcedir . '/Subs-Db-' . $db_type . '.php');
357
		if (version_compare(PHP_VERSION, '5', '<'))
358
			require_once($sourcedir . '/Subs-Compat.php');
359
360
		$db_options = array('persist' => $db_persist);
361
		$port = '';
362
363
		// Figure out the port...
364
		if (!empty($_POST['db_port']))
365
		{
366
			if ($db_type == 'mysql' || $db_type == 'mysqli')
367
			{
368
				$port = ((int) $_POST['db_port'] == ini_get($db_type . 'default_port')) ? '' : (int) $_POST['db_port'];
369
			}
370 View Code Duplication
			elseif ($db_type == 'postgresql')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
371
			{
372
				// PostgreSQL doesn't have a default port setting in php.ini, so just check against the default
373
				$port = ((int) $_POST['db_port'] == 5432) ? '' : (int) $_POST['db_port'];
374
			}
375
		}
376
377
		if (!empty($port))
378
			$db_options['port'] = $port;
379
380
		if (!$db_connection)
381
			$db_connection = smf_db_initiate($db_server, $db_name, $db_user, $db_passwd, $db_prefix, $db_options);
0 ignored issues
show
Bug introduced by
The variable $db_server does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $db_passwd does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
382
	}
383
}
384
385
// This is called upon exiting the installer, for template etc.
386
function installExit($fallThrough = false)
387
{
388
	global $incontext, $installurl, $txt;
389
390
	// Send character set.
391
	header('Content-Type: text/html; charset=' . (isset($txt['lang_character_set']) ? $txt['lang_character_set'] : 'UTF-8'));
392
393
	// We usually dump our templates out.
394
	if (!$fallThrough)
395
	{
396
		// The top install bit.
397
		template_install_above();
398
399
		// Call the template.
400
		if (isset($incontext['sub_template']))
401
		{
402
			$incontext['form_url'] = $installurl . '?step=' . $incontext['current_step'];
403
404
			call_user_func('template_' . $incontext['sub_template']);
405
		}
406
		// @todo REMOVE THIS!!
407
		else
408
		{
409
			if (function_exists('doStep' . $_GET['step']))
410
				call_user_func('doStep' . $_GET['step']);
411
		}
412
		// Show the footer.
413
		template_install_below();
414
	}
415
416
	// Bang - gone!
417
	die();
418
}
419
420
function Welcome()
421
{
422
	global $incontext, $txt, $databases, $installurl;
423
424
	$incontext['page_title'] = $txt['install_welcome'];
425
	$incontext['sub_template'] = 'welcome_message';
426
427
	// Done the submission?
428
	if (isset($_POST['contbutt']))
429
		return true;
430
431
	// See if we think they have already installed it?
432
	if (is_readable(dirname(__FILE__) . '/Settings.php'))
433
	{
434
		$probably_installed = 0;
435
		foreach (file(dirname(__FILE__) . '/Settings.php') as $line)
436
		{
437
			if (preg_match('~^\$db_passwd\s=\s\'([^\']+)\';$~', $line))
438
				$probably_installed++;
439
			if (preg_match('~^\$boardurl\s=\s\'([^\']+)\';~', $line) && !preg_match('~^\$boardurl\s=\s\'http://127\.0\.0\.1/smf\';~', $line))
440
				$probably_installed++;
441
		}
442
443
		if ($probably_installed == 2)
444
			$incontext['warning'] = $txt['error_already_installed'];
445
	}
446
447
	// Is some database support even compiled in?
448
	$incontext['supported_databases'] = array();
449
	foreach ($databases as $key => $db)
450
	{
451
		if ($db['supported'])
452
		{
453
			$type = ($key == 'mysqli') ? 'mysql' : $key;
454
			if (!file_exists(dirname(__FILE__) . '/install_' . $GLOBALS['db_script_version'] . '_' . $type . '.sql'))
455
			{
456
				$databases[$key]['supported'] = false;
457
				$notFoundSQLFile = true;
458
				$txt['error_db_script_missing'] = sprintf($txt['error_db_script_missing'], 'install_' . $GLOBALS['db_script_version'] . '_' . $type . '.sql');
459
			}
460
			else
461
			{
462
				$db_type = $key;
0 ignored issues
show
Unused Code introduced by
$db_type is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
463
				$incontext['supported_databases'][] = $db;
464
			}
465
		}
466
	}
467
468
	// Check the PHP version.
469
	if ((!function_exists('version_compare') || version_compare($GLOBALS['required_php_version'], PHP_VERSION, '>')))
470
		$error = 'error_php_too_low';
471
	// Make sure we have a supported database
472
	elseif (empty($incontext['supported_databases']))
473
		$error = empty($notFoundSQLFile) ? 'error_db_missing' : 'error_db_script_missing';
474
	// How about session support?  Some crazy sysadmin remove it?
475
	elseif (!function_exists('session_start'))
476
		$error = 'error_session_missing';
477
	// Make sure they uploaded all the files.
478
	elseif (!file_exists(dirname(__FILE__) . '/index.php'))
479
		$error = 'error_missing_files';
480
	// Very simple check on the session.save_path for Windows.
481
	// @todo Move this down later if they don't use database-driven sessions?
482
	elseif (@ini_get('session.save_path') == '/tmp' && substr(__FILE__, 1, 2) == ':\\')
483
		$error = 'error_session_save_path';
484
485
	// Since each of the three messages would look the same, anyway...
486
	if (isset($error))
487
		$incontext['error'] = $txt[$error];
488
489
	// Mod_security blocks everything that smells funny. Let SMF handle security.
490
	if (!fixModSecurity() && !isset($_GET['overmodsecurity']))
491
		$incontext['error'] = $txt['error_mod_security'] . '<br><br><a href="' . $installurl . '?overmodsecurity=true">' . $txt['error_message_click'] . '</a> ' . $txt['error_message_bad_try_again'];
492
493
	return false;
494
}
495
496
function CheckFilesWritable()
497
{
498
	global $txt, $incontext;
499
500
	$incontext['page_title'] = $txt['ftp_checking_writable'];
501
	$incontext['sub_template'] = 'chmod_files';
502
503
	$writable_files = array(
504
		'attachments',
505
		'avatars',
506
		'custom_avatar',
507
		'cache',
508
		'Packages',
509
		'Smileys',
510
		'Themes',
511
		'agreement.txt',
512
		'Settings.php'
513
	);
514
	if (file_exists(dirname(__FILE__) . '/Settings_bak.php'))
515
		$writable_files[] = 'Settings_bak.php';
516
517
	foreach ($incontext['detected_languages'] as $lang => $temp)
518
		$extra_files[] = 'Themes/default/languages/' . $lang;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$extra_files was never initialized. Although not strictly required by PHP, it is generally a good practice to add $extra_files = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
519
520
	// With mod_security installed, we could attempt to fix it with .htaccess.
521
	if (function_exists('apache_get_modules') && in_array('mod_security', apache_get_modules()))
522
		$writable_files[] = file_exists(dirname(__FILE__) . '/.htaccess') ? '.htaccess' : '.';
523
524
	$failed_files = array();
525
526
	// On linux, it's easy - just use is_writable!
527
	if (substr(__FILE__, 1, 2) != ':\\')
528
	{
529
		$incontext['systemos'] = 'linux';
530
531
		foreach ($writable_files as $file)
532
		{
533
			if (!is_writable(dirname(__FILE__) . '/' . $file))
534
			{
535
				@chmod(dirname(__FILE__) . '/' . $file, 0755);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
536
537
				// Well, 755 hopefully worked... if not, try 777.
0 ignored issues
show
Unused Code Comprehensibility introduced by
37% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
538
				if (!is_writable(dirname(__FILE__) . '/' . $file) && !@chmod(dirname(__FILE__) . '/' . $file, 0777))
539
					$failed_files[] = $file;
540
			}
541
		}
542 View Code Duplication
		foreach ($extra_files as $file)
0 ignored issues
show
Bug introduced by
The variable $extra_files does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
543
			@chmod(dirname(__FILE__) . (empty($file) ? '' : '/' . $file), 0777);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
544
	}
545
	// Windows is trickier.  Let's try opening for r+...
546
	else
547
	{
548
		$incontext['systemos'] = 'windows';
549
550
		foreach ($writable_files as $file)
551
		{
552
			// Folders can't be opened for write... but the index.php in them can ;)
553
			if (is_dir(dirname(__FILE__) . '/' . $file))
554
				$file .= '/index.php';
555
556
			// Funny enough, chmod actually does do something on windows - it removes the read only attribute.
557
			@chmod(dirname(__FILE__) . '/' . $file, 0777);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
558
			$fp = @fopen(dirname(__FILE__) . '/' . $file, 'r+');
559
560
			// Hmm, okay, try just for write in that case...
561
			if (!is_resource($fp))
562
				$fp = @fopen(dirname(__FILE__) . '/' . $file, 'w');
563
564
			if (!is_resource($fp))
565
				$failed_files[] = $file;
566
567
			@fclose($fp);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
568
		}
569 View Code Duplication
		foreach ($extra_files as $file)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
570
			@chmod(dirname(__FILE__) . (empty($file) ? '' : '/' . $file), 0777);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
571
	}
572
573
	$failure = count($failed_files) >= 1;
574
575
	if (!isset($_SERVER))
576
		return !$failure;
577
578
	// Put the list into context.
579
	$incontext['failed_files'] = $failed_files;
580
581
	// It's not going to be possible to use FTP on windows to solve the problem...
582
	if ($failure && substr(__FILE__, 1, 2) == ':\\')
583
	{
584
		$incontext['error'] = $txt['error_windows_chmod'] . '
585
					<ul style="margin: 2.5ex; font-family: monospace;">
586
						<li>' . implode('</li>
587
						<li>', $failed_files) . '</li>
588
					</ul>';
589
590
		return false;
591
	}
592
	// We're going to have to use... FTP!
593
	elseif ($failure)
594
	{
595
		// Load any session data we might have...
596 View Code Duplication
		if (!isset($_POST['ftp_username']) && isset($_SESSION['installer_temp_ftp']))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
597
		{
598
			$_POST['ftp_server'] = $_SESSION['installer_temp_ftp']['server'];
599
			$_POST['ftp_port'] = $_SESSION['installer_temp_ftp']['port'];
600
			$_POST['ftp_username'] = $_SESSION['installer_temp_ftp']['username'];
601
			$_POST['ftp_password'] = $_SESSION['installer_temp_ftp']['password'];
602
			$_POST['ftp_path'] = $_SESSION['installer_temp_ftp']['path'];
603
		}
604
605
		$incontext['ftp_errors'] = array();
606
607 View Code Duplication
		if (isset($_POST['ftp_username']))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
608
		{
609
			$ftp = new ftp_connection($_POST['ftp_server'], $_POST['ftp_port'], $_POST['ftp_username'], $_POST['ftp_password']);
610
611
			if ($ftp->error === false)
612
			{
613
				// Try it without /home/abc just in case they messed up.
614
				if (!$ftp->chdir($_POST['ftp_path']))
615
				{
616
					$incontext['ftp_errors'][] = $ftp->last_message;
617
					$ftp->chdir(preg_replace('~^/home[2]?/[^/]+?~', '', $_POST['ftp_path']));
618
				}
619
			}
620
		}
621
622
		if (!isset($ftp) || $ftp->error !== false)
623
		{
624
			if (!isset($ftp))
625
				$ftp = new ftp_connection(null);
626
			// Save the error so we can mess with listing...
627
			elseif ($ftp->error !== false && empty($incontext['ftp_errors']) && !empty($ftp->last_message))
628
				$incontext['ftp_errors'][] = $ftp->last_message;
629
630
			list ($username, $detect_path, $found_path) = $ftp->detect_path(dirname(__FILE__));
631
632
			if (empty($_POST['ftp_path']) && $found_path)
633
				$_POST['ftp_path'] = $detect_path;
634
635
			if (!isset($_POST['ftp_username']))
636
				$_POST['ftp_username'] = $username;
637
638
			// Set the username etc, into context.
639
			$incontext['ftp'] = array(
640
				'server' => isset($_POST['ftp_server']) ? $_POST['ftp_server'] : 'localhost',
641
				'port' => isset($_POST['ftp_port']) ? $_POST['ftp_port'] : '21',
642
				'username' => isset($_POST['ftp_username']) ? $_POST['ftp_username'] : '',
643
				'path' => isset($_POST['ftp_path']) ? $_POST['ftp_path'] : '/',
644
				'path_msg' => !empty($found_path) ? $txt['ftp_path_found_info'] : $txt['ftp_path_info'],
645
			);
646
647
			return false;
648
		}
649
		else
650
		{
651
			$_SESSION['installer_temp_ftp'] = array(
652
				'server' => $_POST['ftp_server'],
653
				'port' => $_POST['ftp_port'],
654
				'username' => $_POST['ftp_username'],
655
				'password' => $_POST['ftp_password'],
656
				'path' => $_POST['ftp_path']
657
			);
658
659
			$failed_files_updated = array();
660
661
			foreach ($failed_files as $file)
662
			{
663
				if (!is_writable(dirname(__FILE__) . '/' . $file))
664
					$ftp->chmod($file, 0755);
665
				if (!is_writable(dirname(__FILE__) . '/' . $file))
666
					$ftp->chmod($file, 0777);
667
				if (!is_writable(dirname(__FILE__) . '/' . $file))
668
				{
669
					$failed_files_updated[] = $file;
670
					$incontext['ftp_errors'][] = rtrim($ftp->last_message) . ' -> ' . $file . "\n";
671
				}
672
			}
673
674
			$ftp->close();
675
676
			// Are there any errors left?
677
			if (count($failed_files_updated) >= 1)
678
			{
679
				// Guess there are...
680
				$incontext['failed_files'] = $failed_files_updated;
681
682
				// Set the username etc, into context.
683
				$incontext['ftp'] = $_SESSION['installer_temp_ftp'] += array(
684
					'path_msg' => $txt['ftp_path_info'],
685
				);
686
687
				return false;
688
			}
689
		}
690
	}
691
692
	return true;
693
}
694
695
function DatabaseSettings()
696
{
697
	global $txt, $databases, $incontext, $smcFunc, $sourcedir;
698
699
	$incontext['sub_template'] = 'database_settings';
700
	$incontext['page_title'] = $txt['db_settings'];
701
	$incontext['continue'] = 1;
702
703
	// Set up the defaults.
704
	$incontext['db']['server'] = 'localhost';
705
	$incontext['db']['user'] = '';
706
	$incontext['db']['name'] = '';
707
	$incontext['db']['pass'] = '';
708
	$incontext['db']['type'] = '';
709
	$incontext['supported_databases'] = array();
710
711
	$foundOne = false;
712
	foreach ($databases as $key => $db)
713
	{
714
		// Override with the defaults for this DB if appropriate.
715
		if ($db['supported'])
716
		{
717
			$incontext['supported_databases'][$key] = $db;
718
719
			if (!$foundOne)
720
			{
721
				if (isset($db['default_host']))
722
					$incontext['db']['server'] = ini_get($db['default_host']) or $incontext['db']['server'] = 'localhost';
723
				if (isset($db['default_user']))
724
				{
725
					$incontext['db']['user'] = ini_get($db['default_user']);
726
					$incontext['db']['name'] = ini_get($db['default_user']);
727
				}
728
				if (isset($db['default_password']))
729
					$incontext['db']['pass'] = ini_get($db['default_password']);
730
731
				// For simplicity and less confusion, leave the port blank by default
732
				$incontext['db']['port'] = '';
733
734
				$incontext['db']['type'] = $key;
735
				$foundOne = true;
736
			}
737
		}
738
	}
739
740
	// Override for repost.
741
	if (isset($_POST['db_user']))
742
	{
743
		$incontext['db']['user'] = $_POST['db_user'];
744
		$incontext['db']['name'] =  $_POST['db_name'];
745
		$incontext['db']['server'] = $_POST['db_server'];
746
		$incontext['db']['prefix'] = $_POST['db_prefix'];
747
748
		if (!empty($_POST['db_port']))
749
			$incontext['db']['port'] = $_POST['db_port'];
750
	}
751
	else
752
	{
753
		$incontext['db']['prefix'] = 'smf_';
754
	}
755
756
	// Are we submitting?
757
	if (isset($_POST['db_type']))
758
	{
759
		// What type are they trying?
760
		$db_type = preg_replace('~[^A-Za-z0-9]~', '', $_POST['db_type']);
761
		$db_prefix = $_POST['db_prefix'];
762
		// Validate the prefix.
763
		$valid_prefix = $databases[$db_type]['validate_prefix']($db_prefix);
764
765
		if ($valid_prefix !== true)
766
		{
767
			$incontext['error'] = $valid_prefix;
768
			return false;
769
		}
770
771
		// Take care of these variables...
772
		$vars = array(
773
			'db_type' => $db_type,
774
			'db_name' => $_POST['db_name'],
775
			'db_user' => $_POST['db_user'],
776
			'db_passwd' => isset($_POST['db_passwd']) ? $_POST['db_passwd'] : '',
777
			'db_server' => $_POST['db_server'],
778
			'db_prefix' => $db_prefix,
779
			// The cookiename is special; we want it to be the same if it ever needs to be reinstalled with the same info.
780
			'cookiename' => 'SMFCookie' . abs(crc32($_POST['db_name'] . preg_replace('~[^A-Za-z0-9_$]~', '', $_POST['db_prefix'])) % 1000),
781
		);
782
783
		// Only set the port if we're not using the default
784
		if (!empty($_POST['db_port']))
785
		{
786
			// For MySQL, we can get the "default port" from PHP. PostgreSQL has no such option though.
787
			if (($db_type == 'mysql' || $db_type == 'mysqli') && $_POST['db_port'] != ini_get($db_type . '.default_port'))
788
				$vars['db_port'] = (int) $_POST['db_port'];
789 View Code Duplication
			elseif ($db_type == 'postgresql' && $_POST['db_port'] != 5432)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
790
				$vars['db_port'] = (int) $_POST['db_port'];
791
		}
792
793
		// God I hope it saved!
794 View Code Duplication
		if (!updateSettingsFile($vars) && substr(__FILE__, 1, 2) == ':\\')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
795
		{
796
			$incontext['error'] = $txt['error_windows_chmod'];
797
			return false;
798
		}
799
800
		// Make sure it works.
801
		require(dirname(__FILE__) . '/Settings.php');
802
803
		if (empty($sourcedir))
804
			$sourcedir = dirname(__FILE__) . '/Sources';
805
806
		// Better find the database file!
807
		if (!file_exists($sourcedir . '/Subs-Db-' . $db_type . '.php'))
808
		{
809
			$incontext['error'] = sprintf($txt['error_db_file'], 'Subs-Db-' . $db_type . '.php');
810
			return false;
811
		}
812
813
		// Now include it for database functions!
814
		if (!defined('SMF'))
815
			define('SMF', 1);
816
817
		$modSettings['disableQueryCheck'] = true;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$modSettings was never initialized. Although not strictly required by PHP, it is generally a good practice to add $modSettings = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
818
		if (empty($smcFunc))
819
			$smcFunc = array();
820
821
			require_once($sourcedir . '/Subs-Db-' . $db_type . '.php');
822
823
		// What - running PHP4? The shame!
824
		if (version_compare(PHP_VERSION, '5', '<'))
825
			require_once($sourcedir . '/Subs-Compat.php');
826
827
		// Attempt a connection.
828
		$needsDB = !empty($databases[$db_type]['always_has_db']);
829
		$db_connection = smf_db_initiate($db_server, $db_name, $db_user, $db_passwd, $db_prefix, array('non_fatal' => true, 'dont_select_db' => !$needsDB));
0 ignored issues
show
Bug introduced by
The variable $db_server does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $db_name seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
Bug introduced by
The variable $db_user seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
Bug introduced by
The variable $db_passwd does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
830
831
		// No dice?  Let's try adding the prefix they specified, just in case they misread the instructions ;)
832
		if ($db_connection == null)
833
		{
834
			$db_error = @$smcFunc['db_error']();
835
836
			$db_connection = smf_db_initiate($db_server, $db_name, $_POST['db_prefix'] . $db_user, $db_passwd, $db_prefix, array('non_fatal' => true, 'dont_select_db' => !$needsDB));
0 ignored issues
show
Bug introduced by
The variable $db_name seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
Bug introduced by
The variable $db_user seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
837
			if ($db_connection != null)
838
			{
839
				$db_user = $_POST['db_prefix'] . $db_user;
0 ignored issues
show
Bug introduced by
The variable $db_user seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
840
				updateSettingsFile(array('db_user' => $db_user));
841
			}
842
		}
843
844
		// Still no connection?  Big fat error message :P.
845
		if (!$db_connection)
846
		{
847
			$incontext['error'] = $txt['error_db_connect'] . '<div style="margin: 2.5ex; font-family: monospace;"><strong>' . $db_error . '</strong></div>';
0 ignored issues
show
Bug introduced by
The variable $db_error does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
848
			return false;
849
		}
850
851
		// Do they meet the install requirements?
852
		// @todo Old client, new server?
853
		if (version_compare($databases[$db_type]['version'], preg_replace('~^\D*|\-.+?$~', '', eval($databases[$db_type]['version_check']))) > 0)
0 ignored issues
show
Coding Style introduced by
The function DatabaseSettings() contains an eval expression.

On one hand, eval might be exploited by malicious users if they somehow manage to inject dynamic content. On the other hand, with the emergence of faster PHP runtimes like the HHVM, eval prevents some optimization that they perform.

Loading history...
854
		{
855
			$incontext['error'] = $txt['error_db_too_low'];
856
			return false;
857
		}
858
859
		// Let's try that database on for size... assuming we haven't already lost the opportunity.
860
		if ($db_name != '' && !$needsDB)
861
		{
862
			$smcFunc['db_query']('', "
863
				CREATE DATABASE IF NOT EXISTS `$db_name`",
0 ignored issues
show
Bug introduced by
The variable $db_name seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
864
				array(
865
					'security_override' => true,
866
					'db_error_skip' => true,
867
				),
868
				$db_connection
869
			);
870
871
			// Okay, let's try the prefix if it didn't work...
872
			if (!$smcFunc['db_select_db']($db_name, $db_connection) && $db_name != '')
0 ignored issues
show
Bug introduced by
The variable $db_name seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
873
			{
874
				$smcFunc['db_query']('', "
875
					CREATE DATABASE IF NOT EXISTS `$_POST[db_prefix]$db_name`",
0 ignored issues
show
Bug introduced by
The variable $db_name seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
876
					array(
877
						'security_override' => true,
878
						'db_error_skip' => true,
879
					),
880
					$db_connection
881
				);
882
883
				if ($smcFunc['db_select_db']($_POST['db_prefix'] . $db_name, $db_connection))
0 ignored issues
show
Bug introduced by
The variable $db_name seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
884
				{
885
					$db_name = $_POST['db_prefix'] . $db_name;
0 ignored issues
show
Bug introduced by
The variable $db_name seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
886
					updateSettingsFile(array('db_name' => $db_name));
887
				}
888
			}
889
890
			// Okay, now let's try to connect...
891
			if (!$smcFunc['db_select_db']($db_name, $db_connection))
892
			{
893
				$incontext['error'] = sprintf($txt['error_db_database'], $db_name);
0 ignored issues
show
Bug introduced by
The variable $db_name does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
894
				return false;
895
			}
896
		}
897
898
		return true;
899
	}
900
901
	return false;
902
}
903
904
// Let's start with basic forum type settings.
905
function ForumSettings()
906
{
907
	global $txt, $incontext, $databases, $db_type, $db_connection;
908
909
	$incontext['sub_template'] = 'forum_settings';
910
	$incontext['page_title'] = $txt['install_settings'];
911
912
	// Let's see if we got the database type correct.
913
	if (isset($_POST['db_type'], $databases[$_POST['db_type']]))
914
		$db_type = $_POST['db_type'];
915
916
	// Else we'd better be able to get the connection.
917
	else
918
		load_database();
919
920
	$db_type = isset($_POST['db_type']) ? $_POST['db_type'] : $db_type;
921
922
	// What host and port are we on?
923
	$host = empty($_SERVER['HTTP_HOST']) ? $_SERVER['SERVER_NAME'] . (empty($_SERVER['SERVER_PORT']) || $_SERVER['SERVER_PORT'] == '80' ? '' : ':' . $_SERVER['SERVER_PORT']) : $_SERVER['HTTP_HOST'];
924
925
	// Now, to put what we've learned together... and add a path.
926
	$incontext['detected_url'] = 'http' . (!empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on' ? 's' : '') . '://' . $host . substr($_SERVER['PHP_SELF'], 0, strrpos($_SERVER['PHP_SELF'], '/'));
927
928
	// Check if the database sessions will even work.
929
	$incontext['test_dbsession'] = (ini_get('session.auto_start') != 1);
930
	$incontext['utf8_default'] = $databases[$db_type]['utf8_default'];
931
	$incontext['utf8_required'] = $databases[$db_type]['utf8_required'];
932
933
	$incontext['continue'] = 1;
934
935
	// Submitting?
936
	if (isset($_POST['boardurl']))
937
	{
938 View Code Duplication
		if (substr($_POST['boardurl'], -10) == '/index.php')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
939
			$_POST['boardurl'] = substr($_POST['boardurl'], 0, -10);
940
		elseif (substr($_POST['boardurl'], -1) == '/')
941
			$_POST['boardurl'] = substr($_POST['boardurl'], 0, -1);
942 View Code Duplication
		if (substr($_POST['boardurl'], 0, 7) != 'http://' && substr($_POST['boardurl'], 0, 7) != 'file://' && substr($_POST['boardurl'], 0, 8) != 'https://')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
943
			$_POST['boardurl'] = 'http://' . $_POST['boardurl'];
944
945
		// Save these variables.
946
		$vars = array(
947
			'boardurl' => $_POST['boardurl'],
948
			'boarddir' => addslashes(dirname(__FILE__)),
949
			'sourcedir' => addslashes(dirname(__FILE__)) . '/Sources',
950
			'cachedir' => addslashes(dirname(__FILE__)) . '/cache',
951
			'mbname' => strtr($_POST['mbname'], array('\"' => '"')),
952
			'language' => substr($_SESSION['installer_temp_lang'], 8, -4),
953
			'image_proxy_secret' => substr(sha1(mt_rand()), 0, 20),
954
			'image_proxy_enabled' => !empty($_POST['force_ssl']),
955
		);
956
957
		// Must save!
958 View Code Duplication
		if (!updateSettingsFile($vars) && substr(__FILE__, 1, 2) == ':\\')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
959
		{
960
			$incontext['error'] = $txt['error_windows_chmod'];
961
			return false;
962
		}
963
964
		// Make sure it works.
965
		require(dirname(__FILE__) . '/Settings.php');
966
967
		// UTF-8 requires a setting to override the language charset.
968
		if ((!empty($databases[$db_type]['utf8_support']) && !empty($databases[$db_type]['utf8_required'])) || (empty($databases[$db_type]['utf8_required']) && !empty($databases[$db_type]['utf8_support']) && isset($_POST['utf8'])))
969
		{
970
			if (!empty($databases[$db_type]['utf8_version_check']) && version_compare($databases[$db_type]['utf8_version'], preg_replace('~\-.+?$~', '', eval($databases[$db_type]['utf8_version_check'])), '>'))
0 ignored issues
show
Coding Style introduced by
The function ForumSettings() contains an eval expression.

On one hand, eval might be exploited by malicious users if they somehow manage to inject dynamic content. On the other hand, with the emergence of faster PHP runtimes like the HHVM, eval prevents some optimization that they perform.

Loading history...
971
			{
972
				$incontext['error'] = sprintf($txt['error_utf8_version'], $databases[$db_type]['utf8_version']);
973
				return false;
974
			}
975
			else
976
				// Set the character set here.
977
				updateSettingsFile(array('db_character_set' => 'utf8'));
978
		}
979
980
		// Good, skip on.
981
		return true;
982
	}
983
984
	return false;
985
}
986
987
// Step one: Do the SQL thang.
988
function DatabasePopulation()
989
{
990
	global $db_character_set, $txt, $db_connection, $smcFunc, $databases, $modSettings, $db_type, $db_prefix, $incontext, $db_name, $boardurl;
991
992
	$incontext['sub_template'] = 'populate_database';
993
	$incontext['page_title'] = $txt['db_populate'];
994
	$incontext['continue'] = 1;
995
996
	// Already done?
997
	if (isset($_POST['pop_done']))
998
		return true;
999
1000
	// Reload settings.
1001
	require(dirname(__FILE__) . '/Settings.php');
1002
	load_database();
1003
1004
	// Before running any of the queries, let's make sure another version isn't already installed.
1005
	$result = $smcFunc['db_query']('', '
1006
		SELECT variable, value
1007
		FROM {db_prefix}settings',
1008
		array(
1009
			'db_error_skip' => true,
1010
		)
1011
	);
1012
	$newSettings = array();
1013
	$modSettings = array();
1014
	if ($result !== false)
1015
	{
1016 View Code Duplication
		while ($row = $smcFunc['db_fetch_assoc']($result))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1017
			$modSettings[$row['variable']] = $row['value'];
1018
		$smcFunc['db_free_result']($result);
1019
1020
		// Do they match?  If so, this is just a refresh so charge on!
1021
		if (!isset($modSettings['smfVersion']) || $modSettings['smfVersion'] != $GLOBALS['current_smf_version'])
1022
		{
1023
			$incontext['error'] = $txt['error_versions_do_not_match'];
1024
			return false;
1025
		}
1026
	}
1027
	$modSettings['disableQueryCheck'] = true;
1028
1029
	// If doing UTF8, select it. PostgreSQL requires passing it as a string...
1030
	if (!empty($db_character_set) && $db_character_set == 'utf8' && !empty($databases[$db_type]['utf8_support']))
1031
		$smcFunc['db_query']('', '
1032
			SET NAMES {'. ($db_type == 'postgresql' ? 'string' : 'raw') . ':utf8}',
1033
			array(
1034
				'db_error_skip' => true,
1035
				'utf8' => 'utf8',
1036
			)
1037
		);
1038
1039
	// Windows likes to leave the trailing slash, which yields to C:\path\to\SMF\/attachments...
1040
	if (substr(__DIR__, -1) == '\\')
1041
		$attachdir = __DIR__ . 'attachments';
1042
	else
1043
		$attachdir = __DIR__ . '/attachments';
1044
1045
	$replaces = array(
1046
		'{$db_prefix}' => $db_prefix,
1047
		'{$attachdir}' => json_encode(array(1 => $smcFunc['db_escape_string']($attachdir))),
1048
		'{$boarddir}' => $smcFunc['db_escape_string'](dirname(__FILE__)),
1049
		'{$boardurl}' => $boardurl,
1050
		'{$enableCompressedOutput}' => isset($_POST['compress']) ? '1' : '0',
1051
		'{$databaseSession_enable}' => isset($_POST['dbsession']) ? '1' : '0',
1052
		'{$smf_version}' => $GLOBALS['current_smf_version'],
1053
		'{$current_time}' => time(),
1054
		'{$sched_task_offset}' => 82800 + mt_rand(0, 86399),
1055
		'{$registration_method}' => isset($_POST['reg_mode']) ? $_POST['reg_mode'] : 0,
1056
	);
1057
1058
	foreach ($txt as $key => $value)
1059
	{
1060
		if (substr($key, 0, 8) == 'default_')
1061
			$replaces['{$' . $key . '}'] = $smcFunc['db_escape_string']($value);
1062
	}
1063
	$replaces['{$default_reserved_names}'] = strtr($replaces['{$default_reserved_names}'], array('\\\\n' => '\\n'));
1064
1065
	// MySQL-specific stuff - storage engine and UTF8 handling
1066
	if (substr($db_type, 0, 5) == 'mysql')
1067
	{
1068
		// Just in case the query fails for some reason...
1069
		$engines = array();
1070
1071
		// Figure out storage engines - what do we have, etc.
1072
		$get_engines = $smcFunc['db_query']('', 'SHOW ENGINES', array());
1073
1074 View Code Duplication
		while ($row = $smcFunc['db_fetch_assoc']($get_engines))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1075
		{
1076
			if ($row['Support'] == 'YES' || $row['Support'] == 'DEFAULT')
1077
				$engines[] = $row['Engine'];
1078
		}
1079
1080
		// Done with this now
1081
		$smcFunc['db_free_result']($get_engines);
1082
1083
		// InnoDB is better, so use it if possible...
1084
		$has_innodb = in_array('InnoDB', $engines);
1085
		$replaces['{$engine}'] = $has_innodb ? 'InnoDB' : 'MyISAM';
1086
		$replaces['{$memory}'] = (!$has_innodb && in_array('MEMORY', $engines)) ? 'MEMORY' : $replaces['{$engine}'];
1087
1088
		// If the UTF-8 setting was enabled, add it to the table definitions.
1089
		if (!empty($databases[$db_type]['utf8_support']) && (!empty($databases[$db_type]['utf8_required']) || isset($_POST['utf8'])))
1090
		{
1091
			$replaces['{$engine}'] .= ' DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci';
1092
			$replaces['{$memory}'] .= ' DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci';
1093
		}
1094
1095
		// One last thing - if we don't have InnoDB, we can't do transactions...
1096
		if (!$has_innodb)
1097
		{
1098
			$replaces['START TRANSACTION;'] = '';
1099
			$replaces['COMMIT;'] = '';
1100
		}
1101
	}
1102
	else
1103
	{
1104
		$has_innodb = false;
1105
	}
1106
1107
	// Read in the SQL.  Turn this on and that off... internationalize... etc.
1108
	$type = ($db_type == 'mysqli' ? 'mysql' : $db_type);
1109
	$sql_lines = explode("\n", strtr(implode(' ', file(dirname(__FILE__) . '/install_' . $GLOBALS['db_script_version'] . '_' . $type . '.sql')), $replaces));
1110
1111
	// Execute the SQL.
1112
	$current_statement = '';
1113
	$exists = array();
1114
	$incontext['failures'] = array();
1115
	$incontext['sql_results'] = array(
1116
		'tables' => 0,
1117
		'inserts' => 0,
1118
		'table_dups' => 0,
1119
		'insert_dups' => 0,
1120
	);
1121
	foreach ($sql_lines as $count => $line)
1122
	{
1123
		// No comments allowed!
1124
		if (substr(trim($line), 0, 1) != '#')
1125
			$current_statement .= "\n" . rtrim($line);
1126
1127
		// Is this the end of the query string?
1128
		if (empty($current_statement) || (preg_match('~;[\s]*$~s', $line) == 0 && $count != count($sql_lines)))
1129
			continue;
1130
1131
		// Does this table already exist?  If so, don't insert more data into it!
1132
		if (preg_match('~^\s*INSERT INTO ([^\s\n\r]+?)~', $current_statement, $match) != 0 && in_array($match[1], $exists))
1133
		{
1134
			preg_match_all('~\)[,;]~', $current_statement, $matches);
1135 View Code Duplication
			if (!empty($matches[0]))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1136
				$incontext['sql_results']['insert_dups'] += count($matches[0]);
1137
			else
1138
				$incontext['sql_results']['insert_dups']++;
1139
1140
			$current_statement = '';
1141
			continue;
1142
		}
1143
1144
		if ($smcFunc['db_query']('', $current_statement, array('security_override' => true, 'db_error_skip' => true), $db_connection) === false)
1145
		{
1146
			// Use the appropriate function based on the DB type
1147
			if ($db_type == 'mysql' || $db_type =='mysqli')
1148
				$db_errorno = $db_type . '_errno';
1149
1150
			// Error 1050: Table already exists!
1151
			// @todo Needs to be made better!
1152
			if ((($db_type != 'mysql' && $db_type != 'mysqli') || $db_errorno($db_connection) == 1050) && preg_match('~^\s*CREATE TABLE ([^\s\n\r]+?)~', $current_statement, $match) == 1)
0 ignored issues
show
Bug introduced by
The variable $db_errorno does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1153
			{
1154
				$exists[] = $match[1];
1155
				$incontext['sql_results']['table_dups']++;
1156
			}
1157
			// Don't error on duplicate indexes (or duplicate operators in PostgreSQL.)
1158
			elseif (!preg_match('~^\s*CREATE( UNIQUE)? INDEX ([^\n\r]+?)~', $current_statement, $match) && !($db_type == 'postgresql' && preg_match('~^\s*CREATE OPERATOR (^\n\r]+?)~', $current_statement, $match)))
1159
			{
1160
				// MySQLi requires a connection object. It's optional with MySQL and Postgres
1161
				$incontext['failures'][$count] = $smcFunc['db_error']($db_connection);
1162
			}
1163
		}
1164
		else
1165
		{
1166
			if (preg_match('~^\s*CREATE TABLE ([^\s\n\r]+?)~', $current_statement, $match) == 1)
1167
				$incontext['sql_results']['tables']++;
1168
			elseif (preg_match('~^\s*INSERT INTO ([^\s\n\r]+?)~', $current_statement, $match) == 1)
1169
			{
1170
				preg_match_all('~\)[,;]~', $current_statement, $matches);
1171 View Code Duplication
				if (!empty($matches[0]))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1172
					$incontext['sql_results']['inserts'] += count($matches[0]);
1173
				else
1174
					$incontext['sql_results']['inserts']++;
1175
			}
1176
		}
1177
1178
		$current_statement = '';
1179
1180
		// Wait, wait, I'm still working here!
1181
		set_time_limit(60);
1182
	}
1183
1184
	// Sort out the context for the SQL.
1185
	foreach ($incontext['sql_results'] as $key => $number)
1186
	{
1187
		if ($number == 0)
1188
			unset($incontext['sql_results'][$key]);
1189
		else
1190
			$incontext['sql_results'][$key] = sprintf($txt['db_populate_' . $key], $number);
1191
	}
1192
1193
	// Make sure UTF will be used globally.
1194
	if ((!empty($databases[$db_type]['utf8_support']) && !empty($databases[$db_type]['utf8_required'])) || (empty($databases[$db_type]['utf8_required']) && !empty($databases[$db_type]['utf8_support']) && isset($_POST['utf8'])))
1195
		$newSettings[] = array('global_character_set', 'UTF-8');
1196
1197
	// Maybe we can auto-detect better cookie settings?
1198
	preg_match('~^http[s]?://([^\.]+?)([^/]*?)(/.*)?$~', $boardurl, $matches);
1199
	if (!empty($matches))
1200
	{
1201
		// Default = both off.
1202
		$localCookies = false;
1203
		$globalCookies = false;
1204
1205
		// Okay... let's see.  Using a subdomain other than www.? (not a perfect check.)
1206
		if ($matches[2] != '' && (strpos(substr($matches[2], 1), '.') === false || in_array($matches[1], array('forum', 'board', 'community', 'forums', 'support', 'chat', 'help', 'talk', 'boards', 'www'))))
1207
			$globalCookies = true;
1208
		// If there's a / in the middle of the path, or it starts with ~... we want local.
1209
		if (isset($matches[3]) && strlen($matches[3]) > 3 && (substr($matches[3], 0, 2) == '/~' || strpos(substr($matches[3], 1), '/') !== false))
1210
			$localCookies = true;
1211
1212
		if ($globalCookies)
1213
			$newSettings[] = array('globalCookies', '1');
1214
		if ($localCookies)
1215
			$newSettings[] = array('localCookies', '1');
1216
	}
1217
1218
	// Are we allowing stat collection?
1219
	if (isset($_POST['stats']) && strpos($_POST['boardurl'], 'http://localhost') !== 0)
1220
	{
1221
		// Attempt to register the site etc.
1222
		$fp = @fsockopen("www.simplemachines.org", 80, $errno, $errstr);
1223
		if ($fp)
1224
		{
1225
			$out = "GET /smf/stats/register_stats.php?site=" . base64_encode($_POST['boardurl']) . " HTTP/1.1\r\n";
1226
			$out .= "Host: www.simplemachines.org\r\n";
1227
			$out .= "Connection: Close\r\n\r\n";
1228
			fwrite($fp, $out);
1229
1230
			$return_data = '';
1231
			while (!feof($fp))
1232
				$return_data .= fgets($fp, 128);
1233
1234
			fclose($fp);
1235
1236
			// Get the unique site ID.
1237
			preg_match('~SITE-ID:\s(\w{10})~', $return_data, $ID);
1238
1239
			if (!empty($ID[1]))
1240
				$newSettings[] = array('allow_sm_stats', $ID[1]);
1241
		}
1242
	}
1243
1244
	// Are we enabling SSL?
1245
	if (!empty($_POST['force_ssl']))
1246
		$newSettings[] = array('force_ssl', 2);
1247
1248
	// As of PHP 5.1, setting a timezone is required.
1249
	if (!isset($modSettings['default_timezone']) && function_exists('date_default_timezone_set'))
1250
	{
1251
		$server_offset = mktime(0, 0, 0, 1, 1, 1970);
1252
		$timezone_id = 'Etc/GMT' . ($server_offset > 0 ? '+' : '') . ($server_offset / 3600);
1253
		if (date_default_timezone_set($timezone_id))
1254
			$newSettings[] = array('default_timezone', $timezone_id);
1255
	}
1256
1257
	if (!empty($newSettings))
1258
	{
1259
		$smcFunc['db_insert']('replace',
1260
			'{db_prefix}settings',
1261
			array('variable' => 'string-255', 'value' => 'string-65534'),
1262
			$newSettings,
1263
			array('variable')
1264
		);
1265
	}
1266
1267
	// Let's optimize those new tables, but not on InnoDB, ok?
1268
	if (!$has_innodb)
1269
	{
1270
		db_extend();
1271
		$tables = $smcFunc['db_list_tables']($db_name, $db_prefix . '%');
1272
		foreach ($tables as $table)
1273
		{
1274
			$smcFunc['db_optimize_table']($table) != -1 or $db_messed = true;
1275
1276
			if (!empty($db_messed))
1277
			{
1278
				$incontext['failures'][-1] = $smcFunc['db_error']();
1279
				break;
1280
			}
1281
		}
1282
	}
1283
1284
	// MySQL specific stuff
1285
	if (substr($db_type, 0, 5) != 'mysql')
1286
		return false;
1287
1288
	// Find database user privileges.
1289
	$privs = array();
1290
	$get_privs = $smcFunc['db_query']('', 'SHOW PRIVILEGES', array());
1291
	while ($row = $smcFunc['db_fetch_assoc']($get_privs))
1292
	{
1293
		if ($row['Privilege'] == 'Alter')
1294
			$privs[] = $row['Privilege'];
1295
	}
1296
	$smcFunc['db_free_result']($get_privs);
1297
1298
	// Check for the ALTER privilege.
1299
	if (!empty($databases[$db_type]['alter_support']) && !in_array('Alter', $privs))
1300
	{
1301
		$incontext['error'] = $txt['error_db_alter_priv'];
1302
		return false;
1303
	}
1304
1305
	if (!empty($exists))
1306
	{
1307
		$incontext['page_title'] = $txt['user_refresh_install'];
1308
		$incontext['was_refresh'] = true;
1309
	}
1310
1311
	return false;
1312
}
1313
1314
// Ask for the administrator login information.
1315
function AdminAccount()
1316
{
1317
	global $txt, $db_type, $db_connection, $smcFunc, $incontext, $db_prefix, $db_passwd, $sourcedir, $db_character_set;
1318
1319
	$incontext['sub_template'] = 'admin_account';
1320
	$incontext['page_title'] = $txt['user_settings'];
1321
	$incontext['continue'] = 1;
1322
1323
	// Skipping?
1324
	if (!empty($_POST['skip']))
1325
		return true;
1326
1327
	// Need this to check whether we need the database password.
1328
	require(dirname(__FILE__) . '/Settings.php');
1329
	load_database();
1330
1331
	require_once($sourcedir . '/Subs-Auth.php');
1332
1333
	require_once($sourcedir . '/Subs.php');
1334
1335
	// We need this to properly hash the password for Admin
1336
	$smcFunc['strtolower'] = $db_character_set != 'utf8' && $txt['lang_character_set'] != 'UTF-8' ? 'strtolower' :
1337 View Code Duplication
		function($string){
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1338
			global $sourcedir;
1339
			if (function_exists('mb_strtolower'))
1340
				return mb_strtolower($string, 'UTF-8');
1341
			require_once($sourcedir . '/Subs-Charset.php');
1342
			return utf8_strtolower($string);
1343
		};
1344
1345
	if (!isset($_POST['username']))
1346
		$_POST['username'] = '';
1347
	if (!isset($_POST['email']))
1348
		$_POST['email'] = '';
1349
	if (!isset($_POST['server_email']))
1350
		$_POST['server_email'] = '';
1351
1352
	$incontext['username'] = htmlspecialchars(stripslashes($_POST['username']));
1353
	$incontext['email'] = htmlspecialchars(stripslashes($_POST['email']));
1354
	$incontext['server_email'] = htmlspecialchars(stripslashes($_POST['server_email']));
1355
1356
	$incontext['require_db_confirm'] = empty($db_type);
1357
1358
	// Only allow skipping if we think they already have an account setup.
1359
	$request = $smcFunc['db_query']('', '
1360
		SELECT id_member
1361
		FROM {db_prefix}members
1362
		WHERE id_group = {int:admin_group} OR FIND_IN_SET({int:admin_group}, additional_groups) != 0
1363
		LIMIT 1',
1364
		array(
1365
			'db_error_skip' => true,
1366
			'admin_group' => 1,
1367
		)
1368
	);
1369
	if ($smcFunc['db_num_rows']($request) != 0)
1370
		$incontext['skip'] = 1;
1371
	$smcFunc['db_free_result']($request);
1372
1373
	// Trying to create an account?
1374
	if (isset($_POST['password1']) && !empty($_POST['contbutt']))
1375
	{
1376
		// Wrong password?
1377
		if ($incontext['require_db_confirm'] && $_POST['password3'] != $db_passwd)
1378
		{
1379
			$incontext['error'] = $txt['error_db_connect'];
1380
			return false;
1381
		}
1382
		// Not matching passwords?
1383
		if ($_POST['password1'] != $_POST['password2'])
1384
		{
1385
			$incontext['error'] = $txt['error_user_settings_again_match'];
1386
			return false;
1387
		}
1388
		// No password?
1389
		if (strlen($_POST['password1']) < 4)
1390
		{
1391
			$incontext['error'] = $txt['error_user_settings_no_password'];
1392
			return false;
1393
		}
1394
		if (!file_exists($sourcedir . '/Subs.php'))
1395
		{
1396
			$incontext['error'] = $txt['error_subs_missing'];
1397
			return false;
1398
		}
1399
1400
		// Update the webmaster's email?
1401
		if (!empty($_POST['server_email']) && (empty($webmaster_email) || $webmaster_email == '[email protected]'))
0 ignored issues
show
Bug introduced by
The variable $webmaster_email seems to never exist, and therefore empty should always return true. Did you maybe rename this variable?

This check looks for calls to isset(...) or empty() on variables that are yet undefined. These calls will always produce the same result and can be removed.

This is most likely caused by the renaming of a variable or the removal of a function/method parameter.

Loading history...
Bug introduced by
The variable $webmaster_email does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
1402
			updateSettingsFile(array('webmaster_email' => $_POST['server_email']));
1403
1404
		// Work out whether we're going to have dodgy characters and remove them.
1405
		$invalid_characters = preg_match('~[<>&"\'=\\\]~', $_POST['username']) != 0;
1406
		$_POST['username'] = preg_replace('~[<>&"\'=\\\]~', '', $_POST['username']);
1407
1408
		$result = $smcFunc['db_query']('', '
1409
			SELECT id_member, password_salt
1410
			FROM {db_prefix}members
1411
			WHERE member_name = {string:username} OR email_address = {string:email}
1412
			LIMIT 1',
1413
			array(
1414
				'username' => stripslashes($_POST['username']),
1415
				'email' => stripslashes($_POST['email']),
1416
				'db_error_skip' => true,
1417
			)
1418
		);
1419
		if ($smcFunc['db_num_rows']($result) != 0)
1420
		{
1421
			list ($incontext['member_id'], $incontext['member_salt']) = $smcFunc['db_fetch_row']($result);
1422
			$smcFunc['db_free_result']($result);
1423
1424
			$incontext['account_existed'] = $txt['error_user_settings_taken'];
1425
		}
1426
		elseif ($_POST['username'] == '' || strlen($_POST['username']) > 25)
1427
		{
1428
			// Try the previous step again.
1429
			$incontext['error'] = $_POST['username'] == '' ? $txt['error_username_left_empty'] : $txt['error_username_too_long'];
1430
			return false;
1431
		}
1432
		elseif ($invalid_characters || $_POST['username'] == '_' || $_POST['username'] == '|' || strpos($_POST['username'], '[code') !== false || strpos($_POST['username'], '[/code') !== false)
1433
		{
1434
			// Try the previous step again.
1435
			$incontext['error'] = $txt['error_invalid_characters_username'];
1436
			return false;
1437
		}
1438 View Code Duplication
		elseif (empty($_POST['email']) || !filter_var(stripslashes($_POST['email']), FILTER_VALIDATE_EMAIL) || strlen(stripslashes($_POST['email'])) > 255)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1439
		{
1440
			// One step back, this time fill out a proper admin email address.
1441
			$incontext['error'] = sprintf($txt['error_valid_admin_email_needed'], $_POST['username']);
1442
			return false;
1443
		}
1444 View Code Duplication
		elseif (empty($_POST['server_email']) || !filter_var(stripslashes($_POST['server_email']), FILTER_VALIDATE_EMAIL) || strlen(stripslashes($_POST['server_email'])) > 255)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1445
		{
1446
			// One step back, this time fill out a proper admin email address.
1447
			$incontext['error'] = $txt['error_valid_server_email_needed'];
1448
			return false;
1449
		}
1450
		elseif ($_POST['username'] != '')
1451
		{
1452
			$incontext['member_salt'] = substr(md5(mt_rand()), 0, 4);
1453
1454
			// Format the username properly.
1455
			$_POST['username'] = preg_replace('~[\t\n\r\x0B\0\xA0]+~', ' ', $_POST['username']);
1456
			$ip = isset($_SERVER['REMOTE_ADDR']) ? substr($_SERVER['REMOTE_ADDR'], 0, 255) : '';
1457
1458
			$_POST['password1'] = hash_password(stripslashes($_POST['username']), stripslashes($_POST['password1']));
1459
1460
			$request = $smcFunc['db_insert']('',
1461
				$db_prefix . 'members',
1462
				array(
1463
					'member_name' => 'string-25', 'real_name' => 'string-25', 'passwd' => 'string', 'email_address' => 'string',
1464
					'id_group' => 'int', 'posts' => 'int', 'date_registered' => 'int',
1465
					'password_salt' => 'string', 'lngfile' => 'string', 'personal_text' => 'string', 'avatar' => 'string',
1466
					'member_ip' => 'inet', 'member_ip2' => 'inet', 'buddy_list' => 'string', 'pm_ignore_list' => 'string',
1467
					'website_title' => 'string', 'website_url' => 'string',
1468
					'signature' => 'string', 'usertitle' => 'string', 'secret_question' => 'string',
1469
					'additional_groups' => 'string', 'ignore_boards' => 'string',
1470
				),
1471
				array(
1472
					stripslashes($_POST['username']), stripslashes($_POST['username']), $_POST['password1'], stripslashes($_POST['email']),
1473
					1, 0, time(),
1474
					$incontext['member_salt'], '', '', '',
1475
					$ip, $ip, '', '',
1476
					'', '',
1477
					'', '', '',
1478
					'', '',
1479
				),
1480
				array('id_member')
1481
			);
1482
1483
			// Awww, crud!
1484
			if ($request === false)
1485
			{
1486
				$incontext['error'] = $txt['error_user_settings_query'] . '<br>
1487
				<div style="margin: 2ex;">' . nl2br(htmlspecialchars($smcFunc['db_error']($db_connection))) . '</div>';
1488
				return false;
1489
			}
1490
1491
			$incontext['member_id'] = $smcFunc['db_insert_id']("{$db_prefix}members", 'id_member');
1492
		}
1493
1494
		// If we're here we're good.
1495
		return true;
1496
	}
1497
1498
	return false;
1499
}
1500
1501
// Final step, clean up and a complete message!
1502
function DeleteInstall()
1503
{
1504
	global $txt, $incontext;
1505
	global $smcFunc, $db_character_set, $context, $cookiename;
1506
	global $current_smf_version, $databases, $sourcedir, $forum_version, $modSettings, $user_info, $db_type, $boardurl;
1507
1508
	$incontext['page_title'] = $txt['congratulations'];
1509
	$incontext['sub_template'] = 'delete_install';
1510
	$incontext['continue'] = 0;
1511
1512
	require(dirname(__FILE__) . '/Settings.php');
1513
	load_database();
1514
1515
	chdir(dirname(__FILE__));
1516
1517
	require_once($sourcedir . '/Errors.php');
1518
	require_once($sourcedir . '/Logging.php');
1519
	require_once($sourcedir . '/Subs.php');
1520
	require_once($sourcedir . '/Load.php');
1521
	require_once($sourcedir . '/Security.php');
1522
	require_once($sourcedir . '/Subs-Auth.php');
1523
1524
	// Bring a warning over.
1525
	if (!empty($incontext['account_existed']))
1526
		$incontext['warning'] = $incontext['account_existed'];
1527
1528
	if (!empty($db_character_set) && !empty($databases[$db_type]['utf8_support']))
1529
		$smcFunc['db_query']('', '
1530
			SET NAMES {raw:db_character_set}',
1531
			array(
1532
				'db_character_set' => $db_character_set,
1533
				'db_error_skip' => true,
1534
			)
1535
		);
1536
1537
	// As track stats is by default enabled let's add some activity.
1538
	$smcFunc['db_insert']('ignore',
1539
		'{db_prefix}log_activity',
1540
		array('date' => 'date', 'topics' => 'int', 'posts' => 'int', 'registers' => 'int'),
1541
		array(strftime('%Y-%m-%d', time()), 1, 1, (!empty($incontext['member_id']) ? 1 : 0)),
1542
		array('date')
1543
	);
1544
1545
	// We're going to want our lovely $modSettings now.
1546
	$request = $smcFunc['db_query']('', '
1547
		SELECT variable, value
1548
		FROM {db_prefix}settings',
1549
		array(
1550
			'db_error_skip' => true,
1551
		)
1552
	);
1553
	// Only proceed if we can load the data.
1554
	if ($request)
1555
	{
1556 View Code Duplication
		while ($row = $smcFunc['db_fetch_row']($request))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1557
			$modSettings[$row[0]] = $row[1];
1558
		$smcFunc['db_free_result']($request);
1559
	}
1560
1561
	// Automatically log them in ;)
1562
	if (isset($incontext['member_id']) && isset($incontext['member_salt']))
1563
		setLoginCookie(3153600 * 60, $incontext['member_id'], hash_salt($_POST['password1'], $incontext['member_salt']));
1564
1565
	$result = $smcFunc['db_query']('', '
1566
		SELECT value
1567
		FROM {db_prefix}settings
1568
		WHERE variable = {string:db_sessions}',
1569
		array(
1570
			'db_sessions' => 'databaseSession_enable',
1571
			'db_error_skip' => true,
1572
		)
1573
	);
1574 View Code Duplication
	if ($smcFunc['db_num_rows']($result) != 0)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1575
		list ($db_sessions) = $smcFunc['db_fetch_row']($result);
1576
	$smcFunc['db_free_result']($result);
1577
1578
	if (empty($db_sessions))
1579
		$_SESSION['admin_time'] = time();
1580
	else
1581
	{
1582
		$_SERVER['HTTP_USER_AGENT'] = substr($_SERVER['HTTP_USER_AGENT'], 0, 211);
1583
1584
		$smcFunc['db_insert']('replace',
1585
			'{db_prefix}sessions',
1586
			array(
1587
				'session_id' => 'string', 'last_update' => 'int', 'data' => 'string',
1588
			),
1589
			array(
1590
				session_id(), time(), 'USER_AGENT|s:' . strlen($_SERVER['HTTP_USER_AGENT']) . ':"' . $_SERVER['HTTP_USER_AGENT'] . '";admin_time|i:' . time() . ';',
1591
			),
1592
			array('session_id')
1593
		);
1594
	}
1595
1596
	updateStats('member');
1597
	updateStats('message');
1598
	updateStats('topic');
1599
1600
	// This function is needed to do the updateStats('subject') call.
1601
	$smcFunc['strtolower'] = $db_character_set != 'utf8' && $txt['lang_character_set'] != 'UTF-8' ? 'strtolower' :
1602 View Code Duplication
		function($string){
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1603
			global $sourcedir;
1604
			if (function_exists('mb_strtolower'))
1605
				return mb_strtolower($string, 'UTF-8');
1606
			require_once($sourcedir . '/Subs-Charset.php');
1607
			return utf8_strtolower($string);
1608
		};
1609
1610
	$request = $smcFunc['db_query']('', '
1611
		SELECT id_msg
1612
		FROM {db_prefix}messages
1613
		WHERE id_msg = 1
1614
			AND modified_time = 0
1615
		LIMIT 1',
1616
		array(
1617
			'db_error_skip' => true,
1618
		)
1619
	);
1620
	$context['utf8'] = $db_character_set === 'utf8' || $txt['lang_character_set'] === 'UTF-8';
1621
	if ($smcFunc['db_num_rows']($request) > 0)
1622
		updateStats('subject', 1, htmlspecialchars($txt['default_topic_subject']));
1623
	$smcFunc['db_free_result']($request);
1624
1625
	// Now is the perfect time to fetch the SM files.
1626
	require_once($sourcedir . '/ScheduledTasks.php');
1627
	// Sanity check that they loaded earlier!
1628
	if (isset($modSettings['recycle_board']))
1629
	{
1630
		$forum_version = $current_smf_version;  // The variable is usually defined in index.php so lets just use our variable to do it for us.
1631
		scheduled_fetchSMfiles(); // Now go get those files!
1632
1633
		// We've just installed!
1634
		$user_info['ip'] = $_SERVER['REMOTE_ADDR'];
1635
		$user_info['id'] = isset($incontext['member_id']) ? $incontext['member_id'] : 0;
1636
		logAction('install', array('version' => $forum_version), 'admin');
1637
	}
1638
1639
	// Check if we need some stupid MySQL fix.
1640
	$server_version = $smcFunc['db_server_info']();
1641 View Code Duplication
	if (($db_type == 'mysql' || $db_type == 'mysqli') && in_array(substr($server_version, 0, 6), array('5.0.50', '5.0.51')))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1642
		updateSettings(array('db_mysql_group_by_fix' => '1'));
1643
1644
	// Some final context for the template.
1645
	$incontext['dir_still_writable'] = is_writable(dirname(__FILE__)) && substr(__FILE__, 1, 2) != ':\\';
1646
	$incontext['probably_delete_install'] = isset($_SESSION['installer_temp_ftp']) || is_writable(dirname(__FILE__)) || is_writable(__FILE__);
1647
1648
	// Update hash's cost to an appropriate setting
1649
	updateSettings(array(
1650
		'bcrypt_hash_cost' => hash_benchmark(),
1651
	));
1652
1653
	return false;
1654
}
1655
1656
function updateSettingsFile($vars)
1657
{
1658
	// Modify Settings.php.
1659
	$settingsArray = file(dirname(__FILE__) . '/Settings.php');
1660
1661
	// @todo Do we just want to read the file in clean, and split it this way always?
1662
	if (count($settingsArray) == 1)
1663
		$settingsArray = preg_split('~[\r\n]~', $settingsArray[0]);
1664
1665
	for ($i = 0, $n = count($settingsArray); $i < $n; $i++)
1666
	{
1667
		// Remove the redirect...
1668
		if (trim($settingsArray[$i]) == 'if (file_exists(dirname(__FILE__) . \'/install.php\'))' && trim($settingsArray[$i + 1]) == '{' && trim($settingsArray[$i + 3]) == '}')
1669
		{
1670
			// Get the four lines to nothing.
1671
			$settingsArray[$i] = '';
1672
			$settingsArray[++$i] = '';
1673
			$settingsArray[++$i] = '';
1674
			$settingsArray[++$i] = '';
1675
			continue;
1676
		}
1677
1678
		if (trim($settingsArray[$i]) == '?' . '>')
1679
			$settingsArray[$i] = '';
1680
1681
		// Don't trim or bother with it if it's not a variable.
1682
		if (substr($settingsArray[$i], 0, 1) != '$')
1683
			continue;
1684
1685
		$settingsArray[$i] = rtrim($settingsArray[$i]) . "\n";
1686
1687
		foreach ($vars as $var => $val)
1688 View Code Duplication
			if (strncasecmp($settingsArray[$i], '$' . $var, 1 + strlen($var)) == 0)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1689
			{
1690
				$comment = strstr($settingsArray[$i], '#');
1691
				$settingsArray[$i] = '$' . $var . ' = \'' . $val . '\';' . ($comment != '' ? "\t\t" . $comment : "\n");
1692
				unset($vars[$var]);
1693
			}
1694
	}
1695
1696
	// Uh oh... the file wasn't empty... was it?
1697 View Code Duplication
	if (!empty($vars))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1698
	{
1699
		$settingsArray[$i++] = '';
1700
		foreach ($vars as $var => $val)
1701
			$settingsArray[$i++] = '$' . $var . ' = \'' . $val . '\';' . "\n";
1702
	}
1703
1704
	// Blank out the file - done to fix a oddity with some servers.
1705
	$fp = @fopen(dirname(__FILE__) . '/Settings.php', 'w');
1706
	if (!$fp)
1707
		return false;
1708
	fclose($fp);
1709
1710
	$fp = fopen(dirname(__FILE__) . '/Settings.php', 'r+');
1711
1712
	// Gotta have one of these ;)
1713
	if (trim($settingsArray[0]) != '<?php')
1714
		fwrite($fp, "<?php\n");
1715
1716
	$lines = count($settingsArray);
1717
	for ($i = 0; $i < $lines - 1; $i++)
1718
	{
1719
		// Don't just write a bunch of blank lines.
1720
		if ($settingsArray[$i] != '' || @$settingsArray[$i - 1] != '')
1721
			fwrite($fp, strtr($settingsArray[$i], "\r", ''));
1722
	}
1723
	fwrite($fp, $settingsArray[$i] . '?' . '>');
1724
	fclose($fp);
1725
1726
	// Even though on normal installations the filemtime should prevent this being used by the installer incorrectly
1727
	// it seems that there are times it might not. So let's MAKE it dump the cache.
1728
	if (function_exists('opcache_invalidate'))
1729
		opcache_invalidate(dirname(__FILE__) . '/Settings.php', true);
1730
1731
	return true;
1732
}
1733
1734
function updateDbLastError()
1735
{
1736
	// Write out the db_last_error file with the error timestamp
1737
	file_put_contents(dirname(__FILE__) . '/db_last_error.php', '<' . '?' . "php\n" . '$db_last_error = 0;' . "\n" . '?' . '>');
1738
1739
	return true;
1740
}
1741
1742
// Create an .htaccess file to prevent mod_security. SMF has filtering built-in.
1743
function fixModSecurity()
1744
{
1745
	$htaccess_addition = '
1746
<IfModule mod_security.c>
1747
	# Turn off mod_security filtering.  SMF is a big boy, it doesn\'t need its hands held.
1748
	SecFilterEngine Off
1749
1750
	# The below probably isn\'t needed, but better safe than sorry.
1751
	SecFilterScanPOST Off
1752
</IfModule>';
1753
1754
	if (!function_exists('apache_get_modules') || !in_array('mod_security', apache_get_modules()))
1755
		return true;
1756
	elseif (file_exists(dirname(__FILE__) . '/.htaccess') && is_writable(dirname(__FILE__) . '/.htaccess'))
1757
	{
1758
		$current_htaccess = implode('', file(dirname(__FILE__) . '/.htaccess'));
1759
1760
		// Only change something if mod_security hasn't been addressed yet.
1761
		if (strpos($current_htaccess, '<IfModule mod_security.c>') === false)
1762
		{
1763 View Code Duplication
			if ($ht_handle = fopen(dirname(__FILE__) . '/.htaccess', 'a'))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1764
			{
1765
				fwrite($ht_handle, $htaccess_addition);
1766
				fclose($ht_handle);
1767
				return true;
1768
			}
1769
			else
1770
				return false;
1771
		}
1772
		else
1773
			return true;
1774
	}
1775
	elseif (file_exists(dirname(__FILE__) . '/.htaccess'))
1776
		return strpos(implode('', file(dirname(__FILE__) . '/.htaccess')), '<IfModule mod_security.c>') !== false;
1777
	elseif (is_writable(dirname(__FILE__)))
1778
	{
1779 View Code Duplication
		if ($ht_handle = fopen(dirname(__FILE__) . '/.htaccess', 'w'))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1780
		{
1781
			fwrite($ht_handle, $htaccess_addition);
1782
			fclose($ht_handle);
1783
			return true;
1784
		}
1785
		else
1786
			return false;
1787
	}
1788
	else
1789
		return false;
1790
}
1791
1792
function template_install_above()
1793
{
1794
	global $incontext, $txt, $installurl;
1795
1796
	echo '<!DOCTYPE html>
1797
<html', $txt['lang_rtl'] == true ? ' dir="rtl"' : '', '>
1798
	<head>
1799
		<meta charset="', isset($txt['lang_character_set']) ? $txt['lang_character_set'] : 'UTF-8', '">
1800
		<meta name="robots" content="noindex">
1801
		<title>', $txt['smf_installer'], '</title>
1802
		<link rel="stylesheet" href="Themes/default/css/index.css?alp21">
1803
		<link rel="stylesheet" href="Themes/default/css/install.css?alp21">
1804
		', $txt['lang_rtl'] == true ? '<link rel="stylesheet" href="Themes/default/css/rtl.css?alp21">' : '' , '
1805
1806
		<script src="Themes/default/scripts/jquery-2.1.3.min.js"></script>
1807
		<script src="Themes/default/scripts/script.js"></script>
1808
	</head>
1809
	<body><div id="footerfix">
1810
		<div id="header">
1811
			<h1 class="forumtitle">', $txt['smf_installer'], '</h1>
1812
			<img id="smflogo" src="Themes/default/images/smflogo.png" alt="Simple Machines Forum" title="Simple Machines Forum">
1813
		</div>
1814
		<div id="wrapper">
1815
			<div id="upper_section">
1816
				<div id="inner_section">
1817
					<div id="inner_wrap">';
1818
1819
	// Have we got a language drop down - if so do it on the first step only.
1820
	if (!empty($incontext['detected_languages']) && count($incontext['detected_languages']) > 1 && $incontext['current_step'] == 0)
1821
	{
1822
		echo '
1823
						<div class="news">
1824
							<form action="', $installurl, '" method="get">
1825
								<label for="installer_language">', $txt['installer_language'], ':</label>
1826
								<select id="installer_language" name="lang_file" onchange="location.href = \'', $installurl, '?lang_file=\' + this.options[this.selectedIndex].value;">';
1827
1828
		foreach ($incontext['detected_languages'] as $lang => $name)
1829
			echo '
1830
									<option', isset($_SESSION['installer_temp_lang']) && $_SESSION['installer_temp_lang'] == $lang ? ' selected' : '', ' value="', $lang, '">', $name, '</option>';
1831
1832
		echo '
1833
								</select>
1834
								<noscript><input type="submit" value="', $txt['installer_language_set'], '" class="button_submit" /></noscript>
1835
							</form>
1836
						</div>
1837
						<hr class="clear" />';
1838
	}
1839
1840
	echo '
1841
					</div>
1842
				</div>
1843
			</div>
1844
			<div id="content_section">
1845
				<div id="main_content_section">
1846
					<div id="main_steps">
1847
						<h2>', $txt['upgrade_progress'], '</h2>
1848
						<ul>';
1849
1850 View Code Duplication
	foreach ($incontext['steps'] as $num => $step)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1851
		echo '
1852
							<li class="', $num < $incontext['current_step'] ? 'stepdone' : ($num == $incontext['current_step'] ? 'stepcurrent' : 'stepwaiting'), '">', $txt['upgrade_step'], ' ', $step[0], ': ', $step[1], '</li>';
1853
1854
	echo '
1855
						</ul>
1856
					</div>
1857
					<div id="progress_bar">
1858
						<div id="overall_text">', $incontext['overall_percent'], '%</div>
1859
						<div id="overall_progress" style="width: ', $incontext['overall_percent'], '%;">
1860
							<span>'. $txt['upgrade_overall_progress'], '</span>
1861
						</div>
1862
					</div>
1863
					<div id="main_screen" class="clear">
1864
						<h2>', $incontext['page_title'], '</h2>
1865
						<div class="panel">';
1866
}
1867
1868
function template_install_below()
1869
{
1870
	global $incontext, $txt;
1871
1872
	if (!empty($incontext['continue']) || !empty($incontext['skip']))
1873
	{
1874
		echo '
1875
								<div>';
1876
1877
		if (!empty($incontext['continue']))
1878
			echo '
1879
									<input type="submit" id="contbutt" name="contbutt" value="', $txt['upgrade_continue'], '" onclick="return submitThisOnce(this);" class="button_submit" />';
1880
		if (!empty($incontext['skip']))
1881
			echo '
1882
									<input type="submit" id="skip" name="skip" value="', $txt['upgrade_skip'], '" onclick="return submitThisOnce(this);" class="button_submit" />';
1883
		echo '
1884
								</div>';
1885
	}
1886
1887
	// Show the closing form tag and other data only if not in the last step
1888
	if (count($incontext['steps']) - 1 !== (int) $incontext['current_step'])
1889
		echo '
1890
							</form>';
1891
1892
	echo '
1893
						</div>
1894
					</div>
1895
				</div>
1896
			</div>
1897
		</div></div>
1898
		<div id="footer">
1899
			<ul>
1900
				<li class="copyright"><a href="http://www.simplemachines.org/" title="Simple Machines Forum" target="_blank" class="new_win">SMF &copy; 2016, Simple Machines</a></li>
1901
			</ul>
1902
		</div>
1903
	</body>
1904
</html>';
1905
}
1906
1907
// Welcome them to the wonderful world of SMF!
1908
function template_welcome_message()
1909
{
1910
	global $incontext, $txt;
1911
1912
	echo '
1913
	<script src="http://www.simplemachines.org/smf/current-version.js?version=' . $GLOBALS['current_smf_version'] . '"></script>
1914
	<form action="', $incontext['form_url'], '" method="post">
1915
		<p>', sprintf($txt['install_welcome_desc'], $GLOBALS['current_smf_version']), '</p>
1916
		<div id="version_warning" style="margin: 2ex; padding: 2ex; border: 2px dashed #a92174; color: black; background-color: #fbbbe2; display: none;">
1917
			<div style="float: left; width: 2ex; font-size: 2em; color: red;">!!</div>
1918
			<strong style="text-decoration: underline;">', $txt['error_warning_notice'], '</strong><br>
1919
			<div style="padding-left: 6ex;">
1920
				', sprintf($txt['error_script_outdated'], '<em id="smfVersion" style="white-space: nowrap;">??</em>', '<em id="yourVersion" style="white-space: nowrap;">' . $GLOBALS['current_smf_version'] . '</em>'), '
1921
			</div>
1922
		</div>';
1923
1924
	// Show the warnings, or not.
1925
	if (template_warning_divs())
1926
		echo '
1927
		<h3>', $txt['install_all_lovely'], '</h3>';
1928
1929
	// Say we want the continue button!
1930
	if (empty($incontext['error']))
1931
		$incontext['continue'] = 1;
1932
1933
	// For the latest version stuff.
1934
	echo '
1935
		<script>
1936
			// Latest version?
1937
			function smfCurrentVersion()
1938
			{
1939
				var smfVer, yourVer;
1940
1941
				if (!(\'smfVersion\' in window))
1942
					return;
1943
1944
				window.smfVersion = window.smfVersion.replace(/SMF\s?/g, \'\');
1945
1946
				smfVer = document.getElementById("smfVersion");
1947
				yourVer = document.getElementById("yourVersion");
1948
1949
				setInnerHTML(smfVer, window.smfVersion);
1950
1951
				var currentVersion = getInnerHTML(yourVer);
1952
				if (currentVersion < window.smfVersion)
1953
					document.getElementById(\'version_warning\').style.display = \'\';
1954
			}
1955
			addLoadEvent(smfCurrentVersion);
1956
		</script>';
1957
}
1958
1959
// A shortcut for any warning stuff.
1960
function template_warning_divs()
1961
{
1962
	global $txt, $incontext;
1963
1964
	// Errors are very serious..
1965
	if (!empty($incontext['error']))
1966
		echo '
1967
		<div style="margin: 2ex; padding: 2ex; border: 2px dashed #cc3344; color: black; background-color: #ffe4e9;">
1968
			<div style="float: left; width: 2ex; font-size: 2em; color: red;">!!</div>
1969
			<strong style="text-decoration: underline;">', $txt['upgrade_critical_error'], '</strong><br>
1970
			<div style="padding-left: 6ex;">
1971
				', $incontext['error'], '
1972
			</div>
1973
		</div>';
1974
	// A warning message?
1975
	elseif (!empty($incontext['warning']))
1976
		echo '
1977
		<div style="margin: 2ex; padding: 2ex; border: 2px dashed #cc3344; color: black; background-color: #ffe4e9;">
1978
			<div style="float: left; width: 2ex; font-size: 2em; color: red;">!!</div>
1979
			<strong style="text-decoration: underline;">', $txt['upgrade_warning'], '</strong><br>
1980
			<div style="padding-left: 6ex;">
1981
				', $incontext['warning'], '
1982
			</div>
1983
		</div>';
1984
1985
	return empty($incontext['error']) && empty($incontext['warning']);
1986
}
1987
1988
function template_chmod_files()
1989
{
1990
	global $txt, $incontext;
1991
1992
	echo '
1993
		<p>', $txt['ftp_setup_why_info'], '</p>
1994
		<ul style="margin: 2.5ex; font-family: monospace;">
1995
			<li>', implode('</li>
1996
			<li>', $incontext['failed_files']), '</li>
1997
		</ul>';
1998
1999
	if (isset($incontext['systemos'], $incontext['detected_path']) && $incontext['systemos'] == 'linux')
2000
		echo '
2001
		<hr>
2002
		<p>', $txt['chmod_linux_info'], '</p>
2003
		<tt># chmod a+w ', implode(' ' . $incontext['detected_path'] . '/', $incontext['failed_files']), '</tt>';
2004
2005
	// This is serious!
2006
	if (!template_warning_divs())
2007
		return;
2008
2009
	echo '
2010
		<hr>
2011
		<p>', $txt['ftp_setup_info'], '</p>';
2012
2013
	if (!empty($incontext['ftp_errors']))
2014
		echo '
2015
		<div class="error_message">
2016
			', $txt['error_ftp_no_connect'], '<br><br>
2017
			<code>', implode('<br>', $incontext['ftp_errors']), '</code>
2018
		</div>
2019
		<br>';
2020
2021
	echo '
2022
		<form action="', $incontext['form_url'], '" method="post">
2023
			<table align="center" style="width: 520px; margin: 1em 0; padding: 0; border: 0">
2024
				<tr>
2025
					<td width="26%" valign="top" class="textbox"><label for="ftp_server">', $txt['ftp_server'], ':</label></td>
2026
					<td>
2027
						<div style="float: ', $txt['lang_rtl'] == false ? 'right' : 'left', '; margin-', $txt['lang_rtl'] == false ? 'right' : 'left', ': 1px;"><label for="ftp_port" class="textbox"><strong>', $txt['ftp_port'], ':&nbsp;</strong></label> <input type="text" size="3" name="ftp_port" id="ftp_port" value="', $incontext['ftp']['port'], '" class="input_text" /></div>
2028
						<input type="text" size="30" name="ftp_server" id="ftp_server" value="', $incontext['ftp']['server'], '" style="width: 70%;" class="input_text" />
2029
						<div class="smalltext block">', $txt['ftp_server_info'], '</div>
2030
					</td>
2031
				</tr><tr>
2032
					<td width="26%" valign="top" class="textbox"><label for="ftp_username">', $txt['ftp_username'], ':</label></td>
2033
					<td>
2034
						<input type="text" size="50" name="ftp_username" id="ftp_username" value="', $incontext['ftp']['username'], '" style="width: 99%;" class="input_text" />
2035
						<div class="smalltext block">', $txt['ftp_username_info'], '</div>
2036
					</td>
2037
				</tr><tr>
2038
					<td width="26%" valign="top" class="textbox"><label for="ftp_password">', $txt['ftp_password'], ':</label></td>
2039
					<td>
2040
						<input type="password" size="50" name="ftp_password" id="ftp_password" style="width: 99%;" class="input_password" />
2041
						<div class="smalltext block">', $txt['ftp_password_info'], '</div>
2042
					</td>
2043
				</tr><tr>
2044
					<td width="26%" valign="top" class="textbox"><label for="ftp_path">', $txt['ftp_path'], ':</label></td>
2045
					<td style="padding-bottom: 1ex;">
2046
						<input type="text" size="50" name="ftp_path" id="ftp_path" value="', $incontext['ftp']['path'], '" style="width: 99%;" class="input_text" />
2047
						<div class="smalltext block">', $incontext['ftp']['path_msg'], '</div>
2048
					</td>
2049
				</tr>
2050
			</table>
2051
			<div style="margin: 1ex; margin-top: 1ex; text-align: ', $txt['lang_rtl'] == false ? 'right' : 'left', ';"><input type="submit" value="', $txt['ftp_connect'], '" onclick="return submitThisOnce(this);" class="button_submit" /></div>
2052
		</form>
2053
		<a href="', $incontext['form_url'], '">', $txt['error_message_click'], '</a> ', $txt['ftp_setup_again'];
2054
}
2055
2056
// Get the database settings prepared.
2057
function template_database_settings()
2058
{
2059
	global $incontext, $txt;
2060
2061
	echo '
2062
	<form action="', $incontext['form_url'], '" method="post">
2063
		<p>', $txt['db_settings_info'], '</p>';
2064
2065
	template_warning_divs();
2066
2067
	echo '
2068
		<table width="100%" border="0" style="margin: 1em 0;">';
2069
2070
	// More than one database type?
2071
	if (count($incontext['supported_databases']) > 1)
2072
	{
2073
		echo '
2074
			<tr>
2075
				<td width="20%" valign="top" class="textbox"><label for="db_type_input">', $txt['db_settings_type'], ':</label></td>
2076
				<td>
2077
					<select name="db_type" id="db_type_input" onchange="toggleDBInput();">';
2078
2079
	foreach ($incontext['supported_databases'] as $key => $db)
2080
			echo '
2081
						<option value="', $key, '"', isset($_POST['db_type']) && $_POST['db_type'] == $key ? ' selected' : '', '>', $db['name'], '</option>';
2082
2083
	echo '
2084
					</select>
2085
					<div class="smalltext block">', $txt['db_settings_type_info'], '</div>
2086
				</td>
2087
			</tr>';
2088
	}
2089
	else
2090
	{
2091
		echo '
2092
			<tr style="display: none;">
2093
				<td>
2094
					<input type="hidden" name="db_type" value="', $incontext['db']['type'], '" />
2095
				</td>
2096
			</tr>';
2097
	}
2098
2099
	echo '
2100
			<tr id="db_server_contain">
2101
				<td width="20%" valign="top" class="textbox"><label for="db_server_input">', $txt['db_settings_server'], ':</label></td>
2102
				<td>
2103
					<input type="text" name="db_server" id="db_server_input" value="', $incontext['db']['server'], '" size="30" class="input_text" /><br>
2104
					<div class="smalltext block">', $txt['db_settings_server_info'], '</div>
2105
				</td>
2106
			</tr><tr id="db_port_contain">
2107
				<td width="20%" valign="top" class="textbox"><label for="db_port_input">', $txt['db_settings_port'], ':</label></td>
2108
				<td>
2109
					<input type="text" name="db_port" id="db_port_input" value="', $incontext['db']['port'], '"><br>
2110
					<div class="smalltext block">', $txt['db_settings_port_info'], '</div>
2111
				</td>
2112
			</tr><tr id="db_user_contain">
2113
				<td valign="top" class="textbox"><label for="db_user_input">', $txt['db_settings_username'], ':</label></td>
2114
				<td>
2115
					<input type="text" name="db_user" id="db_user_input" value="', $incontext['db']['user'], '" size="30" class="input_text" /><br>
2116
					<div class="smalltext block">', $txt['db_settings_username_info'], '</div>
2117
				</td>
2118
			</tr><tr id="db_passwd_contain">
2119
				<td valign="top" class="textbox"><label for="db_passwd_input">', $txt['db_settings_password'], ':</label></td>
2120
				<td>
2121
					<input type="password" name="db_passwd" id="db_passwd_input" value="', $incontext['db']['pass'], '" size="30" class="input_password" /><br>
2122
					<div class="smalltext block">', $txt['db_settings_password_info'], '</div>
2123
				</td>
2124
			</tr><tr id="db_name_contain">
2125
				<td valign="top" class="textbox"><label for="db_name_input">', $txt['db_settings_database'], ':</label></td>
2126
				<td>
2127
					<input type="text" name="db_name" id="db_name_input" value="', empty($incontext['db']['name']) ? 'smf' : $incontext['db']['name'], '" size="30" class="input_text" /><br>
2128
					<div class="smalltext block">', $txt['db_settings_database_info'], '
2129
					<span id="db_name_info_warning">', $txt['db_settings_database_info_note'], '</span></div>
2130
				</td>
2131
			</tr><tr id="db_filename_contain" style="display: none;">
2132
				<td valign="top" class="textbox"><label for="db_filename_input">', $txt['db_settings_database_file'], ':</label></td>
2133
				<td>
2134
					<input type="text" name="db_filename" id="db_filename_input" value="', empty($incontext['db']['name']) ? dirname(__FILE__) . '/smf_' . substr(md5(microtime()), 0, 10) : stripslashes($incontext['db']['name']), '" size="30" class="input_text" /><br>
2135
					<div class="smalltext block">', $txt['db_settings_database_file_info'], '</div>
2136
				</td>
2137
			</tr><tr>
2138
				<td valign="top" class="textbox"><label for="db_prefix_input">', $txt['db_settings_prefix'], ':</label></td>
2139
				<td>
2140
					<input type="text" name="db_prefix" id="db_prefix_input" value="', $incontext['db']['prefix'], '" size="30" class="input_text" /><br>
2141
					<div class="smalltext block">', $txt['db_settings_prefix_info'], '</div>
2142
				</td>
2143
			</tr>
2144
		</table>';
2145
2146
	// Toggles a warning related to db names in PostgreSQL
2147
	echo '
2148
	<script>
2149
		function toggleDBInput()
2150
		{
2151
			if (document.getElementById(\'db_type_input\').value == \'postgresql\')
2152
				document.getElementById(\'db_name_info_warning\').style.display = \'none\';
2153
			else
2154
				document.getElementById(\'db_name_info_warning\').style.display = \'\';
2155
		}
2156
		toggleDBInput();
2157
	</script>';
2158
}
2159
2160
// Stick in their forum settings.
2161
function template_forum_settings()
2162
{
2163
	global $incontext, $txt;
2164
2165
	echo '
2166
	<form action="', $incontext['form_url'], '" method="post">
2167
		<h3>', $txt['install_settings_info'], '</h3>';
2168
2169
	template_warning_divs();
2170
2171
	echo '
2172
		<table style="width: 100%; margin: 1em 0;">
2173
			<tr>
2174
				<td class="textbox" style="width: 20%; vertical-align: top;">
2175
					<label for="mbname_input">', $txt['install_settings_name'], ':</label>
2176
				</td>
2177
				<td>
2178
					<input type="text" name="mbname" id="mbname_input" value="', $txt['install_settings_name_default'], '" size="65" class="input_text" />
2179
					<div class="smalltext block">', $txt['install_settings_name_info'], '</div>
2180
				</td>
2181
			</tr>
2182
			<tr>
2183
				<td class="textbox" style="vertical-align: top;">
2184
					<label for="boardurl_input">', $txt['install_settings_url'], ':</label>
2185
				</td>
2186
				<td>
2187
					<input type="text" name="boardurl" id="boardurl_input" value="', $incontext['detected_url'], '" size="65" class="input_text" />
2188
					<br>
2189
					<div class="smalltext block">', $txt['install_settings_url_info'], '</div>
2190
				</td>
2191
			</tr>
2192
			<tr>
2193
				<td class="textbox" style="vertical-align: top;">
2194
					<label for="reg_mode">', $txt['install_settings_reg_mode'], ':</label>
2195
				</td>
2196
				<td>
2197
					<select name="reg_mode" id="reg_mode">
2198
						<optgroup label="', $txt['install_settings_reg_modes'], ':">
2199
							<option value="0" selected>', $txt['install_settings_reg_immediate'], '</option>
2200
							<option value="1">', $txt['install_settings_reg_email'], '</option>
2201
							<option value="2">', $txt['install_settings_reg_admin'], '</option>
2202
							<option value="3">', $txt['install_settings_reg_disabled'], '</option>
2203
						</optgroup>
2204
					</select>
2205
					<br>
2206
					<div class="smalltext block">', $txt['install_settings_reg_mode_info'], '</div>
2207
				</td>
2208
			</tr>
2209
			<tr>
2210
				<td class="textbox" style="vertical-align: top;">', $txt['install_settings_compress'], ':</td>
2211
				<td>
2212
					<input type="checkbox" name="compress" id="compress_check" checked class="input_check" />&nbsp;
2213
					<label for="compress_check">', $txt['install_settings_compress_title'], '</label>
2214
					<br>
2215
					<div class="smalltext block">', $txt['install_settings_compress_info'], '</div>
2216
				</td>
2217
			</tr>
2218
			<tr>
2219
				<td class="textbox" style="vertical-align: top;">', $txt['install_settings_dbsession'], ':</td>
2220
				<td>
2221
					<input type="checkbox" name="dbsession" id="dbsession_check" checked class="input_check" />&nbsp;
2222
					<label for="dbsession_check">', $txt['install_settings_dbsession_title'], '</label>
2223
					<br>
2224
					<div class="smalltext block">', $incontext['test_dbsession'] ? $txt['install_settings_dbsession_info1'] : $txt['install_settings_dbsession_info2'], '</div>
2225
				</td>
2226
			</tr>
2227
			<tr>
2228
				<td class="textbox" style="vertical-align: top;">', $txt['install_settings_utf8'], ':</td>
2229
				<td>
2230
					<input type="checkbox" name="utf8" id="utf8_check"', $incontext['utf8_default'] ? ' checked' : '', ' class="input_check"', $incontext['utf8_required'] ? ' disabled' : '', ' />&nbsp;
2231
					<label for="utf8_check">', $txt['install_settings_utf8_title'], '</label>
2232
					<br>
2233
					<div class="smalltext block">', $txt['install_settings_utf8_info'], '</div>
2234
				</td>
2235
			</tr>
2236
			<tr>
2237
				<td class="textbox" style="vertical-align: top;">', $txt['install_settings_stats'], ':</td>
2238
				<td>
2239
					<input type="checkbox" name="stats" id="stats_check" class="input_check" />&nbsp;
2240
					<label for="stats_check">', $txt['install_settings_stats_title'], '</label>
2241
					<br>
2242
					<div class="smalltext block">', $txt['install_settings_stats_info'], '</div>
2243
				</td>
2244
			</tr>
2245
			<tr>
2246
				<td class="textbox" style="vertical-align: top;">', $txt['force_ssl'], ':</td>
2247
				<td>
2248
					<input type="checkbox" name="force_ssl" id="force_ssl" class="input_check" />&nbsp;
2249
					<label for="force_ssl">', $txt['force_ssl_label'], '</label>
2250
					<br>
2251
					<div class="smalltext block">', $txt['force_ssl_info'], '</div>
2252
				</td>
2253
			</tr>
2254
		</table>
2255
	';
2256
}
2257
2258
// Show results of the database population.
2259
function template_populate_database()
2260
{
2261
	global $incontext, $txt;
2262
2263
	echo '
2264
	<form action="', $incontext['form_url'], '" method="post">
2265
		<p>', !empty($incontext['was_refresh']) ? $txt['user_refresh_install_desc'] : $txt['db_populate_info'], '</p>';
2266
2267
	if (!empty($incontext['sql_results']))
2268
	{
2269
		echo '
2270
		<ul>
2271
			<li>', implode('</li><li>', $incontext['sql_results']), '</li>
2272
		</ul>';
2273
	}
2274
2275
	if (!empty($incontext['failures']))
2276
	{
2277
		echo '
2278
				<div style="color: red;">', $txt['error_db_queries'], '</div>
2279
				<ul>';
2280
2281
		foreach ($incontext['failures'] as $line => $fail)
2282
			echo '
2283
						<li><strong>', $txt['error_db_queries_line'], $line + 1, ':</strong> ', nl2br(htmlspecialchars($fail)), '</li>';
2284
2285
		echo '
2286
				</ul>';
2287
	}
2288
2289
	echo '
2290
		<p>', $txt['db_populate_info2'], '</p>';
2291
2292
	template_warning_divs();
2293
2294
	echo '
2295
	<input type="hidden" name="pop_done" value="1" />';
2296
}
2297
2298
// Create the admin account.
2299
function template_admin_account()
2300
{
2301
	global $incontext, $txt;
2302
2303
	echo '
2304
	<form action="', $incontext['form_url'], '" method="post">
2305
		<p>', $txt['user_settings_info'], '</p>';
2306
2307
	template_warning_divs();
2308
2309
	echo '
2310
		<table width="100%" border="0" style="margin: 2em 0;">
2311
			<tr>
2312
				<td width="18%" valign="top" class="textbox"><label for="username">', $txt['user_settings_username'], ':</label></td>
2313
				<td>
2314
					<input type="text" name="username" id="username" value="', $incontext['username'], '" size="40" class="input_text" />
2315
					<div class="smalltext block">', $txt['user_settings_username_info'], '</div>
2316
				</td>
2317
			</tr><tr>
2318
				<td valign="top" class="textbox"><label for="password1">', $txt['user_settings_password'], ':</label></td>
2319
				<td>
2320
					<input type="password" name="password1" id="password1" size="40" class="input_password" />
2321
					<div class="smalltext block">', $txt['user_settings_password_info'], '</div>
2322
				</td>
2323
			</tr><tr>
2324
				<td valign="top" class="textbox"><label for="password2">', $txt['user_settings_again'], ':</label></td>
2325
				<td>
2326
					<input type="password" name="password2" id="password2" size="40" class="input_password" />
2327
					<div class="smalltext block">', $txt['user_settings_again_info'], '</div>
2328
				</td>
2329
			</tr><tr>
2330
				<td valign="top" class="textbox"><label for="email">', $txt['user_settings_admin_email'], ':</label></td>
2331
				<td>
2332
					<input type="text" name="email" id="email" value="', $incontext['email'], '" size="40" class="input_text" />
2333
					<div class="smalltext block">', $txt['user_settings_admin_email_info'], '</div>
2334
				</td>
2335
			</tr><tr>
2336
				<td valign="top" class="textbox"><label for="server_email">', $txt['user_settings_server_email'], ':</label></td>
2337
				<td>
2338
					<input type="text" name="server_email" id="server_email" value="', $incontext['server_email'], '" size="40" class="input_text" />
2339
					<div class="smalltext block">', $txt['user_settings_server_email_info'], '</div>
2340
				</td>
2341
			</tr>
2342
		</table>';
2343
2344
	if ($incontext['require_db_confirm'])
2345
		echo '
2346
		<h2>', $txt['user_settings_database'], '</h2>
2347
		<p>', $txt['user_settings_database_info'], '</p>
2348
2349
		<div style="margin-bottom: 2ex; padding-', $txt['lang_rtl'] == false ? 'left' : 'right', ': 50px;">
2350
			<input type="password" name="password3" size="30" class="input_password" />
2351
		</div>';
2352
}
2353
2354
// Tell them it's done, and to delete.
2355
function template_delete_install()
2356
{
2357
	global $incontext, $installurl, $txt, $boardurl;
2358
2359
	echo '
2360
		<p>', $txt['congratulations_help'], '</p>';
2361
2362
	template_warning_divs();
2363
2364
	// Install directory still writable?
2365
	if ($incontext['dir_still_writable'])
2366
		echo '
2367
		<em>', $txt['still_writable'], '</em><br>
2368
		<br>';
2369
2370
	// Don't show the box if it's like 99% sure it won't work :P.
2371
	if ($incontext['probably_delete_install'])
2372
		echo '
2373
		<div style="margin: 1ex; font-weight: bold;">
2374
			<label for="delete_self"><input type="checkbox" id="delete_self" onclick="doTheDelete();" class="input_check" /> ', $txt['delete_installer'], !isset($_SESSION['installer_temp_ftp']) ? ' ' . $txt['delete_installer_maybe'] : '', '</label>
2375
		</div>
2376
		<script>
2377
			function doTheDelete()
2378
			{
2379
				var theCheck = document.getElementById ? document.getElementById("delete_self") : document.all.delete_self;
2380
				var tempImage = new Image();
2381
2382
				tempImage.src = "', $installurl, '?delete=1&ts_" + (new Date().getTime());
2383
				tempImage.width = 0;
2384
				theCheck.disabled = true;
2385
			}
2386
		</script>
2387
		<br>';
2388
2389
	echo '
2390
		', sprintf($txt['go_to_your_forum'], $boardurl . '/index.php'), '<br>
2391
		<br>
2392
		', $txt['good_luck'];
2393
}
2394
2395
?>
0 ignored issues
show
Best Practice introduced by
It is not recommended to use PHP's closing tag ?> in files other than templates.

Using a closing tag in PHP files that only contain PHP code is not recommended as you might accidentally add whitespace after the closing tag which would then be output by PHP. This can cause severe problems, for example headers cannot be sent anymore.

A simple precaution is to leave off the closing tag as it is not required, and it also has no negative effects whatsoever.

Loading history...
2396