Skip .svn dir. Leaving CVS dir in case it is left over in some people's downloaded...
[squirrelmail.git] / include / init.php
index 80a17c5cd869cfbcbc6f0f6649048eba38d499fa..53cebad214d7bf98d324108531c20d273165f80b 100644 (file)
  */
 
 /**
- * SquirrelMail version number -- DO NOT CHANGE
+ * This is a development version so in order to track programmer mistakes we
+ * set the error reporting to E_ALL
  */
+error_reporting(E_ALL);
 
-$version = '1.5.2 [CVS]';
 
 /**
- * SquirrelMail internal version number -- DO NOT CHANGE
- * $sm_internal_version = array (release, major, minor)
+ * If register_globals are on, unregister globals.
+ * Second test covers boolean set as string (php_value register_globals off).
  */
-
-$SQM_INTERNAL_VERSION = array(1,5,2);
+if ((bool) ini_get('register_globals') &&
+    strtolower(ini_get('register_globals'))!='off') {
+    /**
+     * Remove all globals that are not reserved by PHP
+     * 'value' and 'key' are used by foreach. Don't unset them inside foreach.
+     */
+    foreach ($GLOBALS as $key => $value) {
+        switch($key) {
+        case 'HTTP_POST_VARS':
+        case '_POST':
+        case 'HTTP_GET_VARS':
+        case '_GET':
+        case 'HTTP_COOKIE_VARS':
+        case '_COOKIE':
+        case 'HTTP_SERVER_VARS':
+        case '_SERVER':
+        case 'HTTP_ENV_VARS':
+        case '_ENV':
+        case 'HTTP_POST_FILES':
+        case '_FILES':
+        case '_REQUEST':
+        case 'HTTP_SESSION_VARS':
+        case '_SESSION':
+        case 'GLOBALS':
+        case 'key':
+        case 'value':
+            break;
+        case 'sInitLocation':
+            // FIXME: variable must be set only in src/login.php
+            break;
+        default:
+            unset($GLOBALS[$key]);
+        }
+    }
+    // Unset variables used in foreach
+    unset($GLOBALS['key']);
+    unset($GLOBALS['value']);
+}
 
 /**
- * This is a development version so in order to track programmer mistakes we
- * set the error reporting to E_ALL
+ * Used as a dummy value, e.g., for passing as an empty
+ * hook argument.
  */
+global $null;
+$null = NULL;
 
-error_reporting(E_ALL);
-
+/**
+ * [#1518885] session.use_cookies = off breaks SquirrelMail
+ *
+ * When session cookies are not used, all http redirects, meta refreshes,
+ * src/download.php and javascript URLs are broken. Setting must be set
+ * before session is started.
+ */
+if (!(bool)ini_get('session.use_cookies') ||
+    ini_get('session.use_cookies') == 'off') {
+    ini_set('session.use_cookies','1');
+}
 
 /**
  * calculate SM_PATH and calculate the base_uri
@@ -41,7 +89,12 @@ error_reporting(E_ALL);
 if (isset($_SERVER['SCRIPT_NAME'])) {
     $a = explode('/',$_SERVER['SCRIPT_NAME']);
 } elseif (isset($HTTP_SERVER_VARS['SCRIPT_NAME'])) {
-    $a = explode('/',$_SERVER['SCRIPT_NAME']);
+    $a = explode('/',$HTTP_SERVER_VARS['SCRIPT_NAME']);
+} else {
+    $error = 'Unable to detect script environment. '
+       .'Please test your PHP settings and send PHP core config, $_SERVER '
+       .'and $HTTP_SERVER_VARS to SquirrelMail developers.';
+    die($error);
 }
 $sSM_PATH = '';
 for($i = count($a) -2;$i > -1; --$i) {
@@ -53,10 +106,8 @@ for($i = count($a) -2;$i > -1; --$i) {
 
 $base_uri = implode('/',array_slice($a,0,$i)). '/';
 
-
-
 define('SM_PATH',$sSM_PATH);
-
+define('SM_BASE_URI', $base_uri);
 /**
  * global var $bInit is used to check if initialisation took place.
  * At this moment it's a workarounf for the include of addrbook_search_html
@@ -66,11 +117,54 @@ define('SM_PATH',$sSM_PATH);
  */
 $bInit = true;
 
+/**
+ * This theme as a failsafe if no themes were found, or if we error
+ * out before anything could be initialised.
+ */
+$color = array();
+$color[0]  = '#DCDCDC';  /* light gray    TitleBar               */
+$color[1]  = '#800000';  /* red                                  */
+$color[2]  = '#CC0000';  /* light red     Warning/Error Messages */
+$color[3]  = '#A0B8C8';  /* green-blue    Left Bar Background    */
+$color[4]  = '#FFFFFF';  /* white         Normal Background      */
+$color[5]  = '#FFFFCC';  /* light yellow  Table Headers          */
+$color[6]  = '#000000';  /* black         Text on left bar       */
+$color[7]  = '#0000CC';  /* blue          Links                  */
+$color[8]  = '#000000';  /* black         Normal text            */
+$color[9]  = '#ABABAB';  /* mid-gray      Darker version of #0   */
+$color[10] = '#666666';  /* dark gray     Darker version of #9   */
+$color[11] = '#770000';  /* dark red      Special Folders color  */
+$color[12] = '#EDEDED';
+$color[13] = '#800000';  /* (dark red)    Color for quoted text -- > 1 quote */
+$color[14] = '#ff0000';  /* (red)         Color for quoted text -- >> 2 or more */
+$color[15] = '#002266';  /* (dark blue)   Unselectable folders */
+$color[16] = '#ff9933';  /* (orange)      Highlight color */
+
 require(SM_PATH . 'functions/global.php');
+require(SM_PATH . 'functions/arrays.php');
+
+/* load default configuration */
+require(SM_PATH . 'config/config_default.php');
+/* reset arrays in default configuration */
+$ldap_server = array();
+$plugins = array();
+$fontsets = array();
+$aTemplateSet = array();
+$aTemplateSet[0]['ID'] = 'default';
+$aTemplateSet[0]['NAME'] = 'Default';
+
+/* load site configuration */
 require(SM_PATH . 'config/config.php');
+/* load local configuration overrides */
+if (file_exists(SM_PATH . 'config/config_local.php')) {
+    require(SM_PATH . 'config/config_local.php');
+}
+
 require(SM_PATH . 'functions/plugin.php');
 require(SM_PATH . 'include/constants.php');
 require(SM_PATH . 'include/languages.php');
+require(SM_PATH . 'class/template/Template.class.php');
+require(SM_PATH . 'class/error.class.php');
 
 /**
  * If magic_quotes_runtime is on, SquirrelMail breaks in new and creative ways.
@@ -88,43 +182,6 @@ if (get_magic_quotes_gpc()) {
     sqstripslashes($_POST);
 }
 
-/**
- * If register_globals are on, unregister globals.
- * Code requires PHP 4.1.0 or newer.
- */
-if ((bool) @ini_get('register_globals')) {
-    /**
-     * Remove all globals from $_GET, $_POST, and $_COOKIE.
-     */
-    foreach ($_REQUEST as $key => $value) {
-        unset($GLOBALS[$key]);
-    }
-    /**
-     * Remove globalized $_FILES variables
-     * Before 4.3.0 $_FILES are included in $_REQUEST.
-     * Unglobalize them in separate call in order to remove dependency
-     * on PHP version.
-     */
-    foreach ($_FILES as $key => $value) {
-        unset($GLOBALS[$key]);
-        // there are three undocumented $_FILES globals.
-        unset($GLOBALS[$key.'_type']);
-        unset($GLOBALS[$key.'_name']);
-        unset($GLOBALS[$key.'_size']);
-    }
-    /**
-     * Remove globalized environment variables.
-     */
-    foreach ($_ENV as $key => $value) {
-        unset($GLOBALS[$key]);
-    }
-    /**
-     * Remove globalized server variables.
-     */
-    foreach ($_SERVER as $key => $value) {
-        unset($GLOBALS[$key]);
-    }
-}
 
 /* strip any tags added to the url from PHP_SELF.
 This fixes hand crafted url XXS expoits for any
@@ -137,29 +194,99 @@ $PHP_SELF = php_self();
  * Initialize the session
  */
 
+/** set the name of the session cookie */
+if (!isset($session_name) || !$session_name) {
+    $session_name = 'SQMSESSID';
+}
+
+/**
+ * if session.auto_start is On then close the session
+ */
+$sSessionAutostartName = session_name();
+$sCookiePath = null;
+if ((isset($sSessionAutostartName) || $sSessionAutostartName == '') &&
+     $sSessionAutostartName !== $session_name) {
+    $sCookiePath = ini_get('session.cookie_path');
+    $sCookieDomain = ini_get('session.cookie_domain');
+    // reset the cookie
+    setcookie($sSessionAutostartName,'',time() - 604800,$sCookiePath,$sCookieDomain);
+    @session_destroy();
+    session_write_close();
+}
+
 /**
  * includes from classes stored in the session
  */
 require(SM_PATH . 'class/mime.class.php');
 
-/** set the name of the session cookie */
-if (!isset($session_name) || !$session_name) {
-    $session_name = 'SQMSESSID';
-}
 ini_set('session.name' , $session_name);
 session_set_cookie_params (0, $base_uri);
 sqsession_is_active();
 
-sqsession_register($base_uri, 'base_uri');
+/**
+ * SquirrelMail internal version number -- DO NOT CHANGE
+ * $sm_internal_version = array (release, major, minor)
+ */
+$SQM_INTERNAL_VERSION = preg_split('/\./', SM_VERSION, 3);
+$SQM_INTERNAL_VERSION[2] = intval($SQM_INTERNAL_VERSION[2]);
+
+
+/* if plugins are disabled only for one user and
+ * the current user is NOT that user, turn them
+ * back on
+ */
+sqgetGlobalVar('username',$username,SQ_SESSION);
+if ($disable_plugins && !empty($disable_plugins_user)
+ && $username != $disable_plugins_user) {
+    $disable_plugins = false;
+}
+
+/* remove all plugins if they are disabled */
+if ($disable_plugins) {
+   $plugins = array();
+}
+
 
 /**
- * Remove globalized session data in rg=on setups
+ * Include Compatibility plugin if available.
+ */
+if (!$disable_plugins && file_exists(SM_PATH . 'plugins/compatibility/functions.php'))
+    include_once(SM_PATH . 'plugins/compatibility/functions.php');
+
+/**
+ * MAIN PLUGIN LOADING CODE HERE
+ * On init, we no longer need to load all plugin setup files.
+ * Now, we load the statically generated hook registrations here
+ * and let the hook calls include only the plugins needed.
  */
-if ((bool) @ini_get('register_globals')) {
+$squirrelmail_plugin_hooks = array();
+if (!$disable_plugins && file_exists(SM_PATH . 'config/plugin_hooks.php')) {
+    require(SM_PATH . 'config/plugin_hooks.php');
+}
+
+/**
+ * allow plugins to override main configuration; hook is placed
+ * here to allow plugins to use session information to do their work
+ */
+do_hook('config_override', $null);
+
+/**
+ * DISABLED.
+ * Remove globalized session data in rg=on setups
+ *
+ * Code can be utilized when session is started, but data is not loaded.
+ * We have already loaded configuration and other important vars. Can't
+ * clean session globals here.
+if ((bool) @ini_get('register_globals') &&
+    strtolower(ini_get('register_globals'))!='off') {
     foreach ($_SESSION as $key => $value) {
         unset($GLOBALS[$key]);
     }
 }
+*/
+
+sqsession_register(SM_BASE_URI,'base_uri');
+
 /**
  * Retrieve the language cookie
  */
@@ -175,44 +302,53 @@ if (!isset($sInitLocation)) {
     $sInitLocation=NULL;
 }
 
-/**
- * MAIN PLUGIN LOADING CODE HERE
- */
-
-/**
- * Include Compatibility plugin if available.
- */
-if (file_exists(SM_PATH . 'plugins/compatibility/functions.php'))
-    include_once(SM_PATH . 'plugins/compatibility/functions.php');
-$squirrelmail_plugin_hooks = array();
+switch ($sInitLocation) {
+    case 'style':
+
+        // need to get the right template set up
+        //
+        sqGetGlobalVar('templateid', $templateid, SQ_GET);
+
+        // sanitize just in case...
+        //
+        $templateid = preg_replace('/(\.\.\/){1,}/', '', $templateid);
+
+        // make sure given template actually is available
+        //
+        $found_templateset = false;
+        for ($i = 0; $i < count($aTemplateSet); ++$i) {
+            if ($aTemplateSet[$i]['ID'] == $templateid) {
+                $found_templateset = true;
+                break;
+            }
+        }
 
-/* On init, register all plugins configured for use. */
-if (isset($plugins) && is_array($plugins)) {
-    // turn on output buffering in order to prevent output of new lines
-    ob_start();
-    foreach ($plugins as $name) {
-        use_plugin($name);
-    }
-    // get output and remove whitespace
-    $output = trim(ob_get_contents());
-    ob_end_clean();
-    // if plugins output more than newlines and spacing, stop script execution.
-    if (!empty($output)) {
-        die($output);
-    }
-}
+// FIXME: do we need/want to check here for actual (physical) presence of template sets?
+        // selected template not available, fall back to default template
+        //
+        if (!$found_templateset) {
+            $sTemplateID = Template::get_default_template_set();
+        } else {
+            $sTemplateID = $templateid;
+        }
 
+        session_write_close();
+        break;
 
-switch ($sInitLocation) {
-    case 'style': session_write_close(); sqsetcookieflush(); break;
     case 'redirect':
-        $prefs_backend = do_hook_function('prefs_backend');
+        /**
+         * directory hashing functions are needed for all setups in case
+         * plugins use own pref files.
+         */
+        require(SM_PATH . 'functions/prefs.php');
+        require(SM_PATH . 'functions/auth.php');
+        /* hook loads custom prefs backend plugins */
+        $prefs_backend = do_hook('prefs_backend', $null);
         if (isset($prefs_backend) && !empty($prefs_backend) && file_exists(SM_PATH . $prefs_backend)) {
             require(SM_PATH . $prefs_backend);
         } elseif (isset($prefs_dsn) && !empty($prefs_dsn)) {
             require(SM_PATH . 'functions/db_prefs.php');
         } else {
-            require(SM_PATH . 'functions/prefs.php');
             require(SM_PATH . 'functions/file_prefs.php');
         }
         //nobreak;
@@ -220,6 +356,39 @@ switch ($sInitLocation) {
         require(SM_PATH . 'functions/display_messages.php' );
         require(SM_PATH . 'functions/page_header.php');
         require(SM_PATH . 'functions/html.php');
+
+        // reset template file cache
+        //
+        $sTemplateID = Template::get_default_template_set();
+        Template::cache_template_file_hierarchy(TRUE);
+
+        /**
+         * Make sure icon variables are setup for the login page.
+         */
+        $icon_theme = $icon_themes[$icon_theme_def]['PATH'];
+        /*
+         * NOTE: The $icon_theme_path var should contain the path to the icon
+         *       theme to use.  If the admin has disabled icons, or the user has
+         *       set the icon theme to "None," no icons will be used.
+         */
+        $icon_theme_path = (!$use_icons || $icon_theme=='none') ? NULL : ($icon_theme == 'template' ? SM_PATH . Template::calculate_template_images_directory($sTemplateID) : $icon_theme);
+
+        /**
+         * cleanup old cookies with a cookie path the same as the standard php.ini
+         * cookie path. All previous SquirrelMail version used the standard php.ini
+         * cookie path for storing the session name. That behaviour changed.
+         */
+        if ($sCookiePath !== SM_BASE_URI) {
+            /**
+             * do not delete the standard sessions with session.name is i.e. PHPSESSID
+             * because they probably belong to other php apps
+             */
+            if (ini_get('session.name') !== $sSessionAutostartName) {
+                //  This does not work. Sometimes the cookie with SQSESSID=deleted and path /
+                // is picked up in webmail.php => login will fail
+                //sqsetcookie(ini_get('session.name'),'',0,$sCookiePath);
+            }
+        }
         break;
     default:
         require(SM_PATH . 'functions/display_messages.php' );
@@ -252,12 +421,25 @@ switch ($sInitLocation) {
             return;
             }
 
+            /**
+             * Initialize the template object (logout_error uses it)
+             */
+            /*
+             * $sTemplateID is not initialized when a user is not logged in, so we
+             * will use the config file defaults here.  If the neccesary variables
+             * are net set, force a default value.
+             */
+            $sTemplateID = Template::get_default_template_set();
+            $oTemplate = Template::construct_template($sTemplateID);
+
             set_up_language($squirrelmail_language, true);
             logout_error( _("You must be logged in to access this page.") );
             exit;
         }
 
+//FIXME: remove next line if the placement of the copy of this line above does not prove to be problematic
         sqgetGlobalVar('username',$username,SQ_SESSION);
+        sqgetGlobalVar('authz',$authz,SQ_SESSION);
 
         /**
          * Setting the prefs backend
@@ -272,13 +454,15 @@ switch ($sInitLocation) {
             $prefs_cache = false; //array();
         }
 
-        $prefs_backend = do_hook_function('prefs_backend');
+        /* see 'redirect' case */
+        require(SM_PATH . 'functions/prefs.php');
+
+        $prefs_backend = do_hook('prefs_backend', $null);
         if (isset($prefs_backend) && !empty($prefs_backend) && file_exists(SM_PATH . $prefs_backend)) {
             require(SM_PATH . $prefs_backend);
         } elseif (isset($prefs_dsn) && !empty($prefs_dsn)) {
             require(SM_PATH . 'functions/db_prefs.php');
         } else {
-            require(SM_PATH . 'functions/prefs.php');
             require(SM_PATH . 'functions/file_prefs.php');
         }
 
@@ -287,7 +471,6 @@ switch ($sInitLocation) {
          */
         require(SM_PATH . 'include/load_prefs.php');
 
-
 // i do not understand the frames language cookie story
         /**
          * We'll need this to later have a noframes version
@@ -306,8 +489,6 @@ switch ($sInitLocation) {
          * Set up the language.
          */
         $err=set_up_language(getPref($data_dir, $username, 'language'));
-        /* this is the last cookie we set so flush it. */
-        sqsetcookieflush();
 
         // Japanese translation used without mbstring support
         if ($err==2) {
@@ -350,30 +531,53 @@ switch ($sInitLocation) {
                 putenv("TZ=".$realTimeZone);
             }
         }
+
+        /**
+         * php 5.1.0 added time zone functions. Set time zone with them in order
+         * to prevent E_STRICT notices and allow time zone modifications in safe_mode.
+         */
+        if (function_exists('date_default_timezone_set')) {
+            if ($timeZone != SMPREF_NONE && $timeZone != "") {
+                date_default_timezone_set($timeZone);
+            } else {
+                // interface runs on server's time zone. Remove php E_STRICT complains
+                $default_timezone = @date_default_timezone_get();
+                date_default_timezone_set($default_timezone);
+            }
+        }
         break;
 }
 
-/**
- * Initialize the template object
- */
-require(SM_PATH . 'class/template/template.class.php');
 /*
- * $sTplDir is not initialized when a user is not logged in, so we will use
- * the config file defaults here.  If the neccesary variables are net set,
- * force a default value.
+ * $sTemplateID is not initialized when a user is not logged in, so we
+ * will use the config file defaults here.  If the neccesary variables
+ * are not set, force a default value.
+ *
+ * If the user is logged in, $sTemplateID will be set in load_prefs.php,
+ * so we shouldn't change it here.
  */
-$aTemplateSet = ( !isset($aTemplateSet) ? array() : $aTemplateSet );
-$templateset_default = ( !isset($templateset_default) ? 0 : $templateset_default );
+if (!isset($sTemplateID)) {
+    $sTemplateID = Template::get_default_template_set();
+    $icon_theme_path = !$use_icons ? NULL : Template::calculate_template_images_directory($sTemplateID);
+}
 
-$sTplDir = ( !isset($aTemplateSet[$templateset_default]['PATH']) ?
-             SM_PATH . 'templates/default/' :
-             $aTemplateSet[$templateset_default]['PATH'] );
-$oTemplate = new Template($sTplDir);
+// template object may have already been constructed in load_prefs.php
+//
+if (empty($oTemplate)) {
+    $oTemplate = Template::construct_template($sTemplateID);
+}
+
+// We want some variables to always be available to the template
+$oTemplate->assign('javascript_on', checkForJavascript());
+$oTemplate->assign('base_uri', sqm_baseuri());
+$always_include = array('sTemplateID', 'icon_theme_path');
+foreach ($always_include as $var) {
+    $oTemplate->assign($var, (isset($$var) ? $$var : NULL));
+}
 
 /**
  * Initialize our custom error handler object
  */
-require(SM_PATH . 'class/error.class.php');
 $oErrorHandler = new ErrorHandler($oTemplate,'error_message.tpl');
 
 /**
@@ -388,17 +592,21 @@ if (version_compare(PHP_VERSION, "4.3.0", ">=")) {
 /**
  * Javascript support detection function
  * @param boolean $reset recheck javascript support if set to true.
- * @return integer SMPREF_JS_ON or SMPREF_JS_OFF ({@see functions/constants.php})
+ * @return integer SMPREF_JS_ON or SMPREF_JS_OFF ({@see include/constants.php})
  * @since 1.5.1
  */
-
 function checkForJavascript($reset = FALSE) {
   global $data_dir, $username, $javascript_on, $javascript_setting;
 
   if ( !$reset && sqGetGlobalVar('javascript_on', $javascript_on, SQ_SESSION) )
     return $javascript_on;
 
-  if ( $reset || !isset($javascript_setting) )
+  if ( ( $reset || !isset($javascript_setting) )
+    // getPref() not defined (nor is it meaningful) when user not
+    // logged in, but that begs the question if $javascript_on is
+    // not in the session in that case, where do we get it from?
+    && ( sqGetGlobalVar('user_is_logged_in', $user_is_logged_in, SQ_SESSION)
+      && $user_is_logged_in) )
     $javascript_setting = getPref($data_dir, $username, 'javascript_setting', SMPREF_JS_AUTODETECT);
 
   if ( !sqGetGlobalVar('new_js_autodetect_results', $js_autodetect_results) &&
@@ -417,4 +625,4 @@ function checkForJavascript($reset = FALSE) {
 function sqm_baseuri() {
     global $base_uri;
     return $base_uri;
-}
\ No newline at end of file
+}