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 $SQM_INTERNAL_VERSION = explode('.', SM_VERSION
, 3);
91 $SQM_INTERNAL_VERSION[2] = intval($SQM_INTERNAL_VERSION[2]);
93 /** set default value in order to block remote access */
94 $allow_remote_configtest=false;
96 /** Load all configuration files before output begins */
98 /* load default configuration */
99 require(SM_PATH
. 'config/config_default.php');
100 /* reset arrays in default configuration */
101 $ldap_server = array();
105 $theme[0]['PATH'] = SM_PATH
. 'themes/default_theme.php';
106 $theme[0]['NAME'] = 'Default';
107 $aTemplateSet = array();
108 $aTemplateSet[0]['ID'] = 'default';
109 $aTemplateSet[0]['NAME'] = 'Default';
110 /* load site configuration */
111 if (file_exists(SM_PATH
. 'config/config.php')) {
112 require(SM_PATH
. 'config/config.php');
114 /* load local configuration overrides */
115 if (file_exists(SM_PATH
. 'config/config_local.php')) {
116 require(SM_PATH
. 'config/config_local.php');
120 * Include Compatibility plugin if available.
122 if (!$disable_plugins && file_exists(SM_PATH
. 'plugins/compatibility/functions.php'))
123 include_once(SM_PATH
. 'plugins/compatibility/functions.php');
126 global $disable_plugins;
127 $squirrelmail_plugin_hooks = array();
128 if (!$disable_plugins && file_exists(SM_PATH
. 'config/plugin_hooks.php')) {
129 require(SM_PATH
. 'config/plugin_hooks.php');
132 /** Warning counter */
136 $IND = str_repeat(' ',4);
139 * get_location starts session and must be run before output is started.
141 $test_location = get_location();
143 ?
><!DOCTYPE HTML
PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
144 "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">
147 <meta name
="robots" content
="noindex,nofollow">
148 <title
>SquirrelMail configtest
</title
>
151 <h1
>SquirrelMail configtest
</h1
>
153 <p
>This script will
try to check some aspects of your SquirrelMail configuration
154 and point you to errors whereever it can find them
. You need to go run
<tt
>conf
.pl
</tt
>
155 in the
<tt
>config
/</tt
> directory first before you run this script
.</p
>
159 $included = array_map('basename', get_included_files() );
160 if(!in_array('config.php', $included)) {
161 if(!file_exists(SM_PATH
. 'config/config.php')) {
162 do_err('Config file '.SM_PATH
. 'config/config.php does not exist!<br />'.
163 'You need to run <tt>conf.pl</tt> first.');
165 do_err('Could not read '.SM_PATH
.'config/config.php! Check file permissions.');
167 if(!in_array('strings.php', $included)) {
168 do_err('Could not include '.SM_PATH
.'functions/strings.php!<br />'.
169 'Check permissions on that file.');
172 /* Block remote use of script */
173 if (! $allow_remote_configtest) {
174 sqGetGlobalVar('REMOTE_ADDR',$client_ip,SQ_SERVER
);
175 sqGetGlobalVar('SERVER_ADDR',$server_ip,SQ_SERVER
);
177 if ((! isset($client_ip) ||
$client_ip!='127.0.0.1') &&
178 (! isset($client_ip) ||
! isset($server_ip) ||
$client_ip!=$server_ip)) {
179 do_err('Enable "Allow remote configtest" option in squirrelmail configuration in order to use this script.');
183 echo "<p><table>\n<tr><td>SquirrelMail version:</td><td><b>" . SM_VERSION
. "</b></td></tr>\n" .
184 '<tr><td>Config file version:</td><td><b>' . $config_version . "</b></td></tr>\n" .
185 '<tr><td>Config file last modified:</td><td><b>' .
186 date ('d F Y H:i:s', filemtime(SM_PATH
. 'config/config.php')) .
187 "</b></td></tr>\n</table>\n</p>\n\n";
189 /* check $config_version */
190 if ($config_version!='1.5.0') {
191 do_err('Configuration file version does not match required version. Please update your configuration file.');
195 /* checking PHP specs */
197 echo "Checking PHP configuration...<br />\n";
199 if(!check_php_version(4,1,0)) {
200 do_err('Insufficient PHP version: '. PHP_VERSION
. '! Minimum required: 4.1.0');
203 echo $IND . 'PHP version ' . PHP_VERSION
. ' OK. (You have: ' . phpversion() . ". Minimum: 4.1.0)<br />\n";
205 echo $IND . 'display_errors: ' . ini_get('display_errors') . "<br />\n";
207 echo $IND . 'error_reporting: ' . ini_get('error_reporting') . "<br />\n";
209 $safe_mode = ini_get('safe_mode');
211 echo $IND . 'safe_mode: ' . $safe_mode;
212 if (empty($prefs_dsn) ||
empty($addrbook_dsn))
213 echo ' (<font color="red">double check data and attachment directory ownership, etc!</font>)';
214 if (!empty($addrbook_dsn) ||
!empty($prefs_dsn) ||
!empty($addrbook_global_dsn))
215 echo ' (<font color="red">does PHP have access to database interface?</font>)';
217 $safe_mode_exec_dir = ini_get('safe_mode_exec_dir');
218 echo $IND . 'safe_mode_exec_dir: ' . $safe_mode_exec_dir . "<br />\n";
221 /* register_globals check: test for boolean false and any string that is not equal to 'off' */
223 if ((bool) ini_get('register_globals') &&
224 strtolower(ini_get('register_globals'))!='off') {
225 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);
229 /* variables_order check */
231 // 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
232 $variables_order = strtoupper(ini_get('variables_order'));
233 if (empty($variables_order))
234 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);
235 else if (strpos($variables_order, 'G') === FALSE
236 ||
strpos($variables_order, 'P') === FALSE
237 ||
strpos($variables_order, 'C') === FALSE
238 ||
strpos($variables_order, 'S') === FALSE) {
239 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);
241 echo $IND . "variables_order OK: $variables_order.<br />\n";
245 /* gpc_order check (removed from PHP as of v5.0) */
247 if (!check_php_version(5)) {
248 // 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
249 $gpc_order = strtoupper(ini_get('gpc_order'));
250 if (empty($gpc_order))
251 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);
252 else if (strpos($gpc_order, 'G') === FALSE
253 ||
strpos($gpc_order, 'P') === FALSE
254 ||
strpos($gpc_order, 'C') === FALSE) {
255 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);
257 echo $IND . "gpc_order OK: $gpc_order.<br />\n";
262 /* check PHP extensions */
264 $php_exts = array('session','pcre');
265 $diff = array_diff($php_exts, get_loaded_extensions());
267 do_err('Required PHP extensions missing: '.implode(', ',$diff) );
270 echo $IND . "PHP extensions OK. Dynamic loading is ";
272 if (!(bool)ini_get('enable_dl') ||
(bool)ini_get('safe_mode')) {
273 echo "disabled.<br />\n";
275 echo "enabled.<br />\n";
279 /* dangerous php settings */
281 * mbstring.func_overload allows to replace original string and regexp functions
282 * with their equivalents from php mbstring extension. It causes problems when
283 * scripts analyze 8bit strings byte after byte or use 8bit strings in regexp tests.
284 * Setting can be controlled in php.ini (php 4.2.0), webserver config (php 4.2.0)
285 * and .htaccess files (php 4.3.5).
287 if (function_exists('mb_internal_encoding') &&
288 check_php_version(4,2,0) &&
289 (int)ini_get('mbstring.func_overload')!=0) {
290 $mb_error='You have enabled mbstring overloading.'
291 .' It can cause problems with SquirrelMail scripts that rely on single byte string functions.';
296 * Do not use SquirrelMail with magic_quotes_* on.
298 if ( (function_exists('get_magic_quotes_runtime') && @get_magic_quotes_runtime
()) ||
299 (function_exists('get_magic_quotes_gpc') && @get_magic_quotes_gpc
()) ||
300 ( (bool) ini_get('magic_quotes_sybase') && ini_get('magic_quotes_sybase') != 'off' )
302 $magic_quotes_warning='You have enabled any one of <tt>magic_quotes_runtime</tt>, '
303 .'<tt>magic_quotes_gpc</tt> or <tt>magic_quotes_sybase</tt> in your PHP '
304 .'configuration. We recommend all those settings to be off. SquirrelMail '
305 .'may work with them on, but when experiencing stray backslashes in your mail '
306 .'or other strange behaviour, it may be advisable to turn them off.';
307 do_err($magic_quotes_warning,false);
310 if (ini_get('short_open_tag') == 0) {
311 $short_open_tag_warning = 'You have configured PHP not to allow short tags '
312 . '(<tt>short_open_tag=off</tt>). This shouldn\'t be a problem with '
313 . 'SquirrelMail or any plugin coded coded according to the '
314 . 'SquirrelMail Coding Guidelines, but if you experience problems with '
315 . 'PHP code being displayed in some of the pages and changing setting '
316 . 'to "on" solves the problem, please file a bug report against the '
317 . 'failing plugin. The correct contact information is most likely '
318 . 'to be found in the plugin documentation.';
319 do_err($short_open_tag_warning, false);
324 echo "Checking paths...<br />\n";
326 if(!file_exists($data_dir)) {
327 // data_dir is not that important in db_setups.
328 if (!empty($prefs_dsn)) {
329 $data_dir_error = "Data dir ($data_dir) does not exist!\n";
330 echo $IND .'<font color="red"><b>ERROR:</b></font> ' . $data_dir_error;
332 do_err("Data dir ($data_dir) does not exist!");
335 // don't check if errors
336 if(!isset($data_dir_error) && !is_dir($data_dir)) {
337 if (!empty($prefs_dsn)) {
338 $data_dir_error = "Data dir ($data_dir) is not a directory!\n";
339 echo $IND . '<font color="red"><b>ERROR:</b></font> ' . $data_dir_error;
341 do_err("Data dir ($data_dir) is not a directory!");
344 // datadir should be executable - but no clean way to test on that
345 if(!isset($data_dir_error) && !sq_is_writable($data_dir)) {
346 if (!empty($prefs_dsn)) {
347 $data_dir_error = "Data dir ($data_dir) is not writable!\n";
348 echo $IND . '<font color="red"><b>ERROR:</b></font> ' . $data_dir_error;
350 do_err("Data dir ($data_dir) is not writable!");
354 if (isset($data_dir_error)) {
355 echo " Some plugins might need access to data directory.<br />\n";
357 // todo_ornot: actually write something and read it back.
358 echo $IND . "Data dir OK.<br />\n";
361 if($data_dir == $attachment_dir) {
362 echo $IND . "Attachment dir is the same as data dir.<br />\n";
363 if (isset($data_dir_error)) {
364 do_err($data_dir_error);
367 if(!file_exists($attachment_dir)) {
368 do_err("Attachment dir ($attachment_dir) does not exist!");
370 if (!is_dir($attachment_dir)) {
371 do_err("Attachment dir ($attachment_dir) is not a directory!");
373 if (!sq_is_writable($attachment_dir)) {
374 do_err("I cannot write to attachment dir ($attachment_dir)!");
376 echo $IND . "Attachment dir OK.<br />\n";
380 echo "Checking plugins...<br />\n";
382 /* check plugins and themes */
383 //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
384 //FIXME: update this list with most recent contents of the Obsolete category - I think it has changed recently
385 $bad_plugins = array(
386 'attachment_common', // Integrated into SquirrelMail 1.2 core
387 'auto_prune_sent', // Obsolete: See Proon Automatic Folder Pruning plugin
388 'compose_new_window', // Integrated into SquirrelMail 1.4 core
389 'delete_move_next', // Integrated into SquirrelMail 1.5 core
390 'disk_quota', // Obsolete: See Check Quota plugin
391 'email_priority', // Integrated into SquirrelMail 1.2 core
392 'emoticons', // Obsolete: See HTML Mail plugin
393 'focus_change', // Integrated into SquirrelMail 1.2 core
394 'folder_settings', // Integrated into SquirrelMail 1.5.1 core
395 'global_sql_addressbook', // Integrated into SquirrelMail 1.4 core
396 'hancock', // Not Working: See Random Signature Taglines plugin
397 'msg_flags', // Integrated into SquirrelMail 1.5.1 core
398 'message_source', // Added to SquirrelMail 1.4 Core Plugins (message_details)
399 'motd', // Integrated into SquirrelMail 1.2 core
400 'paginator', // Integrated into SquirrelMail 1.2 core
401 'printer_friendly', // Integrated into SquirrelMail 1.2 core
402 'procfilter', // Obsolete: See Server Side Filter plugin
403 'redhat_php_cgi_fix', // Integrated into SquirrelMail 1.1.1 core
404 'send_to_semicolon', // Integrated into SquirrelMail 1.4.1 core
405 'spamassassin', // Not working beyond SquirrelMail 1.2.7: See Spamassassin SpamFilter (Frontend) v2 plugin
406 'sqcalendar', // Added to SquirrelMail 1.2 Core Plugins (calendar)
407 'sqclock', // Integrated into SquirrelMail 1.2 core
408 'sql_squirrel_logger', // Obsolete: See Squirrel Logger plugin
409 'tmda', // Obsolete: See TMDA Tools plugin
410 'vacation', // Obsolete: See Vacation Local plugin
411 'view_as_html', // Integrated into SquirrelMail 1.5.1 core
412 'xmailer' // Integrated into SquirrelMail 1.2 core
415 if (isset($plugins[0])) {
416 foreach($plugins as $plugin) {
417 if(!file_exists(SM_PATH
.'plugins/'.$plugin)) {
418 do_err('You have enabled the <i>'.$plugin.'</i> plugin, but I cannot find it.', FALSE);
419 } elseif (!is_readable(SM_PATH
.'plugins/'.$plugin.'/setup.php')) {
420 do_err('You have enabled the <i>'.$plugin.'</i> plugin, but I cannot locate or read its setup.php file.', FALSE);
421 } elseif (in_array($plugin, $bad_plugins)) {
422 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);
427 // load plugin functions
428 include_once(SM_PATH
. 'functions/plugin.php');
430 // turn on output buffering in order to prevent output of new lines
432 foreach ($plugins as $name) {
435 // get output and remove whitespace
436 $output = trim(ob_get_contents());
438 // if plugin outputs more than newlines and spacing, stop script execution.
439 if (!empty($output)) {
440 $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);
441 do_err($plugin_load_error);
448 * Check the contents of the static plugin hooks array file against
449 * the plugin setup file, which may have changed in an upgrade, etc.
450 * This helps remind admins to re-run the configuration utility when
451 * a plugin has been changed or upgraded.
453 $static_squirrelmail_plugin_hooks = $squirrelmail_plugin_hooks;
454 $squirrelmail_plugin_hooks = array();
455 foreach ($plugins as $name) {
456 $function = "squirrelmail_plugin_init_$name";
457 if (function_exists($function)) {
460 // now iterate through each hook and make sure the
461 // plugin is registered on the correct ones in the
462 // static plugin configuration file
464 foreach ($squirrelmail_plugin_hooks as $hook_name => $hooked_plugins)
465 foreach ($hooked_plugins as $hooked_plugin => $hooked_function)
466 if ($hooked_plugin == $name
467 && (empty($static_squirrelmail_plugin_hooks[$hook_name][$hooked_plugin])
468 ||
$static_squirrelmail_plugin_hooks[$hook_name][$hooked_plugin] != $hooked_function))
469 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);
472 $squirrelmail_plugin_hooks = $static_squirrelmail_plugin_hooks;
476 * Print plugin versions
478 echo $IND . "Plugin versions...<br />\n";
479 foreach ($plugins as $name) {
480 $plugin_version = get_plugin_version($name);
481 $english_name = get_plugin_requirement($name, 'english_name');
482 echo $IND . $IND . (empty($english_name) ?
$name . ' ' : $english_name . ' (' . $name . ') ') . (empty($plugin_version) ?
'??' : $plugin_version) . "<br />\n";
484 // check if this plugin has any other plugin
485 // dependencies and if they are satisfied
487 $failed_dependencies = check_plugin_dependencies($name);
488 if ($failed_dependencies === SQ_INCOMPATIBLE
) {
489 do_err($name . ' is NOT COMPATIBLE with this version of SquirrelMail', FALSE);
491 else if (is_array($failed_dependencies)) {
492 $missing_plugins = '';
493 $incompatible_plugins = '';
494 foreach ($failed_dependencies as $depend_name => $depend_requirements) {
495 if ($depend_requirements['version'] == SQ_INCOMPATIBLE
)
496 $incompatible_plugins .= ', ' . $depend_name;
498 $missing_plugins .= ', ' . $depend_name . ' (version ' . $depend_requirements['version'] . ', ' . ($depend_requirements['activate'] ?
'must be activated' : 'need not be activated') . ')';
500 $error_string = (!empty($incompatible_plugins) ?
$name . ' cannot be activated at the same time as the following plugins: ' . trim($incompatible_plugins, ', ') : '')
501 . (!empty($missing_plugins) ?
(!empty($incompatible_plugins) ?
'. ' . $name . ' is also ' : $name . ' is ') . 'missing some dependencies: ' . trim($missing_plugins, ', ') : '');
502 do_err($error_string, FALSE);
509 * This hook was added in 1.5.2 and 1.4.10. Each plugins should print an error
510 * message and return TRUE if there are any errors in its setup/configuration.
512 $plugin_err = boolean_hook_function('configtest', $null, 1);
514 do_err('Some plugin tests failed.');
516 echo $IND . "Plugins OK.<br />\n";
519 echo $IND . "Plugins are not enabled in config.<br />\n";
521 foreach($theme as $thm) {
522 if(!file_exists($thm['PATH'])) {
523 do_err('You have enabled the <i>'.$thm['NAME'].'</i> theme but I cannot find it ('.$thm['PATH'].').', FALSE);
524 } elseif(!is_readable($thm['PATH'])) {
525 do_err('You have enabled the <i>'.$thm['NAME'].'</i> theme but I cannot read it ('.$thm['PATH'].').', FALSE);
529 echo $IND . "Themes OK.<br />\n";
531 if ( $squirrelmail_default_language != 'en_US' ) {
532 $loc_path = SM_PATH
.'locale/'.$squirrelmail_default_language.'/LC_MESSAGES/squirrelmail.mo';
533 if( ! file_exists( $loc_path ) ) {
534 do_err('You have set <i>' . $squirrelmail_default_language .
535 '</i> as your default language, but I cannot find this translation (should be '.
536 'in <tt>' . $loc_path . '</tt>). Please note that you have to download translations '.
537 'separately from the main SquirrelMail package.', FALSE);
538 } elseif ( ! is_readable( $loc_path ) ) {
539 do_err('You have set <i>' . $squirrelmail_default_language .
540 '</i> as your default language, but I cannot read this translation (file '.
541 'in <tt>' . $loc_path . '</tt> unreadable).', FALSE);
543 echo $IND . "Default language OK.<br />\n";
546 echo $IND . "Default language OK.<br />\n";
549 echo $IND . "Base URL detected as: <tt>" . htmlspecialchars($test_location) .
550 "</tt> (location base " . (empty($config_location_base) ?
'autodetected' : 'set to <tt>' .
551 htmlspecialchars($config_location_base)."</tt>") . ")<br />\n";
553 /* check minimal requirements for other security options */
556 if($use_smtp_tls == 1 ||
$use_imap_tls == 1) {
557 if(!check_php_version(4,3,0)) {
558 do_err('You need at least PHP 4.3.0 for SMTP/IMAP TLS!');
560 if(!extension_loaded('openssl')) {
561 do_err('You need the openssl PHP extension to use SMTP/IMAP TLS!');
564 /* starttls extensions */
565 if($use_smtp_tls === 2 ||
$use_imap_tls === 2) {
566 if (! function_exists('stream_socket_enable_crypto')) {
567 do_err('If you want to use STARTTLS extension, you need stream_socket_enable_crypto() function from PHP 5.1.0 and newer.');
571 if ($smtp_auth_mech=='digest-md5' ||
$imap_auth_mech =='digest-md5') {
572 if (!extension_loaded('xml')) {
573 do_err('You need the PHP XML extension to use Digest-MD5 authentication!');
577 /* check outgoing mail */
579 echo "Checking outgoing mail service....<br />\n";
582 // is_executable also checks for existance, but we want to be as precise as possible with the errors
583 if(!file_exists($sendmail_path)) {
584 do_err("Location of sendmail program incorrect ($sendmail_path)!");
586 if(!is_executable($sendmail_path)) {
587 do_err("I cannot execute the sendmail program ($sendmail_path)!");
590 echo $IND . "sendmail OK<br />\n";
592 $stream = fsockopen( ($use_smtp_tls==1?
'tls://':'').$smtpServerAddress, $smtpPort,
593 $errorNumber, $errorString);
595 do_err("Error connecting to SMTP server \"$smtpServerAddress:$smtpPort\".".
596 "Server error: ($errorNumber) ".htmlspecialchars($errorString));
599 // check for SMTP code; should be 2xx to allow us access
600 $smtpline = fgets($stream, 1024);
601 if(((int) $smtpline{0}) > 3) {
602 do_err("Error connecting to SMTP server. Server error: ".
603 htmlspecialchars($smtpline));
606 /* smtp starttls checks */
607 if ($use_smtp_tls===2) {
608 // if something breaks, script should close smtp connection on exit.
611 fwrite($stream,"EHLO $client_ip\r\n");
615 while ($line=fgets($stream, 1024)){
616 if (preg_match("/^250(-|\s)(\S*)\s+(\S.*)/",$line,$match)||
617 preg_match("/^250(-|\s)(\S*)\s+/",$line,$match)) {
618 if (!isset($match[3])) {
619 // simple one word extension
620 $ehlo[strtoupper($match[2])]='';
622 // ehlo-keyword + ehlo-param
623 $ehlo[strtoupper($match[2])]=trim($match[3]);
625 if ($match[1]==' ') {
637 do_err('SMTP EHLO failed. You need ESMTP support for SMTP STARTTLS');
638 } elseif (!array_key_exists('STARTTLS',$ehlo)) {
639 do_err('STARTTLS support is not declared by SMTP server.');
642 fwrite($stream,"STARTTLS\r\n");
643 $starttls_response=fgets($stream, 1024);
644 if ($starttls_response[0]!=2) {
645 $starttls_cmd_err = 'SMTP STARTTLS failed. Server replied: '
646 .htmlspecialchars($starttls_response);
647 do_err($starttls_cmd_err);
648 } elseif(! stream_socket_enable_crypto($stream,true,STREAM_CRYPTO_METHOD_TLS_CLIENT
)) {
649 do_err('Failed to enable encryption on SMTP STARTTLS connection.');
651 echo $IND . "SMTP STARTTLS extension looks OK.<br />\n";
653 // According to RFC we should second ehlo call here.
656 fputs($stream, 'QUIT');
658 echo $IND . 'SMTP server OK (<tt><small>'.
659 trim(htmlspecialchars($smtpline))."</small></tt>)<br />\n";
661 /* POP before SMTP */
662 if($pop_before_smtp) {
663 if (empty($pop_before_smtp_host)) $pop_before_smtp_host = $smtpServerAddress;
664 $stream = fsockopen($pop_before_smtp_host, 110, $err_no, $err_str);
666 do_err("Error connecting to POP Server ($pop_before_smtp_host:110) "
667 . $err_no . ' : ' . htmlspecialchars($err_str));
670 $tmp = fgets($stream, 1024);
671 if (substr($tmp, 0, 3) != '+OK') {
672 do_err("Error connecting to POP Server ($pop_before_smtp_host:110)"
673 . ' '.htmlspecialchars($tmp));
675 fputs($stream, 'QUIT');
677 echo $IND . "POP-before-SMTP OK.<br />\n";
682 * Check the IMAP server
684 echo "Checking IMAP service....<br />\n";
686 /** Can we open a connection? */
687 $stream = fsockopen( ($use_imap_tls==1?
'tls://':'').$imapServerAddress, $imapPort,
688 $errorNumber, $errorString);
690 do_err("Error connecting to IMAP server \"$imapServerAddress:$imapPort\".".
691 "Server error: ($errorNumber) ".
692 htmlspecialchars($errorString));
695 /** Is the first response 'OK'? */
696 $imapline = fgets($stream, 1024);
697 if(substr($imapline, 0,4) != '* OK') {
698 do_err('Error connecting to IMAP server. Server error: '.
699 htmlspecialchars($imapline));
702 echo $IND . 'IMAP server ready (<tt><small>'.
703 htmlspecialchars(trim($imapline))."</small></tt>)<br />\n";
705 /** Check capabilities */
706 fputs($stream, "A001 CAPABILITY\r\n");
708 while ($line=fgets($stream, 1024)){
709 if (preg_match("/A001.*/",$line)) {
716 /* don't display capabilities before STARTTLS */
717 if ($use_imap_tls===2 && stristr($capline, 'STARTTLS') === false) {
718 do_err('Your server doesn\'t support STARTTLS.');
719 } elseif($use_imap_tls===2) {
720 /* try starting starttls */
721 fwrite($stream,"A002 STARTTLS\r\n");
722 $starttls_line=fgets($stream, 1024);
723 if (! preg_match("/^A002 OK.*/i",$starttls_line)) {
724 $imap_starttls_err = 'IMAP STARTTLS failed. Server replied: '
725 .htmlspecialchars($starttls_line);
726 do_err($imap_starttls_err);
727 } elseif (! stream_socket_enable_crypto($stream,true,STREAM_CRYPTO_METHOD_TLS_CLIENT
)) {
728 do_err('Failed to enable encryption on IMAP connection.');
730 echo $IND . "IMAP STARTTLS extension looks OK.<br />\n";
733 // get new capability line
734 fwrite($stream,"A003 CAPABILITY\r\n");
736 while ($line=fgets($stream, 1024)){
737 if (preg_match("/A003.*/",$line)) {
745 echo $IND . 'Capabilities: <tt>'.htmlspecialchars($capline)."</tt><br />\n";
747 if($imap_auth_mech == 'login' && stristr($capline, 'LOGINDISABLED') !== FALSE) {
748 do_err('Your server doesn\'t allow plaintext logins. '.
749 'Try enabling another authentication mechanism like CRAM-MD5, DIGEST-MD5 or TLS-encryption '.
750 'in the SquirrelMail configuration.', FALSE);
753 if (stristr($capline, 'XMAGICTRASH') !== false) {
754 $magic_trash = 'It looks like IMAP_MOVE_EXPUNGE_TO_TRASH option is turned on '
755 .'in your Courier IMAP configuration. Courier does not provide tools that '
756 .'allow to detect folder used for Trash or commands are not documented. '
757 .'SquirrelMail can\'t detect special trash folder. SquirrelMail manages '
758 .'all message deletion or move operations internally and '
759 .'IMAP_MOVE_EXPUNGE_TO_TRASH option can cause errors in message and '
760 .'folder management operations. Please turn off IMAP_MOVE_EXPUNGE_TO_TRASH '
761 .'option in Courier imapd configuration.';
762 do_err($magic_trash,false);
765 /* add warning about IMAP delivery */
766 if (stristr($capline, 'XCOURIEROUTBOX') !== false) {
767 $courier_outbox = 'OUTBOX setting is enabled in your Courier imapd '
768 .'configuration. SquirrelMail uses standard SMTP protocol or sendmail '
769 .'binary to send emails. Courier IMAP delivery method is not supported'
770 .' and can create duplicate email messages.';
771 do_err($courier_outbox,false);
774 /** OK, close connection */
775 fputs($stream, "A004 LOGOUT\r\n");
778 echo "Checking internationalization (i18n) settings...<br />\n";
779 echo "$IND gettext - ";
780 if (function_exists('gettext')) {
781 echo 'Gettext functions are available.'
782 .' On some systems you must have appropriate system locales compiled.'
785 /* optional setlocale() tests. Should work only on glibc systems. */
786 if (sqgetGlobalVar('testlocales',$testlocales,SQ_GET
)) {
787 include_once(SM_PATH
. 'include/languages.php');
788 echo $IND . $IND . 'Testing translations:<br>';
789 foreach ($languages as $lang_code => $lang_data) {
790 /* don't test aliases */
791 if (isset($lang_data['NAME'])) {
792 /* locale can be $lang_code or $lang_data['LOCALE'] */
793 if (isset($lang_data['LOCALE'])) {
794 $setlocale = $lang_data['LOCALE'];
796 $setlocale = $lang_code;
798 /* prepare information about tested locales */
799 if (is_array($setlocale)) {
800 $display_locale = implode(', ',$setlocale);
801 $locale_count = count($setlocale);
803 $display_locale = $setlocale;
806 $tested_locales_msg = 'Tested '.htmlspecialchars($display_locale).' '
807 .($locale_count>1 ?
'locales':'locale'). '.';
809 echo $IND . $IND .$IND . $lang_data['NAME'].' (' .$lang_code. ') - ';
810 $retlocale = sq_setlocale(LC_ALL
,$setlocale);
811 if (is_bool($retlocale)) {
812 echo '<font color="red">unsupported</font>. ';
813 echo $tested_locales_msg;
817 .' setlocale() returned "'.htmlspecialchars($retlocale).'"';
822 echo $IND . $IND . '<a href="configtest.php">Don\'t test translations</a>';
824 echo $IND . $IND . '<a href="configtest.php?testlocales=1">Test translations</a>. '
825 .'This test is not accurate and might work only on some systems.'
829 /* end of translation tests */
831 echo 'Gettext functions are unavailable.'
832 .' SquirrelMail will use slower internal gettext functions.'
835 echo "$IND mbstring - ";
836 if (function_exists('mb_detect_encoding')) {
837 echo "Mbstring functions are available.<br />\n";
839 echo 'Mbstring functions are unavailable.'
840 ." Japanese translation won't work.<br />\n";
842 echo "$IND recode - ";
843 if (function_exists('recode')) {
844 echo "Recode functions are available.<br />\n";
845 } elseif (isset($use_php_recode) && $use_php_recode) {
846 echo "Recode functions are unavailable.<br />\n";
847 do_err('Your configuration requires recode support, but recode support is missing.');
849 echo "Recode functions are unavailable.<br />\n";
851 echo "$IND iconv - ";
852 if (function_exists('iconv')) {
853 echo "Iconv functions are available.<br />\n";
854 } elseif (isset($use_php_iconv) && $use_php_iconv) {
855 echo "Iconv functions are unavailable.<br />\n";
856 do_err('Your configuration requires iconv support, but iconv support is missing.');
858 echo "Iconv functions are unavailable.<br />\n";
860 // same test as in include/init.php + date_default_timezone_set check
861 echo "$IND timezone - ";
862 if ( (!ini_get('safe_mode')) ||
function_exists('date_default_timezone_set') ||
863 !strcmp(ini_get('safe_mode_allowed_env_vars'),'') ||
864 preg_match('/^([\w_]+,)*TZ/', ini_get('safe_mode_allowed_env_vars')) ) {
865 echo "Webmail users can change their time zone settings. \n";
867 echo "Webmail users can't change their time zone settings. \n";
869 if (isset($_ENV['TZ'])) {
870 echo 'Default time zone is '.htmlspecialchars($_ENV['TZ']);
872 echo 'Current time zone is '.date('T');
877 echo "Checking database functions...<br />\n";
878 if($addrbook_dsn ||
$prefs_dsn ||
$addrbook_global_dsn) {
879 @include_once
('DB.php');
880 if (class_exists('DB')) {
881 echo "$IND PHP Pear DB support is present.<br />\n";
883 'dbase' => 'dbase_open',
884 'fbsql' => 'fbsql_connect',
885 'interbase' => 'ibase_connect',
886 'informix' => 'ifx_connect',
887 'msql' => 'msql_connect',
888 'mssql' => 'mssql_connect',
889 'mysql' => 'mysql_connect',
890 'mysqli' => 'mysqli_connect',
891 'oci8' => 'ocilogon',
892 'odbc' => 'odbc_connect',
893 'pgsql' => 'pg_connect',
894 'sqlite' => 'sqlite_open',
895 'sybase' => 'sybase_connect'
900 $dsns['preferences'] = $prefs_dsn;
903 $dsns['addressbook'] = $addrbook_dsn;
905 if($addrbook_global_dsn) {
906 $dsns['global addressbook'] = $addrbook_global_dsn;
909 foreach($dsns as $type => $dsn) {
910 $aDsn = explode(':', $dsn);
911 $dbtype = array_shift($aDsn);
913 if(isset($db_functions[$dbtype]) && function_exists($db_functions[$dbtype])) {
914 echo "$IND$dbtype database support present.<br />\n";
915 } elseif(!(bool)ini_get('enable_dl') ||
(bool)ini_get('safe_mode')) {
916 do_err($dbtype.' database support not present!');
919 do_err($dbtype.' database support not present or not configured!
920 Trying to dynamically load '.$dbtype.' extension.
921 Please note that it is advisable to not rely on dynamic loading of extensions.', FALSE);
925 // now, test this interface:
927 $dbh = DB
::connect($dsn, true);
928 if (DB
::isError($dbh)) {
929 do_err('Database error: '. htmlspecialchars(DB
::errorMessage($dbh)) .
930 ' in ' .$type .' DSN.');
933 echo "$IND$type database connect successful.<br />\n";
936 $db_error='Required PHP PEAR DB support is not available.'
937 .' Is PEAR installed and is the include path set correctly to find <tt>DB.php</tt>?'
938 .' The include path is now: "<tt>' . ini_get('include_path') . '</tt>".';
942 echo $IND."not using database functionality.<br />\n";
946 echo "Checking LDAP functions...<br />\n";
947 if( empty($ldap_server) ) {
948 echo $IND."not using LDAP functionality.<br />\n";
950 if ( !function_exists('ldap_connect') ) {
951 do_err('Required LDAP support is not available.');
953 echo "$IND LDAP support present.<br />\n";
954 foreach ( $ldap_server as $param ) {
956 $linkid = @ldap_connect
($param['host'], (empty($param['port']) ?
389 : $param['port']) );
959 echo "$IND LDAP connect to ".$param['host']." successful: ".$linkid."<br />\n";
961 if ( !empty($param['protocol']) &&
962 !ldap_set_option($linkid, LDAP_OPT_PROTOCOL_VERSION
, $param['protocol']) ) {
963 do_err('Unable to set LDAP protocol');
966 if ( empty($param['binddn']) ) {
967 $bind = @ldap_bind
($linkid);
969 $bind = @ldap_bind
($linkid, $param['binddn'], $param['bindpw']);
973 echo "$IND LDAP Bind Successful <br />";
975 do_err('Unable to Bind to LDAP Server');
978 @ldap_close
($linkid);
980 do_err('Connection to LDAP failed');
986 echo '<hr width="75%" align="center">';
987 echo '<h2 align="center">Summary</h2>';
988 $footer = '<hr width="75%" align="center">';
990 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>';
994 <p
>Congratulations
, your SquirrelMail setup looks fine to me
!</p
>
996 <p
><a href
="login.php">Login now
</a
></p
>