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.
21 function do_err($str, $exit = TRUE) {
23 echo '<p>'.$IND.'<font color="red"><b>ERROR:</b></font> ' .$str. "</p>\n";
25 echo '</body></html>';
30 $IND = str_repeat(' ',4);
34 define('SM_PATH', '../');
36 /* set default value in order to block remote access to script */
37 $allow_remote_configtest=false;
40 * Load config before output begins. functions/strings.php depends on
41 * functions/globals.php. functions/global.php needs to be run before
42 * any html output starts. If config.php is missing, error will be displayed
45 if (file_exists(SM_PATH
. 'config/config.php')) {
46 include(SM_PATH
. 'config/config.php');
47 include(SM_PATH
. 'functions/strings.php');
49 ?
><!DOCTYPE HTML
PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
52 <meta name
="robots" content
="noindex,nofollow">
53 <title
>SquirrelMail configtest
</title
>
56 <h1
>SquirrelMail configtest
</h1
>
58 <p
>This script will
try to check some aspects of your SquirrelMail configuration
59 and point you to errors whereever it can find them
. You need to go run
<tt
>conf
.pl
</tt
>
60 in the
<tt
>config
/</tt
> directory first before you run this script
.</p
>
64 $included = array_map('basename', get_included_files() );
65 if(!in_array('config.php', $included)) {
66 if(!file_exists(SM_PATH
. 'config/config.php')) {
67 do_err('Config file '.SM_PATH
. 'config/config.php does not exist!<br />'.
68 'You need to run <tt>conf.pl</tt> first.');
70 do_err('Could not read '.SM_PATH
.'config/config.php! Check file permissions.');
72 if(!in_array('strings.php', $included)) {
73 do_err('Could not include '.SM_PATH
.'functions/strings.php!<br />'.
74 'Check permissions on that file.');
77 /* Block remote use of script */
78 if (! $allow_remote_configtest) {
79 sqGetGlobalVar('REMOTE_ADDR',$client_ip,SQ_SERVER
);
80 sqGetGlobalVar('SERVER_ADDR',$server_ip,SQ_SERVER
);
82 if ((! isset($client_ip) ||
$client_ip!='127.0.0.1') &&
83 (! isset($client_ip) ||
! isset($server_ip) ||
$client_ip!=$server_ip)) {
84 do_err('Enable "Allow remote configtest" option in squirrelmail configuration in order to use this script.');
87 /* checking PHP specs */
89 echo "<p><table>\n<tr><td>SquirrelMail version:</td><td><b>" . $version . "</b></td></tr>\n" .
90 '<tr><td>Config file version:</td><td><b>' . $config_version . "</b></td></tr>\n" .
91 '<tr><td>Config file last modified:</td><td><b>' .
92 date ('d F Y H:i:s', filemtime(SM_PATH
. 'config/config.php')) .
93 "</b></td></tr>\n</table>\n</p>\n\n";
95 /* TODO: check $config_version here */
97 echo "Checking PHP configuration...<br />\n";
99 if(!check_php_version(4,1,0)) {
100 do_err('Insufficient PHP version: '. PHP_VERSION
. '! Minimum required: 4.1.0');
103 echo $IND . 'PHP version ' . PHP_VERSION
. " OK.<br />\n";
105 $php_exts = array('session','pcre');
106 $diff = array_diff($php_exts, get_loaded_extensions());
108 do_err('Required PHP extensions missing: '.implode(', ',$diff) );
111 echo $IND . "PHP extensions OK.<br />\n";
113 /* dangerous php settings */
115 * mbstring.func_overload allows to replace original string and regexp functions
116 * with their equivalents from php mbstring extension. It causes problems when
117 * scripts analyze 8bit strings byte after byte or use 8bit strings in regexp tests.
118 * Setting can be controlled in php.ini (php 4.2.0), webserver config (php 4.2.0)
119 * and .htaccess files (php 4.3.5).
121 if (function_exists('mb_internal_encoding') &&
122 check_php_version(4,2,0) &&
123 (int)ini_get('mbstring.func_overload')!=0) {
124 $mb_error='You have enabled mbstring overloading.'
125 .' It can cause problems with SquirrelMail scripts that rely on single byte string functions.';
131 echo "Checking paths...<br />\n";
133 if(!file_exists($data_dir)) {
134 // data_dir is not that important in db_setups.
135 if (isset($prefs_dsn) && ! empty($prefs_dsn)) {
136 $data_dir_error = "Data dir ($data_dir) does not exist!\n";
137 echo $IND .'<font color="red"><b>ERROR:</b></font> ' . $data_dir_error;
139 do_err("Data dir ($data_dir) does not exist!");
142 // don't check if errors
143 if(!isset($data_dir_error) && !is_dir($data_dir)) {
144 if (isset($prefs_dsn) && ! empty($prefs_dsn)) {
145 $data_dir_error = "Data dir ($data_dir) is not a directory!\n";
146 echo $IND . '<font color="red"><b>ERROR:</b></font> ' . $data_dir_error;
148 do_err("Data dir ($data_dir) is not a directory!");
151 // datadir should be executable - but no clean way to test on that
152 if(!isset($data_dir_error) && !is_writable($data_dir)) {
153 if (isset($prefs_dsn) && ! empty($prefs_dsn)) {
154 $data_dir_error = "Data dir ($data_dir) is not writable!\n";
155 echo $IND . '<font color="red"><b>ERROR:</b></font> ' . $data_dir_error;
157 do_err("Data dir ($data_dir) is not writable!");
161 if (isset($data_dir_error)) {
162 echo " Some plugins might need access to data directory.<br />\n";
164 // todo_ornot: actually write something and read it back.
165 echo $IND . "Data dir OK.<br />\n";
168 if($data_dir == $attachment_dir) {
169 echo $IND . "Attachment dir is the same as data dir.<br />\n";
170 if (isset($data_dir_error)) {
171 do_err($data_dir_error);
174 if(!file_exists($attachment_dir)) {
175 do_err("Attachment dir ($attachment_dir) does not exist!");
177 if (!is_dir($attachment_dir)) {
178 do_err("Attachment dir ($attachment_dir) is not a directory!");
180 if (!is_writable($attachment_dir)) {
181 do_err("I cannot write to attachment dir ($attachment_dir)!");
183 echo $IND . "Attachment dir OK.<br />\n";
187 /* check plugins and themes */
188 if (isset($plugins[0])) {
189 foreach($plugins as $plugin) {
190 if(!file_exists(SM_PATH
.'plugins/'.$plugin)) {
191 do_err('You have enabled the <i>'.$plugin.'</i> plugin but I cannot find it.', FALSE);
192 } elseif (!is_readable(SM_PATH
.'plugins/'.$plugin.'/setup.php')) {
193 do_err('You have enabled the <i>'.$plugin.'</i> plugin but I cannot read its setup.php file.', FALSE);
196 echo $IND . "Plugins OK.<br />\n";
198 echo $IND . "Plugins are not enabled in config.<br />\n";
200 foreach($theme as $thm) {
201 if(!file_exists($thm['PATH'])) {
202 do_err('You have enabled the <i>'.$thm['NAME'].'</i> theme but I cannot find it ('.$thm['PATH'].').', FALSE);
203 } elseif(!is_readable($thm['PATH'])) {
204 do_err('You have enabled the <i>'.$thm['NAME'].'</i> theme but I cannot read it ('.$thm['PATH'].').', FALSE);
208 echo $IND . "Themes OK.<br />\n";
210 if ( $squirrelmail_default_language != 'en_US' ) {
211 $loc_path = SM_PATH
.'locale/'.$squirrelmail_default_language.'/LC_MESSAGES/squirrelmail.mo';
212 if( ! file_exists( $loc_path ) ) {
213 do_err('You have set <i>' . $squirrelmail_default_language .
214 '</i> as your default language, but I cannot find this translation (should be '.
215 'in <tt>' . $loc_path . '</tt>). Please note that you have to download translations '.
216 'separately from the main SquirrelMail package.', FALSE);
217 } elseif ( ! is_readable( $loc_path ) ) {
218 do_err('You have set <i>' . $squirrelmail_default_language .
219 '</i> as your default language, but I cannot read this translation (file '.
220 'in <tt>' . $loc_path . '</tt> unreadable).', FALSE);
222 echo $IND . "Default language OK.<br />\n";
225 echo $IND . "Default language OK.<br />\n";
228 echo $IND . "Base URL detected as: <tt>" . htmlspecialchars(get_location()) . "</tt><br />\n";
230 /* check minimal requirements for other security options */
233 if($use_smtp_tls == 1 ||
$use_imap_tls == 1) {
234 if(!check_php_version(4,3,0)) {
235 do_err('You need at least PHP 4.3.0 for SMTP/IMAP TLS!');
237 if(!extension_loaded('openssl')) {
238 do_err('You need the openssl PHP extension to use SMTP/IMAP TLS!');
241 /* starttls extensions */
242 if($use_smtp_tls == 2 ||
$use_imap_tls == 2) {
243 if (! function_exists('stream_socket_enable_crypto')) {
244 do_err('If you want to use STARTTLS extension, you need stream_socket_enable_crypto() function from PHP 5.1.0 and newer.');
248 if ($smtp_auth_mech=='digest-md5' ||
$imap_auth_mech =='digest-md5') {
249 if (!extension_loaded('xml')) {
250 do_err('You need the PHP XML extension to use Digest-MD5 authentication!');
254 /* check outgoing mail */
256 echo "Checking outgoing mail service....<br />\n";
259 // is_executable also checks for existance, but we want to be as precise as possible with the errors
260 if(!file_exists($sendmail_path)) {
261 do_err("Location of sendmail program incorrect ($sendmail_path)!");
263 if(!is_executable($sendmail_path)) {
264 do_err("I cannot execute the sendmail program ($sendmail_path)!");
267 echo $IND . "sendmail OK<br />\n";
269 $stream = fsockopen( ($use_smtp_tls==1?
'tls://':'').$smtpServerAddress, $smtpPort,
270 $errorNumber, $errorString);
272 do_err("Error connecting to SMTP server \"$smtpServerAddress:$smtpPort\".".
273 "Server error: ($errorNumber) ".htmlspecialchars($errorString));
276 // check for SMTP code; should be 2xx to allow us access
277 $smtpline = fgets($stream, 1024);
278 if(((int) $smtpline{0}) > 3) {
279 do_err("Error connecting to SMTP server. Server error: ".
280 htmlspecialchars($smtpline));
283 /* smtp starttls checks */
284 if ($use_smtp_tls==2) {
285 // if something breaks, script should close smtp connection on exit.
288 fwrite($stream,"EHLO $client_ip\r\n");
292 while ($line=fgets($stream, 1024)){
293 if (preg_match("/^250(-|\s)(\S*)\s+(\S.*)/",$line,$match)||
294 preg_match("/^250(-|\s)(\S*)\s+/",$line,$match)) {
295 if (!isset($match[3])) {
296 // simple one word extension
297 $ehlo[strtoupper($match[2])]='';
299 // ehlo-keyword + ehlo-param
300 $ehlo[strtoupper($match[2])]=trim($match[3]);
302 if ($match[1]==' ') {
314 do_err('SMTP EHLO failed. You need ESMTP support for SMTP STARTTLS');
315 } elseif (!array_key_exists('STARTTLS',$ehlo)) {
316 do_err('STARTTLS support is not declared by SMTP server.');
319 fwrite($stream,"STARTTLS\r\n");
320 $starttls_response=fgets($stream, 1024);
321 if ($starttls_response[0]!=2) {
322 $starttls_cmd_err = 'SMTP STARTTLS failed. Server replied: '
323 .htmlspecialchars($starttls_response);
324 do_err($starttls_cmd_err);
325 } elseif(! stream_socket_enable_crypto($stream,true,STREAM_CRYPTO_METHOD_TLS_CLIENT
)) {
326 do_err('Failed to enable encryption on SMTP STARTTLS connection.');
328 echo $IND . "SMTP STARTTLS extension looks OK.<br />\n";
330 // According to RFC we should second ehlo call here.
333 fputs($stream, 'QUIT');
335 echo $IND . 'SMTP server OK (<tt><small>'.
336 trim(htmlspecialchars($smtpline))."</small></tt>)<br />\n";
338 /* POP before SMTP */
339 if($pop_before_smtp) {
340 $stream = fsockopen($smtpServerAddress, 110, $err_no, $err_str);
342 do_err("Error connecting to POP Server ($smtpServerAddress:110) "
343 . $err_no . ' : ' . htmlspecialchars($err_str));
346 $tmp = fgets($stream, 1024);
347 if (substr($tmp, 0, 3) != '+OK') {
348 do_err("Error connecting to POP Server ($smtpServerAddress:110)"
349 . ' '.htmlspecialchars($tmp));
351 fputs($stream, 'QUIT');
353 echo $IND . "POP-before-SMTP OK.<br />\n";
358 * Check the IMAP server
360 echo "Checking IMAP service....<br />\n";
362 /** Can we open a connection? */
363 $stream = fsockopen( ($use_imap_tls==1?
'tls://':'').$imapServerAddress, $imapPort,
364 $errorNumber, $errorString);
366 do_err("Error connecting to IMAP server \"$imapServerAddress:$imapPort\".".
367 "Server error: ($errorNumber) ".
368 htmlspecialchars($errorString));
371 /** Is the first response 'OK'? */
372 $imapline = fgets($stream, 1024);
373 if(substr($imapline, 0,4) != '* OK') {
374 do_err('Error connecting to IMAP server. Server error: '.
375 htmlspecialchars($imapline));
378 echo $IND . 'IMAP server ready (<tt><small>'.
379 htmlspecialchars(trim($imapline))."</small></tt>)<br />\n";
381 /** Check capabilities */
382 fputs($stream, "A001 CAPABILITY\r\n");
384 while ($line=fgets($stream, 1024)){
385 if (preg_match("/A001.*/",$line)) {
392 /* don't display capabilities before STARTTLS */
393 if ($use_imap_tls==2 && stristr($capline, 'STARTTLS') === false) {
394 do_err('Your server doesn\'t support STARTTLS.');
396 /* try starting starttls */
397 fwrite($stream,"A002 STARTTLS\r\n");
398 $starttls_line=fgets($stream, 1024);
399 if (! preg_match("/^A002 OK.*/i",$starttls_line)) {
400 $imap_starttls_err = 'IMAP STARTTLS failed. Server replied: '
401 .htmlspecialchars($starttls_line);
402 do_err($imap_starttls_err);
403 } elseif (! stream_socket_enable_crypto($stream,true,STREAM_CRYPTO_METHOD_TLS_CLIENT
)) {
404 do_err('Failed to enable encryption on IMAP connection.');
406 echo $IND . "IMAP STARTTLS extension looks OK.<br />\n";
409 // get new capability line
410 fwrite($stream,"A003 CAPABILITY\r\n");
412 while ($line=fgets($stream, 1024)){
413 if (preg_match("/A003.*/",$line)) {
421 echo $IND . 'Capabilities: <tt>'.htmlspecialchars($capline)."</tt><br />\n";
423 if($imap_auth_mech == 'login' && stristr($capline, 'LOGINDISABLED') !== FALSE) {
424 do_err('Your server doesn\'t allow plaintext logins. '.
425 'Try enabling another authentication mechanism like CRAM-MD5, DIGEST-MD5 or TLS-encryption '.
426 'in the SquirrelMail configuration.', FALSE);
429 /** OK, close connection */
430 fputs($stream, "A004 LOGOUT\r\n");
433 echo "Checking internationalization (i18n) settings...<br />\n";
434 echo "$IND gettext - ";
435 if (function_exists('gettext')) {
436 echo 'Gettext functions are available.'
437 .' On some systems you must have appropriate system locales compiled.'
440 echo 'Gettext functions are unavailable.'
441 .' SquirrelMail will use slower internal gettext functions.'
444 echo "$IND mbstring - ";
445 if (function_exists('mb_detect_encoding')) {
446 echo "Mbstring functions are available.<br />\n";
448 echo 'Mbstring functions are unavailable.'
449 ." Japanese translation won't work.<br />\n";
451 echo "$IND recode - ";
452 if (function_exists('recode')) {
453 echo "Recode functions are available.<br />\n";
454 } elseif (isset($use_php_recode) && $use_php_recode) {
455 echo "Recode functions are unavailable.<br />\n";
456 do_err('Your configuration requires recode support, but recode support is missing.');
458 echo "Recode functions are unavailable.<br />\n";
460 echo "$IND iconv - ";
461 if (function_exists('iconv')) {
462 echo "Iconv functions are available.<br />\n";
463 } elseif (isset($use_php_iconv) && $use_php_iconv) {
464 echo "Iconv functions are unavailable.<br />\n";
465 do_err('Your configuration requires iconv support, but iconv support is missing.');
467 echo "Iconv functions are unavailable.<br />\n";
469 // same test as in include/validate.php
470 echo "$IND timezone - ";
471 if ( (!ini_get('safe_mode')) ||
472 !strcmp(ini_get('safe_mode_allowed_env_vars'),'') ||
473 preg_match('/^([\w_]+,)*TZ/', ini_get('safe_mode_allowed_env_vars')) ) {
474 echo "Webmail users can change their time zone settings.<br />\n";
476 echo "Webmail users can't change their time zone settings.<br />\n";
481 echo "Checking database functions...<br />\n";
482 if($addrbook_dsn ||
$prefs_dsn ||
$addrbook_global_dsn) {
483 @include_once
('DB.php');
484 if (class_exists('DB')) {
485 echo "$IND PHP Pear DB support is present.<br />\n";
487 'dbase' => 'dbase_open',
488 'fbsql' => 'fbsql_connect',
489 'interbase' => 'ibase_connect',
490 'informix' => 'ifx_connect',
491 'msql' => 'msql_connect',
492 'mssql' => 'mssql_connect',
493 'mysql' => 'mysql_connect',
494 'mysqli' => 'mysqli_connect',
495 'oci8' => 'ocilogon',
496 'odbc' => 'odbc_connect',
497 'pgsql' => 'pg_connect',
498 'sqlite' => 'sqlite_open',
499 'sybase' => 'sybase_connect'
504 $dsns['preferences'] = $prefs_dsn;
507 $dsns['addressbook'] = $addrbook_dsn;
509 if($addrbook_global_dsn) {
510 $dsns['global addressbook'] = $addrbook_global_dsn;
513 foreach($dsns as $type => $dsn) {
514 $aDsn = explode(':', $dsn);
515 $dbtype = array_shift($aDsn);
516 if(isset($db_functions[$dbtype]) && function_exists($db_functions[$dbtype])) {
517 echo "$IND$dbtype database support present.<br />\n";
519 // now, test this interface:
521 $dbh = DB
::connect($dsn, true);
522 if (DB
::isError($dbh)) {
523 do_err('Database error: '. htmlspecialchars(DB
::errorMessage($dbh)) .
524 ' in ' .$type .' DSN.');
527 echo "$IND$type database connect successful.<br />\n";
530 do_err($dbtype.' database support not present!');
534 $db_error='Required PHP PEAR DB support is not available.'
535 .' Is PEAR installed and is the include path set correctly to find <tt>DB.php</tt>?'
536 .' The include path is now:<tt>' . ini_get('include_path') . '</tt>.';
540 echo $IND."not using database functionality.<br />\n";
544 echo "Checking LDAP functions...<br />\n";
545 if( empty($ldap_server) ) {
546 echo $IND."not using LDAP functionality.<br />\n";
548 if ( !function_exists('ldap_connect') ) {
549 do_err('Required LDAP support is not available.');
551 echo "$IND LDAP support present.<br />\n";
552 foreach ( $ldap_server as $param ) {
554 $linkid = @ldap_connect
($param['host'], (empty($param['port']) ?
389 : $param['port']) );
557 echo "$IND LDAP connect to ".$param['host']." successful: ".$linkid."<br />\n";
559 if ( !empty($param['protocol']) &&
560 !ldap_set_option($linkid, LDAP_OPT_PROTOCOL_VERSION
, $param['protocol']) ) {
561 do_err('Unable to set LDAP protocol');
564 if ( empty($param['binddn']) ) {
565 $bind = @ldap_bind
($linkid);
567 $bind = @ldap_bind
($param['binddn'], $param['bindpw']);
571 echo "$IND LDAP Bind Successful <br />";
573 do_err('Unable to Bind to LDAP Server');
576 @ldap_close
($linkid);
578 do_err('Connection to LDAP failed');
586 <p
>Congratulations
, your SquirrelMail setup looks fine to me
!</p
>
588 <p
><a href
="login.php">Login now
</a
></p
>