get_magic_quotes_* functions deprecated in PHP 5.3.x. Check for
[squirrelmail.git] / src / configtest.php
index 45822902a5b496f33b5000e2f50ad68e9f7a9896..a89020bffc91798f3e759f76761d918fb8a9ae0a 100644 (file)
@@ -3,7 +3,7 @@
 /**
  * SquirrelMail configtest script
  *
- * @copyright © 2003-2006 The SquirrelMail Project Team
+ * @copyright © 2003-2007 The SquirrelMail Project Team
  * @license http://opensource.org/licenses/gpl-license.php GNU Public License
  * @version $Id$
  * @package squirrelmail
@@ -15,6 +15,9 @@
  * If it throws errors you need to adjust your config.      *
  ************************************************************/
 
+/** This is the configtest page */
+define('PAGE_NAME', 'configtest');
+
 // This script could really use some restructuring as it has grown quite rapidly
 // but is not very 'clean'. Feel free to get some structure into this thing.
 
@@ -81,8 +84,11 @@ ob_implicit_flush();
 /** @ignore */
 define('SM_PATH', '../');
 /** load minimal function set */
+require(SM_PATH . 'include/constants.php');
 require(SM_PATH . 'functions/global.php');
 require(SM_PATH . 'functions/strings.php');
+$SQM_INTERNAL_VERSION = explode('.', SM_VERSION, 3);
+$SQM_INTERNAL_VERSION[2] = intval($SQM_INTERNAL_VERSION[2]);
 
 /** set default value in order to block remote access */
 $allow_remote_configtest=false;
@@ -167,9 +173,8 @@ if (! $allow_remote_configtest) {
         do_err('Enable "Allow remote configtest" option in squirrelmail configuration in order to use this script.');
     }
 }
-/* checking PHP specs */
 
-echo "<p><table>\n<tr><td>SquirrelMail version:</td><td><b>" . $version . "</b></td></tr>\n" .
+echo "<p><table>\n<tr><td>SquirrelMail version:</td><td><b>" . SM_VERSION . "</b></td></tr>\n" .
     '<tr><td>Config file version:</td><td><b>' . $config_version . "</b></td></tr>\n" .
     '<tr><td>Config file last modified:</td><td><b>' .
     date ('d F Y H:i:s', filemtime(SM_PATH . 'config/config.php')) .
@@ -180,6 +185,9 @@ if ($config_version!='1.5.0') {
     do_err('Configuration file version does not match required version. Please update your configuration file.');
 }
 
+
+/* checking PHP specs */
+
 echo "Checking PHP configuration...<br />\n";
 
 if(!check_php_version(4,1,0)) {
@@ -187,18 +195,94 @@ if(!check_php_version(4,1,0)) {
 }
 
 echo $IND . 'PHP version ' . PHP_VERSION . ' OK. (You have: ' . phpversion() . ". Minimum: 4.1.0)<br />\n";
-/* test for boolean false and any string that is not equal to 'off' */
-if ((bool) ini_get('register_globals') && 
+
+echo $IND . 'display_errors: ' . ini_get('display_errors') . "<br />\n";
+
+echo $IND . 'error_reporting: ' . ini_get('error_reporting') . "<br />\n";
+
+$safe_mode = ini_get('safe_mode');
+if ($safe_mode) {
+    echo $IND . 'safe_mode: ' . $safe_mode;
+    if (empty($prefs_dsn) || empty($addrbook_dsn))
+        echo ' (<font color="red">double check data and attachment directory ownership, etc!</font>)';
+    if (!empty($addrbook_dsn) || !empty($prefs_dsn) || !empty($addrbook_global_dsn))
+        echo ' (<font color="red">does PHP have access to database interface?</font>)';
+    echo "<br />\n";
+    $safe_mode_exec_dir = ini_get('safe_mode_exec_dir');
+    echo $IND . 'safe_mode_exec_dir: ' . $safe_mode_exec_dir . "<br />\n";
+}
+
+/* register_globals check: test for boolean false and any string that is not equal to 'off' */
+
+if ((bool) ini_get('register_globals') &&
     strtolower(ini_get('register_globals'))!='off') {
     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);
 }
+
+
+/* variables_order check */
+
+// 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
+$variables_order = strtoupper(ini_get('variables_order'));
+if (empty($variables_order))
+    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);
+else if (strpos($variables_order, 'G') === FALSE
+ || strpos($variables_order, 'P') === FALSE
+ || strpos($variables_order, 'C') === FALSE
+ || strpos($variables_order, 'S') === FALSE) {
+    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);
+} else {
+    echo $IND . "variables_order OK: $variables_order.<br />\n";
+}
+
+
+/* gpc_order check (removed from PHP as of v5.0) */
+
+if (!check_php_version(5)) {
+    // 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
+    $gpc_order = strtoupper(ini_get('gpc_order'));
+    if (empty($gpc_order))
+        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);
+    else if (strpos($gpc_order, 'G') === FALSE
+     || strpos($gpc_order, 'P') === FALSE
+     || strpos($gpc_order, 'C') === FALSE) {
+        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);
+    } else {
+        echo $IND . "gpc_order OK: $gpc_order.<br />\n";
+    }
+}
+
+
+/* check PHP extensions */
+
 $php_exts = array('session','pcre');
 $diff = array_diff($php_exts, get_loaded_extensions());
 if(count($diff)) {
     do_err('Required PHP extensions missing: '.implode(', ',$diff) );
 }
 
-echo $IND . "PHP extensions OK.<br />\n";
+echo $IND . "PHP extensions OK. Dynamic loading is ";
+
+if (!(bool)ini_get('enable_dl') || (bool)ini_get('safe_mode')) {
+    echo "disabled.<br />\n";
+} else {
+    echo "enabled.<br />\n";
+}
+
 
 /* dangerous php settings */
 /**
@@ -216,13 +300,40 @@ if (function_exists('mb_internal_encoding') &&
     do_err($mb_error);
 }
 
+/**
+ * Do not use SquirrelMail with magic_quotes_* on.
+ */
+if ( (function_exists('get_magic_quotes_runtime') &&  @get_magic_quotes_runtime()) ||
+     (function_exists('get_magic_quotes_gpc') && @get_magic_quotes_gpc()) ||
+    ( (bool) ini_get('magic_quotes_sybase') && ini_get('magic_quotes_sybase') != 'off' )
+    ) {
+    $magic_quotes_warning='You have enabled any one of <tt>magic_quotes_runtime</tt>, '
+        .'<tt>magic_quotes_gpc</tt> or <tt>magic_quotes_sybase</tt> in your PHP '
+        .'configuration. We recommend all those settings to be off. SquirrelMail '
+        .'may work with them on, but when experiencing stray backslashes in your mail '
+        .'or other strange behaviour, it may be advisable to turn them off.';
+    do_err($magic_quotes_warning,false);
+}
+
+if (ini_get('short_open_tag') == 0) {
+    $short_open_tag_warning = 'You have configured PHP not to allow short tags '
+        . '(<tt>short_open_tag=off</tt>). This shouldn\'t be a problem with '
+        . 'SquirrelMail or any plugin coded coded according to the '
+        . 'SquirrelMail Coding Guidelines, but if you experience problems with '
+        . 'PHP code being displayed in some of the pages and changing setting '
+        . 'to "on" solves the problem, please file a bug report against the '
+        . 'failing plugin. The correct contact information is most likely '
+        . 'to be found in the plugin documentation.';
+    do_err($short_open_tag_warning, false);
+}
+
 /* checking paths */
 
 echo "Checking paths...<br />\n";
 
 if(!file_exists($data_dir)) {
     // data_dir is not that important in db_setups.
-    if (isset($prefs_dsn) && ! empty($prefs_dsn)) {
+    if (!empty($prefs_dsn)) {
         $data_dir_error = "Data dir ($data_dir) does not exist!\n";
         echo $IND .'<font color="red"><b>ERROR:</b></font> ' . $data_dir_error;
     } else {
@@ -231,7 +342,7 @@ if(!file_exists($data_dir)) {
 }
 // don't check if errors
 if(!isset($data_dir_error) && !is_dir($data_dir)) {
-    if (isset($prefs_dsn) && ! empty($prefs_dsn)) {
+    if (!empty($prefs_dsn)) {
         $data_dir_error = "Data dir ($data_dir) is not a directory!\n";
         echo $IND . '<font color="red"><b>ERROR:</b></font> ' . $data_dir_error;
     } else {
@@ -240,7 +351,7 @@ if(!isset($data_dir_error) && !is_dir($data_dir)) {
 }
 // datadir should be executable - but no clean way to test on that
 if(!isset($data_dir_error) && !is_writable($data_dir)) {
-    if (isset($prefs_dsn) && ! empty($prefs_dsn)) {
+    if (!empty($prefs_dsn)) {
         $data_dir_error = "Data dir ($data_dir) is not writable!\n";
         echo $IND . '<font color="red"><b>ERROR:</b></font> ' . $data_dir_error;
     } else {
@@ -274,6 +385,8 @@ if($data_dir == $attachment_dir) {
 }
 
 
+echo "Checking plugins...<br />\n";
+
 /* check plugins and themes */
 //FIXME: check requirements given in plugin _info() function, such
 //       as required PHP extensions, Pear packages, other plugins, SM version, etc
@@ -330,15 +443,39 @@ if (isset($plugins[0])) {
     ob_end_clean();
     // if plugins output more than newlines and spacing, stop script execution.
     if (!empty($output)) {
-        $plugin_load_error = 'Some output is produced when plugins are loaded.'
-            .' Usually it means error. Output said: '.htmlspecialchars($output);
+        $plugin_load_error = 'Some output is produced when plugins are loaded. Usually this means there is an error in one of the plugin setup or configuration files. The output was: '.htmlspecialchars($output);
         do_err($plugin_load_error);
     }
     /**
-     * This hook was added in 1.5.2. Each plugins should print an error 
+     * Print plugin versions
+     */
+    echo $IND . "Plugin versions...<br />\n";
+    foreach ($plugins as $name) {
+        $plugin_version = get_plugin_version($name);
+        $english_name = get_plugin_requirement($name, 'english_name');
+        echo $IND . $IND . (empty($english_name) ? $name . ' ' : $english_name . ' (' . $name . ') ') . (empty($plugin_version) ? '??' : $plugin_version) . "<br />\n";
+
+        // check if this plugin has any other plugin
+        // dependencies and if they are satisfied
+        //
+        $failed_dependencies = check_plugin_dependencies($name);
+        if ($failed_dependencies === SQ_INCOMPATIBLE) {
+            do_err($name . ' is NOT COMPATIBLE with this version of SquirrelMail', FALSE);
+        }
+        else if (is_array($failed_dependencies)) {
+            $missing_plugins = '';
+            foreach ($failed_dependencies as $depend_name => $depend_requirements) {
+                $missing_plugins .= ', ' . $depend_name . ' (version ' . $depend_requirements['version'] . ', ' . ($depend_requirements['activate'] ? 'must be activated' : 'need not be activated') . ')';
+            }
+            do_err($name . ' is missing some dependencies: ' . trim($missing_plugins, ', '), FALSE);
+        }
+
+    }
+    /**
+     * This hook was added in 1.5.2 and 1.4.10. Each plugins should print an error
      * message and return TRUE if there are any errors in its setup/configuration.
      */
-    $plugin_err = boolean_hook_function('configtest', $null);
+    $plugin_err = boolean_hook_function('configtest', $null, 1);
     if($plugin_err) {
         do_err('Some plugin tests failed.');
     } else {
@@ -456,7 +593,7 @@ if($useSendmail) {
                     break;
                 }
             } else {
-                // 
+                //
                 $ehlo_error = true;
                 $ehlo[]=$line;
                 break;
@@ -737,27 +874,33 @@ if($addrbook_dsn || $prefs_dsn || $addrbook_global_dsn) {
         foreach($dsns as $type => $dsn) {
             $aDsn = explode(':', $dsn);
             $dbtype = array_shift($aDsn);
+
             if(isset($db_functions[$dbtype]) && function_exists($db_functions[$dbtype])) {
                 echo "$IND$dbtype database support present.<br />\n";
+            } elseif(!(bool)ini_get('enable_dl') || (bool)ini_get('safe_mode')) {
+                do_err($dbtype.' database support not present!');
+            } else {
+                // Non-fatal error
+                do_err($dbtype.' database support not present or not configured!
+                    Trying to dynamically load '.$dbtype.' extension.
+                    Please note that it is advisable to not rely on dynamic loading of extensions.', FALSE);
+            }
 
-                // now, test this interface:
 
-                $dbh = DB::connect($dsn, true);
-                if (DB::isError($dbh)) {
-                    do_err('Database error: '. htmlspecialchars(DB::errorMessage($dbh)) .
-                            ' in ' .$type .' DSN.');
-                }
-                $dbh->disconnect();
-                echo "$IND$type database connect successful.<br />\n";
+            // now, test this interface:
 
-            } else {
-                do_err($dbtype.' database support not present!');
+            $dbh = DB::connect($dsn, true);
+            if (DB::isError($dbh)) {
+                do_err('Database error: '. htmlspecialchars(DB::errorMessage($dbh)) .
+                        ' in ' .$type .' DSN.');
             }
+            $dbh->disconnect();
+            echo "$IND$type database connect successful.<br />\n";
         }
     } else {
         $db_error='Required PHP PEAR DB support is not available.'
             .' Is PEAR installed and is the include path set correctly to find <tt>DB.php</tt>?'
-            .' The include path is now:<tt>' . ini_get('include_path') . '</tt>.';
+            .' The include path is now: "<tt>' . ini_get('include_path') . '</tt>".';
         do_err($db_error);
     }
 } else {
@@ -822,4 +965,3 @@ if ($warnings) {
 EOF;
     echo $footer;
 }
-?>