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.';
127 echo "Checking paths...<br />\n";
129 if(!file_exists($data_dir)) {
130 // data_dir is not that important in db_setups.
131 if (isset($prefs_dsn) && ! empty($prefs_dsn)) {
132 $data_dir_error = "Data dir ($data_dir) does not exist!\n";
133 echo $IND .'<font color="red"><b>ERROR:</b></font> ' . $data_dir_error;
135 do_err("Data dir ($data_dir) does not exist!");
138 // don't check if errors
139 if(!isset($data_dir_error) && !is_dir($data_dir)) {
140 if (isset($prefs_dsn) && ! empty($prefs_dsn)) {
141 $data_dir_error = "Data dir ($data_dir) is not a directory!\n";
142 echo $IND . '<font color="red"><b>ERROR:</b></font> ' . $data_dir_error;
144 do_err("Data dir ($data_dir) is not a directory!");
147 // datadir should be executable - but no clean way to test on that
148 if(!isset($data_dir_error) && !is_writable($data_dir)) {
149 if (isset($prefs_dsn) && ! empty($prefs_dsn)) {
150 $data_dir_error = "Data dir ($data_dir) is not writable!\n";
151 echo $IND . '<font color="red"><b>ERROR:</b></font> ' . $data_dir_error;
153 do_err("Data dir ($data_dir) is not writable!");
157 if (isset($data_dir_error)) {
158 echo " Some plugins might need access to data directory.<br />\n";
160 // todo_ornot: actually write something and read it back.
161 echo $IND . "Data dir OK.<br />\n";
164 if($data_dir == $attachment_dir) {
165 echo $IND . "Attachment dir is the same as data dir.<br />\n";
166 if (isset($data_dir_error)) {
167 do_err($data_dir_error);
170 if(!file_exists($attachment_dir)) {
171 do_err("Attachment dir ($attachment_dir) does not exist!");
173 if (!is_dir($attachment_dir)) {
174 do_err("Attachment dir ($attachment_dir) is not a directory!");
176 if (!is_writable($attachment_dir)) {
177 do_err("I cannot write to attachment dir ($attachment_dir)!");
179 echo $IND . "Attachment dir OK.<br />\n";
183 /* check plugins and themes */
184 if (isset($plugins[0])) {
185 foreach($plugins as $plugin) {
186 if(!file_exists(SM_PATH
.'plugins/'.$plugin)) {
187 do_err('You have enabled the <i>'.$plugin.'</i> plugin but I cannot find it.', FALSE);
188 } elseif (!is_readable(SM_PATH
.'plugins/'.$plugin.'/setup.php')) {
189 do_err('You have enabled the <i>'.$plugin.'</i> plugin but I cannot read its setup.php file.', FALSE);
192 echo $IND . "Plugins OK.<br />\n";
194 echo $IND . "Plugins are not enabled in config.<br />\n";
196 foreach($theme as $thm) {
197 if(!file_exists($thm['PATH'])) {
198 do_err('You have enabled the <i>'.$thm['NAME'].'</i> theme but I cannot find it ('.$thm['PATH'].').', FALSE);
199 } elseif(!is_readable($thm['PATH'])) {
200 do_err('You have enabled the <i>'.$thm['NAME'].'</i> theme but I cannot read it ('.$thm['PATH'].').', FALSE);
204 echo $IND . "Themes OK.<br />\n";
206 if ( $squirrelmail_default_language != 'en_US' ) {
207 $loc_path = SM_PATH
.'locale/'.$squirrelmail_default_language.'/LC_MESSAGES/squirrelmail.mo';
208 if( ! file_exists( $loc_path ) ) {
209 do_err('You have set <i>' . $squirrelmail_default_language .
210 '</i> as your default language, but I cannot find this translation (should be '.
211 'in <tt>' . $loc_path . '</tt>). Please note that you have to download translations '.
212 'separately from the main SquirrelMail package.', FALSE);
213 } elseif ( ! is_readable( $loc_path ) ) {
214 do_err('You have set <i>' . $squirrelmail_default_language .
215 '</i> as your default language, but I cannot read this translation (file '.
216 'in <tt>' . $loc_path . '</tt> unreadable).', FALSE);
218 echo $IND . "Default language OK.<br />\n";
221 echo $IND . "Default language OK.<br />\n";
224 echo $IND . "Base URL detected as: <tt>" . htmlspecialchars(get_location()) . "</tt><br />\n";
227 /* check outgoing mail */
229 if($use_smtp_tls ||
$use_imap_tls) {
230 if(!check_php_version(4,3,0)) {
231 do_err('You need at least PHP 4.3.0 for SMTP/IMAP TLS!');
233 if(!extension_loaded('openssl')) {
234 do_err('You need the openssl PHP extension to use SMTP/IMAP TLS!');
238 echo "Checking outgoing mail service....<br />\n";
241 // is_executable also checks for existance, but we want to be as precise as possible with the errors
242 if(!file_exists($sendmail_path)) {
243 do_err("Location of sendmail program incorrect ($sendmail_path)!");
245 if(!is_executable($sendmail_path)) {
246 do_err("I cannot execute the sendmail program ($sendmail_path)!");
249 echo $IND . "sendmail OK<br />\n";
251 $stream = fsockopen( ($use_smtp_tls?
'tls://':'').$smtpServerAddress, $smtpPort,
252 $errorNumber, $errorString);
254 do_err("Error connecting to SMTP server \"$smtpServerAddress:$smtpPort\".".
255 "Server error: ($errorNumber) ".htmlspecialchars($errorString));
258 // check for SMTP code; should be 2xx to allow us access
259 $smtpline = fgets($stream, 1024);
260 if(((int) $smtpline{0}) > 3) {
261 do_err("Error connecting to SMTP server. Server error: ".
262 htmlspecialchars($smtpline));
265 fputs($stream, 'QUIT');
267 echo $IND . 'SMTP server OK (<tt><small>'.
268 trim(htmlspecialchars($smtpline))."</small></tt>)<br />\n";
270 /* POP before SMTP */
271 if($pop_before_smtp) {
272 $stream = fsockopen($smtpServerAddress, 110, $err_no, $err_str);
274 do_err("Error connecting to POP Server ($smtpServerAddress:110) "
275 . $err_no . ' : ' . htmlspecialchars($err_str));
278 $tmp = fgets($stream, 1024);
279 if (substr($tmp, 0, 3) != '+OK') {
280 do_err("Error connecting to POP Server ($smtpServerAddress:110)"
281 . ' '.htmlspecialchars($tmp));
283 fputs($stream, 'QUIT');
285 echo $IND . "POP-before-SMTP OK.<br />\n";
290 * Check the IMAP server
292 echo "Checking IMAP service....<br />\n";
294 /** Can we open a connection? */
295 $stream = fsockopen( ($use_imap_tls?
'tls://':'').$imapServerAddress, $imapPort,
296 $errorNumber, $errorString);
298 do_err("Error connecting to IMAP server \"$imapServerAddress:$imapPort\".".
299 "Server error: ($errorNumber) ".
300 htmlspecialchars($errorString));
303 /** Is the first response 'OK'? */
304 $imapline = fgets($stream, 1024);
305 if(substr($imapline, 0,4) != '* OK') {
306 do_err('Error connecting to IMAP server. Server error: '.
307 htmlspecialchars($imapline));
310 echo $IND . 'IMAP server ready (<tt><small>'.
311 htmlspecialchars(trim($imapline))."</small></tt>)<br />\n";
313 /** Check capabilities */
314 fputs($stream, "A001 CAPABILITY\r\n");
315 $capline = fgets($stream, 1024);
317 echo $IND . 'Capabilities: <tt>'.htmlspecialchars($capline)."</tt><br />\n";
319 if($imap_auth_mech == 'login' && stristr($capline, 'LOGINDISABLED') !== FALSE) {
320 do_err('Your server doesn\'t allow plaintext logins. '.
321 'Try enabling another authentication mechanism like CRAM-MD5, DIGEST-MD5 or TLS-encryption '.
322 'in the SquirrelMail configuration.', FALSE);
324 if($use_imap_tls && stristr($capline, 'STARTTLS') === FALSE) {
325 do_err('You have enabled TLS encryption in the config, but the server does not '.
326 'report STARTTLS capability. TLS is probably not supported.', FALSE);
329 /** OK, close connection */
330 fputs($stream, "A002 LOGOUT\r\n");
333 echo "Checking internationalization (i18n) settings...<br />\n";
334 echo "$IND gettext - ";
335 if (function_exists('gettext')) {
336 echo 'Gettext functions are available.'
337 .' On some systems you must have appropriate system locales compiled.'
340 echo 'Gettext functions are unavailable.'
341 .' SquirrelMail will use slower internal gettext functions.'
344 echo "$IND mbstring - ";
345 if (function_exists('mb_detect_encoding')) {
346 echo "Mbstring functions are available.<br />\n";
348 echo 'Mbstring functions are unavailable.'
349 ." Japanese translation won't work.<br />\n";
351 echo "$IND recode - ";
352 if (function_exists('recode')) {
353 echo "Recode functions are available.<br />\n";
354 } elseif (isset($use_php_recode) && $use_php_recode) {
355 echo "Recode functions are unavailable.<br />\n";
356 do_err('Your configuration requires recode support, but recode support is missing.');
358 echo "Recode functions are unavailable.<br />\n";
360 echo "$IND iconv - ";
361 if (function_exists('iconv')) {
362 echo "Iconv functions are available.<br />\n";
363 } elseif (isset($use_php_iconv) && $use_php_iconv) {
364 echo "Iconv functions are unavailable.<br />\n";
365 do_err('Your configuration requires iconv support, but iconv support is missing.');
367 echo "Iconv functions are unavailable.<br />\n";
369 // same test as in include/validate.php
370 echo "$IND timezone - ";
371 if ( (!ini_get('safe_mode')) ||
372 !strcmp(ini_get('safe_mode_allowed_env_vars'),'') ||
373 preg_match('/^([\w_]+,)*TZ/', ini_get('safe_mode_allowed_env_vars')) ) {
374 echo "Webmail users can change their time zone settings.<br />\n";
376 echo "Webmail users can't change their time zone settings.<br />\n";
381 echo "Checking database functions...<br />\n";
382 if($addrbook_dsn ||
$prefs_dsn ||
$addrbook_global_dsn) {
383 @include_once
('DB.php');
384 if (class_exists('DB')) {
385 echo "$IND PHP Pear DB support is present.<br />\n";
387 'dbase' => 'dbase_open',
388 'fbsql' => 'fbsql_connect',
389 'interbase' => 'ibase_connect',
390 'informix' => 'ifx_connect',
391 'msql' => 'msql_connect',
392 'mssql' => 'mssql_connect',
393 'mysql' => 'mysql_connect',
394 'mysqli' => 'mysqli_connect',
395 'oci8' => 'ocilogon',
396 'odbc' => 'odbc_connect',
397 'pgsql' => 'pg_connect',
398 'sqlite' => 'sqlite_open',
399 'sybase' => 'sybase_connect'
404 $dsns['preferences'] = $prefs_dsn;
407 $dsns['addressbook'] = $addrbook_dsn;
409 if($addrbook_global_dsn) {
410 $dsns['global addressbook'] = $addrbook_global_dsn;
413 foreach($dsns as $type => $dsn) {
414 $aDsn = explode(':', $dsn);
415 $dbtype = array_shift($aDsn);
416 if(isset($db_functions[$dbtype]) && function_exists($db_functions[$dbtype])) {
417 echo "$IND$dbtype database support present.<br />\n";
419 // now, test this interface:
421 $dbh = DB
::connect($dsn, true);
422 if (DB
::isError($dbh)) {
423 do_err('Database error: '. htmlspecialchars(DB
::errorMessage($dbh)) .
424 ' in ' .$type .' DSN.');
427 echo "$IND$type database connect successful.<br />\n";
430 do_err($dbtype.' database support not present!');
434 $db_error='Required PHP PEAR DB support is not available.'
435 .' Is PEAR installed and is the include path set correctly to find <tt>DB.php</tt>?'
436 .' The include path is now:<tt>' . ini_get('include_path') . '</tt>.';
440 echo $IND."not using database functionality.<br />\n";
444 echo "Checking LDAP functions...<br />\n";
445 if( empty($ldap_server) ) {
446 echo $IND."not using LDAP functionality.<br />\n";
448 if ( !function_exists('ldap_connect') ) {
449 do_err('Required LDAP support is not available.');
451 echo "$IND LDAP support present.<br />\n";
452 foreach ( $ldap_server as $param ) {
454 $linkid = @ldap_connect
($param['host'], (empty($param['port']) ?
389 : $param['port']) );
457 echo "$IND LDAP connect to ".$param['host']." successful: ".$linkid."<br />\n";
459 if ( !empty($param['protocol']) &&
460 !ldap_set_option($linkid, LDAP_OPT_PROTOCOL_VERSION
, $param['protocol']) ) {
461 do_err('Unable to set LDAP protocol');
464 if ( empty($param['binddn']) ) {
465 $bind = @ldap_bind
($linkid);
467 $bind = @ldap_bind
($param['binddn'], $param['bindpw']);
471 echo "$IND LDAP Bind Successful <br />";
473 do_err('Unable to Bind to LDAP Server');
476 @ldap_close
($linkid);
478 do_err('Connection to LDAP failed');
486 <p
>Congratulations
, your SquirrelMail setup looks fine to me
!</p
>
488 <p
><a href
="login.php">Login now
</a
></p
>