4 * SquirrelMail configtest script
6 * @copyright © 2003-2007 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 */
25 error_reporting(E_ALL
);
26 ini_set('display_errors',1);
28 /** Blockcopy from init.php. Cleans globals. */
29 if ((bool) ini_get('register_globals') &&
30 strtolower(ini_get('register_globals'))!='off') {
32 * Remove all globals that are not reserved by PHP
33 * 'value' and 'key' are used by foreach. Don't unset them inside foreach.
35 foreach ($GLOBALS as $key => $value) {
37 case 'HTTP_POST_VARS':
41 case 'HTTP_COOKIE_VARS':
43 case 'HTTP_SERVER_VARS':
47 case 'HTTP_POST_FILES':
50 case 'HTTP_SESSION_VARS':
57 unset($GLOBALS[$key]);
60 // Unset variables used in foreach
61 unset($GLOBALS['key']);
62 unset($GLOBALS['value']);
67 * Displays error messages and warnings
68 * @param string $str message
69 * @param boolean $fatal fatal error or only warning
71 function do_err($str, $fatal = TRUE) {
72 global $IND, $warnings;
73 $level = $fatal ?
'FATAL ERROR:' : 'WARNING:';
74 echo '<p>'.$IND.'<font color="red"><b>' . $level . '</b></font> ' .$str. "</p>\n";
76 echo '</body></html>';
85 define('SM_PATH', '../');
86 /** load minimal function set */
87 require(SM_PATH
. 'include/constants.php');
88 require(SM_PATH
. 'functions/global.php');
89 require(SM_PATH
. 'functions/strings.php');
90 require(SM_PATH
. 'functions/files.php');
91 $SQM_INTERNAL_VERSION = explode('.', SM_VERSION
, 3);
92 $SQM_INTERNAL_VERSION[2] = intval($SQM_INTERNAL_VERSION[2]);
94 /** set default value in order to block remote access */
95 $allow_remote_configtest=false;
97 /** Load all configuration files before output begins */
99 /* load default configuration */
100 require(SM_PATH
. 'config/config_default.php');
101 /* reset arrays in default configuration */
102 $ldap_server = array();
106 $theme[0]['PATH'] = SM_PATH
. 'themes/default_theme.php';
107 $theme[0]['NAME'] = 'Default';
108 $aTemplateSet = array();
109 $aTemplateSet[0]['ID'] = 'default';
110 $aTemplateSet[0]['NAME'] = 'Default';
111 /* load site configuration */
112 if (file_exists(SM_PATH
. 'config/config.php')) {
113 require(SM_PATH
. 'config/config.php');
115 /* load local configuration overrides */
116 if (file_exists(SM_PATH
. 'config/config_local.php')) {
117 require(SM_PATH
. 'config/config_local.php');
121 * Include Compatibility plugin if available.
123 if (!$disable_plugins && file_exists(SM_PATH
. 'plugins/compatibility/functions.php'))
124 include_once(SM_PATH
. 'plugins/compatibility/functions.php');
127 global $disable_plugins;
128 $squirrelmail_plugin_hooks = array();
129 if (!$disable_plugins && file_exists(SM_PATH
. 'config/plugin_hooks.php')) {
130 require(SM_PATH
. 'config/plugin_hooks.php');
133 /** Warning counter */
137 $IND = str_repeat(' ',4);
140 * get_location starts session and must be run before output is started.
142 $test_location = get_location();
144 ?
><!DOCTYPE HTML
PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
145 "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">
148 <meta name
="robots" content
="noindex,nofollow">
149 <title
>SquirrelMail configtest
</title
>
152 <h1
>SquirrelMail configtest
</h1
>
154 <p
>This script will
try to check some aspects of your SquirrelMail configuration
155 and point you to errors whereever it can find them
. You need to go run
<tt
>conf
.pl
</tt
>
156 in the
<tt
>config
/</tt
> directory first before you run this script
.</p
>
160 $included = array_map('basename', get_included_files() );
161 if(!in_array('config.php', $included)) {
162 if(!file_exists(SM_PATH
. 'config/config.php')) {
163 do_err('Config file '.SM_PATH
. 'config/config.php does not exist!<br />'.
164 'You need to run <tt>conf.pl</tt> first.');
166 do_err('Could not read '.SM_PATH
.'config/config.php! Check file permissions.');
168 if(!in_array('strings.php', $included)) {
169 do_err('Could not include '.SM_PATH
.'functions/strings.php!<br />'.
170 'Check permissions on that file.');
173 /* Block remote use of script */
174 if (! $allow_remote_configtest) {
175 sqGetGlobalVar('REMOTE_ADDR',$client_ip,SQ_SERVER
);
176 sqGetGlobalVar('SERVER_ADDR',$server_ip,SQ_SERVER
);
178 if ((! isset($client_ip) ||
$client_ip!='127.0.0.1') &&
179 (! isset($client_ip) ||
! isset($server_ip) ||
$client_ip!=$server_ip)) {
180 do_err('Enable "Allow remote configtest" option in squirrelmail configuration in order to use this script.');
184 echo "<p><table>\n<tr><td>SquirrelMail version:</td><td><b>" . SM_VERSION
. "</b></td></tr>\n" .
185 '<tr><td>Config file version:</td><td><b>' . $config_version . "</b></td></tr>\n" .
186 '<tr><td>Config file last modified:</td><td><b>' .
187 date ('d F Y H:i:s', filemtime(SM_PATH
. 'config/config.php')) .
188 "</b></td></tr>\n</table>\n</p>\n\n";
190 /* check $config_version */
191 if ($config_version!='1.5.0') {
192 do_err('Configuration file version does not match required version. Please update your configuration file.');
196 /* checking PHP specs */
198 echo "Checking PHP configuration...<br />\n";
200 if(!check_php_version(4,1,0)) {
201 do_err('Insufficient PHP version: '. PHP_VERSION
. '! Minimum required: 4.1.0');
204 echo $IND . 'PHP version ' . PHP_VERSION
. ' OK. (You have: ' . phpversion() . ". Minimum: 4.1.0)<br />\n";
206 echo $IND . 'display_errors: ' . ini_get('display_errors') . "<br />\n";
208 echo $IND . 'error_reporting: ' . ini_get('error_reporting') . "<br />\n";
210 $safe_mode = ini_get('safe_mode');
212 echo $IND . 'safe_mode: ' . $safe_mode;
213 if (empty($prefs_dsn) ||
empty($addrbook_dsn))
214 echo ' (<font color="red">double check data and attachment directory ownership, etc!</font>)';
215 if (!empty($addrbook_dsn) ||
!empty($prefs_dsn) ||
!empty($addrbook_global_dsn))
216 echo ' (<font color="red">does PHP have access to database interface?</font>)';
218 $safe_mode_exec_dir = ini_get('safe_mode_exec_dir');
219 echo $IND . 'safe_mode_exec_dir: ' . $safe_mode_exec_dir . "<br />\n";
222 /* register_globals check: test for boolean false and any string that is not equal to 'off' */
224 if ((bool) ini_get('register_globals') &&
225 strtolower(ini_get('register_globals'))!='off') {
226 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);
230 /* variables_order check */
232 // 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
233 $variables_order = strtoupper(ini_get('variables_order'));
234 if (empty($variables_order))
235 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);
236 else if (strpos($variables_order, 'G') === FALSE
237 ||
strpos($variables_order, 'P') === FALSE
238 ||
strpos($variables_order, 'C') === FALSE
239 ||
strpos($variables_order, 'S') === FALSE) {
240 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);
242 echo $IND . "variables_order OK: $variables_order.<br />\n";
246 /* gpc_order check (removed from PHP as of v5.0) */
248 if (!check_php_version(5)) {
249 // 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
250 $gpc_order = strtoupper(ini_get('gpc_order'));
251 if (empty($gpc_order))
252 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);
253 else if (strpos($gpc_order, 'G') === FALSE
254 ||
strpos($gpc_order, 'P') === FALSE
255 ||
strpos($gpc_order, 'C') === FALSE) {
256 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);
258 echo $IND . "gpc_order OK: $gpc_order.<br />\n";
263 /* check PHP extensions */
265 $php_exts = array('session','pcre');
266 $diff = array_diff($php_exts, get_loaded_extensions());
268 do_err('Required PHP extensions missing: '.implode(', ',$diff) );
271 echo $IND . "PHP extensions OK. Dynamic loading is ";
273 if (!(bool)ini_get('enable_dl') ||
(bool)ini_get('safe_mode')) {
274 echo "disabled.<br />\n";
276 echo "enabled.<br />\n";
280 /* dangerous php settings */
282 * mbstring.func_overload allows to replace original string and regexp functions
283 * with their equivalents from php mbstring extension. It causes problems when
284 * scripts analyze 8bit strings byte after byte or use 8bit strings in regexp tests.
285 * Setting can be controlled in php.ini (php 4.2.0), webserver config (php 4.2.0)
286 * and .htaccess files (php 4.3.5).
288 if (function_exists('mb_internal_encoding') &&
289 check_php_version(4,2,0) &&
290 (int)ini_get('mbstring.func_overload')!=0) {
291 $mb_error='You have enabled mbstring overloading.'
292 .' It can cause problems with SquirrelMail scripts that rely on single byte string functions.';
297 * Do not use SquirrelMail with magic_quotes_* on.
299 if ( (function_exists('get_magic_quotes_runtime') && @get_magic_quotes_runtime
()) ||
300 (function_exists('get_magic_quotes_gpc') && @get_magic_quotes_gpc
()) ||
301 ( (bool) ini_get('magic_quotes_sybase') && ini_get('magic_quotes_sybase') != 'off' )
303 $magic_quotes_warning='You have enabled any one of <tt>magic_quotes_runtime</tt>, '
304 .'<tt>magic_quotes_gpc</tt> or <tt>magic_quotes_sybase</tt> in your PHP '
305 .'configuration. We recommend all those settings to be off. SquirrelMail '
306 .'may work with them on, but when experiencing stray backslashes in your mail '
307 .'or other strange behaviour, it may be advisable to turn them off.';
308 do_err($magic_quotes_warning,false);
311 if (ini_get('short_open_tag') == 0) {
312 $short_open_tag_warning = 'You have configured PHP not to allow short tags '
313 . '(<tt>short_open_tag=off</tt>). This shouldn\'t be a problem with '
314 . 'SquirrelMail or any plugin coded coded according to the '
315 . 'SquirrelMail Coding Guidelines, but if you experience problems with '
316 . 'PHP code being displayed in some of the pages and changing setting '
317 . 'to "on" solves the problem, please file a bug report against the '
318 . 'failing plugin. The correct contact information is most likely '
319 . 'to be found in the plugin documentation.';
320 do_err($short_open_tag_warning, false);
325 echo "Checking paths...<br />\n";
327 if(!file_exists($data_dir)) {
328 // data_dir is not that important in db_setups.
329 if (!empty($prefs_dsn)) {
330 $data_dir_error = "Data dir ($data_dir) does not exist!\n";
331 echo $IND .'<font color="red"><b>ERROR:</b></font> ' . $data_dir_error;
333 do_err("Data dir ($data_dir) does not exist!");
336 // don't check if errors
337 if(!isset($data_dir_error) && !is_dir($data_dir)) {
338 if (!empty($prefs_dsn)) {
339 $data_dir_error = "Data dir ($data_dir) is not a directory!\n";
340 echo $IND . '<font color="red"><b>ERROR:</b></font> ' . $data_dir_error;
342 do_err("Data dir ($data_dir) is not a directory!");
345 // datadir should be executable - but no clean way to test on that
346 if(!isset($data_dir_error) && !sq_is_writable($data_dir)) {
347 if (!empty($prefs_dsn)) {
348 $data_dir_error = "Data dir ($data_dir) is not writable!\n";
349 echo $IND . '<font color="red"><b>ERROR:</b></font> ' . $data_dir_error;
351 do_err("Data dir ($data_dir) is not writable!");
355 if (isset($data_dir_error)) {
356 echo " Some plugins might need access to data directory.<br />\n";
358 // todo_ornot: actually write something and read it back.
359 echo $IND . "Data dir OK.<br />\n";
362 if($data_dir == $attachment_dir) {
363 echo $IND . "Attachment dir is the same as data dir.<br />\n";
364 if (isset($data_dir_error)) {
365 do_err($data_dir_error);
368 if(!file_exists($attachment_dir)) {
369 do_err("Attachment dir ($attachment_dir) does not exist!");
371 if (!is_dir($attachment_dir)) {
372 do_err("Attachment dir ($attachment_dir) is not a directory!");
374 if (!sq_is_writable($attachment_dir)) {
375 do_err("I cannot write to attachment dir ($attachment_dir)!");
377 echo $IND . "Attachment dir OK.<br />\n";
381 echo "Checking plugins...<br />\n";
383 /* check plugins and themes */
384 //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
385 //FIXME: update this list with most recent contents of the Obsolete category - I think it has changed recently
386 $bad_plugins = array(
387 'attachment_common', // Integrated into SquirrelMail 1.2 core
388 'auto_prune_sent', // Obsolete: See Proon Automatic Folder Pruning plugin
389 'compose_new_window', // Integrated into SquirrelMail 1.4 core
390 'delete_move_next', // Integrated into SquirrelMail 1.5 core
391 'disk_quota', // Obsolete: See Check Quota plugin
392 'email_priority', // Integrated into SquirrelMail 1.2 core
393 'emoticons', // Obsolete: See HTML Mail plugin
394 'focus_change', // Integrated into SquirrelMail 1.2 core
395 'folder_settings', // Integrated into SquirrelMail 1.5.1 core
396 'global_sql_addressbook', // Integrated into SquirrelMail 1.4 core
397 'hancock', // Not Working: See Random Signature Taglines plugin
398 'msg_flags', // Integrated into SquirrelMail 1.5.1 core
399 'message_source', // Added to SquirrelMail 1.4 Core Plugins (message_details)
400 'motd', // Integrated into SquirrelMail 1.2 core
401 'paginator', // Integrated into SquirrelMail 1.2 core
402 'printer_friendly', // Integrated into SquirrelMail 1.2 core
403 'procfilter', // Obsolete: See Server Side Filter plugin
404 'redhat_php_cgi_fix', // Integrated into SquirrelMail 1.1.1 core
405 'send_to_semicolon', // Integrated into SquirrelMail 1.4.1 core
406 'spamassassin', // Not working beyond SquirrelMail 1.2.7: See Spamassassin SpamFilter (Frontend) v2 plugin
407 'sqcalendar', // Added to SquirrelMail 1.2 Core Plugins (calendar)
408 'sqclock', // Integrated into SquirrelMail 1.2 core
409 'sql_squirrel_logger', // Obsolete: See Squirrel Logger plugin
410 'tmda', // Obsolete: See TMDA Tools plugin
411 'vacation', // Obsolete: See Vacation Local plugin
412 'view_as_html', // Integrated into SquirrelMail 1.5.1 core
413 'xmailer' // Integrated into SquirrelMail 1.2 core
416 if (isset($plugins[0])) {
417 foreach($plugins as $plugin) {
418 if(!file_exists(SM_PATH
.'plugins/'.$plugin)) {
419 do_err('You have enabled the <i>'.$plugin.'</i> plugin, but I cannot find it.', FALSE);
420 } elseif (!is_readable(SM_PATH
.'plugins/'.$plugin.'/setup.php')) {
421 do_err('You have enabled the <i>'.$plugin.'</i> plugin, but I cannot locate or read its setup.php file.', FALSE);
422 } elseif (in_array($plugin, $bad_plugins)) {
423 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);
428 // load plugin functions
429 include_once(SM_PATH
. 'functions/plugin.php');
431 // turn on output buffering in order to prevent output of new lines
433 foreach ($plugins as $name) {
436 // get output and remove whitespace
437 $output = trim(ob_get_contents());
439 // if plugin outputs more than newlines and spacing, stop script execution.
440 if (!empty($output)) {
441 $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);
442 do_err($plugin_load_error);
449 * Check the contents of the static plugin hooks array file against
450 * the plugin setup file, which may have changed in an upgrade, etc.
451 * This helps remind admins to re-run the configuration utility when
452 * a plugin has been changed or upgraded.
454 $static_squirrelmail_plugin_hooks = $squirrelmail_plugin_hooks;
455 $squirrelmail_plugin_hooks = array();
456 foreach ($plugins as $name) {
457 $function = "squirrelmail_plugin_init_$name";
458 if (function_exists($function)) {
461 // now iterate through each hook and make sure the
462 // plugin is registered on the correct ones in the
463 // static plugin configuration file
465 foreach ($squirrelmail_plugin_hooks as $hook_name => $hooked_plugins)
466 foreach ($hooked_plugins as $hooked_plugin => $hooked_function)
467 if ($hooked_plugin == $name
468 && (empty($static_squirrelmail_plugin_hooks[$hook_name][$hooked_plugin])
469 ||
$static_squirrelmail_plugin_hooks[$hook_name][$hooked_plugin] != $hooked_function))
470 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);
473 $squirrelmail_plugin_hooks = $static_squirrelmail_plugin_hooks;
477 * Print plugin versions
479 echo $IND . "Plugin versions...<br />\n";
480 foreach ($plugins as $name) {
481 $plugin_version = get_plugin_version($name);
482 $english_name = get_plugin_requirement($name, 'english_name');
483 echo $IND . $IND . (empty($english_name) ?
$name . ' ' : $english_name . ' (' . $name . ') ') . (empty($plugin_version) ?
'??' : $plugin_version) . "<br />\n";
485 // check if this plugin has any other plugin
486 // dependencies and if they are satisfied
488 $failed_dependencies = check_plugin_dependencies($name);
489 if ($failed_dependencies === SQ_INCOMPATIBLE
) {
490 do_err($name . ' is NOT COMPATIBLE with this version of SquirrelMail', FALSE);
492 else if (is_array($failed_dependencies)) {
493 $missing_plugins = '';
494 $incompatible_plugins = '';
495 foreach ($failed_dependencies as $depend_name => $depend_requirements) {
496 if ($depend_requirements['version'] == SQ_INCOMPATIBLE
)
497 $incompatible_plugins .= ', ' . $depend_name;
499 $missing_plugins .= ', ' . $depend_name . ' (version ' . $depend_requirements['version'] . ', ' . ($depend_requirements['activate'] ?
'must be activated' : 'need not be activated') . ')';
501 $error_string = (!empty($incompatible_plugins) ?
$name . ' cannot be activated at the same time as the following plugins: ' . trim($incompatible_plugins, ', ') : '')
502 . (!empty($missing_plugins) ?
(!empty($incompatible_plugins) ?
'. ' . $name . ' is also ' : $name . ' is ') . 'missing some dependencies: ' . trim($missing_plugins, ', ') : '');
503 do_err($error_string, FALSE);
510 * This hook was added in 1.5.2 and 1.4.10. Each plugins should print an error
511 * message and return TRUE if there are any errors in its setup/configuration.
513 $plugin_err = boolean_hook_function('configtest', $null, 1);
515 do_err('Some plugin tests failed.');
517 echo $IND . "Plugins OK.<br />\n";
520 echo $IND . "Plugins are not enabled in config.<br />\n";
522 foreach($theme as $thm) {
523 if(!file_exists($thm['PATH'])) {
524 do_err('You have enabled the <i>'.$thm['NAME'].'</i> theme but I cannot find it ('.$thm['PATH'].').', FALSE);
525 } elseif(!is_readable($thm['PATH'])) {
526 do_err('You have enabled the <i>'.$thm['NAME'].'</i> theme but I cannot read it ('.$thm['PATH'].').', FALSE);
530 echo $IND . "Themes OK.<br />\n";
532 if ( $squirrelmail_default_language != 'en_US' ) {
533 $loc_path = SM_PATH
.'locale/'.$squirrelmail_default_language.'/LC_MESSAGES/squirrelmail.mo';
534 if( ! file_exists( $loc_path ) ) {
535 do_err('You have set <i>' . $squirrelmail_default_language .
536 '</i> as your default language, but I cannot find this translation (should be '.
537 'in <tt>' . $loc_path . '</tt>). Please note that you have to download translations '.
538 'separately from the main SquirrelMail package.', FALSE);
539 } elseif ( ! is_readable( $loc_path ) ) {
540 do_err('You have set <i>' . $squirrelmail_default_language .
541 '</i> as your default language, but I cannot read this translation (file '.
542 'in <tt>' . $loc_path . '</tt> unreadable).', FALSE);
544 echo $IND . "Default language OK.<br />\n";
547 echo $IND . "Default language OK.<br />\n";
550 echo $IND . "Base URL detected as: <tt>" . htmlspecialchars($test_location) .
551 "</tt> (location base " . (empty($config_location_base) ?
'autodetected' : 'set to <tt>' .
552 htmlspecialchars($config_location_base)."</tt>") . ")<br />\n";
554 /* check minimal requirements for other security options */
557 if($use_smtp_tls == 1 ||
$use_imap_tls == 1) {
558 if(!check_php_version(4,3,0)) {
559 do_err('You need at least PHP 4.3.0 for SMTP/IMAP TLS!');
561 if(!extension_loaded('openssl')) {
562 do_err('You need the openssl PHP extension to use SMTP/IMAP TLS!');
565 /* starttls extensions */
566 if($use_smtp_tls === 2 ||
$use_imap_tls === 2) {
567 if (! function_exists('stream_socket_enable_crypto')) {
568 do_err('If you want to use STARTTLS extension, you need stream_socket_enable_crypto() function from PHP 5.1.0 and newer.');
572 if ($smtp_auth_mech=='digest-md5' ||
$imap_auth_mech =='digest-md5') {
573 if (!extension_loaded('xml')) {
574 do_err('You need the PHP XML extension to use Digest-MD5 authentication!');
578 /* check outgoing mail */
580 echo "Checking outgoing mail service....<br />\n";
583 // is_executable also checks for existance, but we want to be as precise as possible with the errors
584 if(!file_exists($sendmail_path)) {
585 do_err("Location of sendmail program incorrect ($sendmail_path)!");
587 if(!is_executable($sendmail_path)) {
588 do_err("I cannot execute the sendmail program ($sendmail_path)!");
591 echo $IND . "sendmail OK<br />\n";
593 $stream = fsockopen( ($use_smtp_tls==1?
'tls://':'').$smtpServerAddress, $smtpPort,
594 $errorNumber, $errorString);
596 do_err("Error connecting to SMTP server \"$smtpServerAddress:$smtpPort\".".
597 "Server error: ($errorNumber) ".htmlspecialchars($errorString));
600 // check for SMTP code; should be 2xx to allow us access
601 $smtpline = fgets($stream, 1024);
602 if(((int) $smtpline{0}) > 3) {
603 do_err("Error connecting to SMTP server. Server error: ".
604 htmlspecialchars($smtpline));
607 /* smtp starttls checks */
608 if ($use_smtp_tls===2) {
609 // if something breaks, script should close smtp connection on exit.
612 fwrite($stream,"EHLO $client_ip\r\n");
616 while ($line=fgets($stream, 1024)){
617 if (preg_match("/^250(-|\s)(\S*)\s+(\S.*)/",$line,$match)||
618 preg_match("/^250(-|\s)(\S*)\s+/",$line,$match)) {
619 if (!isset($match[3])) {
620 // simple one word extension
621 $ehlo[strtoupper($match[2])]='';
623 // ehlo-keyword + ehlo-param
624 $ehlo[strtoupper($match[2])]=trim($match[3]);
626 if ($match[1]==' ') {
638 do_err('SMTP EHLO failed. You need ESMTP support for SMTP STARTTLS');
639 } elseif (!array_key_exists('STARTTLS',$ehlo)) {
640 do_err('STARTTLS support is not declared by SMTP server.');
643 fwrite($stream,"STARTTLS\r\n");
644 $starttls_response=fgets($stream, 1024);
645 if ($starttls_response[0]!=2) {
646 $starttls_cmd_err = 'SMTP STARTTLS failed. Server replied: '
647 .htmlspecialchars($starttls_response);
648 do_err($starttls_cmd_err);
649 } elseif(! stream_socket_enable_crypto($stream,true,STREAM_CRYPTO_METHOD_TLS_CLIENT
)) {
650 do_err('Failed to enable encryption on SMTP STARTTLS connection.');
652 echo $IND . "SMTP STARTTLS extension looks OK.<br />\n";
654 // According to RFC we should second ehlo call here.
657 fputs($stream, 'QUIT');
659 echo $IND . 'SMTP server OK (<tt><small>'.
660 trim(htmlspecialchars($smtpline))."</small></tt>)<br />\n";
662 /* POP before SMTP */
663 if($pop_before_smtp) {
664 if (empty($pop_before_smtp_host)) $pop_before_smtp_host = $smtpServerAddress;
665 $stream = fsockopen($pop_before_smtp_host, 110, $err_no, $err_str);
667 do_err("Error connecting to POP Server ($pop_before_smtp_host:110) "
668 . $err_no . ' : ' . htmlspecialchars($err_str));
671 $tmp = fgets($stream, 1024);
672 if (substr($tmp, 0, 3) != '+OK') {
673 do_err("Error connecting to POP Server ($pop_before_smtp_host:110)"
674 . ' '.htmlspecialchars($tmp));
676 fputs($stream, 'QUIT');
678 echo $IND . "POP-before-SMTP OK.<br />\n";
683 * Check the IMAP server
685 echo "Checking IMAP service....<br />\n";
687 /** Can we open a connection? */
688 $stream = fsockopen( ($use_imap_tls==1?
'tls://':'').$imapServerAddress, $imapPort,
689 $errorNumber, $errorString);
691 do_err("Error connecting to IMAP server \"$imapServerAddress:$imapPort\".".
692 "Server error: ($errorNumber) ".
693 htmlspecialchars($errorString));
696 /** Is the first response 'OK'? */
697 $imapline = fgets($stream, 1024);
698 if(substr($imapline, 0,4) != '* OK') {
699 do_err('Error connecting to IMAP server. Server error: '.
700 htmlspecialchars($imapline));
703 echo $IND . 'IMAP server ready (<tt><small>'.
704 htmlspecialchars(trim($imapline))."</small></tt>)<br />\n";
706 /** Check capabilities */
707 fputs($stream, "A001 CAPABILITY\r\n");
709 while ($line=fgets($stream, 1024)){
710 if (preg_match("/A001.*/",$line)) {
717 /* don't display capabilities before STARTTLS */
718 if ($use_imap_tls===2 && stristr($capline, 'STARTTLS') === false) {
719 do_err('Your server doesn\'t support STARTTLS.');
720 } elseif($use_imap_tls===2) {
721 /* try starting starttls */
722 fwrite($stream,"A002 STARTTLS\r\n");
723 $starttls_line=fgets($stream, 1024);
724 if (! preg_match("/^A002 OK.*/i",$starttls_line)) {
725 $imap_starttls_err = 'IMAP STARTTLS failed. Server replied: '
726 .htmlspecialchars($starttls_line);
727 do_err($imap_starttls_err);
728 } elseif (! stream_socket_enable_crypto($stream,true,STREAM_CRYPTO_METHOD_TLS_CLIENT
)) {
729 do_err('Failed to enable encryption on IMAP connection.');
731 echo $IND . "IMAP STARTTLS extension looks OK.<br />\n";
734 // get new capability line
735 fwrite($stream,"A003 CAPABILITY\r\n");
737 while ($line=fgets($stream, 1024)){
738 if (preg_match("/A003.*/",$line)) {
746 echo $IND . 'Capabilities: <tt>'.htmlspecialchars($capline)."</tt><br />\n";
748 if($imap_auth_mech == 'login' && stristr($capline, 'LOGINDISABLED') !== FALSE) {
749 do_err('Your server doesn\'t allow plaintext logins. '.
750 'Try enabling another authentication mechanism like CRAM-MD5, DIGEST-MD5 or TLS-encryption '.
751 'in the SquirrelMail configuration.', FALSE);
754 if (stristr($capline, 'XMAGICTRASH') !== false) {
755 $magic_trash = 'It looks like IMAP_MOVE_EXPUNGE_TO_TRASH option is turned on '
756 .'in your Courier IMAP configuration. Courier does not provide tools that '
757 .'allow to detect folder used for Trash or commands are not documented. '
758 .'SquirrelMail can\'t detect special trash folder. SquirrelMail manages '
759 .'all message deletion or move operations internally and '
760 .'IMAP_MOVE_EXPUNGE_TO_TRASH option can cause errors in message and '
761 .'folder management operations. Please turn off IMAP_MOVE_EXPUNGE_TO_TRASH '
762 .'option in Courier imapd configuration.';
763 do_err($magic_trash,false);
766 /* add warning about IMAP delivery */
767 if (stristr($capline, 'XCOURIEROUTBOX') !== false) {
768 $courier_outbox = 'OUTBOX setting is enabled in your Courier imapd '
769 .'configuration. SquirrelMail uses standard SMTP protocol or sendmail '
770 .'binary to send emails. Courier IMAP delivery method is not supported'
771 .' and can create duplicate email messages.';
772 do_err($courier_outbox,false);
775 /** OK, close connection */
776 fputs($stream, "A004 LOGOUT\r\n");
779 echo "Checking internationalization (i18n) settings...<br />\n";
780 echo "$IND gettext - ";
781 if (function_exists('gettext')) {
782 echo 'Gettext functions are available.'
783 .' On some systems you must have appropriate system locales compiled.'
786 /* optional setlocale() tests. Should work only on glibc systems. */
787 if (sqgetGlobalVar('testlocales',$testlocales,SQ_GET
)) {
788 include_once(SM_PATH
. 'include/languages.php');
789 echo $IND . $IND . 'Testing translations:<br>';
790 foreach ($languages as $lang_code => $lang_data) {
791 /* don't test aliases */
792 if (isset($lang_data['NAME'])) {
793 /* locale can be $lang_code or $lang_data['LOCALE'] */
794 if (isset($lang_data['LOCALE'])) {
795 $setlocale = $lang_data['LOCALE'];
797 $setlocale = $lang_code;
799 /* prepare information about tested locales */
800 if (is_array($setlocale)) {
801 $display_locale = implode(', ',$setlocale);
802 $locale_count = count($setlocale);
804 $display_locale = $setlocale;
807 $tested_locales_msg = 'Tested '.htmlspecialchars($display_locale).' '
808 .($locale_count>1 ?
'locales':'locale'). '.';
810 echo $IND . $IND .$IND . $lang_data['NAME'].' (' .$lang_code. ') - ';
811 $retlocale = sq_setlocale(LC_ALL
,$setlocale);
812 if (is_bool($retlocale)) {
813 echo '<font color="red">unsupported</font>. ';
814 echo $tested_locales_msg;
818 .' setlocale() returned "'.htmlspecialchars($retlocale).'"';
823 echo $IND . $IND . '<a href="configtest.php">Don\'t test translations</a>';
825 echo $IND . $IND . '<a href="configtest.php?testlocales=1">Test translations</a>. '
826 .'This test is not accurate and might work only on some systems.'
830 /* end of translation tests */
832 echo 'Gettext functions are unavailable.'
833 .' SquirrelMail will use slower internal gettext functions.'
836 echo "$IND mbstring - ";
837 if (function_exists('mb_detect_encoding')) {
838 echo "Mbstring functions are available.<br />\n";
840 echo 'Mbstring functions are unavailable.'
841 ." Japanese translation won't work.<br />\n";
843 echo "$IND recode - ";
844 if (function_exists('recode')) {
845 echo "Recode functions are available.<br />\n";
846 } elseif (isset($use_php_recode) && $use_php_recode) {
847 echo "Recode functions are unavailable.<br />\n";
848 do_err('Your configuration requires recode support, but recode support is missing.');
850 echo "Recode functions are unavailable.<br />\n";
852 echo "$IND iconv - ";
853 if (function_exists('iconv')) {
854 echo "Iconv functions are available.<br />\n";
855 } elseif (isset($use_php_iconv) && $use_php_iconv) {
856 echo "Iconv functions are unavailable.<br />\n";
857 do_err('Your configuration requires iconv support, but iconv support is missing.');
859 echo "Iconv functions are unavailable.<br />\n";
861 // same test as in include/init.php + date_default_timezone_set check
862 echo "$IND timezone - ";
863 if ( (!ini_get('safe_mode')) ||
function_exists('date_default_timezone_set') ||
864 !strcmp(ini_get('safe_mode_allowed_env_vars'),'') ||
865 preg_match('/^([\w_]+,)*TZ/', ini_get('safe_mode_allowed_env_vars')) ) {
866 echo "Webmail users can change their time zone settings. \n";
868 echo "Webmail users can't change their time zone settings. \n";
870 if (isset($_ENV['TZ'])) {
871 echo 'Default time zone is '.htmlspecialchars($_ENV['TZ']);
873 echo 'Current time zone is '.date('T');
878 echo "Checking database functions...<br />\n";
879 if($addrbook_dsn ||
$prefs_dsn ||
$addrbook_global_dsn) {
880 @include_once
('DB.php');
881 if (class_exists('DB')) {
882 echo "$IND PHP Pear DB support is present.<br />\n";
884 'dbase' => 'dbase_open',
885 'fbsql' => 'fbsql_connect',
886 'interbase' => 'ibase_connect',
887 'informix' => 'ifx_connect',
888 'msql' => 'msql_connect',
889 'mssql' => 'mssql_connect',
890 'mysql' => 'mysql_connect',
891 'mysqli' => 'mysqli_connect',
892 'oci8' => 'ocilogon',
893 'odbc' => 'odbc_connect',
894 'pgsql' => 'pg_connect',
895 'sqlite' => 'sqlite_open',
896 'sybase' => 'sybase_connect'
901 $dsns['preferences'] = $prefs_dsn;
904 $dsns['addressbook'] = $addrbook_dsn;
906 if($addrbook_global_dsn) {
907 $dsns['global addressbook'] = $addrbook_global_dsn;
910 foreach($dsns as $type => $dsn) {
911 $aDsn = explode(':', $dsn);
912 $dbtype = array_shift($aDsn);
914 if(isset($db_functions[$dbtype]) && function_exists($db_functions[$dbtype])) {
915 echo "$IND$dbtype database support present.<br />\n";
916 } elseif(!(bool)ini_get('enable_dl') ||
(bool)ini_get('safe_mode')) {
917 do_err($dbtype.' database support not present!');
920 do_err($dbtype.' database support not present or not configured!
921 Trying to dynamically load '.$dbtype.' extension.
922 Please note that it is advisable to not rely on dynamic loading of extensions.', FALSE);
926 // now, test this interface:
928 $dbh = DB
::connect($dsn, true);
929 if (DB
::isError($dbh)) {
930 do_err('Database error: '. htmlspecialchars(DB
::errorMessage($dbh)) .
931 ' in ' .$type .' DSN.');
934 echo "$IND$type database connect successful.<br />\n";
937 $db_error='Required PHP PEAR DB support is not available.'
938 .' Is PEAR installed and is the include path set correctly to find <tt>DB.php</tt>?'
939 .' The include path is now: "<tt>' . ini_get('include_path') . '</tt>".';
943 echo $IND."not using database functionality.<br />\n";
947 echo "Checking LDAP functions...<br />\n";
948 if( empty($ldap_server) ) {
949 echo $IND."not using LDAP functionality.<br />\n";
951 if ( !function_exists('ldap_connect') ) {
952 do_err('Required LDAP support is not available.');
954 echo "$IND LDAP support present.<br />\n";
955 foreach ( $ldap_server as $param ) {
957 $linkid = @ldap_connect
($param['host'], (empty($param['port']) ?
389 : $param['port']) );
960 echo "$IND LDAP connect to ".$param['host']." successful: ".$linkid."<br />\n";
962 if ( !empty($param['protocol']) &&
963 !ldap_set_option($linkid, LDAP_OPT_PROTOCOL_VERSION
, $param['protocol']) ) {
964 do_err('Unable to set LDAP protocol');
967 if ( empty($param['binddn']) ) {
968 $bind = @ldap_bind
($linkid);
970 $bind = @ldap_bind
($linkid, $param['binddn'], $param['bindpw']);
974 echo "$IND LDAP Bind Successful <br />";
976 do_err('Unable to Bind to LDAP Server');
979 @ldap_close
($linkid);
981 do_err('Connection to LDAP failed');
987 echo '<hr width="75%" align="center">';
988 echo '<h2 align="center">Summary</h2>';
989 $footer = '<hr width="75%" align="center">';
991 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>';
995 <p
>Congratulations
, your SquirrelMail setup looks fine to me
!</p
>
997 <p
><a href
="login.php">Login now
</a
></p
>