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 global $disable_plugins;
121 $squirrelmail_plugin_hooks = array();
122 if (!$disable_plugins && file_exists(SM_PATH
. 'config/plugin_hooks.php')) {
123 require(SM_PATH
. 'config/plugin_hooks.php');
126 /** Warning counter */
130 $IND = str_repeat(' ',4);
133 * get_location starts session and must be run before output is started.
135 $test_location = get_location();
137 ?
><!DOCTYPE HTML
PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
138 "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">
141 <meta name
="robots" content
="noindex,nofollow">
142 <title
>SquirrelMail configtest
</title
>
145 <h1
>SquirrelMail configtest
</h1
>
147 <p
>This script will
try to check some aspects of your SquirrelMail configuration
148 and point you to errors whereever it can find them
. You need to go run
<tt
>conf
.pl
</tt
>
149 in the
<tt
>config
/</tt
> directory first before you run this script
.</p
>
153 $included = array_map('basename', get_included_files() );
154 if(!in_array('config.php', $included)) {
155 if(!file_exists(SM_PATH
. 'config/config.php')) {
156 do_err('Config file '.SM_PATH
. 'config/config.php does not exist!<br />'.
157 'You need to run <tt>conf.pl</tt> first.');
159 do_err('Could not read '.SM_PATH
.'config/config.php! Check file permissions.');
161 if(!in_array('strings.php', $included)) {
162 do_err('Could not include '.SM_PATH
.'functions/strings.php!<br />'.
163 'Check permissions on that file.');
166 /* Block remote use of script */
167 if (! $allow_remote_configtest) {
168 sqGetGlobalVar('REMOTE_ADDR',$client_ip,SQ_SERVER
);
169 sqGetGlobalVar('SERVER_ADDR',$server_ip,SQ_SERVER
);
171 if ((! isset($client_ip) ||
$client_ip!='127.0.0.1') &&
172 (! isset($client_ip) ||
! isset($server_ip) ||
$client_ip!=$server_ip)) {
173 do_err('Enable "Allow remote configtest" option in squirrelmail configuration in order to use this script.');
177 echo "<p><table>\n<tr><td>SquirrelMail version:</td><td><b>" . SM_VERSION
. "</b></td></tr>\n" .
178 '<tr><td>Config file version:</td><td><b>' . $config_version . "</b></td></tr>\n" .
179 '<tr><td>Config file last modified:</td><td><b>' .
180 date ('d F Y H:i:s', filemtime(SM_PATH
. 'config/config.php')) .
181 "</b></td></tr>\n</table>\n</p>\n\n";
183 /* check $config_version */
184 if ($config_version!='1.5.0') {
185 do_err('Configuration file version does not match required version. Please update your configuration file.');
189 /* checking PHP specs */
191 echo "Checking PHP configuration...<br />\n";
193 if(!check_php_version(4,1,0)) {
194 do_err('Insufficient PHP version: '. PHP_VERSION
. '! Minimum required: 4.1.0');
197 echo $IND . 'PHP version ' . PHP_VERSION
. ' OK. (You have: ' . phpversion() . ". Minimum: 4.1.0)<br />\n";
199 echo $IND . 'display_errors: ' . ini_get('display_errors') . "<br />\n";
201 echo $IND . 'error_reporting: ' . ini_get('error_reporting') . "<br />\n";
203 $safe_mode = ini_get('safe_mode');
205 echo $IND . 'safe_mode: ' . $safe_mode;
206 if (empty($prefs_dsn) ||
empty($addrbook_dsn))
207 echo ' (<font color="red">double check data and attachment directory ownership, etc!</font>)';
208 if (!empty($addrbook_dsn) ||
!empty($prefs_dsn) ||
!empty($addrbook_global_dsn))
209 echo ' (<font color="red">does PHP have access to database interface?</font>)';
211 $safe_mode_exec_dir = ini_get('safe_mode_exec_dir');
212 echo $IND . 'safe_mode_exec_dir: ' . $safe_mode_exec_dir . "<br />\n";
215 /* register_globals check: test for boolean false and any string that is not equal to 'off' */
217 if ((bool) ini_get('register_globals') &&
218 strtolower(ini_get('register_globals'))!='off') {
219 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);
223 /* variables_order check */
225 // 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
226 $variables_order = strtoupper(ini_get('variables_order'));
227 if (empty($variables_order))
228 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);
229 else if (strpos($variables_order, 'G') === FALSE
230 ||
strpos($variables_order, 'P') === FALSE
231 ||
strpos($variables_order, 'C') === FALSE
232 ||
strpos($variables_order, 'S') === FALSE) {
233 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);
235 echo $IND . "variables_order OK: $variables_order.<br />\n";
239 /* gpc_order check (removed from PHP as of v5.0) */
241 if (!check_php_version(5)) {
242 // 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
243 $gpc_order = strtoupper(ini_get('gpc_order'));
244 if (empty($gpc_order))
245 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);
246 else if (strpos($gpc_order, 'G') === FALSE
247 ||
strpos($gpc_order, 'P') === FALSE
248 ||
strpos($gpc_order, 'C') === FALSE) {
249 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);
251 echo $IND . "gpc_order OK: $gpc_order.<br />\n";
256 /* check PHP extensions */
258 $php_exts = array('session','pcre');
259 $diff = array_diff($php_exts, get_loaded_extensions());
261 do_err('Required PHP extensions missing: '.implode(', ',$diff) );
264 echo $IND . "PHP extensions OK. Dynamic loading is ";
266 if (!(bool)ini_get('enable_dl') ||
(bool)ini_get('safe_mode')) {
267 echo "disabled.<br />\n";
269 echo "enabled.<br />\n";
273 /* dangerous php settings */
275 * mbstring.func_overload allows to replace original string and regexp functions
276 * with their equivalents from php mbstring extension. It causes problems when
277 * scripts analyze 8bit strings byte after byte or use 8bit strings in regexp tests.
278 * Setting can be controlled in php.ini (php 4.2.0), webserver config (php 4.2.0)
279 * and .htaccess files (php 4.3.5).
281 if (function_exists('mb_internal_encoding') &&
282 check_php_version(4,2,0) &&
283 (int)ini_get('mbstring.func_overload')!=0) {
284 $mb_error='You have enabled mbstring overloading.'
285 .' It can cause problems with SquirrelMail scripts that rely on single byte string functions.';
290 * Do not use SquirrelMail with magic_quotes_* on.
292 if ( (function_exists('get_magic_quotes_runtime') && @get_magic_quotes_runtime
()) ||
293 (function_exists('get_magic_quotes_gpc') && @get_magic_quotes_gpc
()) ||
294 ( (bool) ini_get('magic_quotes_sybase') && ini_get('magic_quotes_sybase') != 'off' )
296 $magic_quotes_warning='You have enabled any one of <tt>magic_quotes_runtime</tt>, '
297 .'<tt>magic_quotes_gpc</tt> or <tt>magic_quotes_sybase</tt> in your PHP '
298 .'configuration. We recommend all those settings to be off. SquirrelMail '
299 .'may work with them on, but when experiencing stray backslashes in your mail '
300 .'or other strange behaviour, it may be advisable to turn them off.';
301 do_err($magic_quotes_warning,false);
304 if (ini_get('short_open_tag') == 0) {
305 $short_open_tag_warning = 'You have configured PHP not to allow short tags '
306 . '(<tt>short_open_tag=off</tt>). This shouldn\'t be a problem with '
307 . 'SquirrelMail or any plugin coded coded according to the '
308 . 'SquirrelMail Coding Guidelines, but if you experience problems with '
309 . 'PHP code being displayed in some of the pages and changing setting '
310 . 'to "on" solves the problem, please file a bug report against the '
311 . 'failing plugin. The correct contact information is most likely '
312 . 'to be found in the plugin documentation.';
313 do_err($short_open_tag_warning, false);
318 echo "Checking paths...<br />\n";
320 if(!file_exists($data_dir)) {
321 // data_dir is not that important in db_setups.
322 if (!empty($prefs_dsn)) {
323 $data_dir_error = "Data dir ($data_dir) does not exist!\n";
324 echo $IND .'<font color="red"><b>ERROR:</b></font> ' . $data_dir_error;
326 do_err("Data dir ($data_dir) does not exist!");
329 // don't check if errors
330 if(!isset($data_dir_error) && !is_dir($data_dir)) {
331 if (!empty($prefs_dsn)) {
332 $data_dir_error = "Data dir ($data_dir) is not a directory!\n";
333 echo $IND . '<font color="red"><b>ERROR:</b></font> ' . $data_dir_error;
335 do_err("Data dir ($data_dir) is not a directory!");
338 // datadir should be executable - but no clean way to test on that
339 if(!isset($data_dir_error) && !is_writable($data_dir)) {
340 if (!empty($prefs_dsn)) {
341 $data_dir_error = "Data dir ($data_dir) is not writable!\n";
342 echo $IND . '<font color="red"><b>ERROR:</b></font> ' . $data_dir_error;
344 do_err("Data dir ($data_dir) is not writable!");
348 if (isset($data_dir_error)) {
349 echo " Some plugins might need access to data directory.<br />\n";
351 // todo_ornot: actually write something and read it back.
352 echo $IND . "Data dir OK.<br />\n";
355 if($data_dir == $attachment_dir) {
356 echo $IND . "Attachment dir is the same as data dir.<br />\n";
357 if (isset($data_dir_error)) {
358 do_err($data_dir_error);
361 if(!file_exists($attachment_dir)) {
362 do_err("Attachment dir ($attachment_dir) does not exist!");
364 if (!is_dir($attachment_dir)) {
365 do_err("Attachment dir ($attachment_dir) is not a directory!");
367 if (!is_writable($attachment_dir)) {
368 do_err("I cannot write to attachment dir ($attachment_dir)!");
370 echo $IND . "Attachment dir OK.<br />\n";
374 echo "Checking plugins...<br />\n";
376 /* check plugins and themes */
377 //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
378 //FIXME: update this list with most recent contents of the Obsolete category - I think it has changed recently
379 $bad_plugins = array(
380 'attachment_common', // Integrated into SquirrelMail 1.2 core
381 'auto_prune_sent', // Obsolete: See Proon Automatic Folder Pruning plugin
382 'compose_new_window', // Integrated into SquirrelMail 1.4 core
383 'delete_move_next', // Integrated into SquirrelMail 1.5 core
384 'disk_quota', // Obsolete: See Check Quota plugin
385 'email_priority', // Integrated into SquirrelMail 1.2 core
386 'emoticons', // Obsolete: See HTML Mail plugin
387 'focus_change', // Integrated into SquirrelMail 1.2 core
388 'folder_settings', // Integrated into SquirrelMail 1.5.1 core
389 'global_sql_addressbook', // Integrated into SquirrelMail 1.4 core
390 'hancock', // Not Working: See Random Signature Taglines plugin
391 'msg_flags', // Integrated into SquirrelMail 1.5.1 core
392 'message_source', // Added to SquirrelMail 1.4 Core Plugins (message_details)
393 'motd', // Integrated into SquirrelMail 1.2 core
394 'paginator', // Integrated into SquirrelMail 1.2 core
395 'printer_friendly', // Integrated into SquirrelMail 1.2 core
396 'procfilter', // Obsolete: See Server Side Filter plugin
397 'redhat_php_cgi_fix', // Integrated into SquirrelMail 1.1.1 core
398 'send_to_semicolon', // Integrated into SquirrelMail 1.4.1 core
399 'spamassassin', // Not working beyond SquirrelMail 1.2.7: See Spamassassin SpamFilter (Frontend) v2 plugin
400 'sqcalendar', // Added to SquirrelMail 1.2 Core Plugins (calendar)
401 'sqclock', // Integrated into SquirrelMail 1.2 core
402 'sql_squirrel_logger', // Obsolete: See Squirrel Logger plugin
403 'tmda', // Obsolete: See TMDA Tools plugin
404 'vacation', // Obsolete: See Vacation Local plugin
405 'view_as_html', // Integrated into SquirrelMail 1.5.1 core
406 'xmailer' // Integrated into SquirrelMail 1.2 core
409 if (isset($plugins[0])) {
410 foreach($plugins as $plugin) {
411 if(!file_exists(SM_PATH
.'plugins/'.$plugin)) {
412 do_err('You have enabled the <i>'.$plugin.'</i> plugin, but I cannot find it.', FALSE);
413 } elseif (!is_readable(SM_PATH
.'plugins/'.$plugin.'/setup.php')) {
414 do_err('You have enabled the <i>'.$plugin.'</i> plugin, but I cannot read its setup.php file.', FALSE);
415 } elseif (in_array($plugin, $bad_plugins)) {
416 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);
419 // load plugin functions
420 include_once(SM_PATH
. 'functions/plugin.php');
421 // turn on output buffering in order to prevent output of new lines
423 foreach ($plugins as $name) {
426 // get output and remove whitespace
427 $output = trim(ob_get_contents());
429 // if plugins output more than newlines and spacing, stop script execution.
430 if (!empty($output)) {
431 //FIXME: if the output buffer is checked INSIDE the foreach loop above, we can tell the user WHICH plugin has the problem - seems like a good idea
432 $plugin_load_error = 'Some output is produced when plugins are loaded. Usually this means there is an error in one of the plugin setup or configuration files. The output was: '.htmlspecialchars($output);
433 do_err($plugin_load_error);
436 * Print plugin versions
438 echo $IND . "Plugin versions...<br />\n";
439 foreach ($plugins as $name) {
440 $plugin_version = get_plugin_version($name);
441 $english_name = get_plugin_requirement($name, 'english_name');
442 echo $IND . $IND . (empty($english_name) ?
$name . ' ' : $english_name . ' (' . $name . ') ') . (empty($plugin_version) ?
'??' : $plugin_version) . "<br />\n";
444 // check if this plugin has any other plugin
445 // dependencies and if they are satisfied
447 $failed_dependencies = check_plugin_dependencies($name);
448 if ($failed_dependencies === SQ_INCOMPATIBLE
) {
449 do_err($name . ' is NOT COMPATIBLE with this version of SquirrelMail', FALSE);
451 else if (is_array($failed_dependencies)) {
452 $missing_plugins = '';
453 foreach ($failed_dependencies as $depend_name => $depend_requirements) {
454 $missing_plugins .= ', ' . $depend_name . ' (version ' . $depend_requirements['version'] . ', ' . ($depend_requirements['activate'] ?
'must be activated' : 'need not be activated') . ')';
456 do_err($name . ' is missing some dependencies: ' . trim($missing_plugins, ', '), FALSE);
461 * This hook was added in 1.5.2 and 1.4.10. Each plugins should print an error
462 * message and return TRUE if there are any errors in its setup/configuration.
464 $plugin_err = boolean_hook_function('configtest', $null, 1);
466 do_err('Some plugin tests failed.');
468 echo $IND . "Plugins OK.<br />\n";
471 echo $IND . "Plugins are not enabled in config.<br />\n";
473 foreach($theme as $thm) {
474 if(!file_exists($thm['PATH'])) {
475 do_err('You have enabled the <i>'.$thm['NAME'].'</i> theme but I cannot find it ('.$thm['PATH'].').', FALSE);
476 } elseif(!is_readable($thm['PATH'])) {
477 do_err('You have enabled the <i>'.$thm['NAME'].'</i> theme but I cannot read it ('.$thm['PATH'].').', FALSE);
481 echo $IND . "Themes OK.<br />\n";
483 if ( $squirrelmail_default_language != 'en_US' ) {
484 $loc_path = SM_PATH
.'locale/'.$squirrelmail_default_language.'/LC_MESSAGES/squirrelmail.mo';
485 if( ! file_exists( $loc_path ) ) {
486 do_err('You have set <i>' . $squirrelmail_default_language .
487 '</i> as your default language, but I cannot find this translation (should be '.
488 'in <tt>' . $loc_path . '</tt>). Please note that you have to download translations '.
489 'separately from the main SquirrelMail package.', FALSE);
490 } elseif ( ! is_readable( $loc_path ) ) {
491 do_err('You have set <i>' . $squirrelmail_default_language .
492 '</i> as your default language, but I cannot read this translation (file '.
493 'in <tt>' . $loc_path . '</tt> unreadable).', FALSE);
495 echo $IND . "Default language OK.<br />\n";
498 echo $IND . "Default language OK.<br />\n";
501 echo $IND . "Base URL detected as: <tt>" . htmlspecialchars($test_location) .
502 "</tt> (location base " . (empty($config_location_base) ?
'autodetected' : 'set to <tt>' .
503 htmlspecialchars($config_location_base)."</tt>") . ")<br />\n";
505 /* check minimal requirements for other security options */
508 if($use_smtp_tls == 1 ||
$use_imap_tls == 1) {
509 if(!check_php_version(4,3,0)) {
510 do_err('You need at least PHP 4.3.0 for SMTP/IMAP TLS!');
512 if(!extension_loaded('openssl')) {
513 do_err('You need the openssl PHP extension to use SMTP/IMAP TLS!');
516 /* starttls extensions */
517 if($use_smtp_tls === 2 ||
$use_imap_tls === 2) {
518 if (! function_exists('stream_socket_enable_crypto')) {
519 do_err('If you want to use STARTTLS extension, you need stream_socket_enable_crypto() function from PHP 5.1.0 and newer.');
523 if ($smtp_auth_mech=='digest-md5' ||
$imap_auth_mech =='digest-md5') {
524 if (!extension_loaded('xml')) {
525 do_err('You need the PHP XML extension to use Digest-MD5 authentication!');
529 /* check outgoing mail */
531 echo "Checking outgoing mail service....<br />\n";
534 // is_executable also checks for existance, but we want to be as precise as possible with the errors
535 if(!file_exists($sendmail_path)) {
536 do_err("Location of sendmail program incorrect ($sendmail_path)!");
538 if(!is_executable($sendmail_path)) {
539 do_err("I cannot execute the sendmail program ($sendmail_path)!");
542 echo $IND . "sendmail OK<br />\n";
544 $stream = fsockopen( ($use_smtp_tls==1?
'tls://':'').$smtpServerAddress, $smtpPort,
545 $errorNumber, $errorString);
547 do_err("Error connecting to SMTP server \"$smtpServerAddress:$smtpPort\".".
548 "Server error: ($errorNumber) ".htmlspecialchars($errorString));
551 // check for SMTP code; should be 2xx to allow us access
552 $smtpline = fgets($stream, 1024);
553 if(((int) $smtpline{0}) > 3) {
554 do_err("Error connecting to SMTP server. Server error: ".
555 htmlspecialchars($smtpline));
558 /* smtp starttls checks */
559 if ($use_smtp_tls===2) {
560 // if something breaks, script should close smtp connection on exit.
563 fwrite($stream,"EHLO $client_ip\r\n");
567 while ($line=fgets($stream, 1024)){
568 if (preg_match("/^250(-|\s)(\S*)\s+(\S.*)/",$line,$match)||
569 preg_match("/^250(-|\s)(\S*)\s+/",$line,$match)) {
570 if (!isset($match[3])) {
571 // simple one word extension
572 $ehlo[strtoupper($match[2])]='';
574 // ehlo-keyword + ehlo-param
575 $ehlo[strtoupper($match[2])]=trim($match[3]);
577 if ($match[1]==' ') {
589 do_err('SMTP EHLO failed. You need ESMTP support for SMTP STARTTLS');
590 } elseif (!array_key_exists('STARTTLS',$ehlo)) {
591 do_err('STARTTLS support is not declared by SMTP server.');
594 fwrite($stream,"STARTTLS\r\n");
595 $starttls_response=fgets($stream, 1024);
596 if ($starttls_response[0]!=2) {
597 $starttls_cmd_err = 'SMTP STARTTLS failed. Server replied: '
598 .htmlspecialchars($starttls_response);
599 do_err($starttls_cmd_err);
600 } elseif(! stream_socket_enable_crypto($stream,true,STREAM_CRYPTO_METHOD_TLS_CLIENT
)) {
601 do_err('Failed to enable encryption on SMTP STARTTLS connection.');
603 echo $IND . "SMTP STARTTLS extension looks OK.<br />\n";
605 // According to RFC we should second ehlo call here.
608 fputs($stream, 'QUIT');
610 echo $IND . 'SMTP server OK (<tt><small>'.
611 trim(htmlspecialchars($smtpline))."</small></tt>)<br />\n";
613 /* POP before SMTP */
614 if($pop_before_smtp) {
615 $stream = fsockopen($smtpServerAddress, 110, $err_no, $err_str);
617 do_err("Error connecting to POP Server ($smtpServerAddress:110) "
618 . $err_no . ' : ' . htmlspecialchars($err_str));
621 $tmp = fgets($stream, 1024);
622 if (substr($tmp, 0, 3) != '+OK') {
623 do_err("Error connecting to POP Server ($smtpServerAddress:110)"
624 . ' '.htmlspecialchars($tmp));
626 fputs($stream, 'QUIT');
628 echo $IND . "POP-before-SMTP OK.<br />\n";
633 * Check the IMAP server
635 echo "Checking IMAP service....<br />\n";
637 /** Can we open a connection? */
638 $stream = fsockopen( ($use_imap_tls==1?
'tls://':'').$imapServerAddress, $imapPort,
639 $errorNumber, $errorString);
641 do_err("Error connecting to IMAP server \"$imapServerAddress:$imapPort\".".
642 "Server error: ($errorNumber) ".
643 htmlspecialchars($errorString));
646 /** Is the first response 'OK'? */
647 $imapline = fgets($stream, 1024);
648 if(substr($imapline, 0,4) != '* OK') {
649 do_err('Error connecting to IMAP server. Server error: '.
650 htmlspecialchars($imapline));
653 echo $IND . 'IMAP server ready (<tt><small>'.
654 htmlspecialchars(trim($imapline))."</small></tt>)<br />\n";
656 /** Check capabilities */
657 fputs($stream, "A001 CAPABILITY\r\n");
659 while ($line=fgets($stream, 1024)){
660 if (preg_match("/A001.*/",$line)) {
667 /* don't display capabilities before STARTTLS */
668 if ($use_imap_tls===2 && stristr($capline, 'STARTTLS') === false) {
669 do_err('Your server doesn\'t support STARTTLS.');
670 } elseif($use_imap_tls===2) {
671 /* try starting starttls */
672 fwrite($stream,"A002 STARTTLS\r\n");
673 $starttls_line=fgets($stream, 1024);
674 if (! preg_match("/^A002 OK.*/i",$starttls_line)) {
675 $imap_starttls_err = 'IMAP STARTTLS failed. Server replied: '
676 .htmlspecialchars($starttls_line);
677 do_err($imap_starttls_err);
678 } elseif (! stream_socket_enable_crypto($stream,true,STREAM_CRYPTO_METHOD_TLS_CLIENT
)) {
679 do_err('Failed to enable encryption on IMAP connection.');
681 echo $IND . "IMAP STARTTLS extension looks OK.<br />\n";
684 // get new capability line
685 fwrite($stream,"A003 CAPABILITY\r\n");
687 while ($line=fgets($stream, 1024)){
688 if (preg_match("/A003.*/",$line)) {
696 echo $IND . 'Capabilities: <tt>'.htmlspecialchars($capline)."</tt><br />\n";
698 if($imap_auth_mech == 'login' && stristr($capline, 'LOGINDISABLED') !== FALSE) {
699 do_err('Your server doesn\'t allow plaintext logins. '.
700 'Try enabling another authentication mechanism like CRAM-MD5, DIGEST-MD5 or TLS-encryption '.
701 'in the SquirrelMail configuration.', FALSE);
704 if (stristr($capline, 'XMAGICTRASH') !== false) {
705 $magic_trash = 'It looks like IMAP_MOVE_EXPUNGE_TO_TRASH option is turned on '
706 .'in your Courier IMAP configuration. Courier does not provide tools that '
707 .'allow to detect folder used for Trash or commands are not documented. '
708 .'SquirrelMail can\'t detect special trash folder. SquirrelMail manages '
709 .'all message deletion or move operations internally and '
710 .'IMAP_MOVE_EXPUNGE_TO_TRASH option can cause errors in message and '
711 .'folder management operations. Please turn off IMAP_MOVE_EXPUNGE_TO_TRASH '
712 .'option in Courier imapd configuration.';
713 do_err($magic_trash,false);
716 /* add warning about IMAP delivery */
717 if (stristr($capline, 'XCOURIEROUTBOX') !== false) {
718 $courier_outbox = 'OUTBOX setting is enabled in your Courier imapd '
719 .'configuration. SquirrelMail uses standard SMTP protocol or sendmail '
720 .'binary to send emails. Courier IMAP delivery method is not supported'
721 .' and can create duplicate email messages.';
722 do_err($courier_outbox,false);
725 /** OK, close connection */
726 fputs($stream, "A004 LOGOUT\r\n");
729 echo "Checking internationalization (i18n) settings...<br />\n";
730 echo "$IND gettext - ";
731 if (function_exists('gettext')) {
732 echo 'Gettext functions are available.'
733 .' On some systems you must have appropriate system locales compiled.'
736 /* optional setlocale() tests. Should work only on glibc systems. */
737 if (sqgetGlobalVar('testlocales',$testlocales,SQ_GET
)) {
738 include_once(SM_PATH
. 'include/languages.php');
739 echo $IND . $IND . 'Testing translations:<br>';
740 foreach ($languages as $lang_code => $lang_data) {
741 /* don't test aliases */
742 if (isset($lang_data['NAME'])) {
743 /* locale can be $lang_code or $lang_data['LOCALE'] */
744 if (isset($lang_data['LOCALE'])) {
745 $setlocale = $lang_data['LOCALE'];
747 $setlocale = $lang_code;
749 /* prepare information about tested locales */
750 if (is_array($setlocale)) {
751 $display_locale = implode(', ',$setlocale);
752 $locale_count = count($setlocale);
754 $display_locale = $setlocale;
757 $tested_locales_msg = 'Tested '.htmlspecialchars($display_locale).' '
758 .($locale_count>1 ?
'locales':'locale'). '.';
760 echo $IND . $IND .$IND . $lang_data['NAME'].' (' .$lang_code. ') - ';
761 $retlocale = sq_setlocale(LC_ALL
,$setlocale);
762 if (is_bool($retlocale)) {
763 echo '<font color="red">unsupported</font>. ';
764 echo $tested_locales_msg;
768 .' setlocale() returned "'.htmlspecialchars($retlocale).'"';
773 echo $IND . $IND . '<a href="configtest.php">Don\'t test translations</a>';
775 echo $IND . $IND . '<a href="configtest.php?testlocales=1">Test translations</a>. '
776 .'This test is not accurate and might work only on some systems.'
780 /* end of translation tests */
782 echo 'Gettext functions are unavailable.'
783 .' SquirrelMail will use slower internal gettext functions.'
786 echo "$IND mbstring - ";
787 if (function_exists('mb_detect_encoding')) {
788 echo "Mbstring functions are available.<br />\n";
790 echo 'Mbstring functions are unavailable.'
791 ." Japanese translation won't work.<br />\n";
793 echo "$IND recode - ";
794 if (function_exists('recode')) {
795 echo "Recode functions are available.<br />\n";
796 } elseif (isset($use_php_recode) && $use_php_recode) {
797 echo "Recode functions are unavailable.<br />\n";
798 do_err('Your configuration requires recode support, but recode support is missing.');
800 echo "Recode functions are unavailable.<br />\n";
802 echo "$IND iconv - ";
803 if (function_exists('iconv')) {
804 echo "Iconv functions are available.<br />\n";
805 } elseif (isset($use_php_iconv) && $use_php_iconv) {
806 echo "Iconv functions are unavailable.<br />\n";
807 do_err('Your configuration requires iconv support, but iconv support is missing.');
809 echo "Iconv functions are unavailable.<br />\n";
811 // same test as in include/init.php + date_default_timezone_set check
812 echo "$IND timezone - ";
813 if ( (!ini_get('safe_mode')) ||
function_exists('date_default_timezone_set') ||
814 !strcmp(ini_get('safe_mode_allowed_env_vars'),'') ||
815 preg_match('/^([\w_]+,)*TZ/', ini_get('safe_mode_allowed_env_vars')) ) {
816 echo "Webmail users can change their time zone settings. \n";
818 echo "Webmail users can't change their time zone settings. \n";
820 if (isset($_ENV['TZ'])) {
821 echo 'Default time zone is '.htmlspecialchars($_ENV['TZ']);
823 echo 'Current time zone is '.date('T');
828 echo "Checking database functions...<br />\n";
829 if($addrbook_dsn ||
$prefs_dsn ||
$addrbook_global_dsn) {
830 @include_once
('DB.php');
831 if (class_exists('DB')) {
832 echo "$IND PHP Pear DB support is present.<br />\n";
834 'dbase' => 'dbase_open',
835 'fbsql' => 'fbsql_connect',
836 'interbase' => 'ibase_connect',
837 'informix' => 'ifx_connect',
838 'msql' => 'msql_connect',
839 'mssql' => 'mssql_connect',
840 'mysql' => 'mysql_connect',
841 'mysqli' => 'mysqli_connect',
842 'oci8' => 'ocilogon',
843 'odbc' => 'odbc_connect',
844 'pgsql' => 'pg_connect',
845 'sqlite' => 'sqlite_open',
846 'sybase' => 'sybase_connect'
851 $dsns['preferences'] = $prefs_dsn;
854 $dsns['addressbook'] = $addrbook_dsn;
856 if($addrbook_global_dsn) {
857 $dsns['global addressbook'] = $addrbook_global_dsn;
860 foreach($dsns as $type => $dsn) {
861 $aDsn = explode(':', $dsn);
862 $dbtype = array_shift($aDsn);
864 if(isset($db_functions[$dbtype]) && function_exists($db_functions[$dbtype])) {
865 echo "$IND$dbtype database support present.<br />\n";
866 } elseif(!(bool)ini_get('enable_dl') ||
(bool)ini_get('safe_mode')) {
867 do_err($dbtype.' database support not present!');
870 do_err($dbtype.' database support not present or not configured!
871 Trying to dynamically load '.$dbtype.' extension.
872 Please note that it is advisable to not rely on dynamic loading of extensions.', FALSE);
876 // now, test this interface:
878 $dbh = DB
::connect($dsn, true);
879 if (DB
::isError($dbh)) {
880 do_err('Database error: '. htmlspecialchars(DB
::errorMessage($dbh)) .
881 ' in ' .$type .' DSN.');
884 echo "$IND$type database connect successful.<br />\n";
887 $db_error='Required PHP PEAR DB support is not available.'
888 .' Is PEAR installed and is the include path set correctly to find <tt>DB.php</tt>?'
889 .' The include path is now: "<tt>' . ini_get('include_path') . '</tt>".';
893 echo $IND."not using database functionality.<br />\n";
897 echo "Checking LDAP functions...<br />\n";
898 if( empty($ldap_server) ) {
899 echo $IND."not using LDAP functionality.<br />\n";
901 if ( !function_exists('ldap_connect') ) {
902 do_err('Required LDAP support is not available.');
904 echo "$IND LDAP support present.<br />\n";
905 foreach ( $ldap_server as $param ) {
907 $linkid = @ldap_connect
($param['host'], (empty($param['port']) ?
389 : $param['port']) );
910 echo "$IND LDAP connect to ".$param['host']." successful: ".$linkid."<br />\n";
912 if ( !empty($param['protocol']) &&
913 !ldap_set_option($linkid, LDAP_OPT_PROTOCOL_VERSION
, $param['protocol']) ) {
914 do_err('Unable to set LDAP protocol');
917 if ( empty($param['binddn']) ) {
918 $bind = @ldap_bind
($linkid);
920 $bind = @ldap_bind
($param['binddn'], $param['bindpw']);
924 echo "$IND LDAP Bind Successful <br />";
926 do_err('Unable to Bind to LDAP Server');
929 @ldap_close
($linkid);
931 do_err('Connection to LDAP failed');
937 echo '<hr width="75%" align="center">';
938 echo '<h2 align="center">Summary</h2>';
939 $footer = '<hr width="75%" align="center">';
941 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>';
945 <p
>Congratulations
, your SquirrelMail setup looks fine to me
!</p
>
947 <p
><a href
="login.php">Login now
</a
></p
>