4 * SquirrelMail configtest script
6 * @copyright 2003-2012 The SquirrelMail Project Team
7 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
9 * @package squirrelmail
13 /************************************************************
14 * NOTE: you do not need to change this script! *
15 * If it throws errors you need to adjust your config. *
16 ************************************************************/
18 /** This is the configtest page */
19 define('PAGE_NAME', 'configtest');
21 // This script could really use some restructuring as it has grown quite rapidly
22 // but is not very 'clean'. Feel free to get some structure into this thing.
24 // force verbose error reporting and turn on display of errors, but not before
25 // getting their original values
26 $php_display_errors_original_value = ini_get('display_errors');
27 $php_error_reporting_original_value = ini_get('error_reporting');
28 error_reporting(E_ALL
);
29 ini_set('display_errors',1);
31 /** Blockcopy from init.php. Cleans globals. */
32 if ((bool) ini_get('register_globals') &&
33 strtolower(ini_get('register_globals'))!='off') {
35 * Remove all globals that are not reserved by PHP
36 * 'value' and 'key' are used by foreach. Don't unset them inside foreach.
38 foreach ($GLOBALS as $key => $value) {
40 case 'HTTP_POST_VARS':
44 case 'HTTP_COOKIE_VARS':
46 case 'HTTP_SERVER_VARS':
50 case 'HTTP_POST_FILES':
53 case 'HTTP_SESSION_VARS':
60 unset($GLOBALS[$key]);
63 // Unset variables used in foreach
64 unset($GLOBALS['key']);
65 unset($GLOBALS['value']);
70 * Displays error messages and warnings
71 * @param string $str message
72 * @param boolean $fatal fatal error or only warning
74 function do_err($str, $fatal = TRUE) {
75 global $IND, $warnings;
76 $level = $fatal ?
'FATAL ERROR:' : 'WARNING:';
77 echo '<p>'.$IND.'<font color="red"><b>' . $level . '</b></font> ' .$str. "</p>\n";
79 echo '</body></html>';
88 define('SM_PATH', '../');
89 /** load minimal function set */
90 require(SM_PATH
. 'include/constants.php');
91 require(SM_PATH
. 'functions/global.php');
92 require(SM_PATH
. 'functions/strings.php');
93 require(SM_PATH
. 'functions/files.php');
94 $SQM_INTERNAL_VERSION = explode('.', SM_VERSION
, 3);
95 $SQM_INTERNAL_VERSION[2] = intval($SQM_INTERNAL_VERSION[2]);
97 /** set default value in order to block remote access */
98 $allow_remote_configtest=false;
100 /** Load all configuration files before output begins */
102 /* load default configuration */
103 require(SM_PATH
. 'config/config_default.php');
104 /* reset arrays in default configuration */
105 $ldap_server = array();
109 $theme[0]['PATH'] = SM_PATH
. 'themes/default_theme.php';
110 $theme[0]['NAME'] = 'Default';
111 $aTemplateSet = array();
112 $aTemplateSet[0]['ID'] = 'default';
113 $aTemplateSet[0]['NAME'] = 'Default';
114 /* load site configuration */
115 if (file_exists(SM_PATH
. 'config/config.php')) {
116 require(SM_PATH
. 'config/config.php');
118 /* load local configuration overrides */
119 if (file_exists(SM_PATH
. 'config/config_local.php')) {
120 require(SM_PATH
. 'config/config_local.php');
124 * Include Compatibility plugin if available.
126 if (!$disable_plugins && file_exists(SM_PATH
. 'plugins/compatibility/functions.php'))
127 include_once(SM_PATH
. 'plugins/compatibility/functions.php');
130 global $disable_plugins;
131 $squirrelmail_plugin_hooks = array();
132 if (!$disable_plugins && file_exists(SM_PATH
. 'config/plugin_hooks.php')) {
133 require(SM_PATH
. 'config/plugin_hooks.php');
136 /** Warning counter */
140 $IND = str_repeat(' ',4);
143 * get_location starts session and must be run before output is started.
145 $test_location = get_location();
147 ?
><!DOCTYPE HTML
PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
148 "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">
151 <meta name
="robots" content
="noindex,nofollow">
152 <title
>SquirrelMail configtest
</title
>
155 <h1
>SquirrelMail configtest
</h1
>
157 <p
>This script will
try to check some aspects of your SquirrelMail configuration
158 and point you to errors whereever it can find them
. You need to go run
<tt
>conf
.pl
</tt
>
159 in the
<tt
>config
/</tt
> directory first before you run this script
.</p
>
163 $included = array_map('basename', get_included_files() );
164 if(!in_array('config.php', $included)) {
165 if(!file_exists(SM_PATH
. 'config/config.php')) {
166 do_err('Config file '.SM_PATH
. 'config/config.php does not exist!<br />'.
167 'You need to run <tt>conf.pl</tt> first.');
169 do_err('Could not read '.SM_PATH
.'config/config.php! Check file permissions.');
171 if(!in_array('strings.php', $included)) {
172 do_err('Could not include '.SM_PATH
.'functions/strings.php!<br />'.
173 'Check permissions on that file.');
176 /* Block remote use of script */
177 if (! $allow_remote_configtest) {
178 sqGetGlobalVar('REMOTE_ADDR',$client_ip,SQ_SERVER
);
179 sqGetGlobalVar('SERVER_ADDR',$server_ip,SQ_SERVER
);
181 if ((! isset($client_ip) ||
$client_ip!='127.0.0.1') &&
182 (! isset($client_ip) ||
! isset($server_ip) ||
$client_ip!=$server_ip)) {
183 do_err('Enable "Allow remote configtest" option in squirrelmail configuration in order to use this script.');
187 echo "<p><table>\n<tr><td>SquirrelMail version:</td><td><b>" . SM_VERSION
. "</b></td></tr>\n" .
188 '<tr><td>Config file version:</td><td><b>' . $config_version . "</b></td></tr>\n" .
189 '<tr><td>Config file last modified:</td><td><b>' .
190 date ('d F Y H:i:s', filemtime(SM_PATH
. 'config/config.php')) .
191 "</b></td></tr>\n</table>\n</p>\n\n";
193 /* check $config_version */
194 if ($config_version!='1.5.0') {
195 do_err('Configuration file version does not match required version. Please update your configuration file.');
199 /* checking PHP specs */
201 echo "Checking PHP configuration...<br />\n";
203 if(!check_php_version(4,1,0)) {
204 do_err('Insufficient PHP version: '. PHP_VERSION
. '! Minimum required: 4.1.0');
207 echo $IND . 'PHP version ' . PHP_VERSION
. ' OK. (You have: ' . phpversion() . ". Minimum: 4.1.0)<br />\n";
209 // try to determine information about the user and group the web server is running as
212 $webOwnerInfo = array('name' => 'N/A');
213 if (function_exists('posix_getuid'))
214 $webOwnerID = posix_getuid();
215 if ($webOwnerID === FALSE)
217 if ($webOwnerID !== 'N/A' && function_exists('posix_getpwuid'))
218 $webOwnerInfo = posix_getpwuid($webOwnerID);
220 $webOwnerInfo = array('name' => 'N/A');
222 $webGroupInfo = array('name' => 'N/A');
223 if (function_exists('posix_getgid'))
224 $webGroupID = posix_getgid();
225 if ($webGroupID === FALSE)
227 if ($webGroupID !== 'N/A' && function_exists('posix_getgrgid'))
228 $webGroupInfo = posix_getgrgid($webGroupID);
230 $webGroupInfo = array('name' => 'N/A');
232 echo $IND . 'Running as ' . $webOwnerInfo['name'] . '(' . $webOwnerID
233 . ') / ' . $webGroupInfo['name'] . '(' . $webGroupID . ")<br />\n";
235 echo $IND . 'display_errors: ' . $php_display_errors_original_value . " (overridden with 1 for this page only)<br />\n";
237 echo $IND . 'error_reporting: ' . $php_error_reporting_original_value . " (overridden with 2047 for this page only)<br />\n";
239 $safe_mode = ini_get('safe_mode');
241 //FIXME: should show that safe_mode is off when it is (this only shows the safe_mode setting when it's on) (also might be generally helpful to show things like open_basedir, too or even add phpinfo() output or a link to another script that has phpinfo()
242 echo $IND . 'safe_mode: ' . $safe_mode;
243 if (empty($prefs_dsn) ||
empty($addrbook_dsn))
244 echo ' (<font color="red">double check data and attachment directory ownership, etc!</font>)';
245 if (!empty($addrbook_dsn) ||
!empty($prefs_dsn) ||
!empty($addrbook_global_dsn))
246 echo ' (<font color="red">does PHP have access to database interface?</font>)';
248 $safe_mode_exec_dir = ini_get('safe_mode_exec_dir');
249 echo $IND . 'safe_mode_exec_dir: ' . $safe_mode_exec_dir . "<br />\n";
252 /* register_globals check: test for boolean false and any string that is not equal to 'off' */
254 if ((bool) ini_get('register_globals') &&
255 strtolower(ini_get('register_globals'))!='off') {
256 do_err('You have register_globals turned on. This is not an error, but it CAN be a security hazard. Consider turning register_globals off.', false);
260 /* variables_order check */
262 // FIXME(?): Hmm, how do we distinguish between when an ini setting is not available (ini_set() returns empty string) and when the administrator set the value to an empty string? The latter is sure to be highly rare, so for now, just assume that empty value means the setting isn't even available (could also check PHP version when this setting was implemented) although, we'll also warn the user if it is empty, with a non-fatal error
263 $variables_order = strtoupper(ini_get('variables_order'));
264 if (empty($variables_order))
265 do_err('Your variables_order setting seems to be empty. Make sure it is undefined in any PHP ini files, .htaccess files, etc. and not specifically set to an empty value or SquirrelMail may not function correctly', false);
266 else if (strpos($variables_order, 'G') === FALSE
267 ||
strpos($variables_order, 'P') === FALSE
268 ||
strpos($variables_order, 'C') === FALSE
269 ||
strpos($variables_order, 'S') === FALSE) {
270 do_err('Your variables_order setting is insufficient for SquirrelMail to function. It needs at least "GPCS", but you have it set to "' . htmlspecialchars($variables_order) . '"', true);
272 echo $IND . "variables_order OK: $variables_order.<br />\n";
276 /* gpc_order check (removed from PHP as of v5.0) */
278 if (!check_php_version(5)) {
279 // FIXME(?): Hmm, how do we distinguish between when an ini setting is not available (ini_set() returns empty string) and when the administrator set the value to an empty string? The latter is sure to be highly rare, so for now, just assume that empty value means the setting isn't even available (could also check PHP version when this setting was implemented) although, we'll also warn the user if it is empty, with a non-fatal error
280 $gpc_order = strtoupper(ini_get('gpc_order'));
281 if (empty($gpc_order))
282 do_err('Your gpc_order setting seems to be empty. Make sure it is undefined in any PHP ini files, .htaccess files, etc. and not specifically set to an empty value or SquirrelMail may not function correctly', false);
283 else if (strpos($gpc_order, 'G') === FALSE
284 ||
strpos($gpc_order, 'P') === FALSE
285 ||
strpos($gpc_order, 'C') === FALSE) {
286 do_err('Your gpc_order setting is insufficient for SquirrelMail to function. It needs to be set to "GPC", but you have it set to "' . htmlspecialchars($gpc_order) . '"', true);
288 echo $IND . "gpc_order OK: $gpc_order.<br />\n";
293 /* check PHP extensions */
295 $php_exts = array('session','pcre');
296 $diff = array_diff($php_exts, get_loaded_extensions());
298 do_err('Required PHP extensions missing: '.implode(', ',$diff) );
301 echo $IND . "PHP extensions OK. Dynamic loading is ";
303 if (!(bool)ini_get('enable_dl') ||
(bool)ini_get('safe_mode')) {
304 echo "disabled.<br />\n";
306 echo "enabled.<br />\n";
310 /* dangerous php settings */
312 * mbstring.func_overload allows to replace original string and regexp functions
313 * with their equivalents from php mbstring extension. It causes problems when
314 * scripts analyze 8bit strings byte after byte or use 8bit strings in regexp tests.
315 * Setting can be controlled in php.ini (php 4.2.0), webserver config (php 4.2.0)
316 * and .htaccess files (php 4.3.5).
318 if (function_exists('mb_internal_encoding') &&
319 check_php_version(4,2,0) &&
320 (int)ini_get('mbstring.func_overload')!=0) {
321 $mb_error='You have enabled mbstring overloading.'
322 .' It can cause problems with SquirrelMail scripts that rely on single byte string functions.';
327 * Do not use SquirrelMail with magic_quotes_* on.
329 if ( (function_exists('get_magic_quotes_runtime') && @get_magic_quotes_runtime
()) ||
330 (function_exists('get_magic_quotes_gpc') && @get_magic_quotes_gpc
()) ||
331 ( (bool) ini_get('magic_quotes_sybase') && ini_get('magic_quotes_sybase') != 'off' )
333 $magic_quotes_warning='You have enabled any one of <tt>magic_quotes_runtime</tt>, '
334 .'<tt>magic_quotes_gpc</tt> or <tt>magic_quotes_sybase</tt> in your PHP '
335 .'configuration. We recommend all those settings to be off. SquirrelMail '
336 .'may work with them on, but when experiencing stray backslashes in your mail '
337 .'or other strange behaviour, it may be advisable to turn them off.';
338 do_err($magic_quotes_warning,false);
341 if (ini_get('short_open_tag') == 0) {
342 $short_open_tag_warning = 'You have configured PHP not to allow short tags '
343 . '(<tt>short_open_tag=off</tt>). This shouldn\'t be a problem with '
344 . 'SquirrelMail or any plugin coded coded according to the '
345 . 'SquirrelMail Coding Guidelines, but if you experience problems with '
346 . 'PHP code being displayed in some of the pages and changing setting '
347 . 'to "on" solves the problem, please file a bug report against the '
348 . 'failing plugin. The correct contact information is most likely '
349 . 'to be found in the plugin documentation.';
350 do_err($short_open_tag_warning, false);
354 /* check who the web server is running as if possible */
356 if ($process_info = get_process_owner_info()) {
357 echo $IND . 'Web server is running as user: ' . $process_info['name'] . ' (' . $process_info['uid'] . ")<br />\n";
358 //echo $IND . 'Web server is running as effective user: ' . $process_info['ename'] . ' (' . $process_info['euid'] . ")<br />\n";
359 echo $IND . 'Web server is running as group: ' . $process_info['group'] . ' (' . $process_info['gid'] . ")<br />\n";
360 //echo $IND . 'Web server is running as effective group: ' . $process_info['egroup'] . ' (' . $process_info['egid'] . ")<br />\n";
366 echo "Checking paths...<br />\n";
368 if(!file_exists($data_dir)) {
369 // data_dir is not that important in db_setups.
370 if (!empty($prefs_dsn)) {
371 $data_dir_error = "Data dir ($data_dir) does not exist!\n";
372 echo $IND .'<font color="red"><b>ERROR:</b></font> ' . $data_dir_error;
374 do_err("Data dir ($data_dir) does not exist!");
377 // don't check if errors
378 if(!isset($data_dir_error) && !is_dir($data_dir)) {
379 if (!empty($prefs_dsn)) {
380 $data_dir_error = "Data dir ($data_dir) is not a directory!\n";
381 echo $IND . '<font color="red"><b>ERROR:</b></font> ' . $data_dir_error;
383 do_err("Data dir ($data_dir) is not a directory!");
386 // datadir should be executable - but no clean way to test on that
387 if(!isset($data_dir_error) && !sq_is_writable($data_dir)) {
388 if (!empty($prefs_dsn)) {
389 $data_dir_error = "Data dir ($data_dir) is not writable!\n";
390 echo $IND . '<font color="red"><b>ERROR:</b></font> ' . $data_dir_error;
392 do_err("Data dir ($data_dir) is not writable!");
396 if (isset($data_dir_error)) {
397 echo " Some plugins might need access to data directory.<br />\n";
399 // todo_ornot: actually write something and read it back.
400 echo $IND . "Data dir OK.<br />\n";
403 if($data_dir == $attachment_dir) {
404 echo $IND . "Attachment dir is the same as data dir.<br />\n";
405 if (isset($data_dir_error)) {
406 do_err($data_dir_error);
409 if(!file_exists($attachment_dir)) {
410 do_err("Attachment dir ($attachment_dir) does not exist!");
412 if (!is_dir($attachment_dir)) {
413 do_err("Attachment dir ($attachment_dir) is not a directory!");
415 if (!sq_is_writable($attachment_dir)) {
416 do_err("I cannot write to attachment dir ($attachment_dir)!");
418 echo $IND . "Attachment dir OK.<br />\n";
422 echo "Checking plugins...<br />\n";
424 /* check plugins and themes */
425 //FIXME: check requirements given in plugin _info() function, such as required PHP extensions, Pear packages, other plugins, SM version, etc see development docs for list of returned info from that function
426 //FIXME: update this list with most recent contents of the Obsolete category - I think it has changed recently
427 $bad_plugins = array(
428 'attachment_common', // Integrated into SquirrelMail 1.2 core
429 'auto_prune_sent', // Obsolete: See Proon Automatic Folder Pruning plugin
430 'compose_new_window', // Integrated into SquirrelMail 1.4 core
431 'delete_move_next', // Integrated into SquirrelMail 1.5 core
432 'disk_quota', // Obsolete: See Check Quota plugin
433 'email_priority', // Integrated into SquirrelMail 1.2 core
434 'emoticons', // Obsolete: See HTML Mail plugin
435 'focus_change', // Integrated into SquirrelMail 1.2 core
436 'folder_settings', // Integrated into SquirrelMail 1.5.1 core
437 'global_sql_addressbook', // Integrated into SquirrelMail 1.4 core
438 'hancock', // Not Working: See Random Signature Taglines plugin
439 'msg_flags', // Integrated into SquirrelMail 1.5.1 core
440 'message_source', // Added to SquirrelMail 1.4 Core Plugins (message_details)
441 'motd', // Integrated into SquirrelMail 1.2 core
442 'paginator', // Integrated into SquirrelMail 1.2 core
443 'printer_friendly', // Integrated into SquirrelMail 1.2 core
444 'procfilter', // Obsolete: See Server Side Filter plugin
445 'redhat_php_cgi_fix', // Integrated into SquirrelMail 1.1.1 core
446 'send_to_semicolon', // Integrated into SquirrelMail 1.4.1 core
447 'spamassassin', // Not working beyond SquirrelMail 1.2.7: See Spamassassin SpamFilter (Frontend) v2 plugin
448 'sqcalendar', // Added to SquirrelMail 1.2 Core Plugins (calendar)
449 'sqclock', // Integrated into SquirrelMail 1.2 core
450 'sql_squirrel_logger', // Obsolete: See Squirrel Logger plugin
451 'tmda', // Obsolete: See TMDA Tools plugin
452 'vacation', // Obsolete: See Vacation Local plugin
453 'view_as_html', // Integrated into SquirrelMail 1.5.1 core
454 'xmailer' // Integrated into SquirrelMail 1.2 core
457 if (isset($plugins[0])) {
458 foreach($plugins as $plugin) {
459 if(!file_exists(SM_PATH
.'plugins/'.$plugin)) {
460 do_err('You have enabled the <i>'.$plugin.'</i> plugin, but I cannot find it.', FALSE);
461 } elseif (!is_readable(SM_PATH
.'plugins/'.$plugin.'/setup.php')) {
462 do_err('You have enabled the <i>'.$plugin.'</i> plugin, but I cannot locate or read its setup.php file.', FALSE);
463 } elseif (in_array($plugin, $bad_plugins)) {
464 do_err('You have enabled the <i>'.$plugin.'</i> plugin, which causes problems with this version of SquirrelMail. Please check the ReleaseNotes or other documentation for more information.', false);
469 // load plugin functions
470 include_once(SM_PATH
. 'functions/plugin.php');
472 // turn on output buffering in order to prevent output of new lines
474 foreach ($plugins as $name) {
477 // get output and remove whitespace
478 $output = trim(ob_get_contents());
480 // if plugin outputs more than newlines and spacing, stop script execution.
481 if (!empty($output)) {
482 $plugin_load_error = 'Some output was produced when plugin <i>' . $name . '</i> was loaded. Usually this means there is an error in the plugin\'s setup or configuration file. The output was: '.htmlspecialchars($output);
483 do_err($plugin_load_error);
490 * Check the contents of the static plugin hooks array file against
491 * the plugin setup file, which may have changed in an upgrade, etc.
492 * This helps remind admins to re-run the configuration utility when
493 * a plugin has been changed or upgraded.
495 $static_squirrelmail_plugin_hooks = $squirrelmail_plugin_hooks;
496 $squirrelmail_plugin_hooks = array();
497 foreach ($plugins as $name) {
498 $function = "squirrelmail_plugin_init_$name";
499 if (function_exists($function)) {
502 // now iterate through each hook and make sure the
503 // plugin is registered on the correct ones in the
504 // static plugin configuration file
506 foreach ($squirrelmail_plugin_hooks as $hook_name => $hooked_plugins)
507 foreach ($hooked_plugins as $hooked_plugin => $hooked_function)
508 if ($hooked_plugin == $name
509 && (empty($static_squirrelmail_plugin_hooks[$hook_name][$hooked_plugin])
510 ||
$static_squirrelmail_plugin_hooks[$hook_name][$hooked_plugin] != $hooked_function))
511 do_err('The plugin <i>' . $name . '</i> is supposed to be registered on the <i>' . $hook_name . '</i> hook, but it is not. You need to re-run the configuration utility and re-save your configuration file.', FALSE);
514 $squirrelmail_plugin_hooks = $static_squirrelmail_plugin_hooks;
518 * Print plugin versions
520 echo $IND . "Plugin versions...<br />\n";
521 foreach ($plugins as $name) {
522 $plugin_version = get_plugin_version($name);
523 $english_name = get_plugin_requirement($name, 'english_name');
524 echo $IND . $IND . (empty($english_name) ?
$name . ' ' : $english_name . ' (' . $name . ') ') . (empty($plugin_version) ?
'??' : $plugin_version) . "<br />\n";
526 // check if this plugin has any other plugin
527 // dependencies and if they are satisfied
529 $failed_dependencies = check_plugin_dependencies($name);
530 if ($failed_dependencies === SQ_INCOMPATIBLE
) {
531 do_err($name . ' is NOT COMPATIBLE with this version of SquirrelMail', FALSE);
533 else if (is_array($failed_dependencies)) {
534 $missing_plugins = '';
535 $incompatible_plugins = '';
536 foreach ($failed_dependencies as $depend_name => $depend_requirements) {
537 if ($depend_requirements['version'] == SQ_INCOMPATIBLE
)
538 $incompatible_plugins .= ', ' . $depend_name;
540 $missing_plugins .= ', ' . $depend_name . ' (version ' . $depend_requirements['version'] . ', ' . ($depend_requirements['activate'] ?
'must be activated' : 'need not be activated') . ')';
542 $error_string = (!empty($incompatible_plugins) ?
$name . ' cannot be activated at the same time as the following plugins: ' . trim($incompatible_plugins, ', ') : '')
543 . (!empty($missing_plugins) ?
(!empty($incompatible_plugins) ?
'. ' . $name . ' is also ' : $name . ' is ') . 'missing some dependencies: ' . trim($missing_plugins, ', ') : '');
544 do_err($error_string, FALSE);
551 * This hook was added in 1.5.2 and 1.4.10. Each plugins should print an error
552 * message and return TRUE if there are any errors in its setup/configuration.
554 $plugin_err = boolean_hook_function('configtest', $null, 1);
556 do_err('Some plugin tests failed.');
558 echo $IND . "Plugins OK.<br />\n";
561 echo $IND . "Plugins are not enabled in config.<br />\n";
563 foreach($theme as $thm) {
564 if(!file_exists($thm['PATH'])) {
565 do_err('You have enabled the <i>'.$thm['NAME'].'</i> theme but I cannot find it ('.$thm['PATH'].').', FALSE);
566 } elseif(!is_readable($thm['PATH'])) {
567 do_err('You have enabled the <i>'.$thm['NAME'].'</i> theme but I cannot read it ('.$thm['PATH'].').', FALSE);
571 echo $IND . "Themes OK.<br />\n";
573 if ( $squirrelmail_default_language != 'en_US' ) {
574 $loc_path = SM_PATH
.'locale/'.$squirrelmail_default_language.'/LC_MESSAGES/squirrelmail.mo';
575 if( ! file_exists( $loc_path ) ) {
576 do_err('You have set <i>' . $squirrelmail_default_language .
577 '</i> as your default language, but I cannot find this translation (should be '.
578 'in <tt>' . $loc_path . '</tt>). Please note that you have to download translations '.
579 'separately from the main SquirrelMail package.', FALSE);
580 } elseif ( ! is_readable( $loc_path ) ) {
581 do_err('You have set <i>' . $squirrelmail_default_language .
582 '</i> as your default language, but I cannot read this translation (file '.
583 'in <tt>' . $loc_path . '</tt> unreadable).', FALSE);
585 echo $IND . "Default language OK.<br />\n";
588 echo $IND . "Default language OK.<br />\n";
591 echo $IND . "Base URL detected as: <tt>" . htmlspecialchars($test_location) .
592 "</tt> (location base " . (empty($config_location_base) ?
'autodetected' : 'set to <tt>' .
593 htmlspecialchars($config_location_base)."</tt>") . ")<br />\n";
595 /* check minimal requirements for other security options */
598 if($use_smtp_tls == 1 ||
$use_imap_tls == 1) {
599 if(!check_php_version(4,3,0)) {
600 do_err('You need at least PHP 4.3.0 for SMTP/IMAP TLS!');
602 if(!extension_loaded('openssl')) {
603 do_err('You need the openssl PHP extension to use SMTP/IMAP TLS!');
606 /* starttls extensions */
607 if($use_smtp_tls === 2 ||
$use_imap_tls === 2) {
608 if (! function_exists('stream_socket_enable_crypto')) {
609 do_err('If you want to use STARTTLS extension, you need stream_socket_enable_crypto() function from PHP 5.1.0 and newer.');
613 if ($smtp_auth_mech=='digest-md5' ||
$imap_auth_mech =='digest-md5') {
614 if (!extension_loaded('xml')) {
615 do_err('You need the PHP XML extension to use Digest-MD5 authentication!');
619 /* check outgoing mail */
621 echo "Checking outgoing mail service....<br />\n";
624 // is_executable also checks for existance, but we want to be as precise as possible with the errors
625 if(!file_exists($sendmail_path)) {
626 do_err("Location of sendmail program incorrect ($sendmail_path)!");
628 if(!is_executable($sendmail_path)) {
629 do_err("I cannot execute the sendmail program ($sendmail_path)!");
632 echo $IND . "sendmail OK<br />\n";
634 $stream = fsockopen( ($use_smtp_tls==1?
'tls://':'').$smtpServerAddress, $smtpPort,
635 $errorNumber, $errorString);
637 do_err("Error connecting to SMTP server \"$smtpServerAddress:$smtpPort\".".
638 "Server error: ($errorNumber) ".htmlspecialchars($errorString));
641 // check for SMTP code; should be 2xx to allow us access
642 $smtpline = fgets($stream, 1024);
643 if(((int) $smtpline{0}) > 3) {
644 do_err("Error connecting to SMTP server. Server error: ".
645 htmlspecialchars($smtpline));
648 /* smtp starttls checks */
649 if ($use_smtp_tls===2) {
650 // if something breaks, script should close smtp connection on exit.
653 // format EHLO argument correctly if needed
655 if (preg_match('/^\d+\.\d+\.\d+\.\d+$/', $client_ip))
656 $helohost = '[' . $client_ip . ']';
657 else // some day might add IPv6 here
658 $helohost = $client_ip;
662 fwrite($stream,"EHLO $helohost\r\n");
666 while ($line=fgets($stream, 1024)){
667 if (preg_match("/^250(-|\s)(\S*)\s+(\S.*)/",$line,$match)||
668 preg_match("/^250(-|\s)(\S*)\s+/",$line,$match)) {
669 if (!isset($match[3])) {
670 // simple one word extension
671 $ehlo[strtoupper($match[2])]='';
673 // ehlo-keyword + ehlo-param
674 $ehlo[strtoupper($match[2])]=trim($match[3]);
676 if ($match[1]==' ') {
688 do_err('SMTP EHLO failed. You need ESMTP support for SMTP STARTTLS');
689 } elseif (!array_key_exists('STARTTLS',$ehlo)) {
690 do_err('STARTTLS support is not declared by SMTP server.');
693 fwrite($stream,"STARTTLS\r\n");
694 $starttls_response=fgets($stream, 1024);
695 if ($starttls_response[0]!=2) {
696 $starttls_cmd_err = 'SMTP STARTTLS failed. Server replied: '
697 .htmlspecialchars($starttls_response);
698 do_err($starttls_cmd_err);
699 } elseif(! stream_socket_enable_crypto($stream,true,STREAM_CRYPTO_METHOD_TLS_CLIENT
)) {
700 do_err('Failed to enable encryption on SMTP STARTTLS connection.');
702 echo $IND . "SMTP STARTTLS extension looks OK.<br />\n";
704 // According to RFC we should second ehlo call here.
707 fputs($stream, 'QUIT');
709 echo $IND . 'SMTP server OK (<tt><small>'.
710 trim(htmlspecialchars($smtpline))."</small></tt>)<br />\n";
712 /* POP before SMTP */
713 if($pop_before_smtp) {
714 if (empty($pop_before_smtp_host)) $pop_before_smtp_host = $smtpServerAddress;
715 $stream = fsockopen($pop_before_smtp_host, 110, $err_no, $err_str);
717 do_err("Error connecting to POP Server ($pop_before_smtp_host:110) "
718 . $err_no . ' : ' . htmlspecialchars($err_str));
721 $tmp = fgets($stream, 1024);
722 if (substr($tmp, 0, 3) != '+OK') {
723 do_err("Error connecting to POP Server ($pop_before_smtp_host:110)"
724 . ' '.htmlspecialchars($tmp));
726 fputs($stream, 'QUIT');
728 echo $IND . "POP-before-SMTP OK.<br />\n";
733 * Check the IMAP server
735 echo "Checking IMAP service....<br />\n";
737 /** Can we open a connection? */
738 $stream = fsockopen( ($use_imap_tls==1?
'tls://':'').$imapServerAddress, $imapPort,
739 $errorNumber, $errorString);
741 do_err("Error connecting to IMAP server \"$imapServerAddress:$imapPort\".".
742 "Server error: ($errorNumber) ".
743 htmlspecialchars($errorString));
746 /** Is the first response 'OK'? */
747 $imapline = fgets($stream, 1024);
748 if(substr($imapline, 0,4) != '* OK') {
749 do_err('Error connecting to IMAP server. Server error: '.
750 htmlspecialchars($imapline));
753 echo $IND . 'IMAP server ready (<tt><small>'.
754 htmlspecialchars(trim($imapline))."</small></tt>)<br />\n";
756 /** Check capabilities */
757 fputs($stream, "A001 CAPABILITY\r\n");
759 while ($line=fgets($stream, 1024)){
760 if (preg_match("/A001.*/",$line)) {
767 /* don't display capabilities before STARTTLS */
768 if ($use_imap_tls===2 && stristr($capline, 'STARTTLS') === false) {
769 do_err('Your server doesn\'t support STARTTLS.');
770 } elseif($use_imap_tls===2) {
771 /* try starting starttls */
772 fwrite($stream,"A002 STARTTLS\r\n");
773 $starttls_line=fgets($stream, 1024);
774 if (! preg_match("/^A002 OK.*/i",$starttls_line)) {
775 $imap_starttls_err = 'IMAP STARTTLS failed. Server replied: '
776 .htmlspecialchars($starttls_line);
777 do_err($imap_starttls_err);
778 } elseif (! stream_socket_enable_crypto($stream,true,STREAM_CRYPTO_METHOD_TLS_CLIENT
)) {
779 do_err('Failed to enable encryption on IMAP connection.');
781 echo $IND . "IMAP STARTTLS extension looks OK.<br />\n";
784 // get new capability line
785 fwrite($stream,"A003 CAPABILITY\r\n");
787 while ($line=fgets($stream, 1024)){
788 if (preg_match("/A003.*/",$line)) {
796 echo $IND . 'Capabilities: <tt>'.htmlspecialchars($capline)."</tt><br />\n";
798 if($imap_auth_mech == 'login' && stristr($capline, 'LOGINDISABLED') !== FALSE) {
799 do_err('Your server doesn\'t allow plaintext logins. '.
800 'Try enabling another authentication mechanism like CRAM-MD5, DIGEST-MD5 or TLS-encryption '.
801 'in the SquirrelMail configuration.', FALSE);
804 if (stristr($capline, 'XMAGICTRASH') !== false) {
805 $magic_trash = 'It looks like IMAP_MOVE_EXPUNGE_TO_TRASH option is turned on '
806 .'in your Courier IMAP configuration. Courier does not provide tools that '
807 .'allow to detect folder used for Trash or commands are not documented. '
808 .'SquirrelMail can\'t detect special trash folder. SquirrelMail manages '
809 .'all message deletion or move operations internally and '
810 .'IMAP_MOVE_EXPUNGE_TO_TRASH option can cause errors in message and '
811 .'folder management operations. Please turn off IMAP_MOVE_EXPUNGE_TO_TRASH '
812 .'option in Courier imapd configuration.';
813 do_err($magic_trash,false);
816 /* add warning about IMAP delivery */
817 if (stristr($capline, 'XCOURIEROUTBOX') !== false) {
818 $courier_outbox = 'OUTBOX setting is enabled in your Courier imapd '
819 .'configuration. SquirrelMail uses standard SMTP protocol or sendmail '
820 .'binary to send emails. Courier IMAP delivery method is not supported'
821 .' and can create duplicate email messages.';
822 do_err($courier_outbox,false);
825 /** OK, close connection */
826 fputs($stream, "A004 LOGOUT\r\n");
829 echo "Checking internationalization (i18n) settings...<br />\n";
830 echo "$IND gettext - ";
831 if (function_exists('gettext')) {
832 echo 'Gettext functions are available.'
833 .' On some systems you must have appropriate system locales compiled.'
836 /* optional setlocale() tests. Should work only on glibc systems. */
837 if (sqgetGlobalVar('testlocales',$testlocales,SQ_GET
)) {
838 include_once(SM_PATH
. 'include/languages.php');
839 echo $IND . $IND . 'Testing translations:<br>';
840 foreach ($languages as $lang_code => $lang_data) {
841 /* don't test aliases */
842 if (isset($lang_data['NAME'])) {
843 /* locale can be $lang_code or $lang_data['LOCALE'] */
844 if (isset($lang_data['LOCALE'])) {
845 $setlocale = $lang_data['LOCALE'];
847 $setlocale = $lang_code;
849 /* prepare information about tested locales */
850 if (is_array($setlocale)) {
851 $display_locale = implode(', ',$setlocale);
852 $locale_count = count($setlocale);
854 $display_locale = $setlocale;
857 $tested_locales_msg = 'Tested '.htmlspecialchars($display_locale).' '
858 .($locale_count>1 ?
'locales':'locale'). '.';
860 echo $IND . $IND .$IND . $lang_data['NAME'].' (' .$lang_code. ') - ';
861 $retlocale = sq_setlocale(LC_ALL
,$setlocale);
862 if (is_bool($retlocale)) {
863 echo '<font color="red">unsupported</font>. ';
864 echo $tested_locales_msg;
868 .' setlocale() returned "'.htmlspecialchars($retlocale).'"';
873 echo $IND . $IND . '<a href="configtest.php">Don\'t test translations</a>';
875 echo $IND . $IND . '<a href="configtest.php?testlocales=1">Test translations</a>. '
876 .'This test is not accurate and might work only on some systems.'
880 /* end of translation tests */
882 echo 'Gettext functions are unavailable.'
883 .' SquirrelMail will use slower internal gettext functions.'
886 echo "$IND mbstring - ";
887 if (function_exists('mb_detect_encoding')) {
888 echo "Mbstring functions are available.<br />\n";
890 echo 'Mbstring functions are unavailable.'
891 ." Japanese translation won't work.<br />\n";
893 echo "$IND recode - ";
894 if (function_exists('recode')) {
895 echo "Recode functions are available.<br />\n";
896 } elseif (isset($use_php_recode) && $use_php_recode) {
897 echo "Recode functions are unavailable.<br />\n";
898 do_err('Your configuration requires recode support, but recode support is missing.');
900 echo "Recode functions are unavailable.<br />\n";
902 echo "$IND iconv - ";
903 if (function_exists('iconv')) {
904 echo "Iconv functions are available.<br />\n";
905 } elseif (isset($use_php_iconv) && $use_php_iconv) {
906 echo "Iconv functions are unavailable.<br />\n";
907 do_err('Your configuration requires iconv support, but iconv support is missing.');
909 echo "Iconv functions are unavailable.<br />\n";
911 // same test as in include/init.php + date_default_timezone_set check
912 echo "$IND timezone - ";
913 if ( (!ini_get('safe_mode')) ||
function_exists('date_default_timezone_set') ||
914 !strcmp(ini_get('safe_mode_allowed_env_vars'),'') ||
915 preg_match('/^([\w_]+,)*TZ/', ini_get('safe_mode_allowed_env_vars')) ) {
916 echo "Webmail users can change their time zone settings. \n";
918 echo "Webmail users can't change their time zone settings. \n";
920 if (isset($_ENV['TZ'])) {
921 echo 'Default time zone is '.htmlspecialchars($_ENV['TZ']);
923 echo 'Current time zone is '.date('T');
928 echo "Checking database functions...<br />\n";
929 if($addrbook_dsn ||
$prefs_dsn ||
$addrbook_global_dsn) {
930 @include_once
('DB.php');
931 if (class_exists('DB')) {
932 echo "$IND PHP Pear DB support is present.<br />\n";
934 'dbase' => 'dbase_open',
935 'fbsql' => 'fbsql_connect',
936 'interbase' => 'ibase_connect',
937 'informix' => 'ifx_connect',
938 'msql' => 'msql_connect',
939 'mssql' => 'mssql_connect',
940 'mysql' => 'mysql_connect',
941 'mysqli' => 'mysqli_connect',
942 'oci8' => 'ocilogon',
943 'odbc' => 'odbc_connect',
944 'pgsql' => 'pg_connect',
945 'sqlite' => 'sqlite_open',
946 'sybase' => 'sybase_connect'
951 $dsns['preferences'] = $prefs_dsn;
954 $dsns['addressbook'] = $addrbook_dsn;
956 if($addrbook_global_dsn) {
957 $dsns['global addressbook'] = $addrbook_global_dsn;
960 foreach($dsns as $type => $dsn) {
961 $aDsn = explode(':', $dsn);
962 $dbtype = array_shift($aDsn);
964 if(isset($db_functions[$dbtype]) && function_exists($db_functions[$dbtype])) {
965 echo "$IND$dbtype database support present.<br />\n";
966 } elseif(!(bool)ini_get('enable_dl') ||
(bool)ini_get('safe_mode')) {
967 do_err($dbtype.' database support not present!');
970 do_err($dbtype.' database support not present or not configured!
971 Trying to dynamically load '.$dbtype.' extension.
972 Please note that it is advisable to not rely on dynamic loading of extensions.', FALSE);
976 // now, test this interface:
978 $dbh = DB
::connect($dsn, true);
979 if (DB
::isError($dbh)) {
980 do_err('Database error: '. htmlspecialchars(DB
::errorMessage($dbh)) .
981 ' in ' .$type .' DSN.');
984 echo "$IND$type database connect successful.<br />\n";
987 $db_error='Required PHP PEAR DB support is not available.'
988 .' Is PEAR installed and is the include path set correctly to find <tt>DB.php</tt>?'
989 .' The include path is now: "<tt>' . ini_get('include_path') . '</tt>".';
993 echo $IND."not using database functionality.<br />\n";
997 echo "Checking LDAP functions...<br />\n";
998 if( empty($ldap_server) ) {
999 echo $IND."not using LDAP functionality.<br />\n";
1001 if ( !function_exists('ldap_connect') ) {
1002 do_err('Required LDAP support is not available.');
1004 echo "$IND LDAP support present.<br />\n";
1005 foreach ( $ldap_server as $param ) {
1007 $linkid = @ldap_connect
($param['host'], (empty($param['port']) ?
389 : $param['port']) );
1010 echo "$IND LDAP connect to ".$param['host']." successful: ".$linkid."<br />\n";
1012 if ( !empty($param['protocol']) &&
1013 !ldap_set_option($linkid, LDAP_OPT_PROTOCOL_VERSION
, $param['protocol']) ) {
1014 do_err('Unable to set LDAP protocol');
1017 if ( empty($param['binddn']) ) {
1018 $bind = @ldap_bind
($linkid);
1020 $bind = @ldap_bind
($linkid, $param['binddn'], $param['bindpw']);
1024 echo "$IND LDAP Bind Successful <br />";
1026 do_err('Unable to Bind to LDAP Server');
1029 @ldap_close
($linkid);
1031 do_err('Connection to LDAP failed');
1037 echo '<hr width="75%" align="center">';
1038 echo '<h2 align="center">Summary</h2>';
1039 $footer = '<hr width="75%" align="center">';
1041 echo '<p>No fatal errors were found, but there was at least 1 warning. Please check the flagged issue(s) carefully, as correcting them may prevent erratic, undefined, or incorrect behavior (or flat out breakage).</p>';
1045 <p
>Congratulations
, your SquirrelMail setup looks fine to me
!</p
>
1047 <p
><a href
="login.php">Login now
</a
></p
>