4 * init.php -- initialisation file
6 * File should be loaded in every file in src/ or plugins that occupate an entire frame
8 * @copyright © 2006 The SquirrelMail Project Team
9 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
11 * @package squirrelmail
15 * This is a development version so in order to track programmer mistakes we
16 * set the error reporting to E_ALL
17 FIXME: disabling this for now, because we now have $sm_debug_mode, but the problem with that is that we don't know what it will be until we have loaded the config file, a good 175 lines below after several important files have been included, etc. For now, we'll trust that developers have turned on E_ALL in php.ini anyway, but this can be uncommented if not.
19 //error_reporting(E_ALL);
24 * Make sure we have a page name
27 if ( !defined('PAGE_NAME') ) define('PAGE_NAME', NULL);
31 * If register_globals are on, unregister globals.
32 * Second test covers boolean set as string (php_value register_globals off).
34 if ((bool) ini_get('register_globals') &&
35 strtolower(ini_get('register_globals'))!='off') {
37 * Remove all globals that are not reserved by PHP
38 * 'value' and 'key' are used by foreach. Don't unset them inside foreach.
40 foreach ($GLOBALS as $key => $value) {
42 case 'HTTP_POST_VARS':
46 case 'HTTP_COOKIE_VARS':
48 case 'HTTP_SERVER_VARS':
52 case 'HTTP_POST_FILES':
55 case 'HTTP_SESSION_VARS':
62 unset($GLOBALS[$key]);
65 // Unset variables used in foreach
66 unset($GLOBALS['key']);
67 unset($GLOBALS['value']);
71 * Used as a dummy value, e.g., for passing as an empty
72 * hook argument (where the value is passed by reference,
73 * and therefore NULL itself is not acceptable).
79 * [#1518885] session.use_cookies = off breaks SquirrelMail
81 * When session cookies are not used, all http redirects, meta refreshes,
82 * src/download.php and javascript URLs are broken. Setting must be set
83 * before session is started.
85 if (!(bool)ini_get('session.use_cookies') ||
86 ini_get('session.use_cookies') == 'off') {
87 ini_set('session.use_cookies','1');
92 * calculate SM_PATH and calculate the base_uri
93 * assumptions made: init.php is only called from plugins or from the src dir.
94 * files in the plugin directory may not be part of a subdirectory called "src"
97 if (isset($_SERVER['SCRIPT_NAME'])) {
98 $a = explode('/', $_SERVER['SCRIPT_NAME']);
99 } elseif (isset($HTTP_SERVER_VARS['SCRIPT_NAME'])) {
100 $a = explode('/', $HTTP_SERVER_VARS['SCRIPT_NAME']);
102 $error = 'Unable to detect script environment. Please test your PHP '
103 . 'settings and send your PHP core configuration, $_SERVER and '
104 . '$HTTP_SERVER_VARS contents to the SquirrelMail developers.';
108 for($i = count($a) -2; $i > -1; --$i) {
110 if ($a[$i] === 'src' ||
$a[$i] === 'plugins') {
115 $base_uri = implode('/', array_slice($a, 0, $i)). '/';
117 define('SM_PATH',$sSM_PATH);
118 define('SM_BASE_URI', $base_uri);
122 * global var $bInit is used to check if initialisation took place.
123 * At this moment it's a workarounf for the include of addrbook_search_html
124 * inside compose.php. If we found a better way then remove this. Do only use
125 * this var if you know for sure a page can be called stand alone and be included
131 * This theme as a failsafe if no themes were found, or if we error
132 * out before anything could be initialised.
135 $color[0] = '#DCDCDC'; /* light gray TitleBar */
136 $color[1] = '#800000'; /* red */
137 $color[2] = '#CC0000'; /* light red Warning/Error Messages */
138 $color[3] = '#A0B8C8'; /* green-blue Left Bar Background */
139 $color[4] = '#FFFFFF'; /* white Normal Background */
140 $color[5] = '#FFFFCC'; /* light yellow Table Headers */
141 $color[6] = '#000000'; /* black Text on left bar */
142 $color[7] = '#0000CC'; /* blue Links */
143 $color[8] = '#000000'; /* black Normal text */
144 $color[9] = '#ABABAB'; /* mid-gray Darker version of #0 */
145 $color[10] = '#666666'; /* dark gray Darker version of #9 */
146 $color[11] = '#770000'; /* dark red Special Folders color */
147 $color[12] = '#EDEDED';
148 $color[13] = '#800000'; /* (dark red) Color for quoted text -- > 1 quote */
149 $color[14] = '#ff0000'; /* (red) Color for quoted text -- >> 2 or more */
150 $color[15] = '#002266'; /* (dark blue) Unselectable folders */
151 $color[16] = '#ff9933'; /* (orange) Highlight color */
153 require(SM_PATH
. 'include/constants.php');
154 require(SM_PATH
. 'functions/global.php');
155 require(SM_PATH
. 'functions/strings.php');
156 require(SM_PATH
. 'functions/arrays.php');
158 /* load default configuration */
159 require(SM_PATH
. 'config/config_default.php');
160 /* reset arrays in default configuration */
161 $ldap_server = array();
164 $aTemplateSet = array();
165 $aTemplateSet[0]['ID'] = 'default';
166 $aTemplateSet[0]['NAME'] = 'Default';
168 /* load site configuration */
169 require(SM_PATH
. 'config/config.php');
170 /* load local configuration overrides */
171 if (file_exists(SM_PATH
. 'config/config_local.php')) {
172 require(SM_PATH
. 'config/config_local.php');
177 * Set PHP error reporting level based on the SquirrelMail debug mode
180 if ($sm_debug_mode & SM_DEBUG_MODE_SIMPLE
)
181 $error_level |
= E_ERROR
;
182 if ($sm_debug_mode & SM_DEBUG_MODE_MODERATE
183 ||
$sm_debug_mode & SM_DEBUG_MODE_ADVANCED
)
184 $error_level |
= E_ALL
;
185 if ($sm_debug_mode & SM_DEBUG_MODE_STRICT
)
186 $error_level |
= E_STRICT
;
187 error_reporting($error_level);
190 require(SM_PATH
. 'functions/plugin.php');
191 require(SM_PATH
. 'include/languages.php');
192 require(SM_PATH
. 'class/template/Template.class.php');
193 require(SM_PATH
. 'class/error.class.php');
196 * If magic_quotes_runtime is on, SquirrelMail breaks in new and creative ways.
197 * Force magic_quotes_runtime off.
198 * tassium@squirrelmail.org - I put it here in the hopes that all SM code includes this.
199 * If there's a better place, please let me know.
201 ini_set('magic_quotes_runtime','0');
204 /* if running with magic_quotes_gpc then strip the slashes
205 from POST and GET global arrays */
206 if (function_exists('get_magic_quotes_gpc') && @get_magic_quotes_gpc
()) {
207 sqstripslashes($_GET);
208 sqstripslashes($_POST);
212 /* strip any tags added to the url from PHP_SELF.
213 This fixes hand crafted url XXS expoits for any
214 page that uses PHP_SELF as the FORM action */
215 $_SERVER['PHP_SELF'] = strip_tags($_SERVER['PHP_SELF']);
217 $PHP_SELF = php_self();
220 * Initialize the session
223 /** set the name of the session cookie */
224 if (!isset($session_name) ||
!$session_name) {
225 $session_name = 'SQMSESSID';
229 * When session.auto_start is On we want to destroy/close the session
231 $sSessionAutostartName = session_name();
233 if (isset($sSessionAutostartName) && $sSessionAutostartName !== $session_name) {
234 $sCookiePath = ini_get('session.cookie_path');
235 $sCookieDomain = ini_get('session.cookie_domain');
237 setcookie($sSessionAutostartName,'',time() - 604800,$sCookiePath,$sCookieDomain);
239 session_write_close();
243 * includes from classes stored in the session
245 require(SM_PATH
. 'class/mime.class.php');
247 ini_set('session.name' , $session_name);
248 session_set_cookie_params (0, $base_uri);
249 sqsession_is_active();
252 * When on login page, have to reset the user session, making
253 * sure to save session restore data first
255 if (PAGE_NAME
== 'login') {
256 if (!sqGetGlobalVar('session_expired_post', $sep, SQ_SESSION
))
258 if (!sqGetGlobalVar('session_expired_location', $sel, SQ_SESSION
))
261 session_write_close();
264 * in some rare instances, the session seems to stick
265 * around even after destroying it (!!), so if it does,
266 * we'll manually flatten the $_SESSION data
268 if (!empty($_SESSION))
272 * Allow administrators to define custom session handlers
273 * for SquirrelMail without needing to change anything in
274 * php.ini (application-level).
276 * In config_local.php, admin needs to put:
278 * $custom_session_handlers = array(
280 * 'my_close_handler',
282 * 'my_write_handler',
283 * 'my_destroy_handler',
286 * session_module_name('user');
287 * session_set_save_handler(
288 * $custom_session_handlers[0],
289 * $custom_session_handlers[1],
290 * $custom_session_handlers[2],
291 * $custom_session_handlers[3],
292 * $custom_session_handlers[4],
293 * $custom_session_handlers[5]
296 * We need to replicate that code once here because PHP has
297 * long had a bug that resets the session handler mechanism
298 * when the session data is also destroyed. Because of this
299 * bug, even administrators who define custom session handlers
300 * via a PHP pre-load defined in php.ini (auto_prepend_file)
301 * will still need to define the $custom_session_handlers array
302 * in config_local.php.
304 global $custom_session_handlers;
305 if (!empty($custom_session_handlers)) {
306 $open = $custom_session_handlers[0];
307 $close = $custom_session_handlers[1];
308 $read = $custom_session_handlers[2];
309 $write = $custom_session_handlers[3];
310 $destroy = $custom_session_handlers[4];
311 $gc = $custom_session_handlers[5];
312 session_module_name('user');
313 session_set_save_handler($open, $close, $read, $write, $destroy, $gc);
316 sqsession_is_active();
317 session_regenerate_id();
319 // put session restore data back into session if necessary
321 sqsession_register($sel, 'session_expired_location');
323 sqsession_register($sep, 'session_expired_post');
328 * SquirrelMail internal version number -- DO NOT CHANGE
329 * $sm_internal_version = array (release, major, minor)
331 $SQM_INTERNAL_VERSION = explode('.', SM_VERSION
, 3);
332 $SQM_INTERNAL_VERSION[2] = intval($SQM_INTERNAL_VERSION[2]);
335 /* load prefs system; even when user not logged in, should be OK to do this here */
336 require(SM_PATH
. 'functions/prefs.php');
339 /* if plugins are disabled only for one user and
340 * the current user is NOT that user, turn them
343 sqgetGlobalVar('username',$username,SQ_SESSION
);
344 if ($disable_plugins && !empty($disable_plugins_user)
345 && $username != $disable_plugins_user) {
346 $disable_plugins = false;
350 /* remove all plugins if they are disabled */
351 if ($disable_plugins) {
357 * Include Compatibility plugin if available.
359 if (!$disable_plugins && file_exists(SM_PATH
. 'plugins/compatibility/functions.php'))
360 include_once(SM_PATH
. 'plugins/compatibility/functions.php');
364 * MAIN PLUGIN LOADING CODE HERE
365 * On init, we no longer need to load all plugin setup files.
366 * Now, we load the statically generated hook registrations here
367 * and let the hook calls include only the plugins needed.
369 $squirrelmail_plugin_hooks = array();
370 if (!$disable_plugins && file_exists(SM_PATH
. 'config/plugin_hooks.php')) {
371 //FIXME: if we keep the plugin hooks array static like this, it seems like we should also keep the template files list in a static file too (when a new user session is started or the template set is changed, the code will dynamically iterate through the directory heirarchy of the template directory and catalog all the template files therein (and store the "catalog" in PHP session) -- instead, we could do that once at config-time and keep that static so SM can just include the file just like the line below)
372 require(SM_PATH
. 'config/plugin_hooks.php');
377 * Plugin authors note that the "config_override" hook used to be
378 * executed here, but please adapt your plugin to use this "prefs_backend"
379 * hook instead, making sure that it does NOT return anything, since
380 * doing so will interfere with proper prefs system functionality.
381 * Of course, otherwise, this hook may be used to do any configuration
382 * overrides as needed, as well as set up a custom preferences backend.
384 $prefs_backend = do_hook('prefs_backend', $null);
385 if (isset($prefs_backend) && !empty($prefs_backend) && file_exists(SM_PATH
. $prefs_backend)) {
386 require(SM_PATH
. $prefs_backend);
387 } elseif (isset($prefs_dsn) && !empty($prefs_dsn)) {
388 require(SM_PATH
. 'functions/db_prefs.php');
390 require(SM_PATH
. 'functions/file_prefs.php');
397 * Remove globalized session data in rg=on setups
399 * Code can be utilized when session is started, but data is not loaded.
400 * We have already loaded configuration and other important vars. Can't
401 * clean session globals here, beside, the cleanout of globals at the
402 * top of this file will have removed anything this code would find anyway.
403 if ((bool) @ini_get('register_globals') &&
404 strtolower(ini_get('register_globals'))!='off') {
405 foreach ($_SESSION as $key => $value) {
406 unset($GLOBALS[$key]);
411 sqsession_register(SM_BASE_URI
,'base_uri');
414 * Retrieve the language cookie
416 if (! sqgetGlobalVar('squirrelmail_language',$squirrelmail_language,SQ_COOKIE
)) {
417 $squirrelmail_language = '';
422 * Do something special for some pages. This is based on the PAGE_NAME constant
423 * set at the top of every page.
428 // need to get the right template set up
430 sqGetGlobalVar('templateid', $templateid, SQ_GET
);
432 // sanitize just in case...
434 $templateid = preg_replace('/(\.\.\/){1,}/', '', $templateid);
436 // make sure given template actually is available
438 $found_templateset = false;
439 for ($i = 0; $i < count($aTemplateSet); ++
$i) {
440 if ($aTemplateSet[$i]['ID'] == $templateid) {
441 $found_templateset = true;
446 // FIXME: do we need/want to check here for actual (physical) presence of template sets?
447 // selected template not available, fall back to default template
449 if (!$found_templateset) {
450 $sTemplateID = Template
::get_default_template_set();
452 $sTemplateID = $templateid;
455 session_write_close();
463 require(SM_PATH
. 'functions/auth.php');
467 require(SM_PATH
. 'functions/display_messages.php' );
468 require(SM_PATH
. 'functions/page_header.php');
469 require(SM_PATH
. 'functions/html.php');
471 // reset template file cache
473 $sTemplateID = Template
::get_default_template_set();
474 Template
::cache_template_file_hierarchy(TRUE);
477 * Make sure icon variables are setup for the login page.
479 $icon_theme = $icon_themes[$icon_theme_def]['PATH'];
481 * NOTE: The $icon_theme_path var should contain the path to the icon
482 * theme to use. If the admin has disabled icons, or the user has
483 * set the icon theme to "None," no icons will be used.
485 $icon_theme_path = (!$use_icons ||
$icon_theme=='none') ?
NULL : ($icon_theme == 'template' ? SM_PATH
. Template
::calculate_template_images_directory($sTemplateID) : $icon_theme);
488 * cleanup old cookies with a cookie path the same as the standard php.ini
489 * cookie path. All previous SquirrelMail version used the standard php.ini
490 * cookie path for storing the session name. That behaviour changed.
492 if ($sCookiePath !== SM_BASE_URI
) {
494 * do not delete the standard sessions with session.name is i.e. PHPSESSID
495 * because they probably belong to other php apps
497 if (ini_get('session.name') !== $sSessionAutostartName) {
498 // This does not work. Sometimes the cookie with SQSESSID=deleted and path /
499 // is picked up in webmail.php => login will fail
500 //sqsetcookie(ini_get('session.name'),'',0,$sCookiePath);
505 require(SM_PATH
. 'functions/display_messages.php' );
506 require(SM_PATH
. 'functions/page_header.php');
507 require(SM_PATH
. 'functions/html.php');
511 * Check if we are logged in
513 require(SM_PATH
. 'functions/auth.php');
515 if ( !sqsession_is_registered('user_is_logged_in') ) {
517 // use $message to indicate what logout text the user
518 // will see... if 0, typical "You must be logged in"
519 // if 1, information that the user session was saved
520 // and will be resumed after (re)login
524 // First we store some information in the new session to prevent
527 $session_expired_post = $_POST;
528 $session_expired_location = PAGE_NAME
;
529 if (!sqsession_is_registered('session_expired_post')) {
530 sqsession_register($session_expired_post,'session_expired_post');
532 if (!sqsession_is_registered('session_expired_location')) {
533 sqsession_register($session_expired_location,'session_expired_location');
534 if ($session_expired_location == 'compose')
537 // signout page will deal with users who aren't logged
538 // in on its own; don't show error here
540 if ( PAGE_NAME
== 'signout' ) {
545 * Initialize the template object (logout_error uses it)
548 * $sTemplateID is not initialized when a user is not logged in, so we
549 * will use the config file defaults here. If the neccesary variables
550 * are net set, force a default value.
552 $sTemplateID = Template
::get_default_template_set();
553 $oTemplate = Template
::construct_template($sTemplateID);
555 set_up_language($squirrelmail_language, true);
557 logout_error( _("You must be logged in to access this page.") );
559 logout_error( _("Your session has expired, but will be resumed after logging in again.") );
563 sqgetGlobalVar('authz',$authz,SQ_SESSION
);
566 * Setting the prefs backend
568 sqgetGlobalVar('prefs_cache', $prefs_cache, SQ_SESSION
);
569 sqgetGlobalVar('prefs_are_cached', $prefs_are_cached, SQ_SESSION
);
571 if ( !sqsession_is_registered('prefs_are_cached') ||
572 !isset( $prefs_cache) ||
573 !is_array( $prefs_cache)) {
574 $prefs_are_cached = false;
575 $prefs_cache = false; //array();
579 * initializing user settings
581 require(SM_PATH
. 'include/load_prefs.php');
583 // i do not understand the frames language cookie story
585 * We'll need this to later have a noframes version
587 * Check if the user has a language preference, but no cookie.
588 * Send him a cookie with his language preference, if there is
591 $my_language = getPref($data_dir, $username, 'language');
592 if ($my_language != $squirrelmail_language) {
593 sqsetcookie('squirrelmail_language', $my_language, time()+
2592000, $base_uri);
598 * Set up the language.
600 $err=set_up_language(getPref($data_dir, $username, 'language'));
602 // Japanese translation used without mbstring support
604 $sError = "<p>Your administrator needs to have PHP installed with the multibyte string extension enabled (using configure option --enable-mbstring).</p>\n"
605 . "<p>This system has assumed that you accidently switched to Japanese and has reverted your language preference to English.</p>\n"
606 . "<p>Please refresh this page in order to continue using your webmail.</p>\n";
610 $timeZone = getPref($data_dir, $username, 'timezone');
612 /* Check to see if we are allowed to set the TZ environment variable.
613 * We are able to do this if ...
614 * safe_mode is disabled OR
615 * safe_mode_allowed_env_vars is empty (you are allowed to set any) OR
616 * safe_mode_allowed_env_vars contains TZ
618 $tzChangeAllowed = (!ini_get('safe_mode')) ||
619 !strcmp(ini_get('safe_mode_allowed_env_vars'),'') ||
620 preg_match('/^([\w_]+,)*TZ/', ini_get('safe_mode_allowed_env_vars'));
622 if ( $timeZone != SMPREF_NONE
&& ($timeZone != "")
623 && $tzChangeAllowed ) {
625 // get time zone key, if strict or custom strict timezones are used
626 if (isset($time_zone_type) &&
627 ($time_zone_type == 1 ||
$time_zone_type == 3)) {
628 /* load time zone functions */
629 require(SM_PATH
. 'include/timezones.php');
630 $realTimeZone = sq_get_tz_key($timeZone);
632 $realTimeZone = $timeZone;
637 putenv("TZ=".$realTimeZone);
642 * php 5.1.0 added time zone functions. Set time zone with them in order
643 * to prevent E_STRICT notices and allow time zone modifications in safe_mode.
645 if (function_exists('date_default_timezone_set')) {
646 if ($timeZone != SMPREF_NONE
&& $timeZone != "") {
647 date_default_timezone_set($timeZone);
649 // interface runs on server's time zone. Remove php E_STRICT complains
650 $default_timezone = @date_default_timezone_get
();
651 date_default_timezone_set($default_timezone);
658 * $sTemplateID is not initialized when a user is not logged in, so we
659 * will use the config file defaults here. If the neccesary variables
660 * are not set, force a default value.
662 * If the user is logged in, $sTemplateID will be set in load_prefs.php,
663 * so we shouldn't change it here.
665 if (!isset($sTemplateID)) {
666 $sTemplateID = Template
::get_default_template_set();
667 $icon_theme_path = !$use_icons ?
NULL : Template
::calculate_template_images_directory($sTemplateID);
670 // template object may have already been constructed in load_prefs.php
672 if (empty($oTemplate)) {
673 $oTemplate = Template
::construct_template($sTemplateID);
676 // We want some variables to always be available to the template
678 $oTemplate->assign('javascript_on',
679 (sqGetGlobalVar('user_is_logged_in', $user_is_logged_in, SQ_SESSION
)
680 ?
checkForJavascript() : 0));
681 $oTemplate->assign('base_uri', sqm_baseuri());
682 $always_include = array('sTemplateID', 'icon_theme_path');
683 foreach ($always_include as $var) {
684 $oTemplate->assign($var, (isset($
$var) ? $
$var : NULL));
687 // A few output elements are used often, so just get them once here
689 $nbsp = $oTemplate->fetch('non_breaking_space.tpl');
690 $br = $oTemplate->fetch('line_break.tpl');
693 * Initialize our custom error handler object
695 $oErrorHandler = new ErrorHandler($oTemplate,'error_message.tpl');
698 * Activate custom error handling
700 if (version_compare(PHP_VERSION
, "4.3.0", ">=")) {
701 $oldErrorHandler = set_error_handler(array($oErrorHandler, 'SquirrelMailErrorhandler'));
703 $oldErrorHandler = set_error_handler('SquirrelMailErrorhandler');
707 // ============================================================================
708 // ================= End of Live Code, Beginning of Functions =================
709 // ============================================================================
713 * Javascript support detection function
714 * @param boolean $reset recheck javascript support if set to true.
715 * @return integer SMPREF_JS_ON or SMPREF_JS_OFF ({@see include/constants.php})
718 function checkForJavascript($reset = FALSE) {
719 global $data_dir, $username, $javascript_on, $javascript_setting;
721 if ( !$reset && sqGetGlobalVar('javascript_on', $javascript_on, SQ_SESSION
) )
722 return $javascript_on;
724 $user_is_logged_in = FALSE;
725 if ( $reset ||
!isset($javascript_setting) )
726 $javascript_setting = getPref($data_dir, $username, 'javascript_setting', SMPREF_JS_AUTODETECT
);
728 if ( !sqGetGlobalVar('new_js_autodetect_results', $js_autodetect_results) &&
729 !sqGetGlobalVar('js_autodetect_results', $js_autodetect_results) )
730 $js_autodetect_results = SMPREF_JS_OFF
;
732 if ( $javascript_setting == SMPREF_JS_AUTODETECT
)
733 $javascript_on = $js_autodetect_results;
735 $javascript_on = $javascript_setting;
737 sqsession_register($javascript_on, 'javascript_on');
738 return $javascript_on;
741 function sqm_baseuri() {