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";
- // php has get_class_methods function that can print class methods
- if (is_object($var)) {
- // get class methods if $var is object
- $aMethods=get_class_methods(get_class($var));
- // make sure that $aMethods is array and array is not empty
- if (is_array($aMethods) && $aMethods!=array()) {
- echo "Object methods:\n";
- foreach($aMethods as $method) {
- echo '* ' . $method . "\n";
- }
- }
- 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 '
';
+ return makeInternalLink($url, $text, '_blank', $accesskey);
}
/**
* version of fwrite which checks for failure
+ * @param resource $fp
+ * @param string $string
+ * @return number of written bytes. false on failure
+ * @since 1.4.3
*/
function sq_fwrite($fp, $string) {
// write to file
@@ -918,6 +819,7 @@ function sq_fwrite($fp, $string) {
*
* @param string $charset charset used for encoding. default to us-ascii, 'auto' uses $default_charset global value.
* @return array html translation array
+ * @since 1.5.1
*/
function sq_get_html_translation_table($table,$quote_style=ENT_COMPAT,$charset='us-ascii') {
global $default_charset;
@@ -981,6 +883,7 @@ function sq_get_html_translation_table($table,$quote_style=ENT_COMPAT,$charset='
*
* @param string $charset charset used for encoding. defaults to 'us-ascii', 'auto' uses $default_charset global value.
* @return string sanitized string
+ * @since 1.5.1
*/
function sq_htmlentities($string,$quote_style=ENT_COMPAT,$charset='us-ascii') {
// get translation table
@@ -1033,12 +936,19 @@ function sq_is8bit($string,$charset='') {
* 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
+ * @since 1.5.1 and 1.4.6
*/
function sq_mb_list_encodings() {
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;
@@ -1069,7 +979,10 @@ function sq_mb_list_encodings() {
'windows-1256',
'tis-620',
'iso-2022-jp',
+ 'euc-cn',
'euc-kr',
+ 'euc-tw',
+ 'uhc',
'utf7-imap');
$supported_encodings=array();
@@ -1089,32 +1002,44 @@ function sq_mb_list_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);
+}
+
+
/**
* 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
+ * if $charset is multibyte charset. Detection depends on mbstring
* functions. If mbstring does not support tested multibyte charset,
- * vanilla string length function is used.
+ * vanilla string length function is used.
* @param string $str string
* @param string $charset charset
- * @since 1.5.1
- * @return integer number of characters in string
+ * @since 1.5.1 and 1.4.6
+ * @return integer number of characters in string
*/
-function sq_strlen($str, $charset=''){
+function sq_strlen($str, $charset=null){
// default option
- if ($charset=='') return strlen($str);
+ 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;
+ global $default_charset, $squirrelmail_language;
set_my_charset();
$charset=$default_charset;
+ if ($squirrelmail_language=='ja_JP') $charset='euc-jp';
}
- // lowercase charset name
- $charset=strtolower($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');
@@ -1122,7 +1047,7 @@ function sq_strlen($str, $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,
+ // own strlen detection code is removed because missing strpos,
// strtoupper and substr implementations break string wrapping.
$real_length=strlen($str);
}
@@ -1136,7 +1061,7 @@ function sq_strlen($str, $charset=''){
* @param string $string original string
* @param integer $width padded string width
* @param string $pad padding symbols
- * @param integer $padtype padding type
+ * @param integer $padtype padding type
* (internal php defines, see str_pad() description)
* @param string $charset charset used in original string
* @return string padded string
@@ -1176,14 +1101,32 @@ function sq_str_pad($string, $width, $pad, $padtype, $charset='') {
*/
function sq_substr($string,$start,$length,$charset='auto') {
// use automatic charset detection, if function call asks for it
+ static $charset_auto, $bUse_mb;
+
if ($charset=='auto') {
- global $default_charset;
- set_my_charset();
- $charset=$default_charset;
+ if (!isset($charset_auto)) {
+ global $default_charset, $squirrelmail_language;
+ set_my_charset();
+ $charset=$default_charset;
+ if ($squirrelmail_language=='ja_JP') $charset='euc-jp';
+ $charset_auto = $charset;
+ } else {
+ $charset = $charset_auto;
+ }
}
$charset = strtolower($charset);
- if (function_exists('mb_internal_encoding') &&
- in_array($charset,sq_mb_list_encodings())) {
+
+ // in_array call is expensive => do it once and use a static var for
+ // storing the results
+ if (!isset($bUse_mb)) {
+ if (in_array($charset,sq_mb_list_encodings())) {
+ $bUse_mb = true;
+ } else {
+ $bUse_mb = false;
+ }
+ }
+
+ if ($bUse_mb) {
return mb_substr($string,$start,$length,$charset);
}
// TODO: add mbstring independent code
@@ -1206,14 +1149,31 @@ function sq_substr($string,$start,$length,$charset='auto') {
*/
function sq_strpos($haystack,$needle,$offset,$charset='auto') {
// use automatic charset detection, if function call asks for it
+ static $charset_auto, $bUse_mb;
+
if ($charset=='auto') {
- global $default_charset;
- set_my_charset();
- $charset=$default_charset;
+ if (!isset($charset_auto)) {
+ global $default_charset, $squirrelmail_language;
+ set_my_charset();
+ $charset=$default_charset;
+ if ($squirrelmail_language=='ja_JP') $charset='euc-jp';
+ $charset_auto = $charset;
+ } else {
+ $charset = $charset_auto;
+ }
}
$charset = strtolower($charset);
- if (function_exists('mb_internal_encoding') &&
- in_array($charset,sq_mb_list_encodings())) {
+
+ // in_array call is expensive => do it once and use a static var for
+ // storing the results
+ if (!isset($bUse_mb)) {
+ if (in_array($charset,sq_mb_list_encodings())) {
+ $bUse_mb = true;
+ } else {
+ $bUse_mb = false;
+ }
+ }
+ if ($bUse_mb) {
return mb_strpos($haystack,$needle,$offset,$charset);
}
// TODO: add mbstring independent code
@@ -1234,14 +1194,33 @@ function sq_strpos($haystack,$needle,$offset,$charset='auto') {
*/
function sq_strtoupper($string,$charset='auto') {
// use automatic charset detection, if function call asks for it
+ static $charset_auto, $bUse_mb;
+
if ($charset=='auto') {
- global $default_charset;
- set_my_charset();
- $charset=$default_charset;
+ if (!isset($charset_auto)) {
+ global $default_charset, $squirrelmail_language;
+ set_my_charset();
+ $charset=$default_charset;
+ if ($squirrelmail_language=='ja_JP') $charset='euc-jp';
+ $charset_auto = $charset;
+ } else {
+ $charset = $charset_auto;
+ }
}
$charset = strtolower($charset);
- if (function_exists('mb_internal_encoding') &&
- in_array($charset,sq_mb_list_encodings())) {
+
+ // in_array call is expensive => do it once and use a static var for
+ // storing the results
+ if (!isset($bUse_mb)) {
+ if (function_exists('mb_strtoupper') &&
+ in_array($charset,sq_mb_list_encodings())) {
+ $bUse_mb = true;
+ } else {
+ $bUse_mb = false;
+ }
+ }
+
+ if ($bUse_mb) {
return mb_strtoupper($string,$charset);
}
// TODO: add mbstring independent code
@@ -1249,5 +1228,208 @@ function sq_strtoupper($string,$charset='auto') {
// use vanilla string functions as last option
return strtoupper($string);
}
-$PHP_SELF = php_self();
-?>
\ No newline at end of file
+
+/**
+ * Counts 8bit bytes in string
+ * @param string $string tested string
+ * @return integer number of 8bit bytes
+ */
+function sq_count8bit($string) {
+ $count=0;
+ for ($i=0; $i 127) $count++;
+ }
+ return $count;
+}
+
+/**
+ * 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 30 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 = 30;
+ $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 string A security token
+ *
+ * @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 30 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 = 30;
+ $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;
+
+}
+