to be displayed.
* The output is wrapped in <> and <
> tags.
*
* @return void
*/
function sm_print_r() {
ob_start(); // Buffer output
foreach(func_get_args() as $var) {
print_r($var);
echo "\n";
}
$buffer = ob_get_contents(); // Grab the print_r output
ob_end_clean(); // Silently discard the output & stop buffering
print '';
print htmlentities($buffer);
print '';
}
/**
* version of fwrite which checks for failure
*/
function sq_fwrite($fp, $string) {
// write to file
$count = @fwrite($fp,$string);
// the number of bytes written should be the length of the string
if($count != strlen($string)) {
return FALSE;
}
return $count;
}
/**
* Tests if string contains 8bit symbols.
*
* If charset is not set, function defaults to default_charset.
* $default_charset global must be set correctly if $charset is
* not used.
* @param string $string tested string
* @param string $charset charset used in a string
* @return bool true if 8bit symbols are detected
* @since 1.5.1 and 1.4.4
*/
function sq_is8bit($string,$charset='') {
global $default_charset;
if ($charset=='') $charset=$default_charset;
/**
* Don't use \240 in ranges. Sometimes RH 7.2 doesn't like it.
* Don't use \200-\237 for iso-8859-x charsets. This ranges
* stores control symbols in those charsets.
* Use preg_match instead of ereg in order to avoid problems
* with mbstring overloading
*/
if (preg_match("/^iso-8859/i",$charset)) {
$needle='/\240|[\241-\377]/';
} else {
$needle='/[\200-\237]|\240|[\241-\377]/';
}
return preg_match("$needle",$string);
}
/**
* Function returns number of characters in string.
*
* Returned number might be different from number of bytes in string,
* if $charset is multibyte charset. Detection depends on mbstring
* functions. If mbstring does not support tested multibyte charset,
* vanilla string length function is used.
* @param string $str string
* @param string $charset charset
* @since 1.5.1 and 1.4.6
* @return integer number of characters in string
*/
function sq_strlen($str, $charset=null){
// default option
if (is_null($charset)) return strlen($str);
// lowercase charset name
$charset=strtolower($charset);
// use automatic charset detection, if function call asks for it
if ($charset=='auto') {
global $default_charset;
set_my_charset();
$charset=$default_charset;
}
// Use mbstring only with listed charsets
$aList_of_mb_charsets=array('utf-8','big5','gb2312','gb18030','euc-jp','euc-cn','euc-tw','euc-kr');
// calculate string length according to charset
if (in_array($charset,$aList_of_mb_charsets) && in_array($charset,sq_mb_list_encodings())) {
$real_length = mb_strlen($str,$charset);
} else {
// own strlen detection code is removed because missing strpos,
// strtoupper and substr implementations break string wrapping.
$real_length=strlen($str);
}
return $real_length;
}
/**
* Replacement of mb_list_encodings function
*
* This function provides replacement for function that is available only
* in php 5.x. Function does not test all mbstring encodings. Only the ones
* that might be used in SM translations.
*
* Supported strings are stored in session in order to reduce number of
* mb_internal_encoding function calls.
*
* If mb_list_encodings() function is present, code uses it. Main difference
* from original function behaviour - array values are lowercased in order to
* simplify use of returned array in in_array() checks.
*
* If you want to test all mbstring encodings - fill $list_of_encodings
* array.
* @return array list of encodings supported by php mbstring extension
* @since 1.5.1 and 1.4.6
*/
function sq_mb_list_encodings() {
// check if mbstring extension is present
if (! function_exists('mb_internal_encoding'))
return array();
// php 5+ function
if (function_exists('mb_list_encodings')) {
$ret = mb_list_encodings();
array_walk($ret,'sq_lowercase_array_vals');
return $ret;
}
// don't try to test encodings, if they are already stored in session
if (sqgetGlobalVar('mb_supported_encodings',$mb_supported_encodings,SQ_SESSION))
return $mb_supported_encodings;
// save original encoding
$orig_encoding=mb_internal_encoding();
$list_of_encoding=array(
'pass',
'auto',
'ascii',
'jis',
'utf-8',
'sjis',
'euc-jp',
'iso-8859-1',
'iso-8859-2',
'iso-8859-7',
'iso-8859-9',
'iso-8859-15',
'koi8-r',
'koi8-u',
'big5',
'gb2312',
'gb18030',
'windows-1251',
'windows-1255',
'windows-1256',
'tis-620',
'iso-2022-jp',
'euc-cn',
'euc-kr',
'euc-tw',
'uhc',
'utf7-imap');
$supported_encodings=array();
foreach ($list_of_encoding as $encoding) {
// try setting encodings. suppress warning messages
if (@mb_internal_encoding($encoding))
$supported_encodings[]=$encoding;
}
// restore original encoding
mb_internal_encoding($orig_encoding);
// register list in session
sqsession_register($supported_encodings,'mb_supported_encodings');
return $supported_encodings;
}
/**
* Callback function used to lowercase array values.
* @param string $val array value
* @param mixed $key array key
* @since 1.5.1 and 1.4.6
*/
function sq_lowercase_array_vals(&$val,$key) {
$val = strtolower($val);
}
/**
* Callback function to trim whitespace from a value, to be used in array_walk
* @param string $value value to trim
* @since 1.5.2 and 1.4.7
*/
function sq_trim_value ( &$value ) {
$value = trim($value);
}
/**
* Gathers the list of secuirty tokens currently
* stored in the user's preferences and optionally
* purges old ones from the list.
*
* @param boolean $purge_old Indicates if old tokens
* should be purged from the
* list ("old" is 2 days or
* older unless the administrator
* overrides that value using
* $max_security_token_age in
* config/config_local.php)
* (OPTIONAL; default is to always
* purge old tokens)
*
* @return array The list of tokens
*
* @since 1.4.19 and 1.5.2
*
*/
function sm_get_user_security_tokens($purge_old=TRUE)
{
global $data_dir, $username, $max_token_age_days;
$tokens = getPref($data_dir, $username, 'security_tokens', '');
if (($tokens = unserialize($tokens)) === FALSE || !is_array($tokens))
$tokens = array();
// purge old tokens if necessary
//
if ($purge_old)
{
if (empty($max_token_age_days)) $max_token_age_days = 2;
$now = time();
$discard_token_date = $now - ($max_token_age_days * 86400);
$cleaned_tokens = array();
foreach ($tokens as $token => $timestamp)
if ($timestamp >= $discard_token_date)
$cleaned_tokens[$token] = $timestamp;
$tokens = $cleaned_tokens;
}
return $tokens;
}
/**
* Generates a security token that is then stored in
* the user's preferences with a timestamp for later
* verification/use.
*
* WARNING: If the administrator has turned the token system
* off by setting $disable_security_tokens to TRUE in
* config/config.php or the configuration tool, this
* function will not store tokens in the user
* preferences (but it will still generate and return
* a random string).
*
* @return void
*
* @since 1.4.19 and 1.5.2
*
*/
function sm_generate_security_token()
{
global $data_dir, $username, $disable_security_tokens;
$max_generation_tries = 1000;
$tokens = sm_get_user_security_tokens();
$new_token = GenerateRandomString(12, '', 7);
$count = 0;
while (isset($tokens[$new_token]))
{
$new_token = GenerateRandomString(12, '', 7);
if (++$count > $max_generation_tries)
{
logout_error(_("Fatal token generation error; please contact your system administrator or the SquirrelMail Team"));
exit;
}
}
// is the token system enabled? CAREFUL!
//
if (!$disable_security_tokens)
{
$tokens[$new_token] = time();
setPref($data_dir, $username, 'security_tokens', serialize($tokens));
}
return $new_token;
}
/**
* Validates a given security token and optionally remove it
* from the user's preferences if it was valid. If the token
* is too old but otherwise valid, it will still be rejected.
*
* "Too old" is 2 days or older unless the administrator
* overrides that value using $max_security_token_age in
* config/config_local.php
*
* WARNING: If the administrator has turned the token system
* off by setting $disable_security_tokens to TRUE in
* config/config.php or the configuration tool, this
* function will always return TRUE.
*
* @param string $token The token to validate
* @param int $validity_period The number of seconds tokens are valid
* for (set to zero to remove valid tokens
* after only one use; use 3600 to allow
* tokens to be reused for an hour)
* (OPTIONAL; default is to only allow tokens
* to be used once)
* @param boolean $show_error Indicates that if the token is not
* valid, this function should display
* a generic error, log the user out
* and exit - this function will never
* return in that case.
* (OPTIONAL; default FALSE)
*
* @return boolean TRUE if the token validated; FALSE otherwise
*
* @since 1.4.19 and 1.5.2
*
*/
function sm_validate_security_token($token, $validity_period=0, $show_error=FALSE)
{
global $data_dir, $username, $max_token_age_days,
$disable_security_tokens;
// bypass token validation? CAREFUL!
//
if ($disable_security_tokens) return TRUE;
// don't purge old tokens here because we already
// do it when generating tokens
//
$tokens = sm_get_user_security_tokens(FALSE);
// token not found?
//
if (empty($tokens[$token]))
{
if (!$show_error) return FALSE;
logout_error(_("This page request could not be verified and appears to have expired."));
exit;
}
$now = time();
$timestamp = $tokens[$token];
// whether valid or not, we want to remove it from
// user prefs if it's old enough
//
if ($timestamp < $now - $validity_period)
{
unset($tokens[$token]);
setPref($data_dir, $username, 'security_tokens', serialize($tokens));
}
// reject tokens that are too old
//
if (empty($max_token_age_days)) $max_token_age_days = 2;
$old_token_date = $now - ($max_token_age_days * 86400);
if ($timestamp < $old_token_date)
{
if (!$show_error) return FALSE;
logout_error(_("The current page request appears to have originated from an untrusted source."));
exit;
}
// token OK!
//
return TRUE;
}
$PHP_SELF = php_self();