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"
50 "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">
53 <meta name
="robots" content
="noindex,nofollow">
54 <title
>SquirrelMail configtest
</title
>
57 <h1
>SquirrelMail configtest
</h1
>
59 <p
>This script will
try to check some aspects of your SquirrelMail configuration
60 and point you to errors whereever it can find them
. You need to go run
<tt
>conf
.pl
</tt
>
61 in the
<tt
>config
/</tt
> directory first before you run this script
.</p
>
65 $included = array_map('basename', get_included_files() );
66 if(!in_array('config.php', $included)) {
67 if(!file_exists(SM_PATH
. 'config/config.php')) {
68 do_err('Config file '.SM_PATH
. 'config/config.php does not exist!<br />'.
69 'You need to run <tt>conf.pl</tt> first.');
71 do_err('Could not read '.SM_PATH
.'config/config.php! Check file permissions.');
73 if(!in_array('strings.php', $included)) {
74 do_err('Could not include '.SM_PATH
.'functions/strings.php!<br />'.
75 'Check permissions on that file.');
78 /* Block remote use of script */
79 if (! $allow_remote_configtest) {
80 sqGetGlobalVar('REMOTE_ADDR',$client_ip,SQ_SERVER
);
81 sqGetGlobalVar('SERVER_ADDR',$server_ip,SQ_SERVER
);
83 if ((! isset($client_ip) ||
$client_ip!='127.0.0.1') &&
84 (! isset($client_ip) ||
! isset($server_ip) ||
$client_ip!=$server_ip)) {
85 do_err('Enable "Allow remote configtest" option in squirrelmail configuration in order to use this script.');
88 /* checking PHP specs */
90 echo "<p><table>\n<tr><td>SquirrelMail version:</td><td><b>" . $version . "</b></td></tr>\n" .
91 '<tr><td>Config file version:</td><td><b>' . $config_version . "</b></td></tr>\n" .
92 '<tr><td>Config file last modified:</td><td><b>' .
93 date ('d F Y H:i:s', filemtime(SM_PATH
. 'config/config.php')) .
94 "</b></td></tr>\n</table>\n</p>\n\n";
96 /* check $config_version */
97 if ($config_version!='1.4.0') {
98 do_err('Configuration file version does not match required version. Please update your configuration file.');
101 echo "Checking PHP configuration...<br />\n";
103 if(!check_php_version(4,1,0)) {
104 do_err('Insufficient PHP version: '. PHP_VERSION
. '! Minimum required: 4.1.0');
107 echo $IND . 'PHP version ' . PHP_VERSION
. " OK.<br />\n";
109 $php_exts = array('session','pcre');
110 $diff = array_diff($php_exts, get_loaded_extensions());
112 do_err('Required PHP extensions missing: '.implode(', ',$diff) );
115 echo $IND . "PHP extensions OK.<br />\n";
117 /* dangerous php settings */
119 * mbstring.func_overload allows to replace original string and regexp functions
120 * with their equivalents from php mbstring extension. It causes problems when
121 * scripts analyze 8bit strings byte after byte or use 8bit strings in regexp tests.
122 * Setting can be controlled in php.ini (php 4.2.0), webserver config (php 4.2.0)
123 * and .htaccess files (php 4.3.5).
125 if (function_exists('mb_internal_encoding') &&
126 check_php_version(4,2,0) &&
127 (int)ini_get('mbstring.func_overload')!=0) {
128 $mb_error='You have enabled mbstring overloading.'
129 .' It can cause problems with SquirrelMail scripts that rely on single byte string functions.';
135 echo "Checking paths...<br />\n";
137 if(!file_exists($data_dir)) {
138 // data_dir is not that important in db_setups.
139 if (isset($prefs_dsn) && ! empty($prefs_dsn)) {
140 $data_dir_error = "Data dir ($data_dir) does not exist!\n";
141 echo $IND .'<font color="red"><b>ERROR:</b></font> ' . $data_dir_error;
143 do_err("Data dir ($data_dir) does not exist!");
146 // don't check if errors
147 if(!isset($data_dir_error) && !is_dir($data_dir)) {
148 if (isset($prefs_dsn) && ! empty($prefs_dsn)) {
149 $data_dir_error = "Data dir ($data_dir) is not a directory!\n";
150 echo $IND . '<font color="red"><b>ERROR:</b></font> ' . $data_dir_error;
152 do_err("Data dir ($data_dir) is not a directory!");
155 // datadir should be executable - but no clean way to test on that
156 if(!isset($data_dir_error) && !is_writable($data_dir)) {
157 if (isset($prefs_dsn) && ! empty($prefs_dsn)) {
158 $data_dir_error = "Data dir ($data_dir) is not writable!\n";
159 echo $IND . '<font color="red"><b>ERROR:</b></font> ' . $data_dir_error;
161 do_err("Data dir ($data_dir) is not writable!");
165 if (isset($data_dir_error)) {
166 echo " Some plugins might need access to data directory.<br />\n";
168 // todo_ornot: actually write something and read it back.
169 echo $IND . "Data dir OK.<br />\n";
172 if($data_dir == $attachment_dir) {
173 echo $IND . "Attachment dir is the same as data dir.<br />\n";
174 if (isset($data_dir_error)) {
175 do_err($data_dir_error);
178 if(!file_exists($attachment_dir)) {
179 do_err("Attachment dir ($attachment_dir) does not exist!");
181 if (!is_dir($attachment_dir)) {
182 do_err("Attachment dir ($attachment_dir) is not a directory!");
184 if (!is_writable($attachment_dir)) {
185 do_err("I cannot write to attachment dir ($attachment_dir)!");
187 echo $IND . "Attachment dir OK.<br />\n";
191 /* check plugins and themes */
192 if (isset($plugins[0])) {
193 foreach($plugins as $plugin) {
194 if(!file_exists(SM_PATH
.'plugins/'.$plugin)) {
195 do_err('You have enabled the <i>'.$plugin.'</i> plugin but I cannot find it.', FALSE);
196 } elseif (!is_readable(SM_PATH
.'plugins/'.$plugin.'/setup.php')) {
197 do_err('You have enabled the <i>'.$plugin.'</i> plugin but I cannot read its setup.php file.', FALSE);
200 echo $IND . "Plugins OK.<br />\n";
202 echo $IND . "Plugins are not enabled in config.<br />\n";
204 foreach($theme as $thm) {
205 if(!file_exists($thm['PATH'])) {
206 do_err('You have enabled the <i>'.$thm['NAME'].'</i> theme but I cannot find it ('.$thm['PATH'].').', FALSE);
207 } elseif(!is_readable($thm['PATH'])) {
208 do_err('You have enabled the <i>'.$thm['NAME'].'</i> theme but I cannot read it ('.$thm['PATH'].').', FALSE);
212 echo $IND . "Themes OK.<br />\n";
214 if ( $squirrelmail_default_language != 'en_US' ) {
215 $loc_path = SM_PATH
.'locale/'.$squirrelmail_default_language.'/LC_MESSAGES/squirrelmail.mo';
216 if( ! file_exists( $loc_path ) ) {
217 do_err('You have set <i>' . $squirrelmail_default_language .
218 '</i> as your default language, but I cannot find this translation (should be '.
219 'in <tt>' . $loc_path . '</tt>). Please note that you have to download translations '.
220 'separately from the main SquirrelMail package.', FALSE);
221 } elseif ( ! is_readable( $loc_path ) ) {
222 do_err('You have set <i>' . $squirrelmail_default_language .
223 '</i> as your default language, but I cannot read this translation (file '.
224 'in <tt>' . $loc_path . '</tt> unreadable).', FALSE);
226 echo $IND . "Default language OK.<br />\n";
229 echo $IND . "Default language OK.<br />\n";
232 echo $IND . "Base URL detected as: <tt>" . htmlspecialchars(get_location()) . "</tt><br />\n";
234 /* check minimal requirements for other security options */
237 if($use_smtp_tls == 1 ||
$use_imap_tls == 1) {
238 if(!check_php_version(4,3,0)) {
239 do_err('You need at least PHP 4.3.0 for SMTP/IMAP TLS!');
241 if(!extension_loaded('openssl')) {
242 do_err('You need the openssl PHP extension to use SMTP/IMAP TLS!');
245 /* starttls extensions */
246 if($use_smtp_tls == 2 ||
$use_imap_tls == 2) {
247 if (! function_exists('stream_socket_enable_crypto')) {
248 do_err('If you want to use STARTTLS extension, you need stream_socket_enable_crypto() function from PHP 5.1.0 and newer.');
252 if ($smtp_auth_mech=='digest-md5' ||
$imap_auth_mech =='digest-md5') {
253 if (!extension_loaded('xml')) {
254 do_err('You need the PHP XML extension to use Digest-MD5 authentication!');
258 /* check outgoing mail */
260 echo "Checking outgoing mail service....<br />\n";
263 // is_executable also checks for existance, but we want to be as precise as possible with the errors
264 if(!file_exists($sendmail_path)) {
265 do_err("Location of sendmail program incorrect ($sendmail_path)!");
267 if(!is_executable($sendmail_path)) {
268 do_err("I cannot execute the sendmail program ($sendmail_path)!");
271 echo $IND . "sendmail OK<br />\n";
273 $stream = fsockopen( ($use_smtp_tls==1?
'tls://':'').$smtpServerAddress, $smtpPort,
274 $errorNumber, $errorString);
276 do_err("Error connecting to SMTP server \"$smtpServerAddress:$smtpPort\".".
277 "Server error: ($errorNumber) ".htmlspecialchars($errorString));
280 // check for SMTP code; should be 2xx to allow us access
281 $smtpline = fgets($stream, 1024);
282 if(((int) $smtpline{0}) > 3) {
283 do_err("Error connecting to SMTP server. Server error: ".
284 htmlspecialchars($smtpline));
287 /* smtp starttls checks */
288 if ($use_smtp_tls==2) {
289 // if something breaks, script should close smtp connection on exit.
292 fwrite($stream,"EHLO $client_ip\r\n");
296 while ($line=fgets($stream, 1024)){
297 if (preg_match("/^250(-|\s)(\S*)\s+(\S.*)/",$line,$match)||
298 preg_match("/^250(-|\s)(\S*)\s+/",$line,$match)) {
299 if (!isset($match[3])) {
300 // simple one word extension
301 $ehlo[strtoupper($match[2])]='';
303 // ehlo-keyword + ehlo-param
304 $ehlo[strtoupper($match[2])]=trim($match[3]);
306 if ($match[1]==' ') {
318 do_err('SMTP EHLO failed. You need ESMTP support for SMTP STARTTLS');
319 } elseif (!array_key_exists('STARTTLS',$ehlo)) {
320 do_err('STARTTLS support is not declared by SMTP server.');
323 fwrite($stream,"STARTTLS\r\n");
324 $starttls_response=fgets($stream, 1024);
325 if ($starttls_response[0]!=2) {
326 $starttls_cmd_err = 'SMTP STARTTLS failed. Server replied: '
327 .htmlspecialchars($starttls_response);
328 do_err($starttls_cmd_err);
329 } elseif(! stream_socket_enable_crypto($stream,true,STREAM_CRYPTO_METHOD_TLS_CLIENT
)) {
330 do_err('Failed to enable encryption on SMTP STARTTLS connection.');
332 echo $IND . "SMTP STARTTLS extension looks OK.<br />\n";
334 // According to RFC we should second ehlo call here.
337 fputs($stream, 'QUIT');
339 echo $IND . 'SMTP server OK (<tt><small>'.
340 trim(htmlspecialchars($smtpline))."</small></tt>)<br />\n";
342 /* POP before SMTP */
343 if($pop_before_smtp) {
344 $stream = fsockopen($smtpServerAddress, 110, $err_no, $err_str);
346 do_err("Error connecting to POP Server ($smtpServerAddress:110) "
347 . $err_no . ' : ' . htmlspecialchars($err_str));
350 $tmp = fgets($stream, 1024);
351 if (substr($tmp, 0, 3) != '+OK') {
352 do_err("Error connecting to POP Server ($smtpServerAddress:110)"
353 . ' '.htmlspecialchars($tmp));
355 fputs($stream, 'QUIT');
357 echo $IND . "POP-before-SMTP OK.<br />\n";
362 * Check the IMAP server
364 echo "Checking IMAP service....<br />\n";
366 /** Can we open a connection? */
367 $stream = fsockopen( ($use_imap_tls==1?
'tls://':'').$imapServerAddress, $imapPort,
368 $errorNumber, $errorString);
370 do_err("Error connecting to IMAP server \"$imapServerAddress:$imapPort\".".
371 "Server error: ($errorNumber) ".
372 htmlspecialchars($errorString));
375 /** Is the first response 'OK'? */
376 $imapline = fgets($stream, 1024);
377 if(substr($imapline, 0,4) != '* OK') {
378 do_err('Error connecting to IMAP server. Server error: '.
379 htmlspecialchars($imapline));
382 echo $IND . 'IMAP server ready (<tt><small>'.
383 htmlspecialchars(trim($imapline))."</small></tt>)<br />\n";
385 /** Check capabilities */
386 fputs($stream, "A001 CAPABILITY\r\n");
388 while ($line=fgets($stream, 1024)){
389 if (preg_match("/A001.*/",$line)) {
396 /* don't display capabilities before STARTTLS */
397 if ($use_imap_tls==2 && stristr($capline, 'STARTTLS') === false) {
398 do_err('Your server doesn\'t support STARTTLS.');
399 } elseif($use_imap_tls==2) {
400 /* try starting starttls */
401 fwrite($stream,"A002 STARTTLS\r\n");
402 $starttls_line=fgets($stream, 1024);
403 if (! preg_match("/^A002 OK.*/i",$starttls_line)) {
404 $imap_starttls_err = 'IMAP STARTTLS failed. Server replied: '
405 .htmlspecialchars($starttls_line);
406 do_err($imap_starttls_err);
407 } elseif (! stream_socket_enable_crypto($stream,true,STREAM_CRYPTO_METHOD_TLS_CLIENT
)) {
408 do_err('Failed to enable encryption on IMAP connection.');
410 echo $IND . "IMAP STARTTLS extension looks OK.<br />\n";
413 // get new capability line
414 fwrite($stream,"A003 CAPABILITY\r\n");
416 while ($line=fgets($stream, 1024)){
417 if (preg_match("/A003.*/",$line)) {
425 echo $IND . 'Capabilities: <tt>'.htmlspecialchars($capline)."</tt><br />\n";
427 if($imap_auth_mech == 'login' && stristr($capline, 'LOGINDISABLED') !== FALSE) {
428 do_err('Your server doesn\'t allow plaintext logins. '.
429 'Try enabling another authentication mechanism like CRAM-MD5, DIGEST-MD5 or TLS-encryption '.
430 'in the SquirrelMail configuration.', FALSE);
433 /** OK, close connection */
434 fputs($stream, "A004 LOGOUT\r\n");
437 echo "Checking internationalization (i18n) settings...<br />\n";
438 echo "$IND gettext - ";
439 if (function_exists('gettext')) {
440 echo 'Gettext functions are available.'
441 .' On some systems you must have appropriate system locales compiled.'
444 echo 'Gettext functions are unavailable.'
445 .' SquirrelMail will use slower internal gettext functions.'
448 echo "$IND mbstring - ";
449 if (function_exists('mb_detect_encoding')) {
450 echo "Mbstring functions are available.<br />\n";
452 echo 'Mbstring functions are unavailable.'
453 ." Japanese translation won't work.<br />\n";
455 echo "$IND recode - ";
456 if (function_exists('recode')) {
457 echo "Recode functions are available.<br />\n";
458 } elseif (isset($use_php_recode) && $use_php_recode) {
459 echo "Recode functions are unavailable.<br />\n";
460 do_err('Your configuration requires recode support, but recode support is missing.');
462 echo "Recode functions are unavailable.<br />\n";
464 echo "$IND iconv - ";
465 if (function_exists('iconv')) {
466 echo "Iconv functions are available.<br />\n";
467 } elseif (isset($use_php_iconv) && $use_php_iconv) {
468 echo "Iconv functions are unavailable.<br />\n";
469 do_err('Your configuration requires iconv support, but iconv support is missing.');
471 echo "Iconv functions are unavailable.<br />\n";
473 // same test as in include/validate.php
474 echo "$IND timezone - ";
475 if ( (!ini_get('safe_mode')) ||
476 !strcmp(ini_get('safe_mode_allowed_env_vars'),'') ||
477 preg_match('/^([\w_]+,)*TZ/', ini_get('safe_mode_allowed_env_vars')) ) {
478 echo "Webmail users can change their time zone settings.<br />\n";
480 echo "Webmail users can't change their time zone settings.<br />\n";
485 echo "Checking database functions...<br />\n";
486 if($addrbook_dsn ||
$prefs_dsn ||
$addrbook_global_dsn) {
487 @include_once
('DB.php');
488 if (class_exists('DB')) {
489 echo "$IND PHP Pear DB support is present.<br />\n";
491 'dbase' => 'dbase_open',
492 'fbsql' => 'fbsql_connect',
493 'interbase' => 'ibase_connect',
494 'informix' => 'ifx_connect',
495 'msql' => 'msql_connect',
496 'mssql' => 'mssql_connect',
497 'mysql' => 'mysql_connect',
498 'mysqli' => 'mysqli_connect',
499 'oci8' => 'ocilogon',
500 'odbc' => 'odbc_connect',
501 'pgsql' => 'pg_connect',
502 'sqlite' => 'sqlite_open',
503 'sybase' => 'sybase_connect'
508 $dsns['preferences'] = $prefs_dsn;
511 $dsns['addressbook'] = $addrbook_dsn;
513 if($addrbook_global_dsn) {
514 $dsns['global addressbook'] = $addrbook_global_dsn;
517 foreach($dsns as $type => $dsn) {
518 $aDsn = explode(':', $dsn);
519 $dbtype = array_shift($aDsn);
520 if(isset($db_functions[$dbtype]) && function_exists($db_functions[$dbtype])) {
521 echo "$IND$dbtype database support present.<br />\n";
523 // now, test this interface:
525 $dbh = DB
::connect($dsn, true);
526 if (DB
::isError($dbh)) {
527 do_err('Database error: '. htmlspecialchars(DB
::errorMessage($dbh)) .
528 ' in ' .$type .' DSN.');
531 echo "$IND$type database connect successful.<br />\n";
534 do_err($dbtype.' database support not present!');
538 $db_error='Required PHP PEAR DB support is not available.'
539 .' Is PEAR installed and is the include path set correctly to find <tt>DB.php</tt>?'
540 .' The include path is now:<tt>' . ini_get('include_path') . '</tt>.';
544 echo $IND."not using database functionality.<br />\n";
548 echo "Checking LDAP functions...<br />\n";
549 if( empty($ldap_server) ) {
550 echo $IND."not using LDAP functionality.<br />\n";
552 if ( !function_exists('ldap_connect') ) {
553 do_err('Required LDAP support is not available.');
555 echo "$IND LDAP support present.<br />\n";
556 foreach ( $ldap_server as $param ) {
558 $linkid = @ldap_connect
($param['host'], (empty($param['port']) ?
389 : $param['port']) );
561 echo "$IND LDAP connect to ".$param['host']." successful: ".$linkid."<br />\n";
563 if ( !empty($param['protocol']) &&
564 !ldap_set_option($linkid, LDAP_OPT_PROTOCOL_VERSION
, $param['protocol']) ) {
565 do_err('Unable to set LDAP protocol');
568 if ( empty($param['binddn']) ) {
569 $bind = @ldap_bind
($linkid);
571 $bind = @ldap_bind
($param['binddn'], $param['bindpw']);
575 echo "$IND LDAP Bind Successful <br />";
577 do_err('Unable to Bind to LDAP Server');
580 @ldap_close
($linkid);
582 do_err('Connection to LDAP failed');
590 <p
>Congratulations
, your SquirrelMail setup looks fine to me
!</p
>
592 <p
><a href
="login.php">Login now
</a
></p
>