Source for file global.php

Documentation is available at global.php

  1. <?php
  2.  
  3. /**
  4.  * global.php
  5.  *
  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
  8.  * php versions.
  9.  *
  10.  * @copyright 1999-2020 The SquirrelMail Project Team
  11.  * @license http://opensource.org/licenses/gpl-license.php GNU Public License
  12.  * @version $Id: global.php 14845 2020-01-07 08:09:34Z pdontthink $
  13.  * @package squirrelmail
  14.  */
  15.  
  16. /**
  17.  * These constants are used in the function sqgetGlobalVar(). See
  18.  * sqgetGlobalVar() for a description of what they mean.
  19.  *
  20.  * @since 1.4.0
  21.  */
  22. define('SQ_INORDER',0);
  23. define('SQ_GET',1);
  24. define('SQ_POST',2);
  25. define('SQ_SESSION',3);
  26. define('SQ_COOKIE',4);
  27. define('SQ_SERVER',5);
  28. define('SQ_FORM',6);
  29.  
  30.  
  31. /**
  32.  * returns true if current php version is at mimimum a.b.c
  33.  *
  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
  38.  * @return bool 
  39.  */
  40. function check_php_version ($a '0'$b '0'$c '0')
  41. {
  42.     return version_compare PHP_VERSION"$a.$b.$c"'ge' );
  43. }
  44.  
  45. /**
  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.
  49.  *
  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
  54.  * @return bool 
  55.  */
  56. function check_sm_version($a 0$b 0$c 0)
  57. {
  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 ) ) {
  66.         return FALSE;
  67.     }
  68.     return TRUE;
  69. }
  70.  
  71.  
  72. /**
  73.  * Recursively strip slashes from the values of an array.
  74.  * @param array array the array to strip, passed by reference
  75.  * @return void 
  76.  */
  77. function sqstripslashes(&$array{
  78.     if(count($array0{
  79.         foreach ($array as $index=>$value{
  80.             if (is_array($array[$index])) {
  81.                 sqstripslashes($array[$index]);
  82.             }
  83.             else {
  84.                 $array[$indexstripslashes($value);
  85.             }
  86.         }
  87.     }
  88. }
  89.  
  90. /**
  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.
  94.  *
  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).
  99.  *
  100.  * @since 1.4.12 and 1.5.2
  101.  *
  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"
  111.  *                                function.
  112.  *  sq_call_function_suppress_errors('my_func', array(&$x, $y));
  113.  *
  114.  * @return mixed The return value, if any, of the function being
  115.  *                executed will be returned.
  116.  *
  117.  */
  118. function sq_call_function_suppress_errors($function$args=array()) {
  119.    global $sm_debug_mode;
  120.  
  121.    $display_errors ini_get('display_errors');
  122.    ini_set('display_errors''0');
  123.  
  124.    // if advanced debug mode isn't enabled, don't log the error, either
  125.    //
  126.    if (!($sm_debug_mode SM_DEBUG_MODE_ADVANCED))
  127.       $error_reporting error_reporting(0);
  128.  
  129.    $ret call_user_func_array($function$args);
  130.  
  131.    if (!($sm_debug_mode SM_DEBUG_MODE_ADVANCED))
  132.       error_reporting($error_reporting);
  133.  
  134.    ini_set('display_errors'$display_errors);
  135.    return $ret;
  136. }
  137.  
  138. /**
  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
  142.  * @return void 
  143.  */
  144. function sqsession_register ($var$name{
  145.  
  146.  
  147.     $_SESSION[$name$var;
  148. }
  149.  
  150. /**
  151.  * Delete a variable from the session.
  152.  * @param string $name the name of the var to delete
  153.  * @return void 
  154.  */
  155. function sqsession_unregister ($name{
  156.  
  157.  
  158.     unset($_SESSION[$name]);
  159.  
  160.     // starts throwing warnings in PHP 5.3.0 and is
  161.     // removed in PHP 6 and is redundant anyway
  162.     //session_unregister("$name");
  163. }
  164.  
  165. /**
  166.  * Checks to see if a variable has already been registered
  167.  * in the session.
  168.  * @param string $name the name of the var to check
  169.  * @return bool whether the var has been registered
  170.  */
  171. function sqsession_is_registered ($name{
  172.     $test_name &$name;
  173.     $result false;
  174.  
  175.     if (isset($_SESSION[$test_name])) {
  176.         $result true;
  177.     }
  178.  
  179.     return $result;
  180. }
  181.  
  182.  
  183. /**
  184.   * Retrieves a form variable, from a set of possible similarly named
  185.   * form variables, based on finding a different, single field.  This
  186.   * is intended to allow more than one same-named inputs in a single
  187.   * <form>, where the submit button that is clicked tells us which
  188.   * input we should retrieve.  An example is if we have:
  189.   *     <select name="startMessage_1">
  190.   *     <select name="startMessage_2">
  191.   *     <input type="submit" name="form_submit_1" />
  192.   *     <input type="submit" name="form_submit_2" />
  193.   * and we want to know which one of the select inputs should be
  194.   * returned as $startMessage (without the suffix!), this function
  195.   * decides by looking for either "form_submit_1" or "form_submit_2"
  196.   * (both should not appear).  In this example, $name should be
  197.   * "startMessage" and $indicator_field should be "form_submit".
  198.   *
  199.   * NOTE that form widgets must be named with the suffix "_1", "_2", "_3"
  200.   *      and so on, or this function will not work.
  201.   *
  202.   * If more than one of the indicator fields is found, the first one
  203.   * (numerically) will win.
  204.   *
  205.   * If an indicator field is found without a matching input ($name)
  206.   * field, FALSE is returned.
  207.   *
  208.   * If no indicator fields are found, a field of $name *without* any
  209.   * suffix is searched for (but only if $fallback_no_suffix is TRUE),
  210.   * and if not found, FALSE is ultimately returned.
  211.   *
  212.   * It should also be possible to use the same string for both
  213.   * $name and $indicator_field to look for the first possible
  214.   * widget with a suffix that can be found (and possibly fallback
  215.   * to a widget without a suffix).
  216.   *
  217.   * @param string name the name of the var to search
  218.   * @param mixed value the variable to return
  219.   * @param string indicator_field the name of the field upon which to base
  220.   *                                our decision upon (see above)
  221.   * @param int search constant defining where to look
  222.   * @param bool fallback_no_suffix whether or not to look for $name with
  223.   *                                 no suffix when nothing else is found
  224.   * @param mixed default the value to assign to $value when nothing is found
  225.   * @param int typecast force variable to be cast to given type (please
  226.   *                      use SQ_TYPE_XXX constants or set to FALSE (default)
  227.   *                      to leave variable type unmolested)
  228.   *
  229.   * @return bool whether variable is found.
  230.   */
  231. function sqGetGlobalVarMultiple($name&$value$indicator_field,
  232.                                 $search SQ_INORDER,
  233.                                 $fallback_no_suffix=TRUE$default=NULL,
  234.                                 $typecast=FALSE{
  235.  
  236.     // Set arbitrary max limit -- should be much lower except on the
  237.     // search results page, if there are many (50 or more?) mailboxes
  238.     // shown, this may not be high enough.  Is there some way we should
  239.     // automate this value?
  240.     //
  241.     $max_form_search 100;
  242.  
  243.     for ($i 1$i <= $max_form_search$i++{
  244.         if (sqGetGlobalVar($indicator_field '_' $i$temp$search)) {
  245.             return sqGetGlobalVar($name '_' $i$value$search$default$typecast);
  246.         }
  247.     }
  248.  
  249.  
  250.     // no indicator field found; just try without suffix if allowed
  251.     //
  252.     if ($fallback_no_suffix{
  253.         return sqGetGlobalVar($name$value$search$default$typecast);
  254.     }
  255.  
  256.  
  257.     // no dice, set default and return FALSE
  258.     //
  259.     if (!is_null($default)) {
  260.         $value $default;
  261.     }
  262.     return FALSE;
  263.  
  264. }
  265.  
  266.  
  267. /**
  268.  * Search for the variable $name in one or more of the global variables
  269.  * $_SESSION, $_POST, $_GET, $_COOKIE, and $_SERVER, and set the value of it in
  270.  * the variable $vaule.
  271.  *
  272.  * $search must be one of the defined constants below. The default is
  273.  * SQ_INORDER. Both SQ_INORDER and SQ_FORM stops on the first match.
  274.  *
  275.  * SQ_INORDER searches $_SESSION, then $_POST, and then $_GET.
  276.  * SQ_FORM searches $_POST and then $_GET.
  277.  * SQ_COOKIE searches $_COOKIE only.
  278.  * SQ_GET searches $_GET only.
  279.  * SQ_POST searches $_POST only.
  280.  * SQ_SERVER searches $_SERVER only.
  281.  * SQ_SESSION searches $_SESSION only.
  282.  *
  283.  * Example:
  284.  * sqgetGlobalVar('username', $username, SQ_SESSION);
  285.  * // No quotes around the last parameter, it's a constant - not a string!
  286.  *
  287.  * @param string name the name of the var to search
  288.  * @param mixed value the variable to return
  289.  * @param int search constant defining where to look
  290.  * @param mixed default the value to assign to $value when nothing is found
  291.  * @param int typecast force variable to be cast to given type (please
  292.  *                      use SQ_TYPE_XXX constants or set to FALSE (default)
  293.  *                      to leave variable type unmolested)
  294.  *
  295.  * @return bool whether variable is found.
  296.  */
  297. function sqgetGlobalVar($name&$value$search SQ_INORDER$default NULL$typecast FALSE{
  298.     // The return value defaults to FALSE, i.e. the variable wasn't found.
  299.     $result FALSE;
  300.  
  301.     // Search the global variables to find a match.
  302.     switch ($search{
  303.         default:
  304.             // The default needs to be first here so SQ_INORDER will be used if
  305.             // $search isn't a valid constant.
  306.         case SQ_INORDER:
  307.             // Search $_SESSION, then $_POST, and then $_GET. Stop on the first
  308.             // match.
  309.         case SQ_SESSION:
  310.             if (isset($_SESSION[$name])) {
  311.                 // If a match is found, set the specified variable to the found
  312.                 // value, indicate a match, and stop the search.
  313.                 $value $_SESSION[$name];
  314.                 $result TRUE;
  315.                 break;
  316.             elseif ($search == SQ_SESSION{
  317.                 // Only stop the search if SQ_SESSION is set. SQ_INORDER will
  318.                 // continue with the next clause.
  319.                 break;
  320.             }
  321.         case SQ_FORM:
  322.             // Search $_POST and then $_GET. Stop on the first match.
  323.         case SQ_POST:
  324.             if (isset($_POST[$name])) {
  325.                 // If a match is found, set the specified variable to the found
  326.                 // value, indicate a match, and stop the search.
  327.                 $value $_POST[$name];
  328.                 $result TRUE;
  329.                 break;
  330.             elseif ($search == SQ_POST{
  331.                 // Only stop the search if SQ_POST is set. SQ_INORDER and
  332.                 // SQ_FORM will continue with the next clause.
  333.                 break;
  334.             }
  335.         case SQ_GET:
  336.             if (isset($_GET[$name])) {
  337.                 // If a match is found, set the specified variable to the found
  338.                 // value, indicate a match, and stop the search.
  339.                 $value $_GET[$name];
  340.                 $result TRUE;
  341.                 break;
  342.             }
  343.             // Stop the search regardless of if SQ_INORDER, SQ_FORM, or SQ_GET
  344.             // is set. All three of them ends here.
  345.             break;
  346.         case SQ_COOKIE:
  347.             if (isset($_COOKIE[$name])) {
  348.                 // If a match is found, set the specified variable to the found
  349.                 // value, indicate a match, and stop the search.
  350.                 $value $_COOKIE[$name];
  351.                 $result TRUE;
  352.                 break;
  353.             }
  354.             // Stop the search.
  355.             break;
  356.         case SQ_SERVER:
  357.             if (isset($_SERVER[$name])) {
  358.                 // If a match is found, set the specified variable to the found
  359.                 // value, indicate a match, and stop the search.
  360.                 $value $_SERVER[$name];
  361.                 $result TRUE;
  362.                 break;
  363.             }
  364.             // Stop the search.
  365.             break;
  366.     }
  367.  
  368.     if ($result && $typecast{
  369.         // Only typecast if it's requested and a match is found. The default is
  370.         // not to typecast, which will happen if a valid constant isn't
  371.         // specified.
  372.         switch ($typecast{
  373.             case SQ_TYPE_INT:
  374.                 // Typecast the value and stop.
  375.                 $value = (int) $value;
  376.                 break;
  377.             case SQ_TYPE_STRING:
  378.                 // Typecast the value and stop.
  379.                 $value = (string) $value;
  380.                 break;
  381.             case SQ_TYPE_BOOL:
  382.                 // Typecast the value and stop.
  383.                 $value = (bool) $value;
  384.                 break;
  385.             case SQ_TYPE_BIGINT:
  386.                 // Typecast the value and stop.
  387.                 $value (preg_match('/^[0-9]+$/'$value$value '0');
  388.                 break;
  389.             default:
  390.                 // The default is to do nothing.
  391.                 break;
  392.         }
  393.     else if (!$result && !is_null($default)) {
  394.         // If no match is found and a default value is specified, set it.
  395.         $value $default;
  396.     }
  397.  
  398.     // Return if a match was found or not.
  399.     return $result;
  400. }
  401.  
  402. /**
  403.  * Get an immutable copy of a configuration variable if SquirrelMail
  404.  * is in "secured configuration" mode.  This guarantees the caller
  405.  * gets a copy of the requested value as it is set in the main
  406.  * application configuration (including config_local overrides), and
  407.  * not what it might be after possibly having been modified by some
  408.  * other code (usually a plugin overriding configuration values for
  409.  * one reason or another).
  410.  *
  411.  * WARNING: Please use this function as little as possible, because
  412.  * every time it is called, it forcibly reloads the main configuration
  413.  * file(s).
  414.  *
  415.  * Caller beware that this function will do nothing if SquirrelMail
  416.  * is not in "secured configuration" mode per the $secured_config
  417.  * setting.
  418.  *
  419.  * @param string $var_name The name of the desired variable
  420.  *
  421.  * @return mixed The desired value
  422.  *
  423.  * @since 1.5.2
  424.  *
  425.  */
  426. function get_secured_config_value($var_name{
  427.  
  428.     static $return_values array();
  429.  
  430.     // if we can avoid it, return values that have 
  431.     // already been retrieved (so we don't have to
  432.     // include the config file yet again)
  433.     //
  434.     if (isset($return_values[$var_name])) {
  435.         return $return_values[$var_name];
  436.     }
  437.  
  438.  
  439.     // load site configuration
  440.     //
  441.     require(SM_PATH 'config/config.php');
  442.  
  443.     // load local configuration overrides
  444.     //
  445.     if (file_exists(SM_PATH 'config/config_local.php')) {
  446.         require(SM_PATH 'config/config_local.php');
  447.     }
  448.  
  449.     // if SM isn't in "secured configuration" mode,
  450.     // just return the desired value from the global scope
  451.     // 
  452.     if (!$secured_config{
  453.         global $$var_name;
  454.         $return_values[$var_name= $$var_name;
  455.         return $$var_name;
  456.     }
  457.  
  458.     // else we return what we got from the config file
  459.     //
  460.     $return_values[$var_name= $$var_name;
  461.     return $$var_name;
  462.  
  463. }
  464.  
  465. /**
  466.  * Deletes an existing session, more advanced than the standard PHP
  467.  * session_destroy(), it explicitly deletes the cookies and global vars.
  468.  *
  469.  * WARNING: Older PHP versions have some issues with session management.
  470.  * See http://bugs.php.net/11643 (warning, spammed bug tracker) and
  471.  * http://bugs.php.net/13834. SID constant is not destroyed in PHP 4.1.2,
  472.  * 4.2.3 and maybe other versions. If you restart session after session
  473.  * is destroyed, affected PHP versions produce PHP notice. Bug should
  474.  * be fixed only in 4.3.0
  475.  */
  476. function sqsession_destroy({
  477.  
  478.     /*
  479.      * php.net says we can kill the cookie by setting just the name:
  480.      * http://www.php.net/manual/en/function.setcookie.php
  481.      * maybe this will help fix the session merging again.
  482.      *
  483.      * Changed the theory on this to kill the cookies first starting
  484.      * a new session will provide a new session for all instances of
  485.      * the browser, we don't want that, as that is what is causing the
  486.      * merging of sessions.
  487.      */
  488.  
  489.     global $base_uri$_COOKIE$_SESSION;
  490.  
  491.     if (isset($_COOKIE[session_name()]&& session_name()) {
  492.         sqsetcookie(session_name()$_COOKIE[session_name()]1$base_uri);
  493.  
  494.         /*
  495.          * Make sure to kill /src and /src/ cookies, just in case there are
  496.          * some left-over or malicious ones set in user's browser.
  497.          * NB: Note that an attacker could try to plant a cookie for one
  498.          *     of the /plugins/* directories.  Such cookies can block
  499.          *     access to certain plugin pages, but they do not influence
  500.          *     or fixate the $base_uri cookie, so we don't worry about
  501.          *     trying to delete all of them here.
  502.          */
  503.         sqsetcookie(session_name()$_COOKIE[session_name()]1$base_uri 'src');
  504.         sqsetcookie(session_name()$_COOKIE[session_name()]1$base_uri 'src/');
  505.     }
  506.  
  507.     if (isset($_COOKIE['key']&& $_COOKIE['key']sqsetcookie('key','SQMTRASH',1,$base_uri);
  508.  
  509.     /* Make sure new session id is generated on subsequent session_start() */
  510.     unset($_COOKIE[session_name()]);
  511.     unset($_GET[session_name()]);
  512.     unset($_POST[session_name()]);
  513.  
  514.     $sessid session_id();
  515.     if (!empty$sessid )) {
  516.         $_SESSION array();
  517.         @session_destroy();
  518.     }
  519. }
  520.  
  521. /**
  522.  * Function to verify a session has been started.  If it hasn't
  523.  * start a session up.  php.net doesn't tell you that $_SESSION
  524.  * (even though autoglobal), is not created unless a session is
  525.  * started, unlike $_POST, $_GET and such
  526.  * Update: (see #1685031) the session ID is left over after the
  527.  * session is closed in some PHP setups; this function just becomes
  528.  * a passthru to sqsession_start(), but leaving old code in for
  529.  * edification.
  530.  */
  531. function sqsession_is_active({
  532.     //$sessid = session_id();
  533.     //if ( empty( $sessid ) ) {
  534.         sqsession_start();
  535.     //}
  536. }
  537.  
  538. /**
  539.  * Function to start the session and store the cookie with the session_id as
  540.  * HttpOnly cookie which means that the cookie isn't accessible by javascript
  541.  * (IE6 only)
  542.  * Note that as sqsession_is_active() no longer discriminates as to when
  543.  * it calls this function, session_start() has to have E_NOTICE suppression
  544.  * (thus the @ sign).
  545.  */
  546. function sqsession_start({
  547.     global $base_uri;
  548.  
  549.     sq_call_function_suppress_errors('session_start');
  550.     // was: @session_start();
  551.     $session_id session_id();
  552.  
  553.     // session_starts sets the sessionid cookie but without the httponly var
  554.     // setting the cookie again sets the httponly cookie attribute
  555.     //
  556.     // need to check if headers have been sent, since sqsession_is_active()
  557.     // has become just a passthru to this function, so the sqsetcookie()
  558.     // below is called every time, even after headers have already been sent
  559.     //
  560.     if (!headers_sent())
  561.        sqsetcookie(session_name(),$session_id,false,$base_uri);
  562. }
  563.  
  564.  
  565.  
  566. /**
  567.  * Set a cookie
  568.  *
  569.  * @param string  $sName     The name of the cookie.
  570.  * @param string  $sValue    The value of the cookie.
  571.  * @param int     $iExpire   The time the cookie expires. This is a Unix
  572.  *                            timestamp so is in number of seconds since
  573.  *                            the epoch.
  574.  * @param string  $sPath     The path on the server in which the cookie
  575.  *                            will be available on.
  576.  * @param string  $sDomain   The domain that the cookie is available.
  577.  * @param boolean $bSecure   Indicates that the cookie should only be
  578.  *                            transmitted over a secure HTTPS connection.
  579.  * @param boolean $bHttpOnly Disallow JS to access the cookie (IE6 only)
  580.  * @param boolean $bReplace  Replace previous cookies with same name?
  581.  *
  582.  * @return void 
  583.  *
  584.  * @since 1.4.16 and 1.5.1
  585.  *
  586.  */
  587. function sqsetcookie($sName$sValue='deleted'$iExpire=0$sPath=""$sDomain="",
  588.                      $bSecure=false$bHttpOnly=true$bReplace=false{
  589.  
  590.     // some environments can get overwhelmed by an excessive
  591.     // setting of the same cookie over and over (e.g., many
  592.     // calls to this function via sqsession_is_active() result
  593.     // in repeated setting of the session cookie when $bReplace
  594.     // is FALSE, but something odd happens (during login only)
  595.     // if we change that to default TRUE) ... so we keep our own
  596.     // naive per-request name/value cache and only set the cookie
  597.     // if its value is changing (or never seen before)
  598.     static $cookies array();
  599.     if (isset($cookies[$sName]&& $cookies[$sName=== $sValue)
  600.         return;
  601.     else
  602.         $cookies[$sName$sValue;
  603.  
  604.  
  605.     // if we have a secure connection then limit the cookies to https only.
  606.     global $is_secure_connection;
  607.     if ($sName && $is_secure_connection)
  608.         $bSecure true;
  609.  
  610.     // admin config can override the restriction of secure-only cookies
  611.     global $only_secure_cookies;
  612.     if (!$only_secure_cookies)
  613.         $bSecure false;
  614.  
  615.     if (false && check_php_version(5,2)) {
  616.        // php 5 supports the httponly attribute in setcookie, but because setcookie seems a bit
  617.        // broken we use the header function for php 5.2 as well. We might change that later.
  618.        //setcookie($sName,$sValue,(int) $iExpire,$sPath,$sDomain,$bSecure,$bHttpOnly);
  619.     else {
  620.         if (!empty($sDomain)) {
  621.             // Fix the domain to accept domains with and without 'www.'.
  622.             if (strtolower(substr($sDomain04)) == 'www.')  $sDomain substr($sDomain4);
  623.             $sDomain '.' $sDomain;
  624.  
  625.             // Remove port information.
  626.             $Port strpos($sDomain':');
  627.             if ($Port !== false)  $sDomain substr($sDomain0$Port);
  628.         }
  629.         if (!$sValue$sValue 'deleted';
  630.         header('Set-Cookie: ' rawurlencode($sName'=' rawurlencode($sValue)
  631.                             . (empty($iExpire'' '; expires=' gmdate('D, d-M-Y H:i:s'$iExpire' GMT')
  632.                             . (empty($sPath'' '; path=' $sPath)
  633.                             . (empty($sDomain'' '; domain=' $sDomain)
  634.                             . (!$bSecure '' '; secure')
  635.                             . (!$bHttpOnly '' '; HttpOnly')$bReplace);
  636.     }
  637. }
  638.  
  639.  
  640. /**
  641.  * session_regenerate_id replacement for PHP < 4.3.2
  642.  *
  643.  * This code is borrowed from Gallery, session.php version 1.53.2.1
  644. 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.
  645.  */
  646. if (!function_exists('session_regenerate_id')) {
  647.  
  648.     function php_combined_lcg({
  649.         $tv gettimeofday();
  650.         $lcg['s1'$tv['sec'(~$tv['usec']);
  651.         $lcg['s2'mt_rand();
  652.         $q = (int) ($lcg['s1'53668);
  653.         $lcg['s1'= (int) (40014 ($lcg['s1'53668 $q12211 $q);
  654.         if ($lcg['s1'0{
  655.             $lcg['s1'+= 2147483563;
  656.         }
  657.         $q = (int) ($lcg['s2'52774);
  658.         $lcg['s2'= (int) (40692 ($lcg['s2'52774 $q3791 $q);
  659.         if ($lcg['s2'0{
  660.             $lcg['s2'+= 2147483399;
  661.         }
  662.         $z = (int) ($lcg['s1'$lcg['s2']);
  663.         if ($z 1{
  664.             $z += 2147483562;
  665.         }
  666.         return $z 4.656613e-10;
  667.     }
  668.  
  669.     function session_regenerate_id({
  670.         global $base_uri;
  671.         $tv gettimeofday();
  672.         sqgetGlobalVar('REMOTE_ADDR',$remote_addr,SQ_SERVER);
  673.         $buf sprintf("%.15s%ld%ld%0.8f"$remote_addr$tv['sec']$tv['usec']php_combined_lcg(10);
  674.         session_id(md5($buf));
  675.         if (ini_get('session.use_cookies')) {
  676.             sqsetcookie(session_name()session_id()0$base_uri);
  677.         }
  678.         return TRUE;
  679.     }
  680. }
  681.  
  682.  
  683. /**
  684.  * php_self
  685.  *
  686.  * Attempts to determine the path and filename and any arguments
  687.  * for the currently executing script.  This is usually found in
  688.  * $_SERVER['REQUEST_URI'], but some environments may differ, so
  689.  * this function tries to standardize this value.
  690.  *
  691.  * Note that before SquirrelMail version 1.5.1, this function was
  692.  * stored in function/strings.php.
  693.  *
  694.  * @since 1.2.3
  695.  * @return string The path, filename and any arguments for the
  696.  *                 current script
  697.  */
  698. function php_self({
  699.  
  700.     $request_uri '';
  701.  
  702.     // first try $_SERVER['PHP_SELF'], which seems most reliable
  703.     // (albeit it usually won't include the query string)
  704.     //
  705.     $request_uri ''
  706.     if (!sqgetGlobalVar('PHP_SELF'$request_uriSQ_SERVER)
  707.      || empty($request_uri)) 
  708.  
  709.         // well, then let's try $_SERVER['REQUEST_URI']
  710.         //
  711.         $request_uri '';
  712.         if (!sqgetGlobalVar('REQUEST_URI'$request_uriSQ_SERVER)
  713.          || empty($request_uri)) 
  714.  
  715.             // TODO: anyone have any other ideas?  maybe $_SERVER['SCRIPT_NAME']???
  716.             //
  717.             return '';
  718.         }
  719.  
  720.     }
  721.  
  722.     // we may or may not have any query arguments, depending on 
  723.     // which environment variable was used above, and the PHP
  724.     // version, etc., so let's check for it now
  725.     //
  726.     $query_string '';
  727.     if (strpos($request_uri'?'=== FALSE
  728.      && sqgetGlobalVar('QUERY_STRING'$query_stringSQ_SERVER)
  729.      && !empty($query_string)) {
  730.  
  731.         $request_uri .= '?' $query_string;
  732.     }   
  733.  
  734.     return $request_uri;
  735.  
  736. }
  737.  
  738.  
  739. /**
  740.  * Print variable
  741.  *
  742.  * sm_print_r($some_variable, [$some_other_variable [, ...]]);
  743.  *
  744.  * Debugging function - does the same as print_r, but makes sure special
  745.  * characters are converted to htmlentities first.  This will allow
  746.  * values like <[email protected]> to be displayed.
  747.  * The output is wrapped in <<pre>> and <</pre>> tags.
  748.  * Since 1.4.2 accepts unlimited number of arguments.
  749.  * @since 1.4.1
  750.  * @return void 
  751.  */
  752. function sm_print_r({
  753.     ob_start();  // Buffer output
  754.     foreach(func_get_args(as $var{
  755.         print_r($var);
  756.         echo "\n";
  757.         // php has get_class_methods function that can print class methods
  758.         if (is_object($var)) {
  759.             // get class methods if $var is object
  760.             $aMethods=get_class_methods(get_class($var));
  761.             // make sure that $aMethods is array and array is not empty
  762.             if (is_array($aMethods&& $aMethods!=array()) {
  763.                 echo "Object methods:\n";
  764.                 foreach($aMethods as $method{
  765.                     echo '* ' $method "\n";
  766.                 }
  767.             }
  768.             echo "\n";
  769.         }
  770.     }
  771.     $buffer ob_get_contents()// Grab the print_r output
  772.     ob_end_clean();  // Silently discard the output & stop buffering
  773.     print '<div align="left"><pre>';
  774.     print htmlentities($buffer);
  775.     print '</pre></div>';
  776. }
  777.  
  778.  
  779. /**
  780.   * Sanitize a value using sm_encode_html_special_chars() or similar, but also
  781.   * recursively run sm_encode_html_special_chars() (or similar) on array keys
  782.   * and values.
  783.   *
  784.   * If $value is not a string or an array with strings in it,
  785.   * the value is returned as is.
  786.   *
  787.   * @param mixed $value       The value to be sanitized.
  788.   * @param mixed $quote_style Either boolean or an integer.  If it
  789.   *                            is an integer, it must be the PHP
  790.   *                            constant indicating if/how to escape
  791.   *                            quotes: ENT_QUOTES, ENT_COMPAT, or
  792.   *                            ENT_NOQUOTES.  If it is a boolean value,
  793.   *                            it must be TRUE and thus indicates
  794.   *                            that the only sanitizing to be done
  795.   *                            herein is to replace single and double
  796.   *                            quotes with &#039; and &quot;, no other
  797.   *                            changes are made to $value.  If it is
  798.   *                            boolean and FALSE, behavior reverts
  799.   *                            to same as if the value was ENT_QUOTES
  800.   *                            (OPTIONAL; default is ENT_QUOTES).
  801.   *
  802.   * @return mixed The sanitized value.
  803.   *
  804.   * @since 1.5.2
  805.   *
  806.   ***/
  807. function sq_htmlspecialchars($value$quote_style=ENT_QUOTES{
  808.  
  809.     if ($quote_style === FALSE$quote_style ENT_QUOTES;
  810.  
  811.     // array?  go recursive...
  812.     //
  813.     if (is_array($value)) {
  814.         $return_array array();
  815.         foreach ($value as $key => $val{
  816.             $return_array[sq_htmlspecialchars($key$quote_style)]
  817.                 = sq_htmlspecialchars($val$quote_style);
  818.         }
  819.         return $return_array;
  820.  
  821.     // sanitize strings only
  822.     //
  823.     else if (is_string($value)) {
  824.         if ($quote_style === TRUE)
  825.             return str_replace(array('\'''"')array('&#039;''&quot;')$value);
  826.         else
  827.             return sm_encode_html_special_chars($value$quote_style);
  828.     }
  829.  
  830.     // anything else gets returned with no changes
  831.     //
  832.     return $value;
  833.  
  834. }
  835.  
  836.  
  837. /**
  838.  * Detect whether or not we have a SSL secured (HTTPS) connection
  839.  * connection to the browser
  840.  *
  841.  * It is thought to be so if you have 'SSLOptions +StdEnvVars'
  842.  * in your Apache configuration,
  843.  *     OR if you have HTTPS set to a non-empty value (except "off")
  844.  *        in your HTTP_SERVER_VARS,
  845.  *     OR if you have HTTP_X_FORWARDED_PROTO=https in your HTTP_SERVER_VARS,
  846.  *     OR if you are on port 443.
  847.  *
  848.  * Note: HTTP_X_FORWARDED_PROTO could be sent from the client and
  849.  *       therefore possibly spoofed/hackable.  Thus, SquirrelMail
  850.  *       ignores such headers by default.  The administrator
  851.  *       can tell SM to use such header values by setting
  852.  *       $sq_ignore_http_x_forwarded_headers to boolean FALSE
  853.  *       in config/config.php or by using config/conf.pl.
  854.  *
  855.  * Note: It is possible to run SSL on a port other than 443, and
  856.  *       if that is the case, the administrator should set
  857.  *       $sq_https_port in config/config.php or by using config/conf.pl.
  858.  *
  859.  * @return boolean TRUE if the current connection is SSL-encrypted;
  860.  *                  FALSE otherwise.
  861.  *
  862.  * @since 1.4.17 and 1.5.2
  863.  *
  864.  */
  865. {
  866.     global $sq_ignore_http_x_forwarded_headers$sq_https_port;
  867.     $https_env_var getenv('HTTPS');
  868.     if ($sq_ignore_http_x_forwarded_headers
  869.      || !sqgetGlobalVar('HTTP_X_FORWARDED_PROTO'$forwarded_protoSQ_SERVER))
  870.         $forwarded_proto '';
  871.     if (empty($sq_https_port)) // won't work with port 0 (zero)
  872.        $sq_https_port 443;
  873.     if ((isset($https_env_var&& strcasecmp($https_env_var'on'=== 0)
  874.      || (sqgetGlobalVar('HTTPS'$httpsSQ_SERVER&& !empty($https)
  875.       && strcasecmp($https'off'!== 0)
  876.      || (strcasecmp($forwarded_proto'https'=== 0)
  877.      || (sqgetGlobalVar('SERVER_PORT'$server_portSQ_SERVER)
  878.       && $server_port == $sq_https_port))
  879.         return TRUE;
  880.     return FALSE;
  881. }
  882.  
  883.  
  884. /**
  885.  * Endeavor to detect what user and group PHP is currently
  886.  * running as.  Probably only works in non-Windows environments.
  887.  *
  888.  * @return mixed Boolean FALSE is returned if something went wrong,
  889.  *                otherwise an array is returned with the following
  890.  *                elements:
  891.  *                   uid    The current process' UID (integer)
  892.  *                   euid   The current process' effective UID (integer)
  893.  *                   gid    The current process' GID (integer)
  894.  *                   egid   The current process' effective GID (integer)
  895.  *                   name   The current process' name/handle (string)
  896.  *                   ename  The current process' effective name/handle (string)
  897.  *                   group  The current process' group name (string)
  898.  *                   egroup The current process' effective group name (string)
  899.  *                Note that some of these elements may have empty
  900.  *                values, especially if they could not be determined.
  901.  *
  902.  * @since 1.5.2
  903.  *
  904.  */
  905. {
  906.     if (!function_exists('posix_getuid'))
  907.         return FALSE;
  908.  
  909.     $process_info['uid'posix_getuid();
  910.     $process_info['euid'posix_geteuid();
  911.     $process_info['gid'posix_getgid();
  912.     $process_info['egid'posix_getegid();
  913.  
  914.     $user_info posix_getpwuid($process_info['uid']);
  915.     $euser_info posix_getpwuid($process_info['euid']);
  916.     $group_info posix_getgrgid($process_info['gid']);
  917.     $egroup_info posix_getgrgid($process_info['egid']);
  918.  
  919.     $process_info['name'$user_info['name'];
  920.     $process_info['ename'$euser_info['name'];
  921.     $process_info['group'$user_info['name'];
  922.     $process_info['egroup'$euser_info['name'];
  923.     
  924.     return $process_info;
  925. }

Documentation generated on Mon, 13 Jan 2020 04:22:41 +0100 by phpDocumentor 1.4.3