verbosePerms()   F
last analyzed

Complexity

Conditions 23
Paths > 20000

Size

Total Lines 53
Code Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 23
eloc 29
nc 262144
nop 1
dl 0
loc 53
rs 0
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
 * EGroupware Setup - Check installation enviroment
4
 *
5
 * @link http://www.egroupware.org
6
 * @package setup
7
 * @author Miles Lott <[email protected]>
8
 * @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
9
 * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
10
 */
11
12
use EGroupware\Api;
13
14
$run_by_webserver = !!$_SERVER['PHP_SELF'];
15
$is_windows = strtoupper(substr(PHP_OS,0,3)) == 'WIN';
16
17
if ($run_by_webserver)
18
{
19
	$safe_er = error_reporting();
20
	include ('./inc/functions.inc.php');
21
	error_reporting($safe_er);
22
23
	$GLOBALS['egw_info']['setup']['stage']['header'] = $GLOBALS['egw_setup']->detection->check_header();
24
	if ($GLOBALS['egw_info']['setup']['stage']['header'] == '10')
25
	{
26
		// Check header and authentication
27
		if (!$GLOBALS['egw_setup']->auth('Config') && !$GLOBALS['egw_setup']->auth('Header'))
28
		{
29
			Header('Location: index.php');
30
			exit;
31
		}
32
	}
33
	$passed_icon = '<img src="templates/default/images/completed.png" title="Passed" alt="Passed" align="middle" />';
34
	$error_icon = '<img src="templates/default/images/incomplete.png" title="Error" alt="Error" align="middle" />';
35
	$warning_icon = '<img src="templates/default/images/dep.png" title="Warning" alt="Warning" align="middle" />';
36
}
37
else
38
{
39
	$passed_icon = '>>> Passed ';
40
	$error_icon = '*** Error: ';
41
	$warning_icon = '!!! Warning: ';
42
43
	function lang($msg,$arg1=NULL,$arg2=NULL,$arg3=NULL,$arg4=NULL)
44
	{
45
		return is_null($arg1) ? $msg : str_replace(array('%1','%2','%3','%4'),array($arg1,$arg2,$arg3,$arg4),$msg);
46
	}
47
}
48
49
$checks = array(
50
	'phpversion' => array(
51
		'func' => 'php_version',
52
		'value' => $GLOBALS['egw_setup']->required_php_version,
53
		'verbose_value' => $GLOBALS['egw_setup']->required_php_version.'+',
54
		'recommended' => $GLOBALS['egw_setup']->recommended_php_version,
55
	),
56
	'safe_mode' => array(
57
		'func' => 'php_ini_check',
58
		'value' => 0,
59
		'verbose_value' => 'Off',
60
		'warning' => lang('safe_mode is turned on, which is generaly a good thing as it makes your install more secure.')."\n".
61
			lang('If safe_mode is turned on, EGw is not able to change certain settings on runtime, nor can we load any not yet loaded module.')."\n".
62
			lang('*** You have to do the changes manualy in your php.ini (usualy in /etc on linux) in order to get EGw fully working !!!')."\n".
63
			lang('*** Do NOT update your database via setup, as the update might be interrupted by the max_execution_time, which leaves your DB in an unrecoverable state (your data is lost) !!!')
64
	),
65
	'magic_quotes_runtime' => array(
66
		'func' => 'php_ini_check',
67
		'value' => 0,
68
		'verbose_value' => 'Off',
69
		'safe_mode' => 'magic_quotes_runtime = Off'
70
	),
71
	'register_globals' => array(
72
		'func' => 'php_ini_check',
73
		'value' => 0,
74
		'verbose_value' => 'Off',
75
		'warning' => lang("register_globals is turned On, EGroupware does NOT require it and it's generaly more secure to have it turned Off")
76
	),
77
	'display_errors' => array(
78
		'func' => 'php_ini_check',
79
		'value' => 0,
80
		'verbose_value' => 'Off',
81
		'warning' => lang('%1 is set to %2. This is NOT recommeded for a production system, as displayed error messages can contain passwords or other sensitive information!','display_errors',ini_get('display_errors')),
0 ignored issues
show
Unused Code introduced by
The call to lang() has too many arguments starting with 'display_errors'. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

81
		'warning' => /** @scrutinizer ignore-call */ lang('%1 is set to %2. This is NOT recommeded for a production system, as displayed error messages can contain passwords or other sensitive information!','display_errors',ini_get('display_errors')),

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
82
	),
83
	'memory_limit' => array(
84
		'func' => 'php_ini_check',
85
		'value' => '128M',
86
		'check' => '>=',
87
		'error' => lang('memory_limit is set to less than %1: some applications of EGroupware need more than the recommend 8M, expect occasional failures','24M'),
88
		'change' => 'memory_limit = 24M'
89
	),
90
	'max_execution_time' => array(
91
		'func' => 'php_ini_check',
92
		'value' => 30,
93
		'check' => '>=',
94
		'error' => lang('max_execution_time is set to less than 30 (seconds): EGroupware sometimes needs a higher execution_time, expect occasional failures'),
95
		'safe_mode' => 'max_execution_time = 30'
96
	),
97
	'file_uploads' => array(
98
		'func' => 'php_ini_check',
99
		'value' => 1,
100
		'verbose_value' => 'On',
101
		'error' => lang('File uploads are switched off: You can NOT use any of the filemanagers, nor can you attach files in several applications!'),
102
	),
103
	'upload_max_filesize' => array(
104
		'func' => 'php_ini_check',
105
		'value' => '8M',
106
		'check' => '>=',
107
		'error' => lang('%1 is set to %2, you will NOT be able to upload or attach files bigger then that!','upload_max_filesize',ini_get('upload_max_filesize')),
108
		'change' => 'upload_max_filesize = 8M'
109
	),
110
	'post_max_size' => array(
111
		'func' => 'php_ini_check',
112
		'value' => '8M',
113
		'check' => '>=',
114
		'error' => lang('%1 is set to %2, you will NOT be able to upload or attach files bigger then that!','post_max_size',ini_get('max_post_size')),
115
		'change' => 'post_max_size = 8M'
116
	),
117
	'allow_url_fopen' => array(
118
		'func' => 'php_ini_check',
119
		'value' => 1,
120
		'verbose_value' => 'On',
121
		'error' => lang('%1 setting "%2" = %3 disallows access via http!',
122
			'php.ini', 'allow_url_fopen', array2string(ini_get('allow_url_fopen'))),
123
	),
124
	'session' => array(
125
		'func' => 'extension_check',
126
		'error' => lang('The session extension is required!')
127
	),
128
	'include_path' => array(
129
		'func' => 'php_ini_check',
130
		'value' => '.',
131
		'check' => 'contain',
132
		'error' => lang('include_path need to contain "." - the current directory'),
133
	),
134
	'date.timezone' => array(
135
		'func' => 'php_ini_check',
136
		'value' => 'System/Localtime',
137
		'verbose_value' => '"System/Localtime"',
138
		'check' => '!=',
139
		'error' => lang('No VALID timezone set! ("%1" is NOT sufficient, you have to use a timezone identifer like "%2", see %3full list of valid identifers%4)',
140
			'System/Localtime','Europe/Berlin','<a href="http://www.php.net/manual/en/timezones.php" target="_blank">','</a>'),
141
	),
142
	'pdo' => array(
143
		'func' => 'extension_check',
144
		'error' => lang('The PDO extension plus a database specific driver is needed by the VFS (virtual file system)!'),
145
	),
146
	'mysqli' => array(
147
		'func' => 'extension_check',
148
		'warning' => lang('The %1 extension is needed, if you plan to use a %2 database.','mysql','MySQL')
149
	),
150
	'pdo_mysql' => array(
151
		'func' => 'extension_check',
152
		'warning' => lang('The %1 extension is needed, if you plan to use a %2 database.','pdo_mysql','MySQL')
153
	),
154
	'pgsql' => array(
155
		'func' => 'extension_check',
156
		'warning' => lang('The %1 extension is needed, if you plan to use a %2 database.','pgsql','pgSQL')
157
	),
158
	'pdo_pgsql' => array(
159
		'func' => 'extension_check',
160
		'warning' => lang('The %1 extension is needed, if you plan to use a %2 database.','pdo_pgsql','pgSQL')
161
	),
162
	/* disable checks for other database extensions, as we are not really supporting them anymore
163
	'mssql' => array(
164
		'func' => 'extension_check',
165
		'warning' => lang('The %1 extension is needed, if you plan to use a %2 database.','mssql','MsSQL'),
166
		'win_only' => True
167
	),
168
	'pdo_dblib' => array(
169
		'func' => 'extension_check',
170
		'warning' => lang('The %1 extension is needed, if you plan to use a %2 database.','pdo_dblib','MsSQL'),
171
		'win_only' => True
172
	),
173
	'odbc' => array(
174
		'func' => 'extension_check',
175
		'warning' => lang('The %1 extension is needed, if you plan to use a %2 database.','odbc','MaxDB, MsSQL or Oracle'),
176
	),
177
	'pdo_odbc' => array(
178
		'func' => 'extension_check',
179
		'warning' => lang('The %1 extension is needed, if you plan to use a %2 database.','pdo_odbc','MaxDB, MsSQL or Oracle'),
180
	),
181
	'oci8' => array(
182
		'func' => 'extension_check',
183
		'warning' => lang('The %1 extension is needed, if you plan to use a %2 database.','oci','Oracle'),
184
	),
185
	'pdo_oci' => array(
186
		'func' => 'extension_check',
187
		'warning' => lang('The %1 extension is needed, if you plan to use a %2 database.','pdo_oci','Oracle'),
188
	),*/
189
	'mbstring' => array(
190
		'func' => 'extension_check',
191
		'warning' => lang('The mbstring extension is needed to fully support unicode (utf-8) or other multibyte-charsets.')
192
	),
193
	'ldap' => array(
194
		'func' => 'extension_check',
195
		'warning' => lang("The ldap extension is needed, if you use ldap as account or contact storage, authenticate against ldap or active directory. It's not needed for a standard SQL installation."),
196
	),
197
	'' => array(
198
		'func' => 'dependency_check',
199
		'error' => lang('EGroupware requires several dependencies installed via: %1', 'composer install'),
200
	),
201
	realpath('..') => array(
202
		'func' => 'permission_check',
203
		'is_world_writable' => False,
204
		'only_if_exists' => true,	// quitens "file does not exist" for doc symlinks in Debian to files outside open_basedir
205
		'recursiv' => True
206
	),
207
	realpath('../header.inc.php') => array(
208
		'func' => 'permission_check',
209
		'is_world_readable' => False,
210
		'only_if_exists' => @$GLOBALS['egw_info']['setup']['stage']['header'] != 10
211
	),
212
	'ctype' => array(
213
		'func' => 'extension_check',
214
		'error' => lang("The ctype extension is needed by HTMLpurifier to check content of FCKeditor agains Cross Site Skripting."),
215
	),
216
	'json' => array(
217
		'func' => 'extension_check',
218
		'error' => lang('The json extension is required by EGroupware for AJAX.'),
219
	),
220
	'zip' => array(
221
		'func' => 'extension_check',
222
		'warning' => lang('The zip extension is required for merge-print with office documents.'),
223
	),
224
	'tidy' => array(
225
		'func' => 'extension_check',
226
		'warning' => lang('The tidy extension is need in merge-print to clean up html before inserting it in office documents.'),
227
	),
228
	'xsl' => array(
229
		'func' => 'extension_check',
230
		'warning' => lang('The xsl extension is need in merge-print for processing html and office documents.'),
231
	),
232
	'xmlreader' => array(
233
		'func' => 'extension_check',
234
		'error' => lang('The xmlreader extension is required by EGroupware in several applications.'),
235
	),
236
);
237
if (extension_loaded('session') && ini_get('session.save_handler') == 'files' && ($session_path = realpath(session_save_path())))
238
{
239
	$sp_visible = true;
240
	if (($open_basedir = ini_get('open_basedir')) && $open_basedir != 'none')
241
	{
242
		foreach(explode(PATH_SEPARATOR,$open_basedir) as $dir)
243
		{
244
			$dir = realpath($dir);
245
			if (($sp_visible = substr($session_path,0,strlen($dir)) == $dir)) break;
246
		}
247
	}
248
	if ($sp_visible)	// only check if session_save_path is visible by webserver
249
	{
250
		$checks[$session_path] = array(
251
			'func' => 'permission_check',
252
			'is_writable' => true,
253
			'msg' => lang("Checking if php.ini setting session.save_path='%1' is writable by the webserver",session_save_path()),
254
			'error' => lang('You will NOT be able to log into EGroupware using PHP sessions: "session could not be verified" !!!'),
255
		);
256
	}
257
}
258
$setup_info = $GLOBALS['egw_setup']->detection->get_versions();
259
foreach($setup_info as $app => $app_data)
260
{
261
	if (!isset($app_data['check_install'])) continue;
262
263
	foreach ($app_data['check_install'] as $name => $data)
264
	{
265
		if (isset($checks[$name]))
266
		{
267
			if ($checks[$name] == $data) continue;	// identical check --> ignore it
268
269
			if ($data['func'] == 'pear_check' || in_array($data['func'],array('extension_check','php_ini_check')) && !isset($data['warning']))
270
			{
271
				if (isset($checks[$name]['from']) && $checks[$name]['from'] && !is_array($checks[$name]['from']))
272
				{
273
					$checks[$name]['from'] = array($checks[$name]['from']);
274
				}
275
				if (!isset($data['from'])) $data['from'] = $app;
276
				if (!isset($checks[$name]['from']) || !is_array($checks[$name]['from'])) $checks[$name]['from'] = array();
277
				if (!in_array($data['from'],$checks[$name]['from'])) $checks[$name]['from'][] = $data['from'];
278
			}
279
			else
280
			{
281
				$checks[$app.'_'.$name] = $data;
282
			}
283
		}
284
		else
285
		{
286
			if (!isset($data['from'])) $data['from'] = $app;
287
			$checks[$name] = $data;
288
		}
289
		//echo "added check $data[func]($name) for $app"; _debug_array($data);
290
	}
291
}
292
// load required extensions from composer.json too:
293
$composer = json_decode(file_get_contents(EGW_SERVER_ROOT.'/composer.json'), true);
294
foreach($composer['require'] as $name => $version)
295
{
296
	if (substr($name, 0, 4) === 'ext-' && !isset($checks[substr($name, 4)]))
297
	{
298
		$checks[substr($name, 4)] = [
299
			'func' => 'extension_check',
300
			'error' => lang('The %1 extension is needed from: %2.', substr($name, 4), 'EGroupware'),
301
		];
302
	}
303
}
304
$sorted_checks = array();
305
foreach(array('php_version','php_ini_check','extension_check','pear_check','gd_check','permission_check') as $func)
306
{
307
	foreach($checks as $name => $data)
308
	{
309
		if ($data['func'] == $func)
310
		{
311
			$sorted_checks[$name] = $data;
312
			unset($checks[$name]);
313
		}
314
	}
315
}
316
if ($checks) $sorted_checks += $checks;
317
318
function php_version($name,$args)
319
{
320
	global $passed_icon, $error_icon;
321
	unset($name);	// not used, but required by function signature
322
323
	$version_ok = version_compare(phpversion(),$args['value']) >= 0;
324
325
	echo '<div>'.($version_ok ? $passed_icon : $error_icon).' <span'.($version_ok ? '' : ' class="setup_error"').'>'.
326
		lang('Checking required PHP version %1 (recommended %2)',$args['verbose_value'],$args['recommended']).': '.
0 ignored issues
show
Unused Code introduced by
The call to lang() has too many arguments starting with $args['verbose_value']. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

326
		/** @scrutinizer ignore-call */ 
327
  lang('Checking required PHP version %1 (recommended %2)',$args['verbose_value'],$args['recommended']).': '.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
327
		phpversion().' ==> '.($version_ok ? lang('True') : lang('False'))."</span></div>\n";
328
}
329
330
/**
331
 * Check if given package is installed via composer in EGroupware's vendor directory
332
 *
333
 * @param string $package package-name in composer notation eg. "pear-pear.horde.org/Horde_Imap_Client" or "pear-pear.php.net/Net_Sieve"
334
 */
335
function composer_check($package)
336
{
337
	static $installed=null;
338
	if (!isset($installed))
339
	{
340
		$installed = array();
341
		if (file_exists(EGW_SERVER_ROOT.'/vendor') && file_exists($json=EGW_SERVER_ROOT.'/vendor/composer/installed.json'))
342
		{
343
			foreach(json_decode(file_get_contents($json), true) as $package_data)
344
			{
345
				$installed[strtolower($package_data['name'])] = $package_data['version'];
346
			}
347
		}
348
	}
349
	//error_log(__METHOD__."('$package') returning ".array2string($installed[strtolower($package)]));
350
	return $installed[strtolower($package)];
351
}
352
353
/**
354
 * Check all dependencies from composer.lock are installed
355
 *
356
 * @param boolean $verbose true: list all packages, false: list only missing packages
357
 */
358
function dependency_check($verbose=true)
359
{
360
	global $passed_icon, $warning_icon, $error_icon;
361
362
	if (!file_exists(EGW_SERVER_ROOT.'/vendor') || !file_exists($json=EGW_SERVER_ROOT.'/vendor/composer/installed.json'))
363
	{
364
		echo '<div>'.$error_icon.' <span class="setup_error">'.
365
			lang('No dependencies are installed: you need to run "%1" AND either "%2" OR "%3"!',
366
				'cd '.EGW_SERVER_ROOT, './install-cli.php install', 'composer install')."</div>\n";
0 ignored issues
show
Unused Code introduced by
The call to lang() has too many arguments starting with 'cd ' . EGW_SERVER_ROOT. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

366
			/** @scrutinizer ignore-call */ 
367
   lang('No dependencies are installed: you need to run "%1" AND either "%2" OR "%3"!',

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
367
		return;
368
	}
369
370
	$composer_lock = json_decode(file_get_contents(EGW_SERVER_ROOT.'/composer.lock'), true);
371
	$ok = $wrong_version = $missing = 0;
372
	foreach($composer_lock['packages'] as $package)
373
	{
374
		$installed = composer_check($package['name']);
375
		$version_ok = !empty($installed) && version_compare($installed, $package['version'], '==');
376
377
		if (empty($installed))
378
		{
379
			$missing++;
380
			$icon = $error_icon;
381
			$class = ' class="setup_error"';
382
		}
383
		elseif (!$version_ok)
384
		{
385
			$wrong_version++;
386
			$icon = $warning_icon;
387
			$class = ' class="setup_warning"';
388
		}
389
		else
390
		{
391
			$ok++;
392
			$icon = $passed_icon;
393
			$class = '';
394
		}
395
396
		if ($verbose || !$version_ok)
397
		{
398
			echo '<div>'.$icon.' <span'.$class.'>'.
399
				lang('Checking package %1 is installed', $package['name'].':'.$package['version']).
400
				': '.(empty($installed) ? lang('not installed') : $installed)."</div>\n";
401
		}
402
	}
403
	if ($ok && !$verbose)
404
	{
405
		echo '<div>'.$passed_icon.' <span class="setup_error">'.
406
			lang('Checking dependencies: %1 packages are installed in the required version.', $ok)."</div>\n";
407
	}
408
}
409
410
/**
411
 * @deprecated use composer.json
412
 */
413
function pear_check($package,$args)
414
{
415
	unset($package, $args);
416
}
417
418
function extension_check($name,$args)
419
{
420
	//echo "<p>extension_check($name,".print_r($args,true).")</p>\n";
421
	global $passed_icon, $warning_icon, $is_windows, $error_icon;
422
423
	if (isset($args['win_only']) && $args['win_only'] && !$is_windows)
424
	{
425
		return True;	// check only under windows
426
	}
427
	// we check for the existens of 'dl', as multithreaded webservers dont have it !!!
428
	$available = check_load_extension($name);
429
	$icon = $available ? $passed_icon : (isset($args['error']) ? $error_icon : $warning_icon);
430
	$class = $available ? '' : (isset($args['error']) ? ' class="setup_error"' : ' class="setup_warning"');
431
432
	echo '<div>'.$icon.' <span'.$class.'>'.lang('Checking extension %1 is loaded or loadable', $name).
0 ignored issues
show
Unused Code introduced by
The call to lang() has too many arguments starting with $name. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

432
	echo '<div>'.$icon.' <span'.$class.'>'./** @scrutinizer ignore-call */ lang('Checking extension %1 is loaded or loadable', $name).

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
433
		': '.($available ? lang('True') : lang('False'))."</span></div>\n";
434
435
	if (!$available)
436
	{
437
		if (!isset($args['warning']))
438
		{
439
			$args['warning'] = lang('The %1 extension is needed from: %2.',$name,
440
				is_array($args['from']) ? implode(', ',$args['from']) : $args['from']);
441
		}
442
		echo "<div class='setup_info'>".(isset($args['error']) ? $args['error'] : $args['warning']).'</div>';
443
	}
444
	echo "\n";
445
446
	return $available;
447
}
448
449
function function_check($name,$args)
450
{
451
	global $passed_icon, $warning_icon;
452
453
	$available = function_exists($name);
454
455
	echo '<div>'.($available ? $passed_icon : $warning_icon).' <span'.($available ? '' : ' class="setup_warning"').'>'.lang('Checking function %1 exists',$name).': '.($available ? lang('True') : lang('False'))."</span></div>\n";
0 ignored issues
show
Unused Code introduced by
The call to lang() has too many arguments starting with $name. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

455
	echo '<div>'.($available ? $passed_icon : $warning_icon).' <span'.($available ? '' : ' class="setup_warning"').'>'./** @scrutinizer ignore-call */ lang('Checking function %1 exists',$name).': '.($available ? lang('True') : lang('False'))."</span></div>\n";

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
456
457
	if (!$available)
458
	{
459
		if (!isset($args['warning']))
460
		{
461
			$args['warning'] = lang('The function %1 is needed from: %2.',$name,
462
				is_array($args['from'] ? implode(', ',$args['from']) : $args['from']));
463
		}
464
		echo "<div class='setup_info'>".$args['warning'].'</div>';
465
	}
466
	echo "\n";
467
468
	return $available;
469
}
470
471
function verbosePerms( $in_Perms )
472
{
473
	if($in_Perms & 0x1000)     // FIFO pipe
474
	{
475
		$sP = 'p';
476
	}
477
	elseif($in_Perms & 0x2000) // Character special
478
	{
479
		$sP = 'c';
480
	}
481
	elseif($in_Perms & 0x4000) // Directory
482
	{
483
		$sP = 'd';
484
	}
485
	elseif($in_Perms & 0x6000) // Block special
486
	{
487
		$sP = 'b';
488
	}
489
	elseif($in_Perms & 0x8000) // Regular
490
	{
491
		$sP = '-';
492
	}
493
	elseif($in_Perms & 0xA000) // Symbolic Link
494
	{
495
		$sP = 'l';
496
	}
497
	elseif($in_Perms & 0xC000) // Socket
498
	{
499
		$sP = 's';
500
	}
501
	else                         // UNKNOWN
502
	{
503
		$sP = 'u';
504
	}
505
506
	// owner
507
	$sP .= (($in_Perms & 0x0100) ? 'r' : '-') .
508
	(($in_Perms & 0x0080) ? 'w' : '-') .
509
	(($in_Perms & 0x0040) ? (($in_Perms & 0x0800) ? 's' : 'x' ) :
510
	(($in_Perms & 0x0800) ? 'S' : '-'));
511
512
	// group
513
	$sP .= (($in_Perms & 0x0020) ? 'r' : '-') .
514
	(($in_Perms & 0x0010) ? 'w' : '-') .
515
	(($in_Perms & 0x0008) ? (($in_Perms & 0x0400) ? 's' : 'x' ) :
516
	(($in_Perms & 0x0400) ? 'S' : '-'));
517
518
	// world
519
	$sP .= (($in_Perms & 0x0004) ? 'r' : '-') .
520
	(($in_Perms & 0x0002) ? 'w' : '-') .
521
	(($in_Perms & 0x0001) ? (($in_Perms & 0x0200) ? 't' : 'x' ) :
522
	(($in_Perms & 0x0200) ? 'T' : '-'));
523
	return $sP;
524
}
525
526
function permission_check($name,$args,$verbose=True)
527
{
528
	global $passed_icon, $error_icon, $warning_icon,$is_windows;
529
	//echo "<p>permision_check('$name',".print_r($args,True).",'$verbose')</p>\n";
530
531
	// add a ../ for non-absolute pathes
532
	$rel_name = $name;
533
	if ($name && substr($name,0,3) != '../' && $name[0] != '/' && $name[0] != '\\' && strpos($name,':') === false)
534
	{
535
		$name = '../'.$name;
536
	}
537
538
	if (!file_exists($name) && isset($args['only_if_exists']) && $args['only_if_exists'])
539
	{
540
		return True;
541
	}
542
543
	$perms = $checks = '';
0 ignored issues
show
Unused Code introduced by
The assignment to $checks is dead and can be removed.
Loading history...
544
	if (file_exists($name))
545
	{
546
		$owner = function_exists('posix_getpwuid') ? posix_getpwuid(@fileowner($name)) : array('name' => 'nn');
547
		$group = function_exists('posix_getgrgid') ? posix_getgrgid(@filegroup($name)) : array('name' => 'nn');
548
		$perms = "$owner[name]/$group[name] ".verbosePerms(@fileperms($name));
549
	}
550
551
	$checks = array();
552
	if (isset($args['is_readable']))
553
	{
554
		$checks[] = lang('readable by the webserver');
555
		$check_not = (!$args['is_readable']?lang('not'):'');
556
	}
557
	if (isset($args['is_writable']))
558
	{
559
		$checks[] = lang('writable by the webserver');
560
		$check_not = (!$args['is_writable']?lang('not'):'');
561
	}
562
	if (isset($args['is_world_readable']))
563
	{
564
		$checks[] = lang('world readable');
565
		$check_not = (!$args['is_world_readable']?lang('not'):'');
566
	}
567
	if (isset($args['is_world_writable']))
568
	{
569
		$checks[] = lang('world writable');
570
		$check_not = (!$args['is_world_writable']?lang('not'):'');
571
	}
572
573
	if (isset($args['msg']) && ($msg = $args['msg']))
574
	{
575
		$msg .= ': '.$perms."<br />\n";
576
	}
577
	else
578
	{
579
		$msg = lang('Checking file-permissions of %1 for %2 %3: %4',$rel_name,$check_not,implode(', ',$checks),$perms)."<br />\n";
0 ignored issues
show
Unused Code introduced by
The call to lang() has too many arguments starting with $rel_name. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

579
		$msg = /** @scrutinizer ignore-call */ lang('Checking file-permissions of %1 for %2 %3: %4',$rel_name,$check_not,implode(', ',$checks),$perms)."<br />\n";

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
580
	}
581
	$extra_error_msg = '';
582
	if (isset($args['error']) && $args['error'])
583
	{
584
		$extra_error_msg = "<br />\n".$args['error'];
585
	}
586
	if (!file_exists($name))
587
	{
588
		echo '<div>'. $error_icon . '<span class="setup_error">' . $msg . lang('%1 does not exist !!!',$rel_name).$extra_error_msg."</span></div>\n";
589
		return False;
590
	}
591
	$warning = False;
592
	if (!$GLOBALS['run_by_webserver'] && (@$args['is_readable'] || @$args['is_writable']))
593
	{
594
		echo $warning_icon.' '.$msg. lang('Check can only be performed, if called via a webserver, as the user-id/-name of the webserver is not known.')."\n";
595
		unset($args['is_readable']);
596
		unset($args['is_writable']);
597
		$warning = True;
598
	}
599
	$Ok = True;
600
	if (isset($args['is_writable']) && is_writable($name) != $args['is_writable'])
601
	{
602
		echo '<div>'.$error_icon.' <span class="setup_error">'.$msg.' '.lang('%1 is %2%3 !!!',$rel_name,$args['is_writable']?lang('not').' ':'',lang('writable by the webserver')).$extra_error_msg."</span></div>\n";
603
		$Ok = False;
604
	}
605
	if (isset($args['is_readable']) && is_readable($name) != $args['is_readable'])
606
	{
607
		echo '<div>'.$error_icon.' <span class="setup_error">'.$msg.' '.lang('%1 is %2%3 !!!',$rel_name,$args['is_readable']?lang('not').' ':'',lang('readable by the webserver')).$extra_error_msg."</span></div>\n";
608
		$Ok = False;
609
	}
610
	if (!$is_windows && isset($args['is_world_readable']) && !(fileperms($name) & 04) == $args['is_world_readable'])
611
	{
612
		echo '<div>'.$error_icon.' <span class="setup_error">'.$msg.' '.lang('%1 is %2%3 !!!',$rel_name,$args['is_world_readable']?lang('not').' ':'',lang('world readable')).$extra_error_msg."</span></div>\n";
613
		$Ok = False;
614
	}
615
	if (!$is_windows && isset($args['is_world_writable']) && !(fileperms($name) & 02) == $args['is_world_writable'])
616
	{
617
		echo '<div>'.$error_icon.' <span class="setup_error">'.$msg.' '.lang('%1 is %2%3 !!!',$rel_name,$args['is_world_writable']?lang('not').' ':'',lang('world writable')).$extra_error_msg."</span></div>\n";
618
		$Ok = False;
619
	}
620
	if ($Ok && !$warning && $verbose)
621
	{
622
		echo $passed_icon.' '.$msg;
623
	}
624
	if ($Ok && @$args['recursiv'] && is_dir($name))
625
	{
626
		if ($verbose)
627
		{
628
			@set_time_limit(0);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for set_time_limit(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

628
			/** @scrutinizer ignore-unhandled */ @set_time_limit(0);

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...
629
			echo "<div class='setup_info'>" . lang('This might take a while, please wait ...')."</div>\n";
630
			flush();
631
		}
632
		@set_time_limit(0);
633
		$handle = @opendir($name);
634
		while($handle && ($file = readdir($handle)))
635
		{
636
			if ($file != '.' && $file != '..')
637
			{
638
				$Ok = $Ok && permission_check(($name!='.'?$name.'/':'').$file,$args,False);
639
			}
640
		}
641
		if ($handle) closedir($handle);
0 ignored issues
show
introduced by
$handle is of type false|resource, thus it always evaluated to false.
Loading history...
642
	}
643
	if ($verbose) echo "\n";
644
645
	return $Ok;
646
}
647
648
function mk_value($value)
649
{
650
	$matches = null;
651
	if (!preg_match('/^([0-9]+)([mk]+)$/i',$value,$matches)) return $value;
652
653
	return (strtolower($matches[2]) == 'm' ? 1024*1024 : 1024) * (int) $matches[1];
654
}
655
656
function php_ini_check($name,$args)
657
{
658
	global $passed_icon, $error_icon, $warning_icon, $is_windows;
659
660
	$safe_mode = ini_get('safe_mode');
661
662
	$ini_value = ini_get($name);
663
	$check = isset($args['check']) ? $args['check'] : '=';
664
	$verbose_value = isset($args['verbose_value']) ? $args['verbose_value'] : $args['value'];
665
	$ini_value_verbose = '';
666
	if ($verbose_value == 'On' || $verbose_value == 'Off')
667
	{
668
		$ini_value_verbose = ' = '.($ini_value ? 'On' : 'Off');
669
	}
670
	switch ($check)
671
	{
672
		case 'not set':
673
			$check = lang('not set');
674
			$result = !($ini_value & $args['value']);
675
			break;
676
		case 'set':
677
			$check = lang('set');
678
			$result = !!($ini_value & $args['value']);
679
			break;
680
		case '>=':
681
			$result = !$ini_value ||	// value not used, eg. no memory limit
682
			(int) mk_value($ini_value) >= (int) mk_value($args['value']);
683
			break;
684
		case 'contain':
685
			$check = lang('contain');
686
			$sep = $is_windows ? '/[; ]+/' : '/[: ]+/';
687
			$result = in_array($args['value'],preg_split($sep,$ini_value));
688
			break;
689
		case '!=':
690
			$check = lang('set and not');
691
			$result = !empty($ini_value) && $ini_value != $args['value'];
692
			break;
693
		case '=':
694
		default:
695
			$result = $ini_value == $args['value'];
696
			break;
697
	}
698
	if ($name == 'date.timezone')
699
	{
700
		try {
701
			$tz = new DateTimeZone($ini_value);
702
			unset($tz);
703
		}
704
		catch(Exception $e) {
705
			unset($e);
706
			$result = false;	// no valid timezone
707
		}
708
	}
709
	$msg = ' '.lang('Checking php.ini').": $name $check $verbose_value: <span class='setup_info'>ini_get('$name')='$ini_value'$ini_value_verbose</span>";
710
711
	if ($result)
712
	{
713
		echo "<div>".$passed_icon.$msg."</div>\n";
714
	}
715
	if (!$result)
716
	{
717
		if (isset($args['error']))
718
		{
719
			echo "<div>".$error_icon.' <span class="setup_error">'.$msg.'</span><div class="setup_info">'.$args['error']."</div></div>\n";
720
		}
721
		elseif (isset($args['warning']))
722
		{
723
			echo "<div>".$warning_icon.' <span class="setup_warning">'.$msg.'</span><div class="setup_info">'.$args['warning']."</div></div>\n";
724
		}
725
		elseif (!isset($args['safe_mode']))
726
		{
727
			echo "<div>".$warning_icon.' <span class="setup_warning">'.$msg.'</span><div class="setup_info">'.
728
				lang('%1 is needed by: %2.',$name,is_array($args['from']) ? implode(', ',$args['from']) : $args['from'])
0 ignored issues
show
Unused Code introduced by
The call to lang() has too many arguments starting with $name. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

728
				/** @scrutinizer ignore-call */ 
729
    lang('%1 is needed by: %2.',$name,is_array($args['from']) ? implode(', ',$args['from']) : $args['from'])

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
729
				."</div></div>\n";
730
		}
731
		if (isset($args['safe_mode']) && $safe_mode || @$args['change'])
0 ignored issues
show
introduced by
Consider adding parentheses for clarity. Current Interpretation: (IssetNode && $safe_mode) || @$args['change'], Probably Intended Meaning: IssetNode && ($safe_mode || @$args['change'])
Loading history...
732
		{
733
			if (!isset($args['warning']) && !isset($args['error']))
734
			{
735
				echo '<div>'.$error_icon.' <span class="setup_error">'.$msg.'</span></div>';
736
			}
737
			echo "<div class='setup_error'>\n";
738
			echo '*** '.lang('Please make the following change in your php.ini').' ('.get_php_ini().'): '.(@$args['safe_mode']?$args['safe_mode']:$args['change'])."<br />\n";
0 ignored issues
show
Bug introduced by
Are you sure get_php_ini() of type false|mixed can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

738
			echo '*** '.lang('Please make the following change in your php.ini').' ('./** @scrutinizer ignore-type */ get_php_ini().'): '.(@$args['safe_mode']?$args['safe_mode']:$args['change'])."<br />\n";
Loading history...
739
			echo '*** '.lang('AND reload your webserver, so the above changes take effect !!!')."</div>\n";
740
		}
741
	}
742
	return $result;
743
}
744
745
function get_php_ini()
746
{
747
	ob_start();
748
	phpinfo(INFO_GENERAL);
749
	$phpinfo = ob_get_contents();
750
	ob_end_clean();
751
752
	$found = null;
753
	return preg_match('/\(php.ini\).*<\/td><td[^>]*>([^ <]+)/',$phpinfo,$found) ? $found[1] : False;
754
}
755
756
function gd_check()
757
{
758
	global $passed_icon, $warning_icon;
759
760
	$available = (function_exists('imagecopyresampled')  || function_exists('imagecopyresized'));
761
762
	echo "<div>".($available ? $passed_icon : $warning_icon).' <span'.($available?'':' class="setup_warning"').'>'.lang('Checking for GD support...').': '.($available ? lang('True') : lang('False'))."</span></div>\n";
763
764
	if (!$available)
765
	{
766
		echo lang('Your PHP installation does not have appropriate GD support. You need gd library version 1.8 or newer to see Gantt charts in projects.')."\n";
767
	}
768
	return $available;
769
}
770
771
if ($run_by_webserver)
772
{
773
	$tpl_root = $GLOBALS['egw_setup']->html->setup_tpl_dir('setup');
774
	$setup_tpl = new Api\Framework\Template($tpl_root);
775
	$setup_tpl->set_file(array(
776
		'T_head' => 'head.tpl',
777
		'T_footer' => 'footer.tpl',
778
	));
779
	$ConfigDomain = $_REQUEST['ConfigDomain'];
780
	if (@$_GET['intro']) {
781
		if(($ConfigLang = setup::get_lang()))
782
		{
783
			$GLOBALS['egw_setup']->set_cookie('ConfigLang',$ConfigLang,(int) (time()+(1200*9)),'/');
784
		}
785
		$GLOBALS['egw_setup']->html->show_header(lang('Welcome to the EGroupware Installation'),False,'config');
786
		echo '<h1>'.lang('Welcome to the EGroupware Installation')."</h1>\n";
787
		if(!$ConfigLang)
788
		{
789
			echo '<p><form action="check_install.php?intro=1" method="Post">Please Select your language '.setup_html::lang_select(True,'en')."</form></p>\n";
790
		}
791
		echo '<p>'.lang('The first step in installing EGroupware is to ensure your environment has the necessary settings to correctly run the application.').'</p>';
792
		echo '<p>'.lang('We will now run a series of tests, which may take a few minutes.  Click the link below to proceed.').'</p>';
793
		echo '<h3><a href="check_install.php">'.lang('Run installation tests').'</a></h3>';
794
		echo '<p><a href="manageheader.php">'.lang('Skip the installation tests (not recommended)')."</a></p>\n";
795
		$setup_tpl->pparse('out','T_footer');
796
		exit;
797
	} else {
798
		$GLOBALS['egw_setup']->html->show_header(lang('Checking the EGroupware Installation'),False,'config',$ConfigDomain ? $ConfigDomain . '(' . @$GLOBALS['egw_domain'][$ConfigDomain]['db_type'] . ')' : '');
799
		echo '<h1>'.lang('Checking the EGroupware Installation')."</h1>\n";
800
		# echo "<pre style=\"text-align: left;\">\n";;
801
	}
802
}
803
else
804
{
805
	echo "Checking the EGroupware Installation\n";
806
	echo "====================================\n\n";
807
}
808
809
$Ok = True;
810
foreach ($sorted_checks as $name => $args)
811
{
812
	$check_ok = $args['func']($name,$args);
813
	$Ok = $Ok && $check_ok;
814
}
815
816
if ($run_by_webserver)
817
{
818
	# echo "</pre>\n";;
819
820
	if ($GLOBALS['egw_info']['setup']['stage']['header'] != 10)
821
	{
822
		if (!$Ok)
823
		{
824
			echo '<h3>'.lang('Please fix the above errors (%1) and warnings(%2)',$error_icon,$warning_icon)."</h3>\n";
825
			echo '<h3><a href="check_install.php">'.lang('Click here to re-run the installation tests')."</a></h3>\n";
826
			echo '<h3>'.lang('or %1Continue to the Header Admin%2','<a href="manageheader.php">','</a>')."</h3>\n";
827
		}
828
		else
829
		{
830
			echo '<h3><a href="manageheader.php">'.lang('Continue to the Header Admin')."</a></h3>\n";
831
		}
832
	}
833
	else
834
	{
835
		echo '<h3>';
836
		if (!$Ok)
837
		{
838
			echo lang('Please fix the above errors (%1) and warnings(%2)',$error_icon,$warning_icon).'. ';
839
		}
840
		echo '<br /><a href="'.str_replace('check_install.php','',@$_SERVER['HTTP_REFERER']).'">'.lang('Return to Setup')."</a></h3>\n";
841
	}
842
	$setup_tpl->pparse('out','T_footer');
843
	//echo "</body>\n</html>\n";
844
}
845