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 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.';
126 echo "Checking paths...<br />\n";
128 if(!file_exists($data_dir)) {
129 // data_dir is not that important in db_setups.
130 if (isset($prefs_dsn) && ! empty($prefs_dsn)) {
131 $data_dir_error = "Data dir ($data_dir) does not exist!\n";
132 echo $IND .'<font color="red"><b>ERROR:</b></font> ' . $data_dir_error;
134 do_err("Data dir ($data_dir) does not exist!");
137 // don't check if errors
138 if(!isset($data_dir_error) && !is_dir($data_dir)) {
139 if (isset($prefs_dsn) && ! empty($prefs_dsn)) {
140 $data_dir_error = "Data dir ($data_dir) is not a directory!\n";
141 echo $IND . '<font color="red"><b>ERROR:</b></font> ' . $data_dir_error;
143 do_err("Data dir ($data_dir) is not a directory!");
146 // datadir should be executable - but no clean way to test on that
147 if(!isset($data_dir_error) && !is_writable($data_dir)) {
148 if (isset($prefs_dsn) && ! empty($prefs_dsn)) {
149 $data_dir_error = "Data dir ($data_dir) is not writable!\n";
150 echo $IND . '<font color="red"><b>ERROR:</b></font> ' . $data_dir_error;
152 do_err("Data dir ($data_dir) is not writable!");
156 if (isset($data_dir_error)) {
157 echo " Some plugins might need access to data directory.<br />\n";
159 // todo_ornot: actually write something and read it back.
160 echo $IND . "Data dir OK.<br />\n";
163 if($data_dir == $attachment_dir) {
164 echo $IND . "Attachment dir is the same as data dir.<br />\n";
165 if (isset($data_dir_error)) {
166 do_err($data_dir_error);
169 if(!file_exists($attachment_dir)) {
170 do_err("Attachment dir ($attachment_dir) does not exist!");
172 if (!is_dir($attachment_dir)) {
173 do_err("Attachment dir ($attachment_dir) is not a directory!");
175 if (!is_writable($attachment_dir)) {
176 do_err("I cannot write to attachment dir ($attachment_dir)!");
178 echo $IND . "Attachment dir OK.<br />\n";
182 /* check plugins and themes */
183 if (isset($plugins[0])) {
184 foreach($plugins as $plugin) {
185 if(!file_exists(SM_PATH
.'plugins/'.$plugin)) {
186 do_err('You have enabled the <i>'.$plugin.'</i> plugin but I cannot find it.', FALSE);
187 } elseif (!is_readable(SM_PATH
.'plugins/'.$plugin.'/setup.php')) {
188 do_err('You have enabled the <i>'.$plugin.'</i> plugin but I cannot read its setup.php file.', FALSE);
191 echo $IND . "Plugins OK.<br />\n";
193 echo $IND . "Plugins are not enabled in config.<br />\n";
195 foreach($theme as $thm) {
196 if(!file_exists($thm['PATH'])) {
197 do_err('You have enabled the <i>'.$thm['NAME'].'</i> theme but I cannot find it ('.$thm['PATH'].').', FALSE);
198 } elseif(!is_readable($thm['PATH'])) {
199 do_err('You have enabled the <i>'.$thm['NAME'].'</i> theme but I cannot read it ('.$thm['PATH'].').', FALSE);
203 echo $IND . "Themes OK.<br />\n";
205 if ( $squirrelmail_default_language != 'en_US' ) {
206 $loc_path = SM_PATH
.'locale/'.$squirrelmail_default_language.'/LC_MESSAGES/squirrelmail.mo';
207 if( ! file_exists( $loc_path ) ) {
208 do_err('You have set <i>' . $squirrelmail_default_language .
209 '</i> as your default language, but I cannot find this translation (should be '.
210 'in <tt>' . $loc_path . '</tt>). Please note that you have to download translations '.
211 'separately from the main SquirrelMail package.', FALSE);
212 } elseif ( ! is_readable( $loc_path ) ) {
213 do_err('You have set <i>' . $squirrelmail_default_language .
214 '</i> as your default language, but I cannot read this translation (file '.
215 'in <tt>' . $loc_path . '</tt> unreadable).', FALSE);
217 echo $IND . "Default language OK.<br />\n";
220 echo $IND . "Default language OK.<br />\n";
223 echo $IND . "Base URL detected as: <tt>" . htmlspecialchars(get_location()) . "</tt><br />\n";
226 /* check outgoing mail */
228 if($use_smtp_tls ||
$use_imap_tls) {
229 if(!check_php_version(4,3,0)) {
230 do_err('You need at least PHP 4.3.0 for SMTP/IMAP TLS!');
232 if(!extension_loaded('openssl')) {
233 do_err('You need the openssl PHP extension to use SMTP/IMAP TLS!');
237 echo "Checking outgoing mail service....<br />\n";
240 // is_executable also checks for existance, but we want to be as precise as possible with the errors
241 if(!file_exists($sendmail_path)) {
242 do_err("Location of sendmail program incorrect ($sendmail_path)!");
244 if(!is_executable($sendmail_path)) {
245 do_err("I cannot execute the sendmail program ($sendmail_path)!");
248 echo $IND . "sendmail OK<br />\n";
250 $stream = fsockopen( ($use_smtp_tls?
'tls://':'').$smtpServerAddress, $smtpPort,
251 $errorNumber, $errorString);
253 do_err("Error connecting to SMTP server \"$smtpServerAddress:$smtpPort\".".
254 "Server error: ($errorNumber) ".htmlspecialchars($errorString));
257 // check for SMTP code; should be 2xx to allow us access
258 $smtpline = fgets($stream, 1024);
259 if(((int) $smtpline{0}) > 3) {
260 do_err("Error connecting to SMTP server. Server error: ".
261 htmlspecialchars($smtpline));
264 fputs($stream, 'QUIT');
266 echo $IND . 'SMTP server OK (<tt><small>'.
267 trim(htmlspecialchars($smtpline))."</small></tt>)<br />\n";
269 /* POP before SMTP */
270 if($pop_before_smtp) {
271 $stream = fsockopen($smtpServerAddress, 110, $err_no, $err_str);
273 do_err("Error connecting to POP Server ($smtpServerAddress:110) "
274 . $err_no . ' : ' . htmlspecialchars($err_str));
277 $tmp = fgets($stream, 1024);
278 if (substr($tmp, 0, 3) != '+OK') {
279 do_err("Error connecting to POP Server ($smtpServerAddress:110)"
280 . ' '.htmlspecialchars($tmp));
282 fputs($stream, 'QUIT');
284 echo $IND . "POP-before-SMTP OK.<br />\n";
289 * Check the IMAP server
291 echo "Checking IMAP service....<br />\n";
293 /** Can we open a connection? */
294 $stream = fsockopen( ($use_imap_tls?
'tls://':'').$imapServerAddress, $imapPort,
295 $errorNumber, $errorString);
297 do_err("Error connecting to IMAP server \"$imapServerAddress:$imapPort\".".
298 "Server error: ($errorNumber) ".
299 htmlspecialchars($errorString));
302 /** Is the first response 'OK'? */
303 $imapline = fgets($stream, 1024);
304 if(substr($imapline, 0,4) != '* OK') {
305 do_err('Error connecting to IMAP server. Server error: '.
306 htmlspecialchars($imapline));
309 echo $IND . 'IMAP server ready (<tt><small>'.
310 htmlspecialchars(trim($imapline))."</small></tt>)<br />\n";
312 /** Check capabilities */
313 fputs($stream, "A001 CAPABILITY\r\n");
314 $capline = fgets($stream, 1024);
316 echo $IND . 'Capabilities: <tt>'.htmlspecialchars($capline)."</tt><br />\n";
318 if($imap_auth_mech == 'login' && stristr($capline, 'LOGINDISABLED') !== FALSE) {
319 do_err('Your server doesn\'t allow plaintext logins. '.
320 'Try enabling another authentication mechanism like CRAM-MD5, DIGEST-MD5 or TLS-encryption '.
321 'in the SquirrelMail configuration.', FALSE);
323 /* don't test for STARTTLS in CAPABILITY */
325 /** OK, close connection */
326 fputs($stream, "A002 LOGOUT\r\n");
329 echo "Checking internationalization (i18n) settings...<br />\n";
330 echo "$IND gettext - ";
331 if (function_exists('gettext')) {
332 echo 'Gettext functions are available.'
333 .' On some systems you must have appropriate system locales compiled.'
336 echo 'Gettext functions are unavailable.'
337 .' SquirrelMail will use slower internal gettext functions.'
340 echo "$IND mbstring - ";
341 if (function_exists('mb_detect_encoding')) {
342 echo "Mbstring functions are available.<br />\n";
344 echo 'Mbstring functions are unavailable.'
345 ." Japanese translation won't work.<br />\n";
347 echo "$IND recode - ";
348 if (function_exists('recode')) {
349 echo "Recode functions are available.<br />\n";
350 } elseif (isset($use_php_recode) && $use_php_recode) {
351 echo "Recode functions are unavailable.<br />\n";
352 do_err('Your configuration requires recode support, but recode support is missing.');
354 echo "Recode functions are unavailable.<br />\n";
356 echo "$IND iconv - ";
357 if (function_exists('iconv')) {
358 echo "Iconv functions are available.<br />\n";
359 } elseif (isset($use_php_iconv) && $use_php_iconv) {
360 echo "Iconv functions are unavailable.<br />\n";
361 do_err('Your configuration requires iconv support, but iconv support is missing.');
363 echo "Iconv functions are unavailable.<br />\n";
365 // same test as in include/validate.php
366 echo "$IND timezone - ";
367 if ( (!ini_get('safe_mode')) ||
368 !strcmp(ini_get('safe_mode_allowed_env_vars'),'') ||
369 preg_match('/^([\w_]+,)*TZ/', ini_get('safe_mode_allowed_env_vars')) ) {
370 echo "Webmail users can change their time zone settings.<br />\n";
372 echo "Webmail users can't change their time zone settings.<br />\n";
377 echo "Checking database functions...<br />\n";
378 if($addrbook_dsn ||
$prefs_dsn ||
$addrbook_global_dsn) {
379 @include_once
('DB.php');
380 if (class_exists('DB')) {
381 echo "$IND PHP Pear DB support is present.<br />\n";
383 'dbase' => 'dbase_open',
384 'fbsql' => 'fbsql_connect',
385 'interbase' => 'ibase_connect',
386 'informix' => 'ifx_connect',
387 'msql' => 'msql_connect',
388 'mssql' => 'mssql_connect',
389 'mysql' => 'mysql_connect',
390 'mysqli' => 'mysqli_connect',
391 'oci8' => 'ocilogon',
392 'odbc' => 'odbc_connect',
393 'pgsql' => 'pg_connect',
394 'sqlite' => 'sqlite_open',
395 'sybase' => 'sybase_connect'
400 $dsns['preferences'] = $prefs_dsn;
403 $dsns['addressbook'] = $addrbook_dsn;
405 if($addrbook_global_dsn) {
406 $dsns['global addressbook'] = $addrbook_global_dsn;
409 foreach($dsns as $type => $dsn) {
410 $aDsn = explode(':', $dsn);
411 $dbtype = array_shift($aDsn);
412 if(isset($db_functions[$dbtype]) && function_exists($db_functions[$dbtype])) {
413 echo "$IND$dbtype database support present.<br />\n";
415 // now, test this interface:
417 $dbh = DB
::connect($dsn, true);
418 if (DB
::isError($dbh)) {
419 do_err('Database error: '. htmlspecialchars(DB
::errorMessage($dbh)) .
420 ' in ' .$type .' DSN.');
423 echo "$IND$type database connect successful.<br />\n";
426 do_err($dbtype.' database support not present!');
430 $db_error='Required PHP PEAR DB support is not available.'
431 .' Is PEAR installed and is the include path set correctly to find <tt>DB.php</tt>?'
432 .' The include path is now:<tt>' . ini_get('include_path') . '</tt>.';
436 echo $IND."not using database functionality.<br />\n";
440 echo "Checking LDAP functions...<br />\n";
441 if( empty($ldap_server) ) {
442 echo $IND."not using LDAP functionality.<br />\n";
444 if ( !function_exists('ldap_connect') ) {
445 do_err('Required LDAP support is not available.');
447 echo "$IND LDAP support present.<br />\n";
448 foreach ( $ldap_server as $param ) {
450 $linkid = @ldap_connect
($param['host'], (empty($param['port']) ?
389 : $param['port']) );
453 echo "$IND LDAP connect to ".$param['host']." successful: ".$linkid."<br />\n";
455 if ( !empty($param['protocol']) &&
456 !ldap_set_option($linkid, LDAP_OPT_PROTOCOL_VERSION
, $param['protocol']) ) {
457 do_err('Unable to set LDAP protocol');
460 if ( empty($param['binddn']) ) {
461 $bind = @ldap_bind
($linkid);
463 $bind = @ldap_bind
($param['binddn'], $param['bindpw']);
467 echo "$IND LDAP Bind Successful <br />";
469 do_err('Unable to Bind to LDAP Server');
472 @ldap_close
($linkid);
474 do_err('Connection to LDAP failed');
482 <p
>Congratulations
, your SquirrelMail setup looks fine to me
!</p
>
484 <p
><a href
="login.php">Login now
</a
></p
>