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 /* check $config_version */
96 if ($config_version!='1.4.0') {
97 do_err('Configuration file version does not match required version. Please update your configuration file.');
100 echo "Checking PHP configuration...<br />\n";
102 if(!check_php_version(4,1,0)) {
103 do_err('Insufficient PHP version: '. PHP_VERSION
. '! Minimum required: 4.1.0');
106 echo $IND . 'PHP version ' . PHP_VERSION
. " OK.<br />\n";
108 $php_exts = array('session','pcre');
109 $diff = array_diff($php_exts, get_loaded_extensions());
111 do_err('Required PHP extensions missing: '.implode(', ',$diff) );
114 echo $IND . "PHP extensions OK.<br />\n";
116 /* dangerous php settings */
118 * mbstring.func_overload allows to replace original string and regexp functions
119 * with their equivalents from php mbstring extension. It causes problems when
120 * scripts analyze 8bit strings byte after byte or use 8bit strings in regexp tests.
121 * Setting can be controlled in php.ini (php 4.2.0), webserver config (php 4.2.0)
122 * and .htaccess files (php 4.3.5).
124 if (function_exists('mb_internal_encoding') &&
125 check_php_version(4,2,0) &&
126 (int)ini_get('mbstring.func_overload')!=0) {
127 $mb_error='You have enabled mbstring overloading.'
128 .' It can cause problems with SquirrelMail scripts that rely on single byte string functions.';
134 echo "Checking paths...<br />\n";
136 if(!file_exists($data_dir)) {
137 // data_dir is not that important in db_setups.
138 if (isset($prefs_dsn) && ! empty($prefs_dsn)) {
139 $data_dir_error = "Data dir ($data_dir) does not exist!\n";
140 echo $IND .'<font color="red"><b>ERROR:</b></font> ' . $data_dir_error;
142 do_err("Data dir ($data_dir) does not exist!");
145 // don't check if errors
146 if(!isset($data_dir_error) && !is_dir($data_dir)) {
147 if (isset($prefs_dsn) && ! empty($prefs_dsn)) {
148 $data_dir_error = "Data dir ($data_dir) is not a directory!\n";
149 echo $IND . '<font color="red"><b>ERROR:</b></font> ' . $data_dir_error;
151 do_err("Data dir ($data_dir) is not a directory!");
154 // datadir should be executable - but no clean way to test on that
155 if(!isset($data_dir_error) && !is_writable($data_dir)) {
156 if (isset($prefs_dsn) && ! empty($prefs_dsn)) {
157 $data_dir_error = "Data dir ($data_dir) is not writable!\n";
158 echo $IND . '<font color="red"><b>ERROR:</b></font> ' . $data_dir_error;
160 do_err("Data dir ($data_dir) is not writable!");
164 if (isset($data_dir_error)) {
165 echo " Some plugins might need access to data directory.<br />\n";
167 // todo_ornot: actually write something and read it back.
168 echo $IND . "Data dir OK.<br />\n";
171 if($data_dir == $attachment_dir) {
172 echo $IND . "Attachment dir is the same as data dir.<br />\n";
173 if (isset($data_dir_error)) {
174 do_err($data_dir_error);
177 if(!file_exists($attachment_dir)) {
178 do_err("Attachment dir ($attachment_dir) does not exist!");
180 if (!is_dir($attachment_dir)) {
181 do_err("Attachment dir ($attachment_dir) is not a directory!");
183 if (!is_writable($attachment_dir)) {
184 do_err("I cannot write to attachment dir ($attachment_dir)!");
186 echo $IND . "Attachment dir OK.<br />\n";
190 /* check plugins and themes */
191 if (isset($plugins[0])) {
192 foreach($plugins as $plugin) {
193 if(!file_exists(SM_PATH
.'plugins/'.$plugin)) {
194 do_err('You have enabled the <i>'.$plugin.'</i> plugin but I cannot find it.', FALSE);
195 } elseif (!is_readable(SM_PATH
.'plugins/'.$plugin.'/setup.php')) {
196 do_err('You have enabled the <i>'.$plugin.'</i> plugin but I cannot read its setup.php file.', FALSE);
199 echo $IND . "Plugins OK.<br />\n";
201 echo $IND . "Plugins are not enabled in config.<br />\n";
203 foreach($theme as $thm) {
204 if(!file_exists($thm['PATH'])) {
205 do_err('You have enabled the <i>'.$thm['NAME'].'</i> theme but I cannot find it ('.$thm['PATH'].').', FALSE);
206 } elseif(!is_readable($thm['PATH'])) {
207 do_err('You have enabled the <i>'.$thm['NAME'].'</i> theme but I cannot read it ('.$thm['PATH'].').', FALSE);
211 echo $IND . "Themes OK.<br />\n";
213 if ( $squirrelmail_default_language != 'en_US' ) {
214 $loc_path = SM_PATH
.'locale/'.$squirrelmail_default_language.'/LC_MESSAGES/squirrelmail.mo';
215 if( ! file_exists( $loc_path ) ) {
216 do_err('You have set <i>' . $squirrelmail_default_language .
217 '</i> as your default language, but I cannot find this translation (should be '.
218 'in <tt>' . $loc_path . '</tt>). Please note that you have to download translations '.
219 'separately from the main SquirrelMail package.', FALSE);
220 } elseif ( ! is_readable( $loc_path ) ) {
221 do_err('You have set <i>' . $squirrelmail_default_language .
222 '</i> as your default language, but I cannot read this translation (file '.
223 'in <tt>' . $loc_path . '</tt> unreadable).', FALSE);
225 echo $IND . "Default language OK.<br />\n";
228 echo $IND . "Default language OK.<br />\n";
231 echo $IND . "Base URL detected as: <tt>" . htmlspecialchars(get_location()) . "</tt><br />\n";
233 /* check minimal requirements for other security options */
236 if($use_smtp_tls == 1 ||
$use_imap_tls == 1) {
237 if(!check_php_version(4,3,0)) {
238 do_err('You need at least PHP 4.3.0 for SMTP/IMAP TLS!');
240 if(!extension_loaded('openssl')) {
241 do_err('You need the openssl PHP extension to use SMTP/IMAP TLS!');
244 /* starttls extensions */
245 if($use_smtp_tls == 2 ||
$use_imap_tls == 2) {
246 if (! function_exists('stream_socket_enable_crypto')) {
247 do_err('If you want to use STARTTLS extension, you need stream_socket_enable_crypto() function from PHP 5.1.0 and newer.');
251 if ($smtp_auth_mech=='digest-md5' ||
$imap_auth_mech =='digest-md5') {
252 if (!extension_loaded('xml')) {
253 do_err('You need the PHP XML extension to use Digest-MD5 authentication!');
257 /* check outgoing mail */
259 echo "Checking outgoing mail service....<br />\n";
262 // is_executable also checks for existance, but we want to be as precise as possible with the errors
263 if(!file_exists($sendmail_path)) {
264 do_err("Location of sendmail program incorrect ($sendmail_path)!");
266 if(!is_executable($sendmail_path)) {
267 do_err("I cannot execute the sendmail program ($sendmail_path)!");
270 echo $IND . "sendmail OK<br />\n";
272 $stream = fsockopen( ($use_smtp_tls==1?
'tls://':'').$smtpServerAddress, $smtpPort,
273 $errorNumber, $errorString);
275 do_err("Error connecting to SMTP server \"$smtpServerAddress:$smtpPort\".".
276 "Server error: ($errorNumber) ".htmlspecialchars($errorString));
279 // check for SMTP code; should be 2xx to allow us access
280 $smtpline = fgets($stream, 1024);
281 if(((int) $smtpline{0}) > 3) {
282 do_err("Error connecting to SMTP server. Server error: ".
283 htmlspecialchars($smtpline));
286 /* smtp starttls checks */
287 if ($use_smtp_tls==2) {
288 // if something breaks, script should close smtp connection on exit.
291 fwrite($stream,"EHLO $client_ip\r\n");
295 while ($line=fgets($stream, 1024)){
296 if (preg_match("/^250(-|\s)(\S*)\s+(\S.*)/",$line,$match)||
297 preg_match("/^250(-|\s)(\S*)\s+/",$line,$match)) {
298 if (!isset($match[3])) {
299 // simple one word extension
300 $ehlo[strtoupper($match[2])]='';
302 // ehlo-keyword + ehlo-param
303 $ehlo[strtoupper($match[2])]=trim($match[3]);
305 if ($match[1]==' ') {
317 do_err('SMTP EHLO failed. You need ESMTP support for SMTP STARTTLS');
318 } elseif (!array_key_exists('STARTTLS',$ehlo)) {
319 do_err('STARTTLS support is not declared by SMTP server.');
322 fwrite($stream,"STARTTLS\r\n");
323 $starttls_response=fgets($stream, 1024);
324 if ($starttls_response[0]!=2) {
325 $starttls_cmd_err = 'SMTP STARTTLS failed. Server replied: '
326 .htmlspecialchars($starttls_response);
327 do_err($starttls_cmd_err);
328 } elseif(! stream_socket_enable_crypto($stream,true,STREAM_CRYPTO_METHOD_TLS_CLIENT
)) {
329 do_err('Failed to enable encryption on SMTP STARTTLS connection.');
331 echo $IND . "SMTP STARTTLS extension looks OK.<br />\n";
333 // According to RFC we should second ehlo call here.
336 fputs($stream, 'QUIT');
338 echo $IND . 'SMTP server OK (<tt><small>'.
339 trim(htmlspecialchars($smtpline))."</small></tt>)<br />\n";
341 /* POP before SMTP */
342 if($pop_before_smtp) {
343 $stream = fsockopen($smtpServerAddress, 110, $err_no, $err_str);
345 do_err("Error connecting to POP Server ($smtpServerAddress:110) "
346 . $err_no . ' : ' . htmlspecialchars($err_str));
349 $tmp = fgets($stream, 1024);
350 if (substr($tmp, 0, 3) != '+OK') {
351 do_err("Error connecting to POP Server ($smtpServerAddress:110)"
352 . ' '.htmlspecialchars($tmp));
354 fputs($stream, 'QUIT');
356 echo $IND . "POP-before-SMTP OK.<br />\n";
361 * Check the IMAP server
363 echo "Checking IMAP service....<br />\n";
365 /** Can we open a connection? */
366 $stream = fsockopen( ($use_imap_tls==1?
'tls://':'').$imapServerAddress, $imapPort,
367 $errorNumber, $errorString);
369 do_err("Error connecting to IMAP server \"$imapServerAddress:$imapPort\".".
370 "Server error: ($errorNumber) ".
371 htmlspecialchars($errorString));
374 /** Is the first response 'OK'? */
375 $imapline = fgets($stream, 1024);
376 if(substr($imapline, 0,4) != '* OK') {
377 do_err('Error connecting to IMAP server. Server error: '.
378 htmlspecialchars($imapline));
381 echo $IND . 'IMAP server ready (<tt><small>'.
382 htmlspecialchars(trim($imapline))."</small></tt>)<br />\n";
384 /** Check capabilities */
385 fputs($stream, "A001 CAPABILITY\r\n");
387 while ($line=fgets($stream, 1024)){
388 if (preg_match("/A001.*/",$line)) {
395 /* don't display capabilities before STARTTLS */
396 if ($use_imap_tls==2 && stristr($capline, 'STARTTLS') === false) {
397 do_err('Your server doesn\'t support STARTTLS.');
398 } elseif($use_imap_tls==2) {
399 /* try starting starttls */
400 fwrite($stream,"A002 STARTTLS\r\n");
401 $starttls_line=fgets($stream, 1024);
402 if (! preg_match("/^A002 OK.*/i",$starttls_line)) {
403 $imap_starttls_err = 'IMAP STARTTLS failed. Server replied: '
404 .htmlspecialchars($starttls_line);
405 do_err($imap_starttls_err);
406 } elseif (! stream_socket_enable_crypto($stream,true,STREAM_CRYPTO_METHOD_TLS_CLIENT
)) {
407 do_err('Failed to enable encryption on IMAP connection.');
409 echo $IND . "IMAP STARTTLS extension looks OK.<br />\n";
412 // get new capability line
413 fwrite($stream,"A003 CAPABILITY\r\n");
415 while ($line=fgets($stream, 1024)){
416 if (preg_match("/A003.*/",$line)) {
424 echo $IND . 'Capabilities: <tt>'.htmlspecialchars($capline)."</tt><br />\n";
426 if($imap_auth_mech == 'login' && stristr($capline, 'LOGINDISABLED') !== FALSE) {
427 do_err('Your server doesn\'t allow plaintext logins. '.
428 'Try enabling another authentication mechanism like CRAM-MD5, DIGEST-MD5 or TLS-encryption '.
429 'in the SquirrelMail configuration.', FALSE);
432 /** OK, close connection */
433 fputs($stream, "A004 LOGOUT\r\n");
436 echo "Checking internationalization (i18n) settings...<br />\n";
437 echo "$IND gettext - ";
438 if (function_exists('gettext')) {
439 echo 'Gettext functions are available.'
440 .' On some systems you must have appropriate system locales compiled.'
443 echo 'Gettext functions are unavailable.'
444 .' SquirrelMail will use slower internal gettext functions.'
447 echo "$IND mbstring - ";
448 if (function_exists('mb_detect_encoding')) {
449 echo "Mbstring functions are available.<br />\n";
451 echo 'Mbstring functions are unavailable.'
452 ." Japanese translation won't work.<br />\n";
454 echo "$IND recode - ";
455 if (function_exists('recode')) {
456 echo "Recode functions are available.<br />\n";
457 } elseif (isset($use_php_recode) && $use_php_recode) {
458 echo "Recode functions are unavailable.<br />\n";
459 do_err('Your configuration requires recode support, but recode support is missing.');
461 echo "Recode functions are unavailable.<br />\n";
463 echo "$IND iconv - ";
464 if (function_exists('iconv')) {
465 echo "Iconv functions are available.<br />\n";
466 } elseif (isset($use_php_iconv) && $use_php_iconv) {
467 echo "Iconv functions are unavailable.<br />\n";
468 do_err('Your configuration requires iconv support, but iconv support is missing.');
470 echo "Iconv functions are unavailable.<br />\n";
472 // same test as in include/validate.php
473 echo "$IND timezone - ";
474 if ( (!ini_get('safe_mode')) ||
475 !strcmp(ini_get('safe_mode_allowed_env_vars'),'') ||
476 preg_match('/^([\w_]+,)*TZ/', ini_get('safe_mode_allowed_env_vars')) ) {
477 echo "Webmail users can change their time zone settings.<br />\n";
479 echo "Webmail users can't change their time zone settings.<br />\n";
484 echo "Checking database functions...<br />\n";
485 if($addrbook_dsn ||
$prefs_dsn ||
$addrbook_global_dsn) {
486 @include_once
('DB.php');
487 if (class_exists('DB')) {
488 echo "$IND PHP Pear DB support is present.<br />\n";
490 'dbase' => 'dbase_open',
491 'fbsql' => 'fbsql_connect',
492 'interbase' => 'ibase_connect',
493 'informix' => 'ifx_connect',
494 'msql' => 'msql_connect',
495 'mssql' => 'mssql_connect',
496 'mysql' => 'mysql_connect',
497 'mysqli' => 'mysqli_connect',
498 'oci8' => 'ocilogon',
499 'odbc' => 'odbc_connect',
500 'pgsql' => 'pg_connect',
501 'sqlite' => 'sqlite_open',
502 'sybase' => 'sybase_connect'
507 $dsns['preferences'] = $prefs_dsn;
510 $dsns['addressbook'] = $addrbook_dsn;
512 if($addrbook_global_dsn) {
513 $dsns['global addressbook'] = $addrbook_global_dsn;
516 foreach($dsns as $type => $dsn) {
517 $aDsn = explode(':', $dsn);
518 $dbtype = array_shift($aDsn);
519 if(isset($db_functions[$dbtype]) && function_exists($db_functions[$dbtype])) {
520 echo "$IND$dbtype database support present.<br />\n";
522 // now, test this interface:
524 $dbh = DB
::connect($dsn, true);
525 if (DB
::isError($dbh)) {
526 do_err('Database error: '. htmlspecialchars(DB
::errorMessage($dbh)) .
527 ' in ' .$type .' DSN.');
530 echo "$IND$type database connect successful.<br />\n";
533 do_err($dbtype.' database support not present!');
537 $db_error='Required PHP PEAR DB support is not available.'
538 .' Is PEAR installed and is the include path set correctly to find <tt>DB.php</tt>?'
539 .' The include path is now:<tt>' . ini_get('include_path') . '</tt>.';
543 echo $IND."not using database functionality.<br />\n";
547 echo "Checking LDAP functions...<br />\n";
548 if( empty($ldap_server) ) {
549 echo $IND."not using LDAP functionality.<br />\n";
551 if ( !function_exists('ldap_connect') ) {
552 do_err('Required LDAP support is not available.');
554 echo "$IND LDAP support present.<br />\n";
555 foreach ( $ldap_server as $param ) {
557 $linkid = @ldap_connect
($param['host'], (empty($param['port']) ?
389 : $param['port']) );
560 echo "$IND LDAP connect to ".$param['host']." successful: ".$linkid."<br />\n";
562 if ( !empty($param['protocol']) &&
563 !ldap_set_option($linkid, LDAP_OPT_PROTOCOL_VERSION
, $param['protocol']) ) {
564 do_err('Unable to set LDAP protocol');
567 if ( empty($param['binddn']) ) {
568 $bind = @ldap_bind
($linkid);
570 $bind = @ldap_bind
($param['binddn'], $param['bindpw']);
574 echo "$IND LDAP Bind Successful <br />";
576 do_err('Unable to Bind to LDAP Server');
579 @ldap_close
($linkid);
581 do_err('Connection to LDAP failed');
589 <p
>Congratulations
, your SquirrelMail setup looks fine to me
!</p
>
591 <p
><a href
="login.php">Login now
</a
></p
>