4 * SquirrelMail configtest script
6 * @copyright © 2003-2005 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 if (! isset($client_ip) ||
$client_ip!='127.0.0.1') {
81 do_err('Enable "Allow remote configtest" option in squirrelmail configuration in order to use this script.');
84 /* checking PHP specs */
86 echo "<p><table>\n<tr><td>SquirrelMail version:</td><td><b>" . $version . "</b></td></tr>\n" .
87 '<tr><td>Config file version:</td><td><b>' . $config_version . "</b></td></tr>\n" .
88 '<tr><td>Config file last modified:</td><td><b>' .
89 date ('d F Y H:i:s', filemtime(SM_PATH
. 'config/config.php')) .
90 "</b></td></tr>\n</table>\n</p>\n\n";
92 echo "Checking PHP configuration...<br />\n";
94 if(!check_php_version(4,1,0)) {
95 do_err('Insufficient PHP version: '. PHP_VERSION
. '! Minimum required: 4.1.0');
98 echo $IND . 'PHP version ' . PHP_VERSION
. " OK.<br />\n";
100 $php_exts = array('session','pcre');
101 $diff = array_diff($php_exts, get_loaded_extensions());
103 do_err('Required PHP extensions missing: '.implode(', ',$diff) );
106 echo $IND . "PHP extensions OK.<br />\n";
108 /* dangerous php settings */
110 * mbstring.func_overload allows to replace original string and regexp functions
111 * with their equivalents from php mbstring extension. It causes problems when
112 * scripts analyze 8bit strings byte after byte or use 8bit strings in regexp tests.
113 * Setting can be controlled in php.ini (php 4.2.0), webserver config (php 4.2.0)
114 * and .htaccess files (php 4.3.5).
116 if (function_exists('mb_internal_encoding') &&
117 check_php_version(4,2,0) &&
118 (int)ini_get('mbstring.func_overload')!=0) {
119 $mb_error='You have enabled mbstring overloading.'
120 .' It can cause problems with SquirrelMail scripts that rely on single byte string functions.';
125 * We code with register_globals = off. SquirrelMail should work in such setup
126 * since 1.2.9 and 1.3.0. Running SquirrelMail with register_globals = on can
127 * cause variable corruption and security issues. Globals can be turned off in
128 * php.ini, webserver config and .htaccess files. Scripts can turn off globals only
129 * in php 4.2.3 or older.
131 if ((bool) ini_get('register_globals')) {
132 $rg_error='You have enabled php register_globals.'
133 .' Running PHP installation with register_globals=on can cause problems.'
134 .' See <a href="http://www.php.net/manual/en/security.registerglobals.php">'
135 .'security information about register_globals</a>.';
141 echo "Checking paths...<br />\n";
143 if(!file_exists($data_dir)) {
144 // data_dir is not that important in db_setups.
145 if (isset($prefs_dsn) && ! empty($prefs_dsn)) {
146 $data_dir_error = "Data dir ($data_dir) does not exist!\n";
147 echo $IND .'<font color="red"><b>ERROR:</b></font> ' . $data_dir_error;
149 do_err("Data dir ($data_dir) does not exist!");
152 // don't check if errors
153 if(!isset($data_dir_error) && !is_dir($data_dir)) {
154 if (isset($prefs_dsn) && ! empty($prefs_dsn)) {
155 $data_dir_error = "Data dir ($data_dir) is not a directory!\n";
156 echo $IND . '<font color="red"><b>ERROR:</b></font> ' . $data_dir_error;
158 do_err("Data dir ($data_dir) is not a directory!");
161 // datadir should be executable - but no clean way to test on that
162 if(!isset($data_dir_error) && !is_writable($data_dir)) {
163 if (isset($prefs_dsn) && ! empty($prefs_dsn)) {
164 $data_dir_error = "Data dir ($data_dir) is not writable!\n";
165 echo $IND . '<font color="red"><b>ERROR:</b></font> ' . $data_dir_error;
167 do_err("Data dir ($data_dir) is not writable!");
171 if (isset($data_dir_error)) {
172 echo " Some plugins might need access to data directory.<br />\n";
174 // todo_ornot: actually write something and read it back.
175 echo $IND . "Data dir OK.<br />\n";
178 if($data_dir == $attachment_dir) {
179 echo $IND . "Attachment dir is the same as data dir.<br />\n";
180 if (isset($data_dir_error)) {
181 do_err($data_dir_error);
184 if(!file_exists($attachment_dir)) {
185 do_err("Attachment dir ($attachment_dir) does not exist!");
187 if (!is_dir($attachment_dir)) {
188 do_err("Attachment dir ($attachment_dir) is not a directory!");
190 if (!is_writable($attachment_dir)) {
191 do_err("I cannot write to attachment dir ($attachment_dir)!");
193 echo $IND . "Attachment dir OK.<br />\n";
197 /* check plugins and themes */
198 if (isset($plugins[0])) {
199 foreach($plugins as $plugin) {
200 if(!file_exists(SM_PATH
.'plugins/'.$plugin)) {
201 do_err('You have enabled the <i>'.$plugin.'</i> plugin but I cannot find it.', FALSE);
202 } elseif (!is_readable(SM_PATH
.'plugins/'.$plugin.'/setup.php')) {
203 do_err('You have enabled the <i>'.$plugin.'</i> plugin but I cannot read its setup.php file.', FALSE);
206 echo $IND . "Plugins OK.<br />\n";
208 echo $IND . "Plugins are not enabled in config.<br />\n";
210 foreach($theme as $thm) {
211 if(!file_exists($thm['PATH'])) {
212 do_err('You have enabled the <i>'.$thm['NAME'].'</i> theme but I cannot find it ('.$thm['PATH'].').', FALSE);
213 } elseif(!is_readable($thm['PATH'])) {
214 do_err('You have enabled the <i>'.$thm['NAME'].'</i> theme but I cannot read it ('.$thm['PATH'].').', FALSE);
218 echo $IND . "Themes OK.<br />\n";
220 if ( $squirrelmail_default_language != 'en_US' ) {
221 $loc_path = SM_PATH
.'locale/'.$squirrelmail_default_language.'/LC_MESSAGES/squirrelmail.mo';
222 if( ! file_exists( $loc_path ) ) {
223 do_err('You have set <i>' . $squirrelmail_default_language .
224 '</i> as your default language, but I cannot find this translation (should be '.
225 'in <tt>' . $loc_path . '</tt>). Please note that you have to download translations '.
226 'separately from the main SquirrelMail package.', FALSE);
227 } elseif ( ! is_readable( $loc_path ) ) {
228 do_err('You have set <i>' . $squirrelmail_default_language .
229 '</i> as your default language, but I cannot read this translation (file '.
230 'in <tt>' . $loc_path . '</tt> unreadable).', FALSE);
232 echo $IND . "Default language OK.<br />\n";
235 echo $IND . "Default language OK.<br />\n";
238 echo $IND . "Base URL detected as: <tt>" . htmlspecialchars(get_location()) . "</tt><br />\n";
241 /* check outgoing mail */
243 if($use_smtp_tls ||
$use_imap_tls) {
244 if(!check_php_version(4,3,0)) {
245 do_err('You need at least PHP 4.3.0 for SMTP/IMAP TLS!');
247 if(!extension_loaded('openssl')) {
248 do_err('You need the openssl PHP extension to use SMTP/IMAP TLS!');
252 echo "Checking outgoing mail service....<br />\n";
255 // is_executable also checks for existance, but we want to be as precise as possible with the errors
256 if(!file_exists($sendmail_path)) {
257 do_err("Location of sendmail program incorrect ($sendmail_path)!");
259 if(!is_executable($sendmail_path)) {
260 do_err("I cannot execute the sendmail program ($sendmail_path)!");
263 echo $IND . "sendmail OK<br />\n";
265 $stream = fsockopen( ($use_smtp_tls?
'tls://':'').$smtpServerAddress, $smtpPort,
266 $errorNumber, $errorString);
268 do_err("Error connecting to SMTP server \"$smtpServerAddress:$smtpPort\".".
269 "Server error: ($errorNumber) ".htmlspecialchars($errorString));
272 // check for SMTP code; should be 2xx to allow us access
273 $smtpline = fgets($stream, 1024);
274 if(((int) $smtpline{0}) > 3) {
275 do_err("Error connecting to SMTP server. Server error: ".
276 htmlspecialchars($smtpline));
279 fputs($stream, 'QUIT');
281 echo $IND . 'SMTP server OK (<tt><small>'.
282 trim(htmlspecialchars($smtpline))."</small></tt>)<br />\n";
284 /* POP before SMTP */
285 if($pop_before_smtp) {
286 $stream = fsockopen($smtpServerAddress, 110, $err_no, $err_str);
288 do_err("Error connecting to POP Server ($smtpServerAddress:110) "
289 . $err_no . ' : ' . htmlspecialchars($err_str));
292 $tmp = fgets($stream, 1024);
293 if (substr($tmp, 0, 3) != '+OK') {
294 do_err("Error connecting to POP Server ($smtpServerAddress:110)"
295 . ' '.htmlspecialchars($tmp));
297 fputs($stream, 'QUIT');
299 echo $IND . "POP-before-SMTP OK.<br />\n";
304 * Check the IMAP server
306 echo "Checking IMAP service....<br />\n";
308 /** Can we open a connection? */
309 $stream = fsockopen( ($use_imap_tls?
'tls://':'').$imapServerAddress, $imapPort,
310 $errorNumber, $errorString);
312 do_err("Error connecting to IMAP server \"$imapServerAddress:$imapPort\".".
313 "Server error: ($errorNumber) ".
314 htmlspecialchars($errorString));
317 /** Is the first response 'OK'? */
318 $imapline = fgets($stream, 1024);
319 if(substr($imapline, 0,4) != '* OK') {
320 do_err('Error connecting to IMAP server. Server error: '.
321 htmlspecialchars($imapline));
324 echo $IND . 'IMAP server ready (<tt><small>'.
325 htmlspecialchars(trim($imapline))."</small></tt>)<br />\n";
327 /** Check capabilities */
328 fputs($stream, "A001 CAPABILITY\r\n");
329 $capline = fgets($stream, 1024);
331 echo $IND . 'Capabilities: <tt>'.htmlspecialchars($capline)."</tt><br />\n";
333 if($imap_auth_mech == 'login' && stristr($capline, 'LOGINDISABLED') !== FALSE) {
334 do_err('Your server doesn\'t allow plaintext logins. '.
335 'Try enabling another authentication mechanism like CRAM-MD5, DIGEST-MD5 or TLS-encryption '.
336 'in the SquirrelMail configuration.', FALSE);
338 if($use_imap_tls && stristr($capline, 'STARTTLS') === FALSE) {
339 do_err('You have enabled TLS encryption in the config, but the server does not '.
340 'report STARTTLS capability. TLS is probably not supported.', FALSE);
343 /** OK, close connection */
344 fputs($stream, "A002 LOGOUT\r\n");
347 echo "Checking internationalization (i18n) settings...<br />\n";
348 echo "$IND gettext - ";
349 if (function_exists('gettext')) {
350 echo 'Gettext functions are available.'
351 .' On some systems you must have appropriate system locales compiled.'
354 echo 'Gettext functions are unavailable.'
355 .' SquirrelMail will use slower internal gettext functions.'
358 echo "$IND mbstring - ";
359 if (function_exists('mb_detect_encoding')) {
360 echo "Mbstring functions are available.<br />\n";
362 echo 'Mbstring functions are unavailable.'
363 ." Japanese translation won't work.<br />\n";
365 echo "$IND recode - ";
366 if (function_exists('recode')) {
367 echo "Recode functions are available.<br />\n";
368 } elseif (isset($use_php_recode) && $use_php_recode) {
369 echo "Recode functions are unavailable.<br />\n";
370 do_err('Your configuration requires recode support, but recode support is missing.');
372 echo "Recode functions are unavailable.<br />\n";
374 echo "$IND iconv - ";
375 if (function_exists('iconv')) {
376 echo "Iconv functions are available.<br />\n";
377 } elseif (isset($use_php_iconv) && $use_php_iconv) {
378 echo "Iconv functions are unavailable.<br />\n";
379 do_err('Your configuration requires iconv support, but iconv support is missing.');
381 echo "Iconv functions are unavailable.<br />\n";
383 // same test as in include/validate.php
384 echo "$IND timezone - ";
385 if ( (!ini_get('safe_mode')) ||
386 !strcmp(ini_get('safe_mode_allowed_env_vars'),'') ||
387 preg_match('/^([\w_]+,)*TZ/', ini_get('safe_mode_allowed_env_vars')) ) {
388 echo "Webmail users can change their time zone settings.<br />\n";
390 echo "Webmail users can't change their time zone settings.<br />\n";
395 echo "Checking database functions...<br />\n";
396 if($addrbook_dsn ||
$prefs_dsn ||
$addrbook_global_dsn) {
397 @include_once
('DB.php');
398 if (class_exists('DB')) {
399 echo "$IND PHP Pear DB support is present.<br />\n";
401 'dbase' => 'dbase_open',
402 'fbsql' => 'fbsql_connect',
403 'interbase' => 'ibase_connect',
404 'informix' => 'ifx_connect',
405 'msql' => 'msql_connect',
406 'mssql' => 'mssql_connect',
407 'mysql' => 'mysql_connect',
408 'mysqli' => 'mysqli_connect',
409 'oci8' => 'ocilogon',
410 'odbc' => 'odbc_connect',
411 'pgsql' => 'pg_connect',
412 'sqlite' => 'sqlite_open',
413 'sybase' => 'sybase_connect'
418 $dsns['preferences'] = $prefs_dsn;
421 $dsns['addressbook'] = $addrbook_dsn;
423 if($addrbook_global_dsn) {
424 $dsns['global addressbook'] = $addrbook_global_dsn;
427 foreach($dsns as $type => $dsn) {
428 $aDsn = explode(':', $dsn);
429 $dbtype = array_shift($aDsn);
430 if(isset($db_functions[$dbtype]) && function_exists($db_functions[$dbtype])) {
431 echo "$IND$dbtype database support present.<br />\n";
433 // now, test this interface:
435 $dbh = DB
::connect($dsn, true);
436 if (DB
::isError($dbh)) {
437 do_err('Database error: '. htmlspecialchars(DB
::errorMessage($dbh)) .
438 ' in ' .$type .' DSN.');
441 echo "$IND$type database connect successful.<br />\n";
444 do_err($dbtype.' database support not present!');
448 $db_error='Required PHP PEAR DB support is not available.'
449 .' Is PEAR installed and is the include path set correctly to find <tt>DB.php</tt>?'
450 .' The include path is now:<tt>' . ini_get('include_path') . '</tt>.';
454 echo $IND."not using database functionality.<br />\n";
458 echo "Checking LDAP functions...<br />\n";
459 if( empty($ldap_server) ) {
460 echo $IND."not using LDAP functionality.<br />\n";
462 if ( !function_exists('ldap_connect') ) {
463 do_err('Required LDAP support is not available.');
465 echo "$IND LDAP support present.<br />\n";
466 foreach ( $ldap_server as $param ) {
468 $linkid = @ldap_connect
($param['host'], (empty($param['port']) ?
389 : $param['port']) );
471 echo "$IND LDAP connect to ".$param['host']." successful: ".$linkid."<br />\n";
473 if ( !empty($param['protocol']) &&
474 !ldap_set_option($linkid, LDAP_OPT_PROTOCOL_VERSION
, $param['protocol']) ) {
475 do_err('Unable to set LDAP protocol');
478 if ( empty($param['binddn']) ) {
479 $bind = @ldap_bind
($linkid);
481 $bind = @ldap_bind
($param['binddn'], $param['bindpw']);
485 echo "$IND LDAP Bind Successful <br />";
487 do_err('Unable to Bind to LDAP Server');
490 @ldap_close
($linkid);
492 do_err('Connection to LDAP failed');
500 <p
>Congratulations
, your SquirrelMail setup looks fine to me
!</p
>
502 <p
><a href
="login.php">Login now
</a
></p
>