Fix issue with multi-part related messages not showing all attachments (#2830140).
[squirrelmail.git] / src / configtest.php
CommitLineData
d1ae9d4c 1<?php
134e4174 2
30967a1e 3/**
d1ae9d4c 4 * SquirrelMail configtest script
5 *
30460a05 6 * @copyright 2003-2009 The SquirrelMail Project Team
4b4abf93 7 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
30967a1e 8 * @version $Id$
9 * @package squirrelmail
10 * @subpackage config
d1ae9d4c 11 */
12
13/************************************************************
14 * NOTE: you do not need to change this script! *
15 * If it throws errors you need to adjust your config. *
16 ************************************************************/
17
ebd2391c 18/** This is the configtest page */
19define('PAGE_NAME', 'configtest');
20
df758744 21// This script could really use some restructuring as it has grown quite rapidly
22// but is not very 'clean'. Feel free to get some structure into this thing.
23
8a6b8e1f 24// force verbose error reporting and turn on display of errors, but not before
25// getting their original values
26$php_display_errors_original_value = ini_get('display_errors');
27$php_error_reporting_original_value = ini_get('error_reporting');
dda39a1a 28error_reporting(E_ALL);
29ini_set('display_errors',1);
30
31/** Blockcopy from init.php. Cleans globals. */
32if ((bool) ini_get('register_globals') &&
33 strtolower(ini_get('register_globals'))!='off') {
34 /**
35 * Remove all globals that are not reserved by PHP
36 * 'value' and 'key' are used by foreach. Don't unset them inside foreach.
37 */
38 foreach ($GLOBALS as $key => $value) {
39 switch($key) {
40 case 'HTTP_POST_VARS':
41 case '_POST':
42 case 'HTTP_GET_VARS':
43 case '_GET':
44 case 'HTTP_COOKIE_VARS':
45 case '_COOKIE':
46 case 'HTTP_SERVER_VARS':
47 case '_SERVER':
48 case 'HTTP_ENV_VARS':
49 case '_ENV':
50 case 'HTTP_POST_FILES':
51 case '_FILES':
52 case '_REQUEST':
53 case 'HTTP_SESSION_VARS':
54 case '_SESSION':
55 case 'GLOBALS':
56 case 'key':
57 case 'value':
58 break;
59 default:
60 unset($GLOBALS[$key]);
61 }
62 }
63 // Unset variables used in foreach
64 unset($GLOBALS['key']);
65 unset($GLOBALS['value']);
66}
67
68
69/**
70 * Displays error messages and warnings
71 * @param string $str message
72 * @param boolean $fatal fatal error or only warning
73 */
3a196538 74function do_err($str, $fatal = TRUE) {
f084f987 75 global $IND, $warnings;
76 $level = $fatal ? 'FATAL ERROR:' : 'WARNING:';
3a196538 77 echo '<p>'.$IND.'<font color="red"><b>' . $level . '</b></font> ' .$str. "</p>\n";
78 if($fatal) {
f084f987 79 echo '</body></html>';
80 exit;
3a196538 81 } else {
f084f987 82 $warnings++;
83 }
5b53b7e0 84}
85
5b53b7e0 86ob_implicit_flush();
30967a1e 87/** @ignore */
5b53b7e0 88define('SM_PATH', '../');
dda39a1a 89/** load minimal function set */
b37e457f 90require(SM_PATH . 'include/constants.php');
dda39a1a 91require(SM_PATH . 'functions/global.php');
92require(SM_PATH . 'functions/strings.php');
b578bd7c 93require(SM_PATH . 'functions/files.php');
a895042a 94$SQM_INTERNAL_VERSION = explode('.', SM_VERSION, 3);
b37e457f 95$SQM_INTERNAL_VERSION[2] = intval($SQM_INTERNAL_VERSION[2]);
5b53b7e0 96
dda39a1a 97/** set default value in order to block remote access */
d0184454 98$allow_remote_configtest=false;
99
dda39a1a 100/** Load all configuration files before output begins */
101
102/* load default configuration */
103require(SM_PATH . 'config/config_default.php');
104/* reset arrays in default configuration */
105$ldap_server = array();
106$plugins = array();
107$fontsets = array();
108$theme = array();
109$theme[0]['PATH'] = SM_PATH . 'themes/default_theme.php';
110$theme[0]['NAME'] = 'Default';
111$aTemplateSet = array();
112$aTemplateSet[0]['ID'] = 'default';
113$aTemplateSet[0]['NAME'] = 'Default';
114/* load site configuration */
5b53b7e0 115if (file_exists(SM_PATH . 'config/config.php')) {
dda39a1a 116 require(SM_PATH . 'config/config.php');
5b53b7e0 117}
dda39a1a 118/* load local configuration overrides */
119if (file_exists(SM_PATH . 'config/config_local.php')) {
120 require(SM_PATH . 'config/config_local.php');
121}
122
1dc63862 123/**
124 * Include Compatibility plugin if available.
125 */
126if (!$disable_plugins && file_exists(SM_PATH . 'plugins/compatibility/functions.php'))
127 include_once(SM_PATH . 'plugins/compatibility/functions.php');
128
8459a9bb 129/** Load plugins */
130global $disable_plugins;
131$squirrelmail_plugin_hooks = array();
132if (!$disable_plugins && file_exists(SM_PATH . 'config/plugin_hooks.php')) {
133 require(SM_PATH . 'config/plugin_hooks.php');
134}
135
dda39a1a 136/** Warning counter */
137$warnings = 0;
138
139/** indent */
140$IND = str_repeat('&nbsp;',4);
c772f125 141
69792446 142/**
143 * get_location starts session and must be run before output is started.
144 */
145$test_location = get_location();
146
151562a7 147?><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
148 "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">
d1ae9d4c 149<html>
150<head>
f084f987 151 <meta name="robots" content="noindex,nofollow">
152 <title>SquirrelMail configtest</title>
d1ae9d4c 153</head>
154<body>
155<h1>SquirrelMail configtest</h1>
156
157<p>This script will try to check some aspects of your SquirrelMail configuration
158and point you to errors whereever it can find them. You need to go run <tt>conf.pl</tt>
d18703d3 159in the <tt>config/</tt> directory first before you run this script.</p>
d1ae9d4c 160
161<?php
162
d1ae9d4c 163$included = array_map('basename', get_included_files() );
164if(!in_array('config.php', $included)) {
165 if(!file_exists(SM_PATH . 'config/config.php')) {
166 do_err('Config file '.SM_PATH . 'config/config.php does not exist!<br />'.
f084f987 167 'You need to run <tt>conf.pl</tt> first.');
d1ae9d4c 168 }
169 do_err('Could not read '.SM_PATH.'config/config.php! Check file permissions.');
170}
171if(!in_array('strings.php', $included)) {
172 do_err('Could not include '.SM_PATH.'functions/strings.php!<br />'.
f084f987 173 'Check permissions on that file.');
d1ae9d4c 174}
175
d0184454 176/* Block remote use of script */
177if (! $allow_remote_configtest) {
178 sqGetGlobalVar('REMOTE_ADDR',$client_ip,SQ_SERVER);
a15f9d93 179 sqGetGlobalVar('SERVER_ADDR',$server_ip,SQ_SERVER);
180
181 if ((! isset($client_ip) || $client_ip!='127.0.0.1') &&
f084f987 182 (! isset($client_ip) || ! isset($server_ip) || $client_ip!=$server_ip)) {
f8a1ed5a 183 do_err('Enable "Allow remote configtest" option in squirrelmail configuration in order to use this script.');
d0184454 184 }
185}
d1ae9d4c 186
b37e457f 187echo "<p><table>\n<tr><td>SquirrelMail version:</td><td><b>" . SM_VERSION . "</b></td></tr>\n" .
f084f987 188 '<tr><td>Config file version:</td><td><b>' . $config_version . "</b></td></tr>\n" .
189 '<tr><td>Config file last modified:</td><td><b>' .
190 date ('d F Y H:i:s', filemtime(SM_PATH . 'config/config.php')) .
191 "</b></td></tr>\n</table>\n</p>\n\n";
d1ae9d4c 192
c3da9f50 193/* check $config_version */
65efa982 194if ($config_version!='1.5.0') {
c3da9f50 195 do_err('Configuration file version does not match required version. Please update your configuration file.');
196}
a15f9d93 197
a1912bbc 198
199/* checking PHP specs */
200
d1ae9d4c 201echo "Checking PHP configuration...<br />\n";
202
abd74f7d 203if(!check_php_version(4,1,0)) {
204 do_err('Insufficient PHP version: '. PHP_VERSION . '! Minimum required: 4.1.0');
d1ae9d4c 205}
206
3a196538 207echo $IND . 'PHP version ' . PHP_VERSION . ' OK. (You have: ' . phpversion() . ". Minimum: 4.1.0)<br />\n";
a1912bbc 208
8a6b8e1f 209echo $IND . 'display_errors: ' . $php_display_errors_original_value . " (overridden with 1 for this page only)<br />\n";
0cc820f9 210
8a6b8e1f 211echo $IND . 'error_reporting: ' . $php_error_reporting_original_value . " (overridden with 2047 for this page only)<br />\n";
0cc820f9 212
ccbde363 213$safe_mode = ini_get('safe_mode');
214if ($safe_mode) {
215 echo $IND . 'safe_mode: ' . $safe_mode;
216 if (empty($prefs_dsn) || empty($addrbook_dsn))
217 echo ' (<font color="red">double check data and attachment directory ownership, etc!</font>)';
dc528046 218 if (!empty($addrbook_dsn) || !empty($prefs_dsn) || !empty($addrbook_global_dsn))
ccbde363 219 echo ' (<font color="red">does PHP have access to database interface?</font>)';
220 echo "<br />\n";
221 $safe_mode_exec_dir = ini_get('safe_mode_exec_dir');
222 echo $IND . 'safe_mode_exec_dir: ' . $safe_mode_exec_dir . "<br />\n";
223}
224
a1912bbc 225/* register_globals check: test for boolean false and any string that is not equal to 'off' */
226
dc528046 227if ((bool) ini_get('register_globals') &&
a3b99374 228 strtolower(ini_get('register_globals'))!='off') {
b00dce9b 229 do_err('You have register_globals turned on. This is not an error, but it CAN be a security hazard. Consider turning register_globals off.', false);
c772f125 230}
a1912bbc 231
232
233/* variables_order check */
234
b00dce9b 235// FIXME(?): Hmm, how do we distinguish between when an ini setting is not available (ini_set() returns empty string) and when the administrator set the value to an empty string? The latter is sure to be highly rare, so for now, just assume that empty value means the setting isn't even available (could also check PHP version when this setting was implemented) although, we'll also warn the user if it is empty, with a non-fatal error
47fa8e9b 236$variables_order = strtoupper(ini_get('variables_order'));
237if (empty($variables_order))
b00dce9b 238 do_err('Your variables_order setting seems to be empty. Make sure it is undefined in any PHP ini files, .htaccess files, etc. and not specifically set to an empty value or SquirrelMail may not function correctly', false);
47fa8e9b 239else if (strpos($variables_order, 'G') === FALSE
a1912bbc 240 || strpos($variables_order, 'P') === FALSE
241 || strpos($variables_order, 'C') === FALSE
47fa8e9b 242 || strpos($variables_order, 'S') === FALSE) {
b00dce9b 243 do_err('Your variables_order setting is insufficient for SquirrelMail to function. It needs at least "GPCS", but you have it set to "' . htmlspecialchars($variables_order) . '"', true);
a1912bbc 244} else {
245 echo $IND . "variables_order OK: $variables_order.<br />\n";
246}
247
248
47fa8e9b 249/* gpc_order check (removed from PHP as of v5.0) */
250
251if (!check_php_version(5)) {
b00dce9b 252 // FIXME(?): Hmm, how do we distinguish between when an ini setting is not available (ini_set() returns empty string) and when the administrator set the value to an empty string? The latter is sure to be highly rare, so for now, just assume that empty value means the setting isn't even available (could also check PHP version when this setting was implemented) although, we'll also warn the user if it is empty, with a non-fatal error
47fa8e9b 253 $gpc_order = strtoupper(ini_get('gpc_order'));
254 if (empty($gpc_order))
b00dce9b 255 do_err('Your gpc_order setting seems to be empty. Make sure it is undefined in any PHP ini files, .htaccess files, etc. and not specifically set to an empty value or SquirrelMail may not function correctly', false);
47fa8e9b 256 else if (strpos($gpc_order, 'G') === FALSE
257 || strpos($gpc_order, 'P') === FALSE
258 || strpos($gpc_order, 'C') === FALSE) {
b00dce9b 259 do_err('Your gpc_order setting is insufficient for SquirrelMail to function. It needs to be set to "GPC", but you have it set to "' . htmlspecialchars($gpc_order) . '"', true);
47fa8e9b 260 } else {
261 echo $IND . "gpc_order OK: $gpc_order.<br />\n";
262 }
a1912bbc 263}
264
265
266/* check PHP extensions */
267
d1ae9d4c 268$php_exts = array('session','pcre');
269$diff = array_diff($php_exts, get_loaded_extensions());
270if(count($diff)) {
271 do_err('Required PHP extensions missing: '.implode(', ',$diff) );
272}
273
d053c206 274echo $IND . "PHP extensions OK. Dynamic loading is ";
275
276if (!(bool)ini_get('enable_dl') || (bool)ini_get('safe_mode')) {
277 echo "disabled.<br />\n";
278} else {
279 echo "enabled.<br />\n";
280}
281
d1ae9d4c 282
8f186a2a 283/* dangerous php settings */
284/**
285 * mbstring.func_overload allows to replace original string and regexp functions
286 * with their equivalents from php mbstring extension. It causes problems when
d0184454 287 * scripts analyze 8bit strings byte after byte or use 8bit strings in regexp tests.
9211bcef 288 * Setting can be controlled in php.ini (php 4.2.0), webserver config (php 4.2.0)
8f186a2a 289 * and .htaccess files (php 4.3.5).
290 */
291if (function_exists('mb_internal_encoding') &&
9211bcef 292 check_php_version(4,2,0) &&
8f186a2a 293 (int)ini_get('mbstring.func_overload')!=0) {
294 $mb_error='You have enabled mbstring overloading.'
295 .' It can cause problems with SquirrelMail scripts that rely on single byte string functions.';
296 do_err($mb_error);
297}
d1ae9d4c 298
99c1c0d6 299/**
300 * Do not use SquirrelMail with magic_quotes_* on.
301 */
430a19f3 302if ( (function_exists('get_magic_quotes_runtime') && @get_magic_quotes_runtime()) ||
303 (function_exists('get_magic_quotes_gpc') && @get_magic_quotes_gpc()) ||
99c1c0d6 304 ( (bool) ini_get('magic_quotes_sybase') && ini_get('magic_quotes_sybase') != 'off' )
305 ) {
306 $magic_quotes_warning='You have enabled any one of <tt>magic_quotes_runtime</tt>, '
307 .'<tt>magic_quotes_gpc</tt> or <tt>magic_quotes_sybase</tt> in your PHP '
308 .'configuration. We recommend all those settings to be off. SquirrelMail '
309 .'may work with them on, but when experiencing stray backslashes in your mail '
310 .'or other strange behaviour, it may be advisable to turn them off.';
311 do_err($magic_quotes_warning,false);
312}
313
dc528046 314if (ini_get('short_open_tag') == 0) {
315 $short_open_tag_warning = 'You have configured PHP not to allow short tags '
316 . '(<tt>short_open_tag=off</tt>). This shouldn\'t be a problem with '
317 . 'SquirrelMail or any plugin coded coded according to the '
318 . 'SquirrelMail Coding Guidelines, but if you experience problems with '
319 . 'PHP code being displayed in some of the pages and changing setting '
320 . 'to "on" solves the problem, please file a bug report against the '
321 . 'failing plugin. The correct contact information is most likely '
322 . 'to be found in the plugin documentation.';
323 do_err($short_open_tag_warning, false);
324}
99c1c0d6 325
e45a534b 326
327/* check who the web server is running as if possible */
328
329if ($process_info = get_process_owner_info()) {
330 echo $IND . 'Web server is running as user: ' . $process_info['name'] . ' (' . $process_info['uid'] . ")<br />\n";
331 //echo $IND . 'Web server is running as effective user: ' . $process_info['ename'] . ' (' . $process_info['euid'] . ")<br />\n";
332 echo $IND . 'Web server is running as group: ' . $process_info['group'] . ' (' . $process_info['gid'] . ")<br />\n";
333 //echo $IND . 'Web server is running as effective group: ' . $process_info['egroup'] . ' (' . $process_info['egid'] . ")<br />\n";
334}
335
336
d1ae9d4c 337/* checking paths */
338
339echo "Checking paths...<br />\n";
340
341if(!file_exists($data_dir)) {
d0184454 342 // data_dir is not that important in db_setups.
ccbde363 343 if (!empty($prefs_dsn)) {
d0184454 344 $data_dir_error = "Data dir ($data_dir) does not exist!\n";
345 echo $IND .'<font color="red"><b>ERROR:</b></font> ' . $data_dir_error;
346 } else {
347 do_err("Data dir ($data_dir) does not exist!");
348 }
91e0dccc 349}
d0184454 350// don't check if errors
351if(!isset($data_dir_error) && !is_dir($data_dir)) {
ccbde363 352 if (!empty($prefs_dsn)) {
d0184454 353 $data_dir_error = "Data dir ($data_dir) is not a directory!\n";
354 echo $IND . '<font color="red"><b>ERROR:</b></font> ' . $data_dir_error;
355 } else {
356 do_err("Data dir ($data_dir) is not a directory!");
357 }
91e0dccc 358}
d4eaadbe 359// datadir should be executable - but no clean way to test on that
0a496c76 360if(!isset($data_dir_error) && !sq_is_writable($data_dir)) {
ccbde363 361 if (!empty($prefs_dsn)) {
d0184454 362 $data_dir_error = "Data dir ($data_dir) is not writable!\n";
363 echo $IND . '<font color="red"><b>ERROR:</b></font> ' . $data_dir_error;
364 } else {
365 do_err("Data dir ($data_dir) is not writable!");
366 }
d1ae9d4c 367}
368
d0184454 369if (isset($data_dir_error)) {
370 echo " Some plugins might need access to data directory.<br />\n";
371} else {
372 // todo_ornot: actually write something and read it back.
373 echo $IND . "Data dir OK.<br />\n";
374}
d1ae9d4c 375
376if($data_dir == $attachment_dir) {
377 echo $IND . "Attachment dir is the same as data dir.<br />\n";
d0184454 378 if (isset($data_dir_error)) {
379 do_err($data_dir_error);
380 }
d1ae9d4c 381} else {
382 if(!file_exists($attachment_dir)) {
383 do_err("Attachment dir ($attachment_dir) does not exist!");
91e0dccc 384 }
d1ae9d4c 385 if (!is_dir($attachment_dir)) {
386 do_err("Attachment dir ($attachment_dir) is not a directory!");
91e0dccc 387 }
0a496c76 388 if (!sq_is_writable($attachment_dir)) {
d1ae9d4c 389 do_err("I cannot write to attachment dir ($attachment_dir)!");
390 }
391 echo $IND . "Attachment dir OK.<br />\n";
392}
393
394
646b17e0 395echo "Checking plugins...<br />\n";
396
d1ae9d4c 397/* check plugins and themes */
d17b7894 398//FIXME: check requirements given in plugin _info() function, such as required PHP extensions, Pear packages, other plugins, SM version, etc see development docs for list of returned info from that function
399//FIXME: update this list with most recent contents of the Obsolete category - I think it has changed recently
f084f987 400$bad_plugins = array(
0880efc9 401 'attachment_common', // Integrated into SquirrelMail 1.2 core
eb7bd9b7 402 'auto_prune_sent', // Obsolete: See Proon Automatic Folder Pruning plugin
0880efc9 403 'compose_new_window', // Integrated into SquirrelMail 1.4 core
404 'delete_move_next', // Integrated into SquirrelMail 1.5 core
eb7bd9b7 405 'disk_quota', // Obsolete: See Check Quota plugin
0880efc9 406 'email_priority', // Integrated into SquirrelMail 1.2 core
eb7bd9b7 407 'emoticons', // Obsolete: See HTML Mail plugin
0880efc9 408 'focus_change', // Integrated into SquirrelMail 1.2 core
409 'folder_settings', // Integrated into SquirrelMail 1.5.1 core
410 'global_sql_addressbook', // Integrated into SquirrelMail 1.4 core
eb7bd9b7 411 'hancock', // Not Working: See Random Signature Taglines plugin
0880efc9 412 'msg_flags', // Integrated into SquirrelMail 1.5.1 core
413 'message_source', // Added to SquirrelMail 1.4 Core Plugins (message_details)
414 'motd', // Integrated into SquirrelMail 1.2 core
415 'paginator', // Integrated into SquirrelMail 1.2 core
416 'printer_friendly', // Integrated into SquirrelMail 1.2 core
eb7bd9b7 417 'procfilter', // Obsolete: See Server Side Filter plugin
0880efc9 418 'redhat_php_cgi_fix', // Integrated into SquirrelMail 1.1.1 core
419 'send_to_semicolon', // Integrated into SquirrelMail 1.4.1 core
420 'spamassassin', // Not working beyond SquirrelMail 1.2.7: See Spamassassin SpamFilter (Frontend) v2 plugin
421 'sqcalendar', // Added to SquirrelMail 1.2 Core Plugins (calendar)
422 'sqclock', // Integrated into SquirrelMail 1.2 core
eb7bd9b7 423 'sql_squirrel_logger', // Obsolete: See Squirrel Logger plugin
424 'tmda', // Obsolete: See TMDA Tools plugin
425 'vacation', // Obsolete: See Vacation Local plugin
0880efc9 426 'view_as_html', // Integrated into SquirrelMail 1.5.1 core
427 'xmailer' // Integrated into SquirrelMail 1.2 core
f084f987 428 );
3a196538 429
5b53b7e0 430if (isset($plugins[0])) {
431 foreach($plugins as $plugin) {
432 if(!file_exists(SM_PATH .'plugins/'.$plugin)) {
f084f987 433 do_err('You have enabled the <i>'.$plugin.'</i> plugin, but I cannot find it.', FALSE);
5b53b7e0 434 } elseif (!is_readable(SM_PATH .'plugins/'.$plugin.'/setup.php')) {
1dc63862 435 do_err('You have enabled the <i>'.$plugin.'</i> plugin, but I cannot locate or read its setup.php file.', FALSE);
f084f987 436 } elseif (in_array($plugin, $bad_plugins)) {
437 do_err('You have enabled the <i>'.$plugin.'</i> plugin, which causes problems with this version of SquirrelMail. Please check the ReleaseNotes or other documentation for more information.', false);
438 }
d1ae9d4c 439 }
1dc63862 440
441
69792446 442 // load plugin functions
443 include_once(SM_PATH . 'functions/plugin.php');
1dc63862 444
69792446 445 // turn on output buffering in order to prevent output of new lines
446 ob_start();
447 foreach ($plugins as $name) {
448 use_plugin($name);
1dc63862 449
450 // get output and remove whitespace
451 $output = trim(ob_get_contents());
452
453 // if plugin outputs more than newlines and spacing, stop script execution.
454 if (!empty($output)) {
455 $plugin_load_error = 'Some output was produced when plugin <i>' . $name . '</i> was loaded. Usually this means there is an error in the plugin\'s setup or configuration file. The output was: '.htmlspecialchars($output);
456 do_err($plugin_load_error);
457 }
69792446 458 }
69792446 459 ob_end_clean();
1dc63862 460
461
462 /**
463 * Check the contents of the static plugin hooks array file against
464 * the plugin setup file, which may have changed in an upgrade, etc.
465 * This helps remind admins to re-run the configuration utility when
466 * a plugin has been changed or upgraded.
467 */
468 $static_squirrelmail_plugin_hooks = $squirrelmail_plugin_hooks;
469 $squirrelmail_plugin_hooks = array();
470 foreach ($plugins as $name) {
471 $function = "squirrelmail_plugin_init_$name";
472 if (function_exists($function)) {
473 $function();
474
475 // now iterate through each hook and make sure the
476 // plugin is registered on the correct ones in the
477 // static plugin configuration file
478 //
479 foreach ($squirrelmail_plugin_hooks as $hook_name => $hooked_plugins)
480 foreach ($hooked_plugins as $hooked_plugin => $hooked_function)
481 if ($hooked_plugin == $name
482 && (empty($static_squirrelmail_plugin_hooks[$hook_name][$hooked_plugin])
483 || $static_squirrelmail_plugin_hooks[$hook_name][$hooked_plugin] != $hooked_function))
484 do_err('The plugin <i>' . $name . '</i> is supposed to be registered on the <i>' . $hook_name . '</i> hook, but it is not. You need to re-run the configuration utility and re-save your configuration file.', FALSE);
485 }
69792446 486 }
1dc63862 487 $squirrelmail_plugin_hooks = $static_squirrelmail_plugin_hooks;
488
489
dc528046 490 /**
56f9bb83 491 * Print plugin versions
492 */
56f9bb83 493 echo $IND . "Plugin versions...<br />\n";
494 foreach ($plugins as $name) {
d95b10b3 495 $plugin_version = get_plugin_version($name);
daa0c5b8 496 $english_name = get_plugin_requirement($name, 'english_name');
497 echo $IND . $IND . (empty($english_name) ? $name . ' ' : $english_name . ' (' . $name . ') ') . (empty($plugin_version) ? '??' : $plugin_version) . "<br />\n";
2cbaf68d 498
dc528046 499 // check if this plugin has any other plugin
2cbaf68d 500 // dependencies and if they are satisfied
501 //
502 $failed_dependencies = check_plugin_dependencies($name);
f258865c 503 if ($failed_dependencies === SQ_INCOMPATIBLE) {
03a69f57 504 do_err($name . ' is NOT COMPATIBLE with this version of SquirrelMail', FALSE);
505 }
506 else if (is_array($failed_dependencies)) {
2cbaf68d 507 $missing_plugins = '';
e1a125cd 508 $incompatible_plugins = '';
fc6228e4 509 foreach ($failed_dependencies as $depend_name => $depend_requirements) {
e1a125cd 510 if ($depend_requirements['version'] == SQ_INCOMPATIBLE)
511 $incompatible_plugins .= ', ' . $depend_name;
512 else
513 $missing_plugins .= ', ' . $depend_name . ' (version ' . $depend_requirements['version'] . ', ' . ($depend_requirements['activate'] ? 'must be activated' : 'need not be activated') . ')';
2cbaf68d 514 }
e1a125cd 515 $error_string = (!empty($incompatible_plugins) ? $name . ' cannot be activated at the same time as the following plugins: ' . trim($incompatible_plugins, ', ') : '')
516 . (!empty($missing_plugins) ? (!empty($incompatible_plugins) ? '. ' . $name . ' is also ' : $name . ' is ') . 'missing some dependencies: ' . trim($missing_plugins, ', ') : '');
517 do_err($error_string, FALSE);
2cbaf68d 518 }
519
56f9bb83 520 }
1dc63862 521
522
69792446 523 /**
dc528046 524 * This hook was added in 1.5.2 and 1.4.10. Each plugins should print an error
6e515418 525 * message and return TRUE if there are any errors in its setup/configuration.
69792446 526 */
62fb877b 527 $plugin_err = boolean_hook_function('configtest', $null, 1);
69792446 528 if($plugin_err) {
529 do_err('Some plugin tests failed.');
530 } else {
531 echo $IND . "Plugins OK.<br />\n";
532 }
5b53b7e0 533} else {
534 echo $IND . "Plugins are not enabled in config.<br />\n";
d1ae9d4c 535}
d1ae9d4c 536foreach($theme as $thm) {
537 if(!file_exists($thm['PATH'])) {
538 do_err('You have enabled the <i>'.$thm['NAME'].'</i> theme but I cannot find it ('.$thm['PATH'].').', FALSE);
539 } elseif(!is_readable($thm['PATH'])) {
540 do_err('You have enabled the <i>'.$thm['NAME'].'</i> theme but I cannot read it ('.$thm['PATH'].').', FALSE);
541 }
542}
543
544echo $IND . "Themes OK.<br />\n";
545
07337c9b 546if ( $squirrelmail_default_language != 'en_US' ) {
547 $loc_path = SM_PATH .'locale/'.$squirrelmail_default_language.'/LC_MESSAGES/squirrelmail.mo';
548 if( ! file_exists( $loc_path ) ) {
f8a1ed5a 549 do_err('You have set <i>' . $squirrelmail_default_language .
f084f987 550 '</i> as your default language, but I cannot find this translation (should be '.
551 'in <tt>' . $loc_path . '</tt>). Please note that you have to download translations '.
552 'separately from the main SquirrelMail package.', FALSE);
07337c9b 553 } elseif ( ! is_readable( $loc_path ) ) {
f8a1ed5a 554 do_err('You have set <i>' . $squirrelmail_default_language .
f084f987 555 '</i> as your default language, but I cannot read this translation (file '.
556 'in <tt>' . $loc_path . '</tt> unreadable).', FALSE);
07337c9b 557 } else {
558 echo $IND . "Default language OK.<br />\n";
559 }
560} else {
561 echo $IND . "Default language OK.<br />\n";
562}
563
74530cf4 564echo $IND . "Base URL detected as: <tt>" . htmlspecialchars($test_location) .
565 "</tt> (location base " . (empty($config_location_base) ? 'autodetected' : 'set to <tt>' .
566 htmlspecialchars($config_location_base)."</tt>") . ")<br />\n";
23649466 567
a15f9d93 568/* check minimal requirements for other security options */
d1ae9d4c 569
a15f9d93 570/* imaps or ssmtp */
571if($use_smtp_tls == 1 || $use_imap_tls == 1) {
d1ae9d4c 572 if(!check_php_version(4,3,0)) {
573 do_err('You need at least PHP 4.3.0 for SMTP/IMAP TLS!');
574 }
575 if(!extension_loaded('openssl')) {
576 do_err('You need the openssl PHP extension to use SMTP/IMAP TLS!');
577 }
578}
a15f9d93 579/* starttls extensions */
1c4f110f 580if($use_smtp_tls === 2 || $use_imap_tls === 2) {
a15f9d93 581 if (! function_exists('stream_socket_enable_crypto')) {
582 do_err('If you want to use STARTTLS extension, you need stream_socket_enable_crypto() function from PHP 5.1.0 and newer.');
583 }
584}
585/* digest-md5 */
586if ($smtp_auth_mech=='digest-md5' || $imap_auth_mech =='digest-md5') {
587 if (!extension_loaded('xml')) {
588 do_err('You need the PHP XML extension to use Digest-MD5 authentication!');
589 }
590}
591
592/* check outgoing mail */
d1ae9d4c 593
594echo "Checking outgoing mail service....<br />\n";
595
596if($useSendmail) {
597 // is_executable also checks for existance, but we want to be as precise as possible with the errors
598 if(!file_exists($sendmail_path)) {
599 do_err("Location of sendmail program incorrect ($sendmail_path)!");
91e0dccc 600 }
d1ae9d4c 601 if(!is_executable($sendmail_path)) {
602 do_err("I cannot execute the sendmail program ($sendmail_path)!");
603 }
604
605 echo $IND . "sendmail OK<br />\n";
606} else {
a15f9d93 607 $stream = fsockopen( ($use_smtp_tls==1?'tls://':'').$smtpServerAddress, $smtpPort,
f084f987 608 $errorNumber, $errorString);
d1ae9d4c 609 if(!$stream) {
610 do_err("Error connecting to SMTP server \"$smtpServerAddress:$smtpPort\".".
f084f987 611 "Server error: ($errorNumber) ".htmlspecialchars($errorString));
d1ae9d4c 612 }
613
614 // check for SMTP code; should be 2xx to allow us access
615 $smtpline = fgets($stream, 1024);
616 if(((int) $smtpline{0}) > 3) {
9c941728 617 do_err("Error connecting to SMTP server. Server error: ".
f084f987 618 htmlspecialchars($smtpline));
d1ae9d4c 619 }
620
a15f9d93 621 /* smtp starttls checks */
1c4f110f 622 if ($use_smtp_tls===2) {
a15f9d93 623 // if something breaks, script should close smtp connection on exit.
624
a820ac9d 625
626 // format EHLO argument correctly if needed
627 //
870ffc40 628 if (preg_match('/^\d+\.\d+\.\d+\.\d+$/', $client_ip))
a820ac9d 629 $helohost = '[' . $client_ip . ']';
630 else // some day might add IPv6 here
631 $helohost = $client_ip;
632
633
a15f9d93 634 // say helo
a820ac9d 635 fwrite($stream,"EHLO $helohost\r\n");
a15f9d93 636
637 $ehlo=array();
638 $ehlo_error = false;
639 while ($line=fgets($stream, 1024)){
640 if (preg_match("/^250(-|\s)(\S*)\s+(\S.*)/",$line,$match)||
f084f987 641 preg_match("/^250(-|\s)(\S*)\s+/",$line,$match)) {
a15f9d93 642 if (!isset($match[3])) {
643 // simple one word extension
644 $ehlo[strtoupper($match[2])]='';
645 } else {
646 // ehlo-keyword + ehlo-param
647 $ehlo[strtoupper($match[2])]=trim($match[3]);
648 }
649 if ($match[1]==' ') {
650 $ret = $line;
651 break;
652 }
653 } else {
dc528046 654 //
a15f9d93 655 $ehlo_error = true;
656 $ehlo[]=$line;
657 break;
658 }
659 }
660 if ($ehlo_error) {
661 do_err('SMTP EHLO failed. You need ESMTP support for SMTP STARTTLS');
662 } elseif (!array_key_exists('STARTTLS',$ehlo)) {
663 do_err('STARTTLS support is not declared by SMTP server.');
664 }
665
666 fwrite($stream,"STARTTLS\r\n");
667 $starttls_response=fgets($stream, 1024);
668 if ($starttls_response[0]!=2) {
669 $starttls_cmd_err = 'SMTP STARTTLS failed. Server replied: '
670 .htmlspecialchars($starttls_response);
671 do_err($starttls_cmd_err);
672 } elseif(! stream_socket_enable_crypto($stream,true,STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
673 do_err('Failed to enable encryption on SMTP STARTTLS connection.');
674 } else {
675 echo $IND . "SMTP STARTTLS extension looks OK.<br />\n";
676 }
677 // According to RFC we should second ehlo call here.
678 }
679
d1ae9d4c 680 fputs($stream, 'QUIT');
681 fclose($stream);
9c941728 682 echo $IND . 'SMTP server OK (<tt><small>'.
f084f987 683 trim(htmlspecialchars($smtpline))."</small></tt>)<br />\n";
d1ae9d4c 684
685 /* POP before SMTP */
686 if($pop_before_smtp) {
783e926e 687 if (empty($pop_before_smtp_host)) $pop_before_smtp_host = $smtpServerAddress;
688 $stream = fsockopen($pop_before_smtp_host, 110, $err_no, $err_str);
d1ae9d4c 689 if (!$stream) {
783e926e 690 do_err("Error connecting to POP Server ($pop_before_smtp_host:110) "
f084f987 691 . $err_no . ' : ' . htmlspecialchars($err_str));
d1ae9d4c 692 }
693
694 $tmp = fgets($stream, 1024);
695 if (substr($tmp, 0, 3) != '+OK') {
783e926e 696 do_err("Error connecting to POP Server ($pop_before_smtp_host:110)"
f084f987 697 . ' '.htmlspecialchars($tmp));
d1ae9d4c 698 }
699 fputs($stream, 'QUIT');
700 fclose($stream);
701 echo $IND . "POP-before-SMTP OK.<br />\n";
702 }
703}
704
df758744 705/**
706 * Check the IMAP server
707 */
d1ae9d4c 708echo "Checking IMAP service....<br />\n";
709
df758744 710/** Can we open a connection? */
a15f9d93 711$stream = fsockopen( ($use_imap_tls==1?'tls://':'').$imapServerAddress, $imapPort,
f084f987 712 $errorNumber, $errorString);
d1ae9d4c 713if(!$stream) {
70b71161 714 do_err("Error connecting to IMAP server \"$imapServerAddress:$imapPort\".".
f084f987 715 "Server error: ($errorNumber) ".
716 htmlspecialchars($errorString));
d1ae9d4c 717}
718
df758744 719/** Is the first response 'OK'? */
d1ae9d4c 720$imapline = fgets($stream, 1024);
721if(substr($imapline, 0,4) != '* OK') {
f084f987 722 do_err('Error connecting to IMAP server. Server error: '.
723 htmlspecialchars($imapline));
d1ae9d4c 724}
725
df758744 726echo $IND . 'IMAP server ready (<tt><small>'.
9c941728 727 htmlspecialchars(trim($imapline))."</small></tt>)<br />\n";
d1ae9d4c 728
df758744 729/** Check capabilities */
730fputs($stream, "A001 CAPABILITY\r\n");
a15f9d93 731$capline = '';
732while ($line=fgets($stream, 1024)){
f084f987 733 if (preg_match("/A001.*/",$line)) {
734 break;
735 } else {
736 $capline.=$line;
737 }
a15f9d93 738}
739
740/* don't display capabilities before STARTTLS */
1c4f110f 741if ($use_imap_tls===2 && stristr($capline, 'STARTTLS') === false) {
a15f9d93 742 do_err('Your server doesn\'t support STARTTLS.');
1c4f110f 743} elseif($use_imap_tls===2) {
a15f9d93 744 /* try starting starttls */
745 fwrite($stream,"A002 STARTTLS\r\n");
746 $starttls_line=fgets($stream, 1024);
747 if (! preg_match("/^A002 OK.*/i",$starttls_line)) {
748 $imap_starttls_err = 'IMAP STARTTLS failed. Server replied: '
f084f987 749 .htmlspecialchars($starttls_line);
a15f9d93 750 do_err($imap_starttls_err);
751 } elseif (! stream_socket_enable_crypto($stream,true,STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
752 do_err('Failed to enable encryption on IMAP connection.');
753 } else {
754 echo $IND . "IMAP STARTTLS extension looks OK.<br />\n";
755 }
756
757 // get new capability line
758 fwrite($stream,"A003 CAPABILITY\r\n");
759 $capline='';
760 while ($line=fgets($stream, 1024)){
761 if (preg_match("/A003.*/",$line)) {
762 break;
763 } else {
764 $capline.=$line;
765 }
766 }
767}
df758744 768
769echo $IND . 'Capabilities: <tt>'.htmlspecialchars($capline)."</tt><br />\n";
770
771if($imap_auth_mech == 'login' && stristr($capline, 'LOGINDISABLED') !== FALSE) {
772 do_err('Your server doesn\'t allow plaintext logins. '.
f084f987 773 'Try enabling another authentication mechanism like CRAM-MD5, DIGEST-MD5 or TLS-encryption '.
774 'in the SquirrelMail configuration.', FALSE);
df758744 775}
df758744 776
ceb7ad3c 777if (stristr($capline, 'XMAGICTRASH') !== false) {
778 $magic_trash = 'It looks like IMAP_MOVE_EXPUNGE_TO_TRASH option is turned on '
779 .'in your Courier IMAP configuration. Courier does not provide tools that '
780 .'allow to detect folder used for Trash or commands are not documented. '
781 .'SquirrelMail can\'t detect special trash folder. SquirrelMail manages '
782 .'all message deletion or move operations internally and '
783 .'IMAP_MOVE_EXPUNGE_TO_TRASH option can cause errors in message and '
784 .'folder management operations. Please turn off IMAP_MOVE_EXPUNGE_TO_TRASH '
785 .'option in Courier imapd configuration.';
786 do_err($magic_trash,false);
787}
788
0fa9bde7 789/* add warning about IMAP delivery */
790if (stristr($capline, 'XCOURIEROUTBOX') !== false) {
791 $courier_outbox = 'OUTBOX setting is enabled in your Courier imapd '
792 .'configuration. SquirrelMail uses standard SMTP protocol or sendmail '
793 .'binary to send emails. Courier IMAP delivery method is not supported'
794 .' and can create duplicate email messages.';
795 do_err($courier_outbox,false);
796}
797
df758744 798/** OK, close connection */
a15f9d93 799fputs($stream, "A004 LOGOUT\r\n");
df758744 800fclose($stream);
801
17fca61d 802echo "Checking internationalization (i18n) settings...<br />\n";
0ed3bdc3 803echo "$IND gettext - ";
804if (function_exists('gettext')) {
8f186a2a 805 echo 'Gettext functions are available.'
806 .' On some systems you must have appropriate system locales compiled.'
807 ."<br />\n";
fd72907b 808
809 /* optional setlocale() tests. Should work only on glibc systems. */
810 if (sqgetGlobalVar('testlocales',$testlocales,SQ_GET)) {
867fed37 811 include_once(SM_PATH . 'include/languages.php');
fd72907b 812 echo $IND . $IND . 'Testing translations:<br>';
813 foreach ($languages as $lang_code => $lang_data) {
814 /* don't test aliases */
815 if (isset($lang_data['NAME'])) {
816 /* locale can be $lang_code or $lang_data['LOCALE'] */
817 if (isset($lang_data['LOCALE'])) {
818 $setlocale = $lang_data['LOCALE'];
819 } else {
820 $setlocale = $lang_code;
821 }
822 /* prepare information about tested locales */
823 if (is_array($setlocale)) {
824 $display_locale = implode(', ',$setlocale);
825 $locale_count = count($setlocale);
826 } else {
827 $display_locale = $setlocale;
828 $locale_count = 1;
829 }
830 $tested_locales_msg = 'Tested '.htmlspecialchars($display_locale).' '
831 .($locale_count>1 ? 'locales':'locale'). '.';
832
833 echo $IND . $IND .$IND . $lang_data['NAME'].' (' .$lang_code. ') - ';
834 $retlocale = sq_setlocale(LC_ALL,$setlocale);
835 if (is_bool($retlocale)) {
836 echo '<font color="red">unsupported</font>. ';
837 echo $tested_locales_msg;
838 } else {
839 echo 'supported. '
840 .$tested_locales_msg
841 .' setlocale() returned "'.htmlspecialchars($retlocale).'"';
842 }
843 echo "<br />\n";
844 }
845 }
846 echo $IND . $IND . '<a href="configtest.php">Don\'t test translations</a>';
847 } else {
848 echo $IND . $IND . '<a href="configtest.php?testlocales=1">Test translations</a>. '
849 .'This test is not accurate and might work only on some systems.'
850 ."\n";
851 }
852 echo "<br />\n";
853 /* end of translation tests */
0ed3bdc3 854} else {
8f186a2a 855 echo 'Gettext functions are unavailable.'
856 .' SquirrelMail will use slower internal gettext functions.'
857 ."<br />\n";
0ed3bdc3 858}
859echo "$IND mbstring - ";
860if (function_exists('mb_detect_encoding')) {
861 echo "Mbstring functions are available.<br />\n";
862} else {
8f186a2a 863 echo 'Mbstring functions are unavailable.'
864 ." Japanese translation won't work.<br />\n";
0ed3bdc3 865}
866echo "$IND recode - ";
867if (function_exists('recode')) {
868 echo "Recode functions are available.<br />\n";
ba17b6c7 869} elseif (isset($use_php_recode) && $use_php_recode) {
0ed3bdc3 870 echo "Recode functions are unavailable.<br />\n";
871 do_err('Your configuration requires recode support, but recode support is missing.');
872} else {
873 echo "Recode functions are unavailable.<br />\n";
874}
875echo "$IND iconv - ";
876if (function_exists('iconv')) {
877 echo "Iconv functions are available.<br />\n";
ba17b6c7 878} elseif (isset($use_php_iconv) && $use_php_iconv) {
0ed3bdc3 879 echo "Iconv functions are unavailable.<br />\n";
880 do_err('Your configuration requires iconv support, but iconv support is missing.');
881} else {
882 echo "Iconv functions are unavailable.<br />\n";
883}
867fed37 884// same test as in include/init.php + date_default_timezone_set check
0ed3bdc3 885echo "$IND timezone - ";
867fed37 886if ( (!ini_get('safe_mode')) || function_exists('date_default_timezone_set') ||
f084f987 887 !strcmp(ini_get('safe_mode_allowed_env_vars'),'') ||
888 preg_match('/^([\w_]+,)*TZ/', ini_get('safe_mode_allowed_env_vars')) ) {
fd72907b 889 echo "Webmail users can change their time zone settings. \n";
0ed3bdc3 890} else {
fd72907b 891 echo "Webmail users can't change their time zone settings. \n";
4764a7ff 892}
fd72907b 893if (isset($_ENV['TZ'])) {
894 echo 'Default time zone is '.htmlspecialchars($_ENV['TZ']);
895} else {
896 echo 'Current time zone is '.date('T');
897}
898echo ".<br />\n";
d18703d3 899
4764a7ff 900// Pear DB tests
d18703d3 901echo "Checking database functions...<br />\n";
902if($addrbook_dsn || $prefs_dsn || $addrbook_global_dsn) {
134e4174 903 @include_once('DB.php');
904 if (class_exists('DB')) {
905 echo "$IND PHP Pear DB support is present.<br />\n";
906 $db_functions=array(
f084f987 907 'dbase' => 'dbase_open',
908 'fbsql' => 'fbsql_connect',
909 'interbase' => 'ibase_connect',
910 'informix' => 'ifx_connect',
911 'msql' => 'msql_connect',
912 'mssql' => 'mssql_connect',
913 'mysql' => 'mysql_connect',
914 'mysqli' => 'mysqli_connect',
915 'oci8' => 'ocilogon',
916 'odbc' => 'odbc_connect',
917 'pgsql' => 'pg_connect',
918 'sqlite' => 'sqlite_open',
919 'sybase' => 'sybase_connect'
920 );
134e4174 921
922 $dsns = array();
923 if($prefs_dsn) {
924 $dsns['preferences'] = $prefs_dsn;
925 }
926 if($addrbook_dsn) {
927 $dsns['addressbook'] = $addrbook_dsn;
928 }
929 if($addrbook_global_dsn) {
930 $dsns['global addressbook'] = $addrbook_global_dsn;
931 }
932
933 foreach($dsns as $type => $dsn) {
ba17b6c7 934 $aDsn = explode(':', $dsn);
935 $dbtype = array_shift($aDsn);
d053c206 936
134e4174 937 if(isset($db_functions[$dbtype]) && function_exists($db_functions[$dbtype])) {
938 echo "$IND$dbtype database support present.<br />\n";
d053c206 939 } elseif(!(bool)ini_get('enable_dl') || (bool)ini_get('safe_mode')) {
940 do_err($dbtype.' database support not present!');
941 } else {
942 // Non-fatal error
943 do_err($dbtype.' database support not present or not configured!
944 Trying to dynamically load '.$dbtype.' extension.
945 Please note that it is advisable to not rely on dynamic loading of extensions.', FALSE);
946 }
134e4174 947
134e4174 948
d053c206 949 // now, test this interface:
134e4174 950
d053c206 951 $dbh = DB::connect($dsn, true);
952 if (DB::isError($dbh)) {
953 do_err('Database error: '. htmlspecialchars(DB::errorMessage($dbh)) .
954 ' in ' .$type .' DSN.');
d18703d3 955 }
d053c206 956 $dbh->disconnect();
957 echo "$IND$type database connect successful.<br />\n";
134e4174 958 }
959 } else {
8f186a2a 960 $db_error='Required PHP PEAR DB support is not available.'
961 .' Is PEAR installed and is the include path set correctly to find <tt>DB.php</tt>?'
dc528046 962 .' The include path is now: "<tt>' . ini_get('include_path') . '</tt>".';
8f186a2a 963 do_err($db_error);
134e4174 964 }
4764a7ff 965} else {
d18703d3 966 echo $IND."not using database functionality.<br />\n";
0ed3bdc3 967}
7562c55b 968
969// LDAP DB tests
970echo "Checking LDAP functions...<br />\n";
971if( empty($ldap_server) ) {
134e4174 972 echo $IND."not using LDAP functionality.<br />\n";
7562c55b 973} else {
d0184454 974 if ( !function_exists('ldap_connect') ) {
7562c55b 975 do_err('Required LDAP support is not available.');
976 } else {
134e4174 977 echo "$IND LDAP support present.<br />\n";
7562c55b 978 foreach ( $ldap_server as $param ) {
979
d0184454 980 $linkid = @ldap_connect($param['host'], (empty($param['port']) ? 389 : $param['port']) );
7562c55b 981
982 if ( $linkid ) {
f084f987 983 echo "$IND LDAP connect to ".$param['host']." successful: ".$linkid."<br />\n";
91e0dccc 984
7562c55b 985 if ( !empty($param['protocol']) &&
f084f987 986 !ldap_set_option($linkid, LDAP_OPT_PROTOCOL_VERSION, $param['protocol']) ) {
7562c55b 987 do_err('Unable to set LDAP protocol');
91e0dccc 988 }
7562c55b 989
990 if ( empty($param['binddn']) ) {
d0184454 991 $bind = @ldap_bind($linkid);
7562c55b 992 } else {
eb2ae346 993 $bind = @ldap_bind($linkid, $param['binddn'], $param['bindpw']);
7562c55b 994 }
995
996 if ( $bind ) {
997 echo "$IND LDAP Bind Successful <br />";
998 } else {
999 do_err('Unable to Bind to LDAP Server');
1000 }
91e0dccc 1001
d0184454 1002 @ldap_close($linkid);
7562c55b 1003 } else {
1004 do_err('Connection to LDAP failed');
1005 }
1006 }
1007 }
1008}
a2b193bc 1009
3a196538 1010echo '<hr width="75%" align="center">';
1011echo '<h2 align="center">Summary</h2>';
1012$footer = '<hr width="75%" align="center">';
1013if ($warnings) {
b00dce9b 1014 echo '<p>No fatal errors were found, but there was at least 1 warning. Please check the flagged issue(s) carefully, as correcting them may prevent erratic, undefined, or incorrect behavior (or flat out breakage).</p>';
f084f987 1015 echo $footer;
3a196538 1016} else {
f084f987 1017 print <<< EOF
d1ae9d4c 1018<p>Congratulations, your SquirrelMail setup looks fine to me!</p>
1019
13721b47 1020<p><a href="login.php">Login now</a></p>
d1ae9d4c 1021
1022</body>
3a196538 1023</html>
1024EOF;
f084f987 1025 echo $footer;
3a196538 1026}