From 7c9d922b96f9a88b350d6e07f5bde84ccc40f9b0 Mon Sep 17 00:00:00 2001 From: thomascube <thomas@roundcube.net> Date: Tue, 02 Mar 2010 16:27:53 -0500 Subject: [PATCH] New recent check based on UIDs --- program/include/rcube_shared.inc | 481 ++++++++++++++++++++++++++++------------------------ 1 files changed, 258 insertions(+), 223 deletions(-) diff --git a/program/include/rcube_shared.inc b/program/include/rcube_shared.inc index d82b1fe..f4f23a2 100644 --- a/program/include/rcube_shared.inc +++ b/program/include/rcube_shared.inc @@ -28,62 +28,6 @@ /** - * Provide details about the client's browser - * - * @return array Key-value pairs of browser properties - */ -function rcube_browser() -{ - $HTTP_USER_AGENT = $_SERVER['HTTP_USER_AGENT']; - - $bw['ver'] = 0; - $bw['win'] = stristr($HTTP_USER_AGENT, 'win'); - $bw['mac'] = stristr($HTTP_USER_AGENT, 'mac'); - $bw['linux'] = stristr($HTTP_USER_AGENT, 'linux'); - $bw['unix'] = stristr($HTTP_USER_AGENT, 'unix'); - - $bw['ns4'] = stristr($HTTP_USER_AGENT, 'mozilla/4') && !stristr($HTTP_USER_AGENT, 'msie'); - $bw['ns'] = ($bw['ns4'] || stristr($HTTP_USER_AGENT, 'netscape')); - $bw['ie'] = stristr($HTTP_USER_AGENT, 'msie'); - $bw['mz'] = stristr($HTTP_USER_AGENT, 'mozilla/5'); - $bw['opera'] = stristr($HTTP_USER_AGENT, 'opera'); - $bw['safari'] = stristr($HTTP_USER_AGENT, 'safari'); - - if($bw['ns']) - { - $test = eregi("mozilla\/([0-9\.]+)", $HTTP_USER_AGENT, $regs); - $bw['ver'] = $test ? (float)$regs[1] : 0; - } - if($bw['mz']) - { - $test = ereg("rv:([0-9\.]+)", $HTTP_USER_AGENT, $regs); - $bw['ver'] = $test ? (float)$regs[1] : 0; - } - if($bw['ie']) - { - $test = eregi("msie ([0-9\.]+)", $HTTP_USER_AGENT, $regs); - $bw['ver'] = $test ? (float)$regs[1] : 0; - } - if($bw['opera']) - { - $test = eregi("opera ([0-9\.]+)", $HTTP_USER_AGENT, $regs); - $bw['ver'] = $test ? (float)$regs[1] : 0; - } - - if(eregi(" ([a-z]{2})-([a-z]{2})", $HTTP_USER_AGENT, $regs)) - $bw['lang'] = $regs[1]; - else - $bw['lang'] = 'en'; - - $bw['dom'] = ($bw['mz'] || $bw['safari'] || ($bw['ie'] && $bw['ver']>=5) || ($bw['opera'] && $bw['ver']>=7)); - $bw['pngalpha'] = $bw['mz'] || $bw['safari'] || ($bw['ie'] && $bw['ver']>=5.5) || - ($bw['ie'] && $bw['ver']>=5 && $bw['mac']) || ($bw['opera'] && $bw['ver']>=7) ? TRUE : FALSE; - - return $bw; -} - - -/** * Send HTTP headers to prevent caching this page */ function send_nocacheing_headers() @@ -93,8 +37,16 @@ header("Expires: ".gmdate("D, d M Y H:i:s")." GMT"); header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT"); - header("Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0"); + header("Cache-Control: private, must-revalidate, post-check=0, pre-check=0"); header("Pragma: no-cache"); + // Request browser to disable DNS prefetching (CVE-2010-0464) + header("X-DNS-Prefetch-Control: off"); + + // We need to set the following headers to make downloads work using IE in HTTPS mode. + if (rcube_https_check()) { + header('Pragma: '); + header('Cache-Control: '); + } } @@ -143,7 +95,7 @@ else header("Last-Modified: ".gmdate("D, d M Y H:i:s", $mdate)." GMT"); - header("Cache-Control: max-age=0"); + header("Cache-Control: private, must-revalidate, max-age=0"); header("Expires: "); header("Pragma: "); @@ -159,72 +111,6 @@ /** - * Convert a variable into a javascript object notation - * - * @param mixed Input value - * @return string Serialized JSON string - */ -function json_serialize($var) -{ - if (is_object($var)) - $var = get_object_vars($var); - - if (is_array($var)) - { - // empty array - if (!sizeof($var)) - return '[]'; - else - { - $keys_arr = array_keys($var); - $is_assoc = $have_numeric = 0; - - for ($i=0; $i<sizeof($keys_arr); ++$i) - { - if (is_numeric($keys_arr[$i])) - $have_numeric = 1; - if (!is_numeric($keys_arr[$i]) || $keys_arr[$i] != $i) - $is_assoc = 1; - if ($is_assoc && $have_numeric) - break; - } - - $brackets = $is_assoc ? '{}' : '[]'; - $pairs = array(); - - foreach ($var as $key => $value) - { - // enclose key with quotes if it is not variable-name conform - if (!ereg("^[_a-zA-Z]{1}[_a-zA-Z0-9]*$", $key) /* || is_js_reserved_word($key) */) - $key = "'$key'"; - - $pairs[] = sprintf("%s%s", $is_assoc ? "$key:" : '', json_serialize($value)); - } - - return $brackets{0} . implode(',', $pairs) . $brackets{1}; - } - } - else if (is_numeric($var) && strval(intval($var)) === strval($var)) - return $var; - else if (is_bool($var)) - return $var ? '1' : '0'; - else - return "'".JQ($var)."'"; - -} - -/** - * Function to convert an array to a javascript array - * Actually an alias function for json_serialize() - * @deprecated - */ -function array2js($arr, $type='') -{ - return json_serialize($arr); -} - - -/** * Similar function as in_array() but case-insensitive * * @param mixed Needle value @@ -233,8 +119,9 @@ */ function in_array_nocase($needle, $haystack) { + $needle = mb_strtolower($needle); foreach ($haystack as $value) - if (strtolower($needle)===strtolower($value)) + if ($needle===mb_strtolower($value)) return true; return false; @@ -250,7 +137,7 @@ function get_boolean($str) { $str = strtolower($str); - if(in_array($str, array('false', '0', 'no', 'nein', ''), TRUE)) + if (in_array($str, array('false', '0', 'no', 'nein', ''), TRUE)) return FALSE; else return TRUE; @@ -261,31 +148,34 @@ * Parse a human readable string for a number of bytes * * @param string Input string - * @return int Number of bytes + * @return float Number of bytes */ function parse_bytes($str) { if (is_numeric($str)) - return intval($str); - - if (preg_match('/([0-9]+)([a-z])/i', $str, $regs)) + return floatval($str); + + if (preg_match('/([0-9\.]+)\s*([a-z]*)/i', $str, $regs)) { $bytes = floatval($regs[1]); switch (strtolower($regs[2])) { case 'g': + case 'gb': $bytes *= 1073741824; break; case 'm': + case 'mb': $bytes *= 1048576; break; case 'k': + case 'kb': $bytes *= 1024; break; } } - return intval($bytes); + return floatval($bytes); } /** @@ -299,17 +189,17 @@ if ($bytes > 1073741824) { $gb = $bytes/1073741824; - $str = sprintf($gb>=10 ? "%d GB" : "%.1f GB", $gb); + $str = sprintf($gb>=10 ? "%d " : "%.1f ", $gb) . rcube_label('GB'); } else if ($bytes > 1048576) { $mb = $bytes/1048576; - $str = sprintf($mb>=10 ? "%d MB" : "%.1f MB", $mb); + $str = sprintf($mb>=10 ? "%d " : "%.1f ", $mb) . rcube_label('MB'); } else if ($bytes > 1024) - $str = sprintf("%d KB", round($bytes/1024)); + $str = sprintf("%d ", round($bytes/1024)) . rcube_label('KB'); else - $str = sprintf('%d B', $bytes); + $str = sprintf('%d ', $bytes) . rcube_label('B'); return $str; } @@ -332,7 +222,7 @@ return $path; // cut base_url to the last directory - if (strpos($base_url, '/')>7) + if (strrpos($base_url, '/')>7) { $host_url = substr($base_url, 0, strpos($base_url, '/')); $base_url = substr($base_url, 0, strrpos($base_url, '/')); @@ -361,62 +251,51 @@ return $abs_path; } - /** - * Wrapper function for strlen + * Wrapper function for wordwrap */ -function rc_strlen($str) +function rc_wordwrap($string, $width=75, $break="\n", $cut=false) { - if (function_exists('mb_strlen')) - return mb_strlen($str); - else - return strlen($str); -} - -/** - * Wrapper function for strtolower - */ -function rc_strtolower($str) -{ - if (function_exists('mb_strtolower')) - return mb_strtolower($str); - else - return strtolower($str); -} + $para = explode($break, $string); + $string = ''; + while (count($para)) { + $list = explode(' ', array_shift($para)); + $len = 0; + while (count($list)) { + $line = array_shift($list); + $l = mb_strlen($line); + $newlen = $len + $l + ($len ? 1 : 0); -/** - * Wrapper function for substr - */ -function rc_substr($str, $start, $len=null) -{ - if (function_exists('mb_substr')) - return mb_substr($str, $start, $len); - else - return substr($str, $start, $len); + if ($newlen <= $width) { + $string .= ($len ? ' ' : '').$line; + $len += (1 + $l); + } else { + if ($l > $width) { + if ($cut) { + $start = 0; + while ($l) { + $str = mb_substr($line, $start, $width); + $strlen = mb_strlen($str); + $string .= ($len ? $break : '').$str; + $start += $strlen; + $l -= $strlen; + $len = $strlen; + } + } else { + $string .= ($len ? $break : '').$line; + if (count($list)) $string .= $break; + $len = 0; + } + } else { + $string .= $break.$line; + $len = $l; + } + } + } + if (count($para)) $string .= $break; + } + return $string; } - -/** - * Wrapper function for strpos - */ -function rc_strpos($haystack, $needle, $offset=0) -{ - if (function_exists('mb_strpos')) - return mb_strpos($haystack, $needle, $offset); - else - return strpos($haystack, $needle, $offset); -} - -/** - * Wrapper function for strrpos - */ -function rc_strrpos($haystack, $needle, $offset=0) -{ - if (function_exists('mb_strrpos')) - return mb_strrpos($haystack, $needle, $offset); - else - return strrpos($haystack, $needle, $offset); -} - /** * Read a specific HTTP request header @@ -440,30 +319,6 @@ return $hdrs[$key]; } - - -/** - * Replace the middle part of a string with ... - * if it is longer than the allowed length - * - * @param string Input string - * @param int Max. length - * @param string Replace removed chars with this - * @return string Abbreviated string - */ -function abbreviate_string($str, $maxlength, $place_holder='...') -{ - $length = rc_strlen($str); - $first_part_length = floor($maxlength/2) - rc_strlen($place_holder); - - if ($length > $maxlength) - { - $second_starting_location = $length - $maxlength + $first_part_length + 1; - $str = rc_substr($str, 0, $first_part_length) . $place_holder . rc_substr($str, $second_starting_location, $length); - } - - return $str; -} /** @@ -544,9 +399,34 @@ /** + * Replace the middle part of a string with ... + * if it is longer than the allowed length + * + * @param string Input string + * @param int Max. length + * @param string Replace removed chars with this + * @return string Abbreviated string + */ +function abbreviate_string($str, $maxlength, $place_holder='...') +{ + $length = mb_strlen($str); + + if ($length > $maxlength) + { + $place_holder_length = mb_strlen($place_holder); + $first_part_length = floor(($maxlength - $place_holder_length)/2); + $second_starting_location = $length - $maxlength + $first_part_length + $place_holder_length; + $str = mb_substr($str, 0, $first_part_length) . $place_holder . mb_substr($str, $second_starting_location); + } + + return $str; +} + +/** * A method to guess the mime_type of an attachment. * * @param string $path Path to the file. + * @param string $name File name (with suffix) * @param string $failover Mime type supplied for failover. * * @return string @@ -554,32 +434,35 @@ * @see http://de2.php.net/manual/en/ref.fileinfo.php * @see http://de2.php.net/mime_content_type */ -function rc_mime_content_type($path, $failover = 'unknown/unknown') +function rc_mime_content_type($path, $name, $failover = 'application/octet-stream') { $mime_type = null; $mime_magic = rcmail::get_instance()->config->get('mime_magic'); + $mime_ext = @include(RCMAIL_CONFIG_DIR . '/mimetypes.php'); + $suffix = $name ? substr($name, strrpos($name, '.')+1) : '*'; - if (!extension_loaded('fileinfo')) { - @dl('fileinfo.' . PHP_SHLIB_SUFFIX); + // use file name suffix with hard-coded mime-type map + if (is_array($mime_ext)) { + $mime_type = $mime_ext[$suffix]; } - - if (function_exists('finfo_open')) { + // try fileinfo extension if available + if (!$mime_type && function_exists('finfo_open')) { if ($finfo = finfo_open(FILEINFO_MIME, $mime_magic)) { $mime_type = finfo_file($finfo, $path); finfo_close($finfo); } } + // try PHP's mime_content_type if (!$mime_type && function_exists('mime_content_type')) { - $mime_type = mime_content_type($path); + $mime_type = mime_content_type($path); } - + // fall back to user-submitted string if (!$mime_type) { $mime_type = $failover; } return $mime_type; } - /** * A method to guess encoding of a string. @@ -598,10 +481,12 @@ // FIXME: the order is important, because sometimes // iso string is detected as euc-jp and etc. $enc = array( - 'UTF-8', 'ISO-8859-1', 'ISO-8859-2', 'ISO-8859-3', 'ISO-8859-4', - 'ISO-8859-5', 'ISO-8859-6', 'ISO-8859-7', 'ISO-8859-8', 'ISO-8859-9', - 'ISO-8859-10', 'ISO-8859-13', 'ISO-8859-14', 'ISO-8859-15', 'ISO-8859-16', - 'WINDOWS-1252', 'WINDOWS-1251', 'EUC-JP', 'EUC-TW', 'KOI8-R' + 'UTF-8', 'SJIS', 'BIG5', 'GB2312', + 'ISO-8859-1', 'ISO-8859-2', 'ISO-8859-3', 'ISO-8859-4', + 'ISO-8859-5', 'ISO-8859-6', 'ISO-8859-7', 'ISO-8859-8', 'ISO-8859-9', + 'ISO-8859-10', 'ISO-8859-13', 'ISO-8859-14', 'ISO-8859-15', 'ISO-8859-16', + 'WINDOWS-1252', 'WINDOWS-1251', 'EUC-JP', 'EUC-TW', 'KOI8-R', + 'ISO-2022-KR', 'ISO-2022-JP' ); $result = mb_detect_encoding($string, join(',', $enc)); @@ -609,4 +494,154 @@ return $result ? $result : $failover; } +/** + * Removes non-unicode characters from input + * + * @param mixed $input String or array. + * @return string + */ +function rc_utf8_clean($input) +{ + // handle input of type array + if (is_array($input)) { + foreach ($input as $idx => $val) + $input[$idx] = rc_utf8_clean($val); + return $input; + } + + if (!is_string($input) || $input == '') + return $input; + + // iconv/mbstring are much faster (especially with long strings) + if (function_exists('mb_convert_encoding') && ($res = mb_convert_encoding($input, 'UTF-8', 'UTF-8')) !== false) + return $res; + + if (function_exists('iconv') && ($res = @iconv('UTF-8', 'UTF-8//IGNORE', $input)) !== false) + return $res; + + $regexp = '/^('. +// '[\x00-\x7F]'. // UTF8-1 + '|[\xC2-\xDF][\x80-\xBF]'. // UTF8-2 + '|\xE0[\xA0-\xBF][\x80-\xBF]'. // UTF8-3 + '|[\xE1-\xEC][\x80-\xBF][\x80-\xBF]'. // UTF8-3 + '|\xED[\x80-\x9F][\x80-\xBF]'. // UTF8-3 + '|[\xEE-\xEF][\x80-\xBF][\x80-\xBF]'. // UTF8-3 + '|\xF0[\x90-\xBF][\x80-\xBF][\x80-\xBF]'. // UTF8-4 + '|[\xF1-\xF3][\x80-\xBF][\x80-\xBF][\x80-\xBF]'.// UTF8-4 + '|\xF4[\x80-\x8F][\x80-\xBF][\x80-\xBF]'. // UTF8-4 + ')$/'; + + $seq = ''; + $out = ''; + + for ($i = 0, $len = strlen($input); $i < $len; $i++) { + $chr = $input[$i]; + $ord = ord($chr); + // 1-byte character + if ($ord <= 0x7F) { + if ($seq) + $out .= preg_match($regexp, $seq) ? $seq : ''; + $seq = ''; + $out .= $chr; + // first (or second) byte of multibyte sequence + } else if ($ord >= 0xC0) { + if (strlen($seq)>1) { + $out .= preg_match($regexp, $seq) ? $seq : ''; + $seq = ''; + } else if ($seq && ord($seq) < 0xC0) { + $seq = ''; + } + $seq .= $chr; + // next byte of multibyte sequence + } else if ($seq) { + $seq .= $chr; + } + } + + if ($seq) + $out .= preg_match($regexp, $seq) ? $seq : ''; + + return $out; +} + + +/** + * Convert a variable into a javascript object notation + * + * @param mixed Input value + * @return string Serialized JSON string + */ +function json_serialize($input) +{ + $input = rc_utf8_clean($input); + + // sometimes even using rc_utf8_clean() the input contains invalid UTF-8 sequences + // that's why we have @ here + return @json_encode($input); +} + + +/** + * Explode quoted string + * + * @param string Delimiter expression string for preg_match() + * @param string Input string + */ +function rcube_explode_quoted_string($delimiter, $string) +{ + $result = array(); + $strlen = strlen($string); + + for ($q=$p=$i=0; $i < $strlen; $i++) { + if ($string[$i] == "\"" && $string[$i-1] != "\\") { + $q = $q ? false : true; + } + else if (!$q && preg_match("/$delimiter/", $string[$i])) { + $result[] = substr($string, $p, $i - $p); + $p = $i + 1; + } + } + + $result[] = substr($string, $p); + return $result; +} + + +/** + * mbstring replacement functions + */ + +if (!extension_loaded('mbstring')) +{ + function mb_strlen($str) + { + return strlen($str); + } + + function mb_strtolower($str) + { + return strtolower($str); + } + + function mb_strtoupper($str) + { + return strtoupper($str); + } + + function mb_substr($str, $start, $len=null) + { + return substr($str, $start, $len); + } + + function mb_strpos($haystack, $needle, $offset=0) + { + return strpos($haystack, $needle, $offset); + } + + function mb_strrpos($haystack, $needle, $offset=0) + { + return strrpos($haystack, $needle, $offset); + } +} + ?> -- Gitblit v1.9.1