4 * SquirrelMail configtest script
6 * Copyright (c) 2003-2005 The SquirrelMail Project Team
7 * Licensed under the GNU GPL. For full terms see the file COPYING.
10 * @package squirrelmail
14 /************************************************************
15 * NOTE: you do not need to change this script! *
16 * If it throws errors you need to adjust your config. *
17 ************************************************************/
19 // This script could really use some restructuring as it has grown quite rapidly
20 // but is not very 'clean'. Feel free to get some structure into this thing.
22 function do_err($str, $exit = TRUE) {
24 echo '<p>'.$IND.'<font color="red"><b>ERROR:</b></font> ' .$str. "</p>\n";
26 echo '</body></html>';
31 $IND = str_repeat(' ',4);
35 define('SM_PATH', '../');
37 /* set default value in order to block remote access to script */
38 $allow_remote_configtest=false;
41 * Load config before output begins. functions/strings.php depends on
42 * functions/globals.php. functions/global.php needs to be run before
43 * any html output starts. If config.php is missing, error will be displayed
46 if (file_exists(SM_PATH
. 'config/config.php')) {
47 include(SM_PATH
. 'config/config.php');
48 include(SM_PATH
. 'functions/strings.php');
50 ?
><!DOCTYPE HTML
PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
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 if (! isset($client_ip) ||
$client_ip!='127.0.0.1') {
82 do_err('Enable "Allow remote configtest" option in squirrelmail configuration in order to use this script.');
85 /* checking PHP specs */
87 echo "<p><table>\n<tr><td>SquirrelMail version:</td><td><b>" . $version . "</b></td></tr>\n" .
88 '<tr><td>Config file version:</td><td><b>' . $config_version . "</b></td></tr>\n" .
89 '<tr><td>Config file last modified:</td><td><b>' .
90 date ('d F Y H:i:s', filemtime(SM_PATH
. 'config/config.php')) .
91 "</b></td></tr>\n</table>\n</p>\n\n";
93 echo "Checking PHP configuration...<br />\n";
95 if(!check_php_version(4,1,0)) {
96 do_err('Insufficient PHP version: '. PHP_VERSION
. '! Minimum required: 4.1.0');
99 echo $IND . 'PHP version ' . PHP_VERSION
. " OK.<br />\n";
101 $php_exts = array('session','pcre');
102 $diff = array_diff($php_exts, get_loaded_extensions());
104 do_err('Required PHP extensions missing: '.implode(', ',$diff) );
107 echo $IND . "PHP extensions OK.<br />\n";
109 /* dangerous php settings */
111 * mbstring.func_overload allows to replace original string and regexp functions
112 * with their equivalents from php mbstring extension. It causes problems when
113 * scripts analyze 8bit strings byte after byte or use 8bit strings in regexp tests.
114 * Setting can be controlled in php.ini (php 4.2.0), webserver config (php 4.2.0)
115 * and .htaccess files (php 4.3.5).
117 if (function_exists('mb_internal_encoding') &&
118 check_php_version(4,2,0) &&
119 (int)ini_get('mbstring.func_overload')!=0) {
120 $mb_error='You have enabled mbstring overloading.'
121 .' It can cause problems with SquirrelMail scripts that rely on single byte string functions.';
126 * We code with register_globals = off. SquirrelMail should work in such setup
127 * since 1.2.9 and 1.3.0. Running SquirrelMail with register_globals = on can
128 * cause variable corruption and security issues. Globals can be turned off in
129 * php.ini, webserver config and .htaccess files. Scripts can turn off globals only
130 * in php 4.2.3 or older.
132 if ((bool) ini_get('register_globals')) {
133 $rg_error='You have enabled php register_globals.'
134 .' Running PHP installation with register_globals=on can cause problems.'
135 .' See <a href="http://www.php.net/manual/en/security.registerglobals.php">'
136 .'security information about register_globals</a>.';
142 echo "Checking paths...<br />\n";
144 if(!file_exists($data_dir)) {
145 // data_dir is not that important in db_setups.
146 if (isset($prefs_dsn) && ! empty($prefs_dsn)) {
147 $data_dir_error = "Data dir ($data_dir) does not exist!\n";
148 echo $IND .'<font color="red"><b>ERROR:</b></font> ' . $data_dir_error;
150 do_err("Data dir ($data_dir) does not exist!");
153 // don't check if errors
154 if(!isset($data_dir_error) && !is_dir($data_dir)) {
155 if (isset($prefs_dsn) && ! empty($prefs_dsn)) {
156 $data_dir_error = "Data dir ($data_dir) is not a directory!\n";
157 echo $IND . '<font color="red"><b>ERROR:</b></font> ' . $data_dir_error;
159 do_err("Data dir ($data_dir) is not a directory!");
162 // datadir should be executable - but no clean way to test on that
163 if(!isset($data_dir_error) && !is_writable($data_dir)) {
164 if (isset($prefs_dsn) && ! empty($prefs_dsn)) {
165 $data_dir_error = "Data dir ($data_dir) is not writable!\n";
166 echo $IND . '<font color="red"><b>ERROR:</b></font> ' . $data_dir_error;
168 do_err("Data dir ($data_dir) is not writable!");
172 if (isset($data_dir_error)) {
173 echo " Some plugins might need access to data directory.<br />\n";
175 // todo_ornot: actually write something and read it back.
176 echo $IND . "Data dir OK.<br />\n";
179 if($data_dir == $attachment_dir) {
180 echo $IND . "Attachment dir is the same as data dir.<br />\n";
181 if (isset($data_dir_error)) {
182 do_err($data_dir_error);
185 if(!file_exists($attachment_dir)) {
186 do_err("Attachment dir ($attachment_dir) does not exist!");
188 if (!is_dir($attachment_dir)) {
189 do_err("Attachment dir ($attachment_dir) is not a directory!");
191 if (!is_writable($attachment_dir)) {
192 do_err("I cannot write to attachment dir ($attachment_dir)!");
194 echo $IND . "Attachment dir OK.<br />\n";
198 /* check plugins and themes */
199 if (isset($plugins[0])) {
200 foreach($plugins as $plugin) {
201 if(!file_exists(SM_PATH
.'plugins/'.$plugin)) {
202 do_err('You have enabled the <i>'.$plugin.'</i> plugin but I cannot find it.', FALSE);
203 } elseif (!is_readable(SM_PATH
.'plugins/'.$plugin.'/setup.php')) {
204 do_err('You have enabled the <i>'.$plugin.'</i> plugin but I cannot read its setup.php file.', FALSE);
207 echo $IND . "Plugins OK.<br />\n";
209 echo $IND . "Plugins are not enabled in config.<br />\n";
211 foreach($theme as $thm) {
212 if(!file_exists($thm['PATH'])) {
213 do_err('You have enabled the <i>'.$thm['NAME'].'</i> theme but I cannot find it ('.$thm['PATH'].').', FALSE);
214 } elseif(!is_readable($thm['PATH'])) {
215 do_err('You have enabled the <i>'.$thm['NAME'].'</i> theme but I cannot read it ('.$thm['PATH'].').', FALSE);
219 echo $IND . "Themes OK.<br />\n";
221 if ( $squirrelmail_default_language != 'en_US' ) {
222 $loc_path = SM_PATH
.'locale/'.$squirrelmail_default_language.'/LC_MESSAGES/squirrelmail.mo';
223 if( ! file_exists( $loc_path ) ) {
224 do_err('You have set <i>' . $squirrelmail_default_language .
225 '</i> as your default language, but I cannot find this translation (should be '.
226 'in <tt>' . $loc_path . '</tt>). Please note that you have to download translations '.
227 'separately from the main SquirrelMail package.', FALSE);
228 } elseif ( ! is_readable( $loc_path ) ) {
229 do_err('You have set <i>' . $squirrelmail_default_language .
230 '</i> as your default language, but I cannot read this translation (file '.
231 'in <tt>' . $loc_path . '</tt> unreadable).', FALSE);
233 echo $IND . "Default language OK.<br />\n";
236 echo $IND . "Default language OK.<br />\n";
239 echo $IND . "Base URL detected as: <tt>" . htmlspecialchars(get_location()) . "</tt><br />\n";
242 /* check outgoing mail */
244 if($use_smtp_tls ||
$use_imap_tls) {
245 if(!check_php_version(4,3,0)) {
246 do_err('You need at least PHP 4.3.0 for SMTP/IMAP TLS!');
248 if(!extension_loaded('openssl')) {
249 do_err('You need the openssl PHP extension to use SMTP/IMAP TLS!');
253 echo "Checking outgoing mail service....<br />\n";
256 // is_executable also checks for existance, but we want to be as precise as possible with the errors
257 if(!file_exists($sendmail_path)) {
258 do_err("Location of sendmail program incorrect ($sendmail_path)!");
260 if(!is_executable($sendmail_path)) {
261 do_err("I cannot execute the sendmail program ($sendmail_path)!");
264 echo $IND . "sendmail OK<br />\n";
266 $stream = fsockopen( ($use_smtp_tls?
'tls://':'').$smtpServerAddress, $smtpPort,
267 $errorNumber, $errorString);
269 do_err("Error connecting to SMTP server \"$smtpServerAddress:$smtpPort\".".
270 "Server error: ($errorNumber) ".htmlspecialchars($errorString));
273 // check for SMTP code; should be 2xx to allow us access
274 $smtpline = fgets($stream, 1024);
275 if(((int) $smtpline{0}) > 3) {
276 do_err("Error connecting to SMTP server. Server error: ".
277 htmlspecialchars($smtpline));
280 fputs($stream, 'QUIT');
282 echo $IND . 'SMTP server OK (<tt><small>'.
283 trim(htmlspecialchars($smtpline))."</small></tt>)<br />\n";
285 /* POP before SMTP */
286 if($pop_before_smtp) {
287 $stream = fsockopen($smtpServerAddress, 110, $err_no, $err_str);
289 do_err("Error connecting to POP Server ($smtpServerAddress:110) "
290 . $err_no . ' : ' . htmlspecialchars($err_str));
293 $tmp = fgets($stream, 1024);
294 if (substr($tmp, 0, 3) != '+OK') {
295 do_err("Error connecting to POP Server ($smtpServerAddress:110)"
296 . ' '.htmlspecialchars($tmp));
298 fputs($stream, 'QUIT');
300 echo $IND . "POP-before-SMTP OK.<br />\n";
305 * Check the IMAP server
307 echo "Checking IMAP service....<br />\n";
309 /** Can we open a connection? */
310 $stream = fsockopen( ($use_imap_tls?
'tls://':'').$imapServerAddress, $imapPort,
311 $errorNumber, $errorString);
313 do_err("Error connecting to IMAP server \"$imapServerAddress:$imapPort\".".
314 "Server error: ($errorNumber) ".
315 htmlspecialchars($errorString));
318 /** Is the first response 'OK'? */
319 $imapline = fgets($stream, 1024);
320 if(substr($imapline, 0,4) != '* OK') {
321 do_err('Error connecting to IMAP server. Server error: '.
322 htmlspecialchars($imapline));
325 echo $IND . 'IMAP server ready (<tt><small>'.
326 htmlspecialchars(trim($imapline))."</small></tt>)<br />\n";
328 /** Check capabilities */
329 fputs($stream, "A001 CAPABILITY\r\n");
330 $capline = fgets($stream, 1024);
332 echo $IND . 'Capabilities: <tt>'.htmlspecialchars($capline)."</tt><br />\n";
334 if($imap_auth_mech == 'login' && stristr($capline, 'LOGINDISABLED') !== FALSE) {
335 do_err('Your server doesn\'t allow plaintext logins. '.
336 'Try enabling another authentication mechanism like CRAM-MD5, DIGEST-MD5 or TLS-encryption '.
337 'in the SquirrelMail configuration.', FALSE);
339 if($use_imap_tls && stristr($capline, 'STARTTLS') === FALSE) {
340 do_err('You have enabled TLS encryption in the config, but the server does not '.
341 'report STARTTLS capability. TLS is probably not supported.', FALSE);
344 /** OK, close connection */
345 fputs($stream, "A002 LOGOUT\r\n");
348 echo "Checking internationalization (i18n) settings...<br />\n";
349 echo "$IND gettext - ";
350 if (function_exists('gettext')) {
351 echo 'Gettext functions are available.'
352 .' On some systems you must have appropriate system locales compiled.'
355 echo 'Gettext functions are unavailable.'
356 .' SquirrelMail will use slower internal gettext functions.'
359 echo "$IND mbstring - ";
360 if (function_exists('mb_detect_encoding')) {
361 echo "Mbstring functions are available.<br />\n";
363 echo 'Mbstring functions are unavailable.'
364 ." Japanese translation won't work.<br />\n";
366 echo "$IND recode - ";
367 if (function_exists('recode')) {
368 echo "Recode functions are available.<br />\n";
369 } elseif (isset($use_php_recode) && $use_php_recode) {
370 echo "Recode functions are unavailable.<br />\n";
371 do_err('Your configuration requires recode support, but recode support is missing.');
373 echo "Recode functions are unavailable.<br />\n";
375 echo "$IND iconv - ";
376 if (function_exists('iconv')) {
377 echo "Iconv functions are available.<br />\n";
378 } elseif (isset($use_php_iconv) && $use_php_iconv) {
379 echo "Iconv functions are unavailable.<br />\n";
380 do_err('Your configuration requires iconv support, but iconv support is missing.');
382 echo "Iconv functions are unavailable.<br />\n";
384 // same test as in include/validate.php
385 echo "$IND timezone - ";
386 if ( (!ini_get('safe_mode')) ||
387 !strcmp(ini_get('safe_mode_allowed_env_vars'),'') ||
388 preg_match('/^([\w_]+,)*TZ/', ini_get('safe_mode_allowed_env_vars')) ) {
389 echo "Webmail users can change their time zone settings.<br />\n";
391 echo "Webmail users can't change their time zone settings.<br />\n";
396 echo "Checking database functions...<br />\n";
397 if($addrbook_dsn ||
$prefs_dsn ||
$addrbook_global_dsn) {
398 @include_once
('DB.php');
399 if (class_exists('DB')) {
400 echo "$IND PHP Pear DB support is present.<br />\n";
402 'dbase' => 'dbase_open',
403 'fbsql' => 'fbsql_connect',
404 'interbase' => 'ibase_connect',
405 'informix' => 'ifx_connect',
406 'msql' => 'msql_connect',
407 'mssql' => 'mssql_connect',
408 'mysql' => 'mysql_connect',
409 'mysqli' => 'mysqli_connect',
410 'oci8' => 'ocilogon',
411 'odbc' => 'odbc_connect',
412 'pgsql' => 'pg_connect',
413 'sqlite' => 'sqlite_open',
414 'sybase' => 'sybase_connect'
419 $dsns['preferences'] = $prefs_dsn;
422 $dsns['addressbook'] = $addrbook_dsn;
424 if($addrbook_global_dsn) {
425 $dsns['global addressbook'] = $addrbook_global_dsn;
428 foreach($dsns as $type => $dsn) {
429 $aDsn = explode(':', $dsn);
430 $dbtype = array_shift($aDsn);
431 if(isset($db_functions[$dbtype]) && function_exists($db_functions[$dbtype])) {
432 echo "$IND$dbtype database support present.<br />\n";
434 // now, test this interface:
436 $dbh = DB
::connect($dsn, true);
437 if (DB
::isError($dbh)) {
438 do_err('Database error: '. htmlspecialchars(DB
::errorMessage($dbh)) .
439 ' in ' .$type .' DSN.');
442 echo "$IND$type database connect successful.<br />\n";
445 do_err($dbtype.' database support not present!');
449 $db_error='Required PHP PEAR DB support is not available.'
450 .' Is PEAR installed and is the include path set correctly to find <tt>DB.php</tt>?'
451 .' The include path is now:<tt>' . ini_get('include_path') . '</tt>.';
455 echo $IND."not using database functionality.<br />\n";
459 echo "Checking LDAP functions...<br />\n";
460 if( empty($ldap_server) ) {
461 echo $IND."not using LDAP functionality.<br />\n";
463 if ( !function_exists('ldap_connect') ) {
464 do_err('Required LDAP support is not available.');
466 echo "$IND LDAP support present.<br />\n";
467 foreach ( $ldap_server as $param ) {
469 $linkid = @ldap_connect
($param['host'], (empty($param['port']) ?
389 : $param['port']) );
472 echo "$IND LDAP connect to ".$param['host']." successful: ".$linkid."<br />\n";
474 if ( !empty($param['protocol']) &&
475 !ldap_set_option($linkid, LDAP_OPT_PROTOCOL_VERSION
, $param['protocol']) ) {
476 do_err('Unable to set LDAP protocol');
479 if ( empty($param['binddn']) ) {
480 $bind = @ldap_bind
($linkid);
482 $bind = @ldap_bind
($param['binddn'], $param['bindpw']);
486 echo "$IND LDAP Bind Successful <br />";
488 do_err('Unable to Bind to LDAP Server');
491 @ldap_close
($linkid);
493 do_err('Connection to LDAP failed');
501 <p
>Congratulations
, your SquirrelMail setup looks fine to me
!</p
>
503 <p
><a href
="login.php">Login now
</a
></p
>