6 * This includes code to update < 4.1.0 globals to the newer format
7 * It also has some session register functions that work across various
10 * @copyright 1999-2021 The SquirrelMail Project Team
11 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
13 * @package squirrelmail
17 * These constants are used in the function sqgetGlobalVar(). See
18 * sqgetGlobalVar() for a description of what they mean.
22 define('SQ_INORDER',0);
25 define('SQ_SESSION',3);
26 define('SQ_COOKIE',4);
27 define('SQ_SERVER',5);
32 * returns true if current php version is at mimimum a.b.c
34 * Called: check_php_version(4,1)
35 * @param int a major version number
36 * @param int b minor version number
37 * @param int c release number
40 function check_php_version ($a = '0', $b = '0', $c = '0')
42 return version_compare ( PHP_VERSION
, "$a.$b.$c", 'ge' );
46 * returns true if the current internal SM version is at minimum a.b.c
47 * These are plain integer comparisons, as our internal version is
48 * constructed by us, as an array of 3 ints.
50 * Called: check_sm_version(1,3,3)
51 * @param int a major version number
52 * @param int b minor version number
53 * @param int c release number
56 function check_sm_version($a = 0, $b = 0, $c = 0)
58 global $SQM_INTERNAL_VERSION;
59 if ( !isset($SQM_INTERNAL_VERSION) ||
60 $SQM_INTERNAL_VERSION[0] < $a ||
61 ( $SQM_INTERNAL_VERSION[0] == $a &&
62 $SQM_INTERNAL_VERSION[1] < $b) ||
63 ( $SQM_INTERNAL_VERSION[0] == $a &&
64 $SQM_INTERNAL_VERSION[1] == $b &&
65 $SQM_INTERNAL_VERSION[2] < $c ) ) {
73 * Recursively strip slashes from the values of an array.
74 * @param array array the array to strip, passed by reference
77 function sqstripslashes(&$array) {
78 if(count($array) > 0) {
79 foreach ($array as $index=>$value) {
80 if (is_array($array[$index])) {
81 sqstripslashes($array[$index]);
84 $array[$index] = stripslashes($value);
91 * Squelch error output to screen (only) for the given function.
92 * If the SquirrelMail debug mode SM_DEBUG_MODE_ADVANCED is not
93 * enabled, error output will not go to the log, either.
95 * This provides an alternative to the @ error-suppression
96 * operator where errors will not be shown in the interface
97 * but will show up in the server log file (assuming the
98 * administrator has configured PHP logging).
100 * @since 1.4.12 and 1.5.2
102 * @param string $function The function to be executed
103 * @param array $args The arguments to be passed to the function
104 * (OPTIONAL; default no arguments)
105 * NOTE: The caller must take extra action if
106 * the function being called is supposed
107 * to use any of the parameters by
108 * reference. In the following example,
109 * $x is passed by reference and $y is
110 * passed by value to the "my_func"
112 * sq_call_function_suppress_errors('my_func', array(&$x, $y));
114 * @return mixed The return value, if any, of the function being
115 * executed will be returned.
118 function sq_call_function_suppress_errors($function, $args=array()) {
119 global $sm_debug_mode;
121 $display_errors = ini_get('display_errors');
122 ini_set('display_errors', '0');
124 // if advanced debug mode isn't enabled, don't log the error, either
126 if (!($sm_debug_mode & SM_DEBUG_MODE_ADVANCED
))
127 $error_reporting = error_reporting(0);
129 $ret = call_user_func_array($function, $args);
131 if (!($sm_debug_mode & SM_DEBUG_MODE_ADVANCED
))
132 error_reporting($error_reporting);
134 ini_set('display_errors', $display_errors);
139 * Add a variable to the session.
140 * @param mixed $var the variable to register
141 * @param string $name the name to refer to this variable
144 function sqsession_register ($var, $name) {
146 sqsession_is_active();
148 $_SESSION[$name] = $var;
152 * Delete a variable from the session.
153 * @param string $name the name of the var to delete
156 function sqsession_unregister ($name) {
158 sqsession_is_active();
160 unset($_SESSION[$name]);
162 // starts throwing warnings in PHP 5.3.0 and is
163 // removed in PHP 6 and is redundant anyway
164 //session_unregister("$name");
168 * Checks to see if a variable has already been registered
170 * @param string $name the name of the var to check
171 * @return bool whether the var has been registered
173 function sqsession_is_registered ($name) {
177 if (isset($_SESSION[$test_name])) {
186 * Retrieves a form variable, from a set of possible similarly named
187 * form variables, based on finding a different, single field. This
188 * is intended to allow more than one same-named inputs in a single
189 * <form>, where the submit button that is clicked tells us which
190 * input we should retrieve. An example is if we have:
191 * <select name="startMessage_1">
192 * <select name="startMessage_2">
193 * <input type="submit" name="form_submit_1" />
194 * <input type="submit" name="form_submit_2" />
195 * and we want to know which one of the select inputs should be
196 * returned as $startMessage (without the suffix!), this function
197 * decides by looking for either "form_submit_1" or "form_submit_2"
198 * (both should not appear). In this example, $name should be
199 * "startMessage" and $indicator_field should be "form_submit".
201 * NOTE that form widgets must be named with the suffix "_1", "_2", "_3"
202 * and so on, or this function will not work.
204 * If more than one of the indicator fields is found, the first one
205 * (numerically) will win.
207 * If an indicator field is found without a matching input ($name)
208 * field, FALSE is returned.
210 * If no indicator fields are found, a field of $name *without* any
211 * suffix is searched for (but only if $fallback_no_suffix is TRUE),
212 * and if not found, FALSE is ultimately returned.
214 * It should also be possible to use the same string for both
215 * $name and $indicator_field to look for the first possible
216 * widget with a suffix that can be found (and possibly fallback
217 * to a widget without a suffix).
219 * @param string name the name of the var to search
220 * @param mixed value the variable to return
221 * @param string indicator_field the name of the field upon which to base
222 * our decision upon (see above)
223 * @param int search constant defining where to look
224 * @param bool fallback_no_suffix whether or not to look for $name with
225 * no suffix when nothing else is found
226 * @param mixed default the value to assign to $value when nothing is found
227 * @param int typecast force variable to be cast to given type (please
228 * use SQ_TYPE_XXX constants or set to FALSE (default)
229 * to leave variable type unmolested)
231 * @return bool whether variable is found.
233 function sqGetGlobalVarMultiple($name, &$value, $indicator_field,
234 $search = SQ_INORDER
,
235 $fallback_no_suffix=TRUE, $default=NULL,
238 // Set arbitrary max limit -- should be much lower except on the
239 // search results page, if there are many (50 or more?) mailboxes
240 // shown, this may not be high enough. Is there some way we should
241 // automate this value?
243 $max_form_search = 100;
245 for ($i = 1; $i <= $max_form_search; $i++
) {
246 if (sqGetGlobalVar($indicator_field . '_' . $i, $temp, $search)) {
247 return sqGetGlobalVar($name . '_' . $i, $value, $search, $default, $typecast);
252 // no indicator field found; just try without suffix if allowed
254 if ($fallback_no_suffix) {
255 return sqGetGlobalVar($name, $value, $search, $default, $typecast);
259 // no dice, set default and return FALSE
261 if (!is_null($default)) {
270 * Search for the variable $name in one or more of the global variables
271 * $_SESSION, $_POST, $_GET, $_COOKIE, and $_SERVER, and set the value of it in
272 * the variable $vaule.
274 * $search must be one of the defined constants below. The default is
275 * SQ_INORDER. Both SQ_INORDER and SQ_FORM stops on the first match.
277 * SQ_INORDER searches $_SESSION, then $_POST, and then $_GET.
278 * SQ_FORM searches $_POST and then $_GET.
279 * SQ_COOKIE searches $_COOKIE only.
280 * SQ_GET searches $_GET only.
281 * SQ_POST searches $_POST only.
282 * SQ_SERVER searches $_SERVER only.
283 * SQ_SESSION searches $_SESSION only.
286 * sqgetGlobalVar('username', $username, SQ_SESSION);
287 * // No quotes around the last parameter, it's a constant - not a string!
289 * @param string name the name of the var to search
290 * @param mixed value the variable to return
291 * @param int search constant defining where to look
292 * @param mixed default the value to assign to $value when nothing is found
293 * @param int typecast force variable to be cast to given type (please
294 * use SQ_TYPE_XXX constants or set to FALSE (default)
295 * to leave variable type unmolested)
297 * @return bool whether variable is found.
299 function sqgetGlobalVar($name, &$value, $search = SQ_INORDER
, $default = NULL, $typecast = FALSE) {
300 // The return value defaults to FALSE, i.e. the variable wasn't found.
303 // Search the global variables to find a match.
306 // The default needs to be first here so SQ_INORDER will be used if
307 // $search isn't a valid constant.
309 // Search $_SESSION, then $_POST, and then $_GET. Stop on the first
312 if (isset($_SESSION[$name])) {
313 // If a match is found, set the specified variable to the found
314 // value, indicate a match, and stop the search.
315 $value = $_SESSION[$name];
318 } elseif ($search == SQ_SESSION
) {
319 // Only stop the search if SQ_SESSION is set. SQ_INORDER will
320 // continue with the next clause.
324 // Search $_POST and then $_GET. Stop on the first match.
326 if (isset($_POST[$name])) {
327 // If a match is found, set the specified variable to the found
328 // value, indicate a match, and stop the search.
329 $value = $_POST[$name];
332 } elseif ($search == SQ_POST
) {
333 // Only stop the search if SQ_POST is set. SQ_INORDER and
334 // SQ_FORM will continue with the next clause.
338 if (isset($_GET[$name])) {
339 // If a match is found, set the specified variable to the found
340 // value, indicate a match, and stop the search.
341 $value = $_GET[$name];
345 // Stop the search regardless of if SQ_INORDER, SQ_FORM, or SQ_GET
346 // is set. All three of them ends here.
349 if (isset($_COOKIE[$name])) {
350 // If a match is found, set the specified variable to the found
351 // value, indicate a match, and stop the search.
352 $value = $_COOKIE[$name];
359 if (isset($_SERVER[$name])) {
360 // If a match is found, set the specified variable to the found
361 // value, indicate a match, and stop the search.
362 $value = $_SERVER[$name];
370 if ($result && $typecast) {
371 // Only typecast if it's requested and a match is found. The default is
372 // not to typecast, which will happen if a valid constant isn't
376 // Typecast the value and stop.
377 $value = (int) $value;
380 // Typecast the value and stop.
381 $value = (string) $value;
384 // Typecast the value and stop.
385 $value = (bool) $value;
388 // Typecast the value and stop.
389 $value = (preg_match('/^[0-9]+$/', $value) ?
$value : '0');
392 // The default is to do nothing.
395 } else if (!$result && !is_null($default)) {
396 // If no match is found and a default value is specified, set it.
400 // Return if a match was found or not.
405 * Get an immutable copy of a configuration variable if SquirrelMail
406 * is in "secured configuration" mode. This guarantees the caller
407 * gets a copy of the requested value as it is set in the main
408 * application configuration (including config_local overrides), and
409 * not what it might be after possibly having been modified by some
410 * other code (usually a plugin overriding configuration values for
411 * one reason or another).
413 * WARNING: Please use this function as little as possible, because
414 * every time it is called, it forcibly reloads the main configuration
417 * Caller beware that this function will do nothing if SquirrelMail
418 * is not in "secured configuration" mode per the $secured_config
421 * @param string $var_name The name of the desired variable
423 * @return mixed The desired value
428 function get_secured_config_value($var_name) {
430 static $return_values = array();
432 // if we can avoid it, return values that have
433 // already been retrieved (so we don't have to
434 // include the config file yet again)
436 if (isset($return_values[$var_name])) {
437 return $return_values[$var_name];
441 // load site configuration
443 require(SM_PATH
. 'config/config.php');
445 // load local configuration overrides
447 if (file_exists(SM_PATH
. 'config/config_local.php')) {
448 require(SM_PATH
. 'config/config_local.php');
451 // if SM isn't in "secured configuration" mode,
452 // just return the desired value from the global scope
454 if (!$secured_config) {
456 $return_values[$var_name] = $
$var_name;
460 // else we return what we got from the config file
462 $return_values[$var_name] = $
$var_name;
468 * Deletes an existing session, more advanced than the standard PHP
469 * session_destroy(), it explicitly deletes the cookies and global vars.
471 * WARNING: Older PHP versions have some issues with session management.
472 * See http://bugs.php.net/11643 (warning, spammed bug tracker) and
473 * http://bugs.php.net/13834. SID constant is not destroyed in PHP 4.1.2,
474 * 4.2.3 and maybe other versions. If you restart session after session
475 * is destroyed, affected PHP versions produce PHP notice. Bug should
476 * be fixed only in 4.3.0
478 function sqsession_destroy() {
481 * php.net says we can kill the cookie by setting just the name:
482 * http://www.php.net/manual/en/function.setcookie.php
483 * maybe this will help fix the session merging again.
485 * Changed the theory on this to kill the cookies first starting
486 * a new session will provide a new session for all instances of
487 * the browser, we don't want that, as that is what is causing the
488 * merging of sessions.
491 global $base_uri, $_COOKIE, $_SESSION;
493 if (isset($_COOKIE[session_name()]) && session_name()) {
494 sqsetcookie(session_name(), $_COOKIE[session_name()], 1, $base_uri);
497 * Make sure to kill /src and /src/ cookies, just in case there are
498 * some left-over or malicious ones set in user's browser.
499 * NB: Note that an attacker could try to plant a cookie for one
500 * of the /plugins/* directories. Such cookies can block
501 * access to certain plugin pages, but they do not influence
502 * or fixate the $base_uri cookie, so we don't worry about
503 * trying to delete all of them here.
505 sqsetcookie(session_name(), $_COOKIE[session_name()], 1, $base_uri . 'src');
506 sqsetcookie(session_name(), $_COOKIE[session_name()], 1, $base_uri . 'src/');
509 if (isset($_COOKIE['key']) && $_COOKIE['key']) sqsetcookie('key','SQMTRASH',1,$base_uri);
511 /* Make sure new session id is generated on subsequent session_start() */
512 unset($_COOKIE[session_name()]);
513 unset($_GET[session_name()]);
514 unset($_POST[session_name()]);
516 $sessid = session_id();
517 if (!empty( $sessid )) {
524 * Function to verify a session has been started. If it hasn't
525 * start a session up. php.net doesn't tell you that $_SESSION
526 * (even though autoglobal), is not created unless a session is
527 * started, unlike $_POST, $_GET and such
528 * Update: (see #1685031) the session ID is left over after the
529 * session is closed in some PHP setups; this function just becomes
530 * a passthru to sqsession_start(), but leaving old code in for
533 function sqsession_is_active() {
534 //$sessid = session_id();
535 //if ( empty( $sessid ) ) {
541 * Function to start the session and store the cookie with the session_id as
542 * HttpOnly cookie which means that the cookie isn't accessible by javascript
544 * Note that as sqsession_is_active() no longer discriminates as to when
545 * it calls this function, session_start() has to have E_NOTICE suppression
548 function sqsession_start() {
551 sq_call_function_suppress_errors('session_start');
552 // was: @session_start();
553 $session_id = session_id();
555 // session_starts sets the sessionid cookie but without the httponly var
556 // setting the cookie again sets the httponly cookie attribute
558 // need to check if headers have been sent, since sqsession_is_active()
559 // has become just a passthru to this function, so the sqsetcookie()
560 // below is called every time, even after headers have already been sent
563 sqsetcookie(session_name(),$session_id,false,$base_uri);
571 * @param string $sName The name of the cookie.
572 * @param string $sValue The value of the cookie.
573 * @param int $iExpire The time the cookie expires. This is a Unix
574 * timestamp so is in number of seconds since
576 * @param string $sPath The path on the server in which the cookie
577 * will be available on.
578 * @param string $sDomain The domain that the cookie is available.
579 * @param boolean $bSecure Indicates that the cookie should only be
580 * transmitted over a secure HTTPS connection.
581 * @param boolean $bHttpOnly Disallow JS to access the cookie (IE6 only)
582 * @param boolean $bReplace Replace previous cookies with same name?
583 * @param string $sSameSite Optional override of the default SameSite
584 * cookie policy detemined from the global
585 * configuration item $same_site_cookies
586 * (which can be set in config/config_local.php)
587 * (should be NULL to accept the configured global
588 * default or one of "Lax" "Strict" or "None"
589 * but "None" will not work if $bSecure is FALSE.
590 * Can also be set set to an empty string in order
591 * to NOT specify the SameSite cookie attribute at
592 * all and accept whatever the browser default is)
596 * @since 1.4.16 and 1.5.1
599 function sqsetcookie($sName, $sValue='deleted', $iExpire=0, $sPath="", $sDomain="",
600 $bSecure=false, $bHttpOnly=true, $bReplace=false, $sSameSite=NULL) {
602 // some environments can get overwhelmed by an excessive
603 // setting of the same cookie over and over (e.g., many
604 // calls to this function via sqsession_is_active() result
605 // in repeated setting of the session cookie when $bReplace
606 // is FALSE, but something odd happens (during login only)
607 // if we change that to default TRUE) ... so we keep our own
608 // naive per-request name/value cache and only set the cookie
609 // if its value is changing (or never seen before)
610 static $cookies = array();
611 if (isset($cookies[$sName]) && $cookies[$sName] === $sValue)
614 $cookies[$sName] = $sValue;
617 // if we have a secure connection then limit the cookies to https only.
618 global $is_secure_connection;
619 if ($sName && $is_secure_connection)
622 // admin config can override the restriction of secure-only cookies
623 global $only_secure_cookies;
624 if (!$only_secure_cookies)
627 // use global SameSite setting, but allow override
628 // The global $same_site_cookies (for which an override value
629 // can be specified in config/config_local.php) defaults to
630 // "Strict" when it is NULL (when not given in the config file),
631 // or can be manually set to "Lax" "Strict" or "None" if desired
632 // or can be set to an empty string in order to not specify
633 // SameSite at all and use the browser default
634 if (is_null($sSameSite)) {
635 global $same_site_cookies;
636 if (is_null($same_site_cookies))
637 $sSameSite = 'Strict';
639 $sSameSite = $same_site_cookies;
642 if (false && check_php_version(5,2)) {
643 // php 5 supports the httponly attribute in setcookie, but because setcookie seems a bit
644 // broken we use the header function for php 5.2 as well. We might change that later.
645 //setcookie($sName,$sValue,(int) $iExpire,$sPath,$sDomain,$bSecure,$bHttpOnly);
647 if (!empty($sDomain)) {
648 // Fix the domain to accept domains with and without 'www.'.
649 if (strtolower(substr($sDomain, 0, 4)) == 'www.') $sDomain = substr($sDomain, 4);
650 $sDomain = '.' . $sDomain;
652 // Remove port information.
653 $Port = strpos($sDomain, ':');
654 if ($Port !== false) $sDomain = substr($sDomain, 0, $Port);
656 if (!$sValue) $sValue = 'deleted';
657 header('Set-Cookie: ' . rawurlencode($sName) . '=' . rawurlencode($sValue)
658 . (empty($iExpire) ?
'' : '; expires=' . gmdate('D, d-M-Y H:i:s', $iExpire) . ' GMT')
659 . (empty($sPath) ?
'' : '; path=' . $sPath)
660 . (empty($sDomain) ?
'' : '; domain=' . $sDomain)
661 . (!$bSecure ?
'' : '; secure')
662 . (!$bHttpOnly ?
'' : '; HttpOnly')
663 . (empty($sSameSite) ?
'' : '; SameSite=' . $sSameSite), $bReplace);
669 * session_regenerate_id replacement for PHP < 4.3.2
671 * This code is borrowed from Gallery, session.php version 1.53.2.1
672 FIXME: I saw this code on php.net (in the manual); that's where it comes from originally, but I don't think we need it - it's just redundant to all the hard work we already did seeding the random number generator IMO. I think we can just call to GenerateRandomString() and dump the rest.
674 if (!function_exists('session_regenerate_id')) {
676 function php_combined_lcg() {
677 $tv = gettimeofday();
678 $lcg['s1'] = $tv['sec'] ^
(~
$tv['usec']);
679 $lcg['s2'] = mt_rand();
680 $q = (int) ($lcg['s1'] / 53668);
681 $lcg['s1'] = (int) (40014 * ($lcg['s1'] - 53668 * $q) - 12211 * $q);
682 if ($lcg['s1'] < 0) {
683 $lcg['s1'] +
= 2147483563;
685 $q = (int) ($lcg['s2'] / 52774);
686 $lcg['s2'] = (int) (40692 * ($lcg['s2'] - 52774 * $q) - 3791 * $q);
687 if ($lcg['s2'] < 0) {
688 $lcg['s2'] +
= 2147483399;
690 $z = (int) ($lcg['s1'] - $lcg['s2']);
694 return $z * 4.656613e-10;
697 function session_regenerate_id() {
699 $tv = gettimeofday();
700 sqgetGlobalVar('REMOTE_ADDR',$remote_addr,SQ_SERVER
);
701 $buf = sprintf("%.15s%ld%ld%0.8f", $remote_addr, $tv['sec'], $tv['usec'], php_combined_lcg() * 10);
702 session_id(md5($buf));
703 if (ini_get('session.use_cookies')) {
704 sqsetcookie(session_name(), session_id(), 0, $base_uri);
714 * Attempts to determine the path and filename and any arguments
715 * for the currently executing script. This is usually found in
716 * $_SERVER['REQUEST_URI'], but some environments may differ, so
717 * this function tries to standardize this value.
719 * Note that before SquirrelMail version 1.5.1, this function was
720 * stored in function/strings.php.
723 * @return string The path, filename and any arguments for the
726 function php_self($with_query_string=TRUE) {
728 static $request_uri = '';
729 if (!empty($request_uri))
730 return ($with_query_string ?
$request_uri : (strpos($request_uri, '?') !== FALSE ?
substr($request_uri, 0, strpos($request_uri, '?')) : $request_uri));
732 // first try $_SERVER['PHP_SELF'], which seems most reliable
733 // (albeit it usually won't include the query string)
736 if (!sqgetGlobalVar('PHP_SELF', $request_uri, SQ_SERVER
)
737 ||
empty($request_uri)) {
739 // well, then let's try $_SERVER['REQUEST_URI']
742 if (!sqgetGlobalVar('REQUEST_URI', $request_uri, SQ_SERVER
)
743 ||
empty($request_uri)) {
745 // TODO: anyone have any other ideas? maybe $_SERVER['SCRIPT_NAME']???
752 // we may or may not have any query arguments, depending on
753 // which environment variable was used above, and the PHP
754 // version, etc., so let's check for it now
757 if (strpos($request_uri, '?') === FALSE
758 && sqgetGlobalVar('QUERY_STRING', $query_string, SQ_SERVER
)
759 && !empty($query_string)) {
761 $request_uri .= '?' . $query_string;
764 global $php_self_pattern, $php_self_replacement;
765 if (!empty($php_self_pattern))
766 $request_uri = preg_replace($php_self_pattern, $php_self_replacement, $request_uri);
767 return ($with_query_string ?
$request_uri : (strpos($request_uri, '?') !== FALSE ?
substr($request_uri, 0, strpos($request_uri, '?')) : $request_uri));
775 * sm_print_r($some_variable, [$some_other_variable [, ...]]);
777 * Debugging function - does the same as print_r, but makes sure special
778 * characters are converted to htmlentities first. This will allow
779 * values like <some@email.address> to be displayed.
780 * The output is wrapped in <<pre>> and <</pre>> tags.
781 * Since 1.4.2 accepts unlimited number of arguments.
785 function sm_print_r() {
786 ob_start(); // Buffer output
787 foreach(func_get_args() as $var) {
790 // php has get_class_methods function that can print class methods
791 if (is_object($var)) {
792 // get class methods if $var is object
793 $aMethods=get_class_methods(get_class($var));
794 // make sure that $aMethods is array and array is not empty
795 if (is_array($aMethods) && $aMethods!=array()) {
796 echo "Object methods:\n";
797 foreach($aMethods as $method) {
798 echo '* ' . $method . "\n";
804 $buffer = ob_get_contents(); // Grab the print_r output
805 ob_end_clean(); // Silently discard the output & stop buffering
806 print '<div align="left"><pre>';
807 print htmlentities($buffer);
808 print '</pre></div>';
813 * Sanitize a value using sm_encode_html_special_chars() or similar, but also
814 * recursively run sm_encode_html_special_chars() (or similar) on array keys
817 * If $value is not a string or an array with strings in it,
818 * the value is returned as is.
820 * @param mixed $value The value to be sanitized.
821 * @param mixed $quote_style Either boolean or an integer. If it
822 * is an integer, it must be the PHP
823 * constant indicating if/how to escape
824 * quotes: ENT_QUOTES, ENT_COMPAT, or
825 * ENT_NOQUOTES. If it is a boolean value,
826 * it must be TRUE and thus indicates
827 * that the only sanitizing to be done
828 * herein is to replace single and double
829 * quotes with ' and ", no other
830 * changes are made to $value. If it is
831 * boolean and FALSE, behavior reverts
832 * to same as if the value was ENT_QUOTES
833 * (OPTIONAL; default is ENT_QUOTES).
835 * @return mixed The sanitized value.
840 function sq_htmlspecialchars($value, $quote_style=ENT_QUOTES
) {
842 if ($quote_style === FALSE) $quote_style = ENT_QUOTES
;
844 // array? go recursive...
846 if (is_array($value)) {
847 $return_array = array();
848 foreach ($value as $key => $val) {
849 $return_array[sq_htmlspecialchars($key, $quote_style)]
850 = sq_htmlspecialchars($val, $quote_style);
852 return $return_array;
854 // sanitize strings only
856 } else if (is_string($value)) {
857 if ($quote_style === TRUE)
858 return str_replace(array('\'', '"'), array(''', '"'), $value);
860 return sm_encode_html_special_chars($value, $quote_style);
863 // anything else gets returned with no changes
871 * Detect whether or not we have a SSL secured (HTTPS) connection
872 * connection to the browser
874 * It is thought to be so if you have 'SSLOptions +StdEnvVars'
875 * in your Apache configuration,
876 * OR if you have HTTPS set to a non-empty value (except "off")
877 * in your HTTP_SERVER_VARS,
878 * OR if you have HTTP_X_FORWARDED_PROTO=https in your HTTP_SERVER_VARS,
879 * OR if you are on port 443.
881 * Note: HTTP_X_FORWARDED_PROTO could be sent from the client and
882 * therefore possibly spoofed/hackable. Thus, SquirrelMail
883 * ignores such headers by default. The administrator
884 * can tell SM to use such header values by setting
885 * $sq_ignore_http_x_forwarded_headers to boolean FALSE
886 * in config/config.php or by using config/conf.pl.
888 * Note: It is possible to run SSL on a port other than 443, and
889 * if that is the case, the administrator should set
890 * $sq_https_port in config/config.php or by using config/conf.pl.
892 * @return boolean TRUE if the current connection is SSL-encrypted;
895 * @since 1.4.17 and 1.5.2
898 function is_ssl_secured_connection()
900 global $sq_ignore_http_x_forwarded_headers, $sq_https_port;
901 $https_env_var = getenv('HTTPS');
902 if ($sq_ignore_http_x_forwarded_headers
903 ||
!sqgetGlobalVar('HTTP_X_FORWARDED_PROTO', $forwarded_proto, SQ_SERVER
))
904 $forwarded_proto = '';
905 if (empty($sq_https_port)) // won't work with port 0 (zero)
906 $sq_https_port = 443;
907 if ((isset($https_env_var) && strcasecmp($https_env_var, 'on') === 0)
908 ||
(sqgetGlobalVar('HTTPS', $https, SQ_SERVER
) && !empty($https)
909 && strcasecmp($https, 'off') !== 0)
910 ||
(strcasecmp($forwarded_proto, 'https') === 0)
911 ||
(sqgetGlobalVar('SERVER_PORT', $server_port, SQ_SERVER
)
912 && $server_port == $sq_https_port))
919 * Endeavor to detect what user and group PHP is currently
920 * running as. Probably only works in non-Windows environments.
922 * @return mixed Boolean FALSE is returned if something went wrong,
923 * otherwise an array is returned with the following
925 * uid The current process' UID (integer)
926 * euid The current process' effective UID (integer)
927 * gid The current process' GID (integer)
928 * egid The current process' effective GID (integer)
929 * name The current process' name/handle (string)
930 * ename The current process' effective name/handle (string)
931 * group The current process' group name (string)
932 * egroup The current process' effective group name (string)
933 * Note that some of these elements may have empty
934 * values, especially if they could not be determined.
939 function get_process_owner_info()
941 if (!function_exists('posix_getuid'))
944 $process_info['uid'] = posix_getuid();
945 $process_info['euid'] = posix_geteuid();
946 $process_info['gid'] = posix_getgid();
947 $process_info['egid'] = posix_getegid();
949 $user_info = posix_getpwuid($process_info['uid']);
950 $euser_info = posix_getpwuid($process_info['euid']);
951 $group_info = posix_getgrgid($process_info['gid']);
952 $egroup_info = posix_getgrgid($process_info['egid']);
954 $process_info['name'] = $user_info['name'];
955 $process_info['ename'] = $euser_info['name'];
956 $process_info['group'] = $user_info['name'];
957 $process_info['egroup'] = $euser_info['name'];
959 return $process_info;