4 * SquirrelMail configtest script
6 * @copyright © 2003-2006 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 script could really use some restructuring as it has grown quite rapidly
19 // but is not very 'clean'. Feel free to get some structure into this thing.
22 function do_err($str, $fatal = TRUE) {
23 global $IND, $warnings;
24 $level = $fatal ?
'FATAL ERROR:' : 'WARNING:';
25 echo '<p>'.$IND.'<font color="red"><b>' . $level . '</b></font> ' .$str. "</p>\n";
27 echo '</body></html>';
34 $IND = str_repeat(' ',4);
38 define('SM_PATH', '../');
40 /* set default value in order to block remote access to script */
41 $allow_remote_configtest=false;
44 * Load config before output begins. functions/strings.php depends on
45 * functions/globals.php. functions/global.php needs to be run before
46 * any html output starts. If config.php is missing, error will be displayed
49 if (file_exists(SM_PATH
. 'config/config.php')) {
50 include(SM_PATH
. 'config/config.php');
51 include(SM_PATH
. 'functions/strings.php');
53 ?
><!DOCTYPE HTML
PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
54 "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">
57 <meta name
="robots" content
="noindex,nofollow">
58 <title
>SquirrelMail configtest
</title
>
61 <h1
>SquirrelMail configtest
</h1
>
63 <p
>This script will
try to check some aspects of your SquirrelMail configuration
64 and point you to errors whereever it can find them
. You need to go run
<tt
>conf
.pl
</tt
>
65 in the
<tt
>config
/</tt
> directory first before you run this script
.</p
>
69 $included = array_map('basename', get_included_files() );
70 if(!in_array('config.php', $included)) {
71 if(!file_exists(SM_PATH
. 'config/config.php')) {
72 do_err('Config file '.SM_PATH
. 'config/config.php does not exist!<br />'.
73 'You need to run <tt>conf.pl</tt> first.');
75 do_err('Could not read '.SM_PATH
.'config/config.php! Check file permissions.');
77 if(!in_array('strings.php', $included)) {
78 do_err('Could not include '.SM_PATH
.'functions/strings.php!<br />'.
79 'Check permissions on that file.');
82 /* Block remote use of script */
83 if (! $allow_remote_configtest) {
84 sqGetGlobalVar('REMOTE_ADDR',$client_ip,SQ_SERVER
);
85 sqGetGlobalVar('SERVER_ADDR',$server_ip,SQ_SERVER
);
87 if ((! isset($client_ip) ||
$client_ip!='127.0.0.1') &&
88 (! isset($client_ip) ||
! isset($server_ip) ||
$client_ip!=$server_ip)) {
89 do_err('Enable "Allow remote configtest" option in squirrelmail configuration in order to use this script.');
92 /* checking PHP specs */
94 echo "<p><table>\n<tr><td>SquirrelMail version:</td><td><b>" . $version . "</b></td></tr>\n" .
95 '<tr><td>Config file version:</td><td><b>' . $config_version . "</b></td></tr>\n" .
96 '<tr><td>Config file last modified:</td><td><b>' .
97 date ('d F Y H:i:s', filemtime(SM_PATH
. 'config/config.php')) .
98 "</b></td></tr>\n</table>\n</p>\n\n";
100 /* check $config_version */
101 if ($config_version!='1.4.0') {
102 do_err('Configuration file version does not match required version. Please update your configuration file.');
105 echo "Checking PHP configuration...<br />\n";
107 if(!check_php_version(4,1,0)) {
108 do_err('Insufficient PHP version: '. PHP_VERSION
. '! Minimum required: 4.1.0');
111 echo $IND . 'PHP version ' . PHP_VERSION
. ' OK. (You have: ' . phpversion() . ". Minimum: 4.1.0)<br />\n";
113 $php_exts = array('session','pcre');
114 $diff = array_diff($php_exts, get_loaded_extensions());
116 do_err('Required PHP extensions missing: '.implode(', ',$diff) );
119 echo $IND . "PHP extensions OK.<br />\n";
121 /* dangerous php settings */
123 * mbstring.func_overload allows to replace original string and regexp functions
124 * with their equivalents from php mbstring extension. It causes problems when
125 * scripts analyze 8bit strings byte after byte or use 8bit strings in regexp tests.
126 * Setting can be controlled in php.ini (php 4.2.0), webserver config (php 4.2.0)
127 * and .htaccess files (php 4.3.5).
129 if (function_exists('mb_internal_encoding') &&
130 check_php_version(4,2,0) &&
131 (int)ini_get('mbstring.func_overload')!=0) {
132 $mb_error='You have enabled mbstring overloading.'
133 .' It can cause problems with SquirrelMail scripts that rely on single byte string functions.';
139 echo "Checking paths...<br />\n";
141 if(!file_exists($data_dir)) {
142 // data_dir is not that important in db_setups.
143 if (isset($prefs_dsn) && ! empty($prefs_dsn)) {
144 $data_dir_error = "Data dir ($data_dir) does not exist!\n";
145 echo $IND .'<font color="red"><b>ERROR:</b></font> ' . $data_dir_error;
147 do_err("Data dir ($data_dir) does not exist!");
150 // don't check if errors
151 if(!isset($data_dir_error) && !is_dir($data_dir)) {
152 if (isset($prefs_dsn) && ! empty($prefs_dsn)) {
153 $data_dir_error = "Data dir ($data_dir) is not a directory!\n";
154 echo $IND . '<font color="red"><b>ERROR:</b></font> ' . $data_dir_error;
156 do_err("Data dir ($data_dir) is not a directory!");
159 // datadir should be executable - but no clean way to test on that
160 if(!isset($data_dir_error) && !is_writable($data_dir)) {
161 if (isset($prefs_dsn) && ! empty($prefs_dsn)) {
162 $data_dir_error = "Data dir ($data_dir) is not writable!\n";
163 echo $IND . '<font color="red"><b>ERROR:</b></font> ' . $data_dir_error;
165 do_err("Data dir ($data_dir) is not writable!");
169 if (isset($data_dir_error)) {
170 echo " Some plugins might need access to data directory.<br />\n";
172 // todo_ornot: actually write something and read it back.
173 echo $IND . "Data dir OK.<br />\n";
176 if($data_dir == $attachment_dir) {
177 echo $IND . "Attachment dir is the same as data dir.<br />\n";
178 if (isset($data_dir_error)) {
179 do_err($data_dir_error);
182 if(!file_exists($attachment_dir)) {
183 do_err("Attachment dir ($attachment_dir) does not exist!");
185 if (!is_dir($attachment_dir)) {
186 do_err("Attachment dir ($attachment_dir) is not a directory!");
188 if (!is_writable($attachment_dir)) {
189 do_err("I cannot write to attachment dir ($attachment_dir)!");
191 echo $IND . "Attachment dir OK.<br />\n";
195 /* check plugins and themes */
196 $bad_plugins = array(
197 'attachment_common', // Integrated into SM 1.2 Core
198 'auto_prune_sent', // Obsolete: See Proon Automatic Folder Pruning plugin
199 'compose_new_window', // Integrated into SM 1.4 Core
200 'delete_move_next', // Integrated into SM 1.5 Core
201 'disk_quota', // Obsolete: See Check Quota plugin
202 'email_priority', // Integrated into SM 1.2 Core
203 'emoticons', // Obsolete: See HTML Mail plugin
204 'focus_change', // Integrated into SM 1.2 Core
205 'folder_preferences', //
206 'global_sql_addressbook', // Integrated into SM 1.4 Core
207 'hancock', // Not Working: See Random Signature Taglines plugin
208 'message_source', // Added to SM 1.4 Core Plugins (message_details)
209 'motd', // Integrated into SM 1.2 Core
210 'paginator', // Integrated into SM 1.2 Core
211 'printer_friendly', // Integrated into SM 1.2 Core
212 'procfilter', // Obsolete: See Server Side Filter plugin
213 'redhat_php_cgi_fix', // Integrated into SM 1.1.1 Core
214 'send_to_semicolon', // Integrated into SM 1.4.1 Core
215 'spamassassin', // Not working beyond SM 1.2.7: See Spamassassin SpamFilter (Frontend) v2 plugin
216 'sqcalendar', // Added to SM 1.2 Core Plugins (calendar)
217 'sqclock', // Integrated into SM 1.2 Core
218 'sql_squirrel_logger', // Obsolete: See Squirrel Logger plugin
219 'tmda', // Obsolete: See TMDA Tools plugin
220 'vacation', // Obsolete: See Vacation Local plugin
221 'view_as_html', // Integrated into SM 1.5.1 Core
222 'xmailer' // Integrated into SM 1.2 Core
225 if (isset($plugins[0])) {
226 foreach($plugins as $plugin) {
227 if(!file_exists(SM_PATH
.'plugins/'.$plugin)) {
228 do_err('You have enabled the <i>'.$plugin.'</i> plugin, but I cannot find it.', FALSE);
229 } elseif (!is_readable(SM_PATH
.'plugins/'.$plugin.'/setup.php')) {
230 do_err('You have enabled the <i>'.$plugin.'</i> plugin, but I cannot read its setup.php file.', FALSE);
231 } elseif (in_array($plugin, $bad_plugins)) {
232 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);
235 echo $IND . "Plugins OK.<br />\n";
237 echo $IND . "Plugins are not enabled in config.<br />\n";
239 foreach($theme as $thm) {
240 if(!file_exists($thm['PATH'])) {
241 do_err('You have enabled the <i>'.$thm['NAME'].'</i> theme but I cannot find it ('.$thm['PATH'].').', FALSE);
242 } elseif(!is_readable($thm['PATH'])) {
243 do_err('You have enabled the <i>'.$thm['NAME'].'</i> theme but I cannot read it ('.$thm['PATH'].').', FALSE);
247 echo $IND . "Themes OK.<br />\n";
249 if ( $squirrelmail_default_language != 'en_US' ) {
250 $loc_path = SM_PATH
.'locale/'.$squirrelmail_default_language.'/LC_MESSAGES/squirrelmail.mo';
251 if( ! file_exists( $loc_path ) ) {
252 do_err('You have set <i>' . $squirrelmail_default_language .
253 '</i> as your default language, but I cannot find this translation (should be '.
254 'in <tt>' . $loc_path . '</tt>). Please note that you have to download translations '.
255 'separately from the main SquirrelMail package.', FALSE);
256 } elseif ( ! is_readable( $loc_path ) ) {
257 do_err('You have set <i>' . $squirrelmail_default_language .
258 '</i> as your default language, but I cannot read this translation (file '.
259 'in <tt>' . $loc_path . '</tt> unreadable).', FALSE);
261 echo $IND . "Default language OK.<br />\n";
264 echo $IND . "Default language OK.<br />\n";
267 echo $IND . "Base URL detected as: <tt>" . htmlspecialchars(get_location()) . "</tt><br />\n";
269 /* check minimal requirements for other security options */
272 if($use_smtp_tls == 1 ||
$use_imap_tls == 1) {
273 if(!check_php_version(4,3,0)) {
274 do_err('You need at least PHP 4.3.0 for SMTP/IMAP TLS!');
276 if(!extension_loaded('openssl')) {
277 do_err('You need the openssl PHP extension to use SMTP/IMAP TLS!');
280 /* starttls extensions */
281 if($use_smtp_tls == 2 ||
$use_imap_tls == 2) {
282 if (! function_exists('stream_socket_enable_crypto')) {
283 do_err('If you want to use STARTTLS extension, you need stream_socket_enable_crypto() function from PHP 5.1.0 and newer.');
287 if ($smtp_auth_mech=='digest-md5' ||
$imap_auth_mech =='digest-md5') {
288 if (!extension_loaded('xml')) {
289 do_err('You need the PHP XML extension to use Digest-MD5 authentication!');
293 /* check outgoing mail */
295 echo "Checking outgoing mail service....<br />\n";
298 // is_executable also checks for existance, but we want to be as precise as possible with the errors
299 if(!file_exists($sendmail_path)) {
300 do_err("Location of sendmail program incorrect ($sendmail_path)!");
302 if(!is_executable($sendmail_path)) {
303 do_err("I cannot execute the sendmail program ($sendmail_path)!");
306 echo $IND . "sendmail OK<br />\n";
308 $stream = fsockopen( ($use_smtp_tls==1?
'tls://':'').$smtpServerAddress, $smtpPort,
309 $errorNumber, $errorString);
311 do_err("Error connecting to SMTP server \"$smtpServerAddress:$smtpPort\".".
312 "Server error: ($errorNumber) ".htmlspecialchars($errorString));
315 // check for SMTP code; should be 2xx to allow us access
316 $smtpline = fgets($stream, 1024);
317 if(((int) $smtpline{0}) > 3) {
318 do_err("Error connecting to SMTP server. Server error: ".
319 htmlspecialchars($smtpline));
322 /* smtp starttls checks */
323 if ($use_smtp_tls==2) {
324 // if something breaks, script should close smtp connection on exit.
327 fwrite($stream,"EHLO $client_ip\r\n");
331 while ($line=fgets($stream, 1024)){
332 if (preg_match("/^250(-|\s)(\S*)\s+(\S.*)/",$line,$match)||
333 preg_match("/^250(-|\s)(\S*)\s+/",$line,$match)) {
334 if (!isset($match[3])) {
335 // simple one word extension
336 $ehlo[strtoupper($match[2])]='';
338 // ehlo-keyword + ehlo-param
339 $ehlo[strtoupper($match[2])]=trim($match[3]);
341 if ($match[1]==' ') {
353 do_err('SMTP EHLO failed. You need ESMTP support for SMTP STARTTLS');
354 } elseif (!array_key_exists('STARTTLS',$ehlo)) {
355 do_err('STARTTLS support is not declared by SMTP server.');
358 fwrite($stream,"STARTTLS\r\n");
359 $starttls_response=fgets($stream, 1024);
360 if ($starttls_response[0]!=2) {
361 $starttls_cmd_err = 'SMTP STARTTLS failed. Server replied: '
362 .htmlspecialchars($starttls_response);
363 do_err($starttls_cmd_err);
364 } elseif(! stream_socket_enable_crypto($stream,true,STREAM_CRYPTO_METHOD_TLS_CLIENT
)) {
365 do_err('Failed to enable encryption on SMTP STARTTLS connection.');
367 echo $IND . "SMTP STARTTLS extension looks OK.<br />\n";
369 // According to RFC we should second ehlo call here.
372 fputs($stream, 'QUIT');
374 echo $IND . 'SMTP server OK (<tt><small>'.
375 trim(htmlspecialchars($smtpline))."</small></tt>)<br />\n";
377 /* POP before SMTP */
378 if($pop_before_smtp) {
379 $stream = fsockopen($smtpServerAddress, 110, $err_no, $err_str);
381 do_err("Error connecting to POP Server ($smtpServerAddress:110) "
382 . $err_no . ' : ' . htmlspecialchars($err_str));
385 $tmp = fgets($stream, 1024);
386 if (substr($tmp, 0, 3) != '+OK') {
387 do_err("Error connecting to POP Server ($smtpServerAddress:110)"
388 . ' '.htmlspecialchars($tmp));
390 fputs($stream, 'QUIT');
392 echo $IND . "POP-before-SMTP OK.<br />\n";
397 * Check the IMAP server
399 echo "Checking IMAP service....<br />\n";
401 /** Can we open a connection? */
402 $stream = fsockopen( ($use_imap_tls==1?
'tls://':'').$imapServerAddress, $imapPort,
403 $errorNumber, $errorString);
405 do_err("Error connecting to IMAP server \"$imapServerAddress:$imapPort\".".
406 "Server error: ($errorNumber) ".
407 htmlspecialchars($errorString));
410 /** Is the first response 'OK'? */
411 $imapline = fgets($stream, 1024);
412 if(substr($imapline, 0,4) != '* OK') {
413 do_err('Error connecting to IMAP server. Server error: '.
414 htmlspecialchars($imapline));
417 echo $IND . 'IMAP server ready (<tt><small>'.
418 htmlspecialchars(trim($imapline))."</small></tt>)<br />\n";
420 /** Check capabilities */
421 fputs($stream, "A001 CAPABILITY\r\n");
423 while ($line=fgets($stream, 1024)){
424 if (preg_match("/A001.*/",$line)) {
431 /* don't display capabilities before STARTTLS */
432 if ($use_imap_tls==2 && stristr($capline, 'STARTTLS') === false) {
433 do_err('Your server doesn\'t support STARTTLS.');
434 } elseif($use_imap_tls==2) {
435 /* try starting starttls */
436 fwrite($stream,"A002 STARTTLS\r\n");
437 $starttls_line=fgets($stream, 1024);
438 if (! preg_match("/^A002 OK.*/i",$starttls_line)) {
439 $imap_starttls_err = 'IMAP STARTTLS failed. Server replied: '
440 .htmlspecialchars($starttls_line);
441 do_err($imap_starttls_err);
442 } elseif (! stream_socket_enable_crypto($stream,true,STREAM_CRYPTO_METHOD_TLS_CLIENT
)) {
443 do_err('Failed to enable encryption on IMAP connection.');
445 echo $IND . "IMAP STARTTLS extension looks OK.<br />\n";
448 // get new capability line
449 fwrite($stream,"A003 CAPABILITY\r\n");
451 while ($line=fgets($stream, 1024)){
452 if (preg_match("/A003.*/",$line)) {
460 echo $IND . 'Capabilities: <tt>'.htmlspecialchars($capline)."</tt><br />\n";
462 if($imap_auth_mech == 'login' && stristr($capline, 'LOGINDISABLED') !== FALSE) {
463 do_err('Your server doesn\'t allow plaintext logins. '.
464 'Try enabling another authentication mechanism like CRAM-MD5, DIGEST-MD5 or TLS-encryption '.
465 'in the SquirrelMail configuration.', FALSE);
468 /** OK, close connection */
469 fputs($stream, "A004 LOGOUT\r\n");
472 echo "Checking internationalization (i18n) settings...<br />\n";
473 echo "$IND gettext - ";
474 if (function_exists('gettext')) {
475 echo 'Gettext functions are available.'
476 .' On some systems you must have appropriate system locales compiled.'
479 echo 'Gettext functions are unavailable.'
480 .' SquirrelMail will use slower internal gettext functions.'
483 echo "$IND mbstring - ";
484 if (function_exists('mb_detect_encoding')) {
485 echo "Mbstring functions are available.<br />\n";
487 echo 'Mbstring functions are unavailable.'
488 ." Japanese translation won't work.<br />\n";
490 echo "$IND recode - ";
491 if (function_exists('recode')) {
492 echo "Recode functions are available.<br />\n";
493 } elseif (isset($use_php_recode) && $use_php_recode) {
494 echo "Recode functions are unavailable.<br />\n";
495 do_err('Your configuration requires recode support, but recode support is missing.');
497 echo "Recode functions are unavailable.<br />\n";
499 echo "$IND iconv - ";
500 if (function_exists('iconv')) {
501 echo "Iconv functions are available.<br />\n";
502 } elseif (isset($use_php_iconv) && $use_php_iconv) {
503 echo "Iconv functions are unavailable.<br />\n";
504 do_err('Your configuration requires iconv support, but iconv support is missing.');
506 echo "Iconv functions are unavailable.<br />\n";
508 // same test as in include/validate.php
509 echo "$IND timezone - ";
510 if ( (!ini_get('safe_mode')) ||
511 !strcmp(ini_get('safe_mode_allowed_env_vars'),'') ||
512 preg_match('/^([\w_]+,)*TZ/', ini_get('safe_mode_allowed_env_vars')) ) {
513 echo "Webmail users can change their time zone settings.<br />\n";
515 echo "Webmail users can't change their time zone settings.<br />\n";
520 echo "Checking database functions...<br />\n";
521 if($addrbook_dsn ||
$prefs_dsn ||
$addrbook_global_dsn) {
522 @include_once
('DB.php');
523 if (class_exists('DB')) {
524 echo "$IND PHP Pear DB support is present.<br />\n";
526 'dbase' => 'dbase_open',
527 'fbsql' => 'fbsql_connect',
528 'interbase' => 'ibase_connect',
529 'informix' => 'ifx_connect',
530 'msql' => 'msql_connect',
531 'mssql' => 'mssql_connect',
532 'mysql' => 'mysql_connect',
533 'mysqli' => 'mysqli_connect',
534 'oci8' => 'ocilogon',
535 'odbc' => 'odbc_connect',
536 'pgsql' => 'pg_connect',
537 'sqlite' => 'sqlite_open',
538 'sybase' => 'sybase_connect'
543 $dsns['preferences'] = $prefs_dsn;
546 $dsns['addressbook'] = $addrbook_dsn;
548 if($addrbook_global_dsn) {
549 $dsns['global addressbook'] = $addrbook_global_dsn;
552 foreach($dsns as $type => $dsn) {
553 $aDsn = explode(':', $dsn);
554 $dbtype = array_shift($aDsn);
555 if(isset($db_functions[$dbtype]) && function_exists($db_functions[$dbtype])) {
556 echo "$IND$dbtype database support present.<br />\n";
558 // now, test this interface:
560 $dbh = DB
::connect($dsn, true);
561 if (DB
::isError($dbh)) {
562 do_err('Database error: '. htmlspecialchars(DB
::errorMessage($dbh)) .
563 ' in ' .$type .' DSN.');
566 echo "$IND$type database connect successful.<br />\n";
569 do_err($dbtype.' database support not present!');
573 $db_error='Required PHP PEAR DB support is not available.'
574 .' Is PEAR installed and is the include path set correctly to find <tt>DB.php</tt>?'
575 .' The include path is now:<tt>' . ini_get('include_path') . '</tt>.';
579 echo $IND."not using database functionality.<br />\n";
583 echo "Checking LDAP functions...<br />\n";
584 if( empty($ldap_server) ) {
585 echo $IND."not using LDAP functionality.<br />\n";
587 if ( !function_exists('ldap_connect') ) {
588 do_err('Required LDAP support is not available.');
590 echo "$IND LDAP support present.<br />\n";
591 foreach ( $ldap_server as $param ) {
593 $linkid = @ldap_connect
($param['host'], (empty($param['port']) ?
389 : $param['port']) );
596 echo "$IND LDAP connect to ".$param['host']." successful: ".$linkid."<br />\n";
598 if ( !empty($param['protocol']) &&
599 !ldap_set_option($linkid, LDAP_OPT_PROTOCOL_VERSION
, $param['protocol']) ) {
600 do_err('Unable to set LDAP protocol');
603 if ( empty($param['binddn']) ) {
604 $bind = @ldap_bind
($linkid);
606 $bind = @ldap_bind
($param['binddn'], $param['bindpw']);
610 echo "$IND LDAP Bind Successful <br />";
612 do_err('Unable to Bind to LDAP Server');
615 @ldap_close
($linkid);
617 do_err('Connection to LDAP failed');
623 echo '<hr width="75%" align="center">';
624 echo '<h2 align="center">Summary</h2>';
625 $footer = '<hr width="75%" align="center">';
627 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>';
631 <p
>Congratulations
, your SquirrelMail setup looks fine to me
!</p
>
633 <p
><a href
="login.php">Login now
</a
></p
>