+ return rcube_charset_convert($name, 'UTF7-IMAP');
+}
+
+
+function rcmail_quota_display($attrib)
+{
+ global $OUTPUT;
+
+ if (!$attrib['id'])
+ $attrib['id'] = 'rcmquotadisplay';
+
+ if(isset($attrib['display']))
+ $_SESSION['quota_display'] = $attrib['display'];
+
+ $OUTPUT->add_gui_object('quotadisplay', $attrib['id']);
+
+ $quota = rcmail_quota_content($attrib);
+
+ $OUTPUT->add_script('$(document).ready(function(){
+ rcmail.set_quota('.json_serialize($quota).')});', 'foot');
+
+ return html::span($attrib, '');
+}
+
+
+function rcmail_quota_content($attrib=NULL)
+{
+ global $RCMAIL;
+
+ $quota = $RCMAIL->imap->get_quota();
+ $quota = $RCMAIL->plugins->exec_hook('quota', $quota);
+
+ $quota_result = (array) $quota;
+ $quota_result['type'] = isset($_SESSION['quota_display']) ? $_SESSION['quota_display'] : '';
+
+ if (!$quota['total'] && $RCMAIL->config->get('quota_zero_as_unlimited')) {
+ $quota_result['title'] = rcube_label('unlimited');
+ $quota_result['percent'] = 0;
+ }
+ else if ($quota['total']) {
+ if (!isset($quota['percent']))
+ $quota_result['percent'] = min(100, round(($quota['used']/max(1,$quota['total']))*100));
+
+ $title = sprintf('%s / %s (%.0f%%)',
+ show_bytes($quota['used'] * 1024), show_bytes($quota['total'] * 1024),
+ $quota_result['percent']);
+
+ $quota_result['title'] = $title;
+
+ if ($attrib['width'])
+ $quota_result['width'] = $attrib['width'];
+ if ($attrib['height'])
+ $quota_result['height'] = $attrib['height'];
+ }
+ else {
+ $quota_result['title'] = rcube_label('unknown');
+ $quota_result['percent'] = 0;
+ }
+
+ return $quota_result;
+}
+
+
+/**
+ * Outputs error message according to server error/response codes
+ *
+ * @param string Fallback message label
+ * @param string Fallback message label arguments
+ *
+ * @return void
+ */
+function rcmail_display_server_error($fallback=null, $fallback_args=null)
+{
+ global $RCMAIL;
+
+ $err_code = $RCMAIL->imap->get_error_code();
+ $res_code = $RCMAIL->imap->get_response_code();
+
+ if ($res_code == rcube_imap::NOPERM) {
+ $RCMAIL->output->show_message('errornoperm', 'error');
+ }
+ else if ($res_code == rcube_imap::READONLY) {
+ $RCMAIL->output->show_message('errorreadonly', 'error');
+ }
+ else if ($err_code && ($err_str = $RCMAIL->imap->get_error_str())) {
+ $RCMAIL->output->show_message('servererrormsg', 'error', array('msg' => $err_str));
+ }
+ else if ($fallback) {
+ $RCMAIL->output->show_message($fallback, 'error', $fallback_args);
+ }
+
+ return true;
+}
+
+
+/**
+ * Output HTML editor scripts
+ *
+ * @param string Editor mode
+ * @return void
+ */
+function rcube_html_editor($mode='')
+{
+ global $RCMAIL, $CONFIG;
+
+ $hook = $RCMAIL->plugins->exec_hook('hmtl_editor', array('mode' => $mode));
+
+ if ($hook['abort'])
+ return;
+
+ $lang = strtolower($_SESSION['language']);
+
+ // TinyMCE uses 'tw' for zh_TW (which is wrong, because tw is a code of Twi language)
+ $lang = ($lang == 'zh_tw') ? 'tw' : substr($lang, 0, 2);
+
+ if (!file_exists(INSTALL_PATH . 'program/js/tiny_mce/langs/'.$lang.'.js'))
+ $lang = 'en';
+
+ $RCMAIL->output->include_script('tiny_mce/tiny_mce.js');
+ $RCMAIL->output->include_script('editor.js');
+ $RCMAIL->output->add_script(sprintf("rcmail_editor_init('\$__skin_path', '%s', %d, '%s');",
+ JQ($lang), intval($CONFIG['enable_spellcheck']), $mode),
+ 'foot');
+}
+
+
+/**
+ * Replaces TinyMCE's emoticon images with plain-text representation
+ *
+ * @param string HTML content
+ * @return string HTML content
+ */
+function rcmail_replace_emoticons($html)
+{
+ $emoticons = array(
+ '8-)' => 'smiley-cool',
+ ':-#' => 'smiley-foot-in-mouth',
+ ':-*' => 'smiley-kiss',
+ ':-X' => 'smiley-sealed',
+ ':-P' => 'smiley-tongue-out',
+ ':-@' => 'smiley-yell',
+ ":'(" => 'smiley-cry',
+ ':-(' => 'smiley-frown',
+ ':-D' => 'smiley-laughing',
+ ':-)' => 'smiley-smile',
+ ':-S' => 'smiley-undecided',
+ ':-$' => 'smiley-embarassed',
+ 'O:-)' => 'smiley-innocent',
+ ':-|' => 'smiley-money-mouth',
+ ':-O' => 'smiley-surprised',
+ ';-)' => 'smiley-wink',
+ );
+
+ foreach ($emoticons as $idx => $file) {
+ // <img title="Cry" src="http://.../program/js/tiny_mce/plugins/emotions/img/smiley-cry.gif" border="0" alt="Cry" />
+ $search[] = '/<img title="[a-z ]+" src="https?:\/\/[a-z0-9_.\/-]+\/tiny_mce\/plugins\/emotions\/img\/'.$file.'.gif"[^>]+\/>/i';
+ $replace[] = $idx;
+ }
+
+ return preg_replace($search, $replace, $html);
+}
+
+
+/**
+ * Check if working in SSL mode
+ *
+ * @param integer HTTPS port number
+ * @param boolean Enables 'use_https' option checking
+ * @return boolean
+ */
+function rcube_https_check($port=null, $use_https=true)
+{
+ global $RCMAIL;
+
+ if (!empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) != 'off')
+ return true;
+ if (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) == 'https')
+ return true;
+ if ($port && $_SERVER['SERVER_PORT'] == $port)
+ return true;
+ if ($use_https && isset($RCMAIL) && $RCMAIL->config->get('use_https'))
+ return true;
+
+ return false;
+}
+
+
+/**
+ * For backward compatibility.
+ *
+ * @global rcmail $RCMAIL
+ * @param string $var_name Variable name.
+ * @return void
+ */
+function rcube_sess_unset($var_name=null)
+{
+ global $RCMAIL;
+
+ $RCMAIL->session->remove($var_name);
+}
+
+
+
+/**
+ * Replaces hostname variables
+ *
+ * @param string $name Hostname
+ * @param string $host Optional IMAP hostname
+ * @return string
+ */
+function rcube_parse_host($name, $host='')
+{
+ // %n - host
+ $n = preg_replace('/:\d+$/', '', $_SERVER['SERVER_NAME']);
+ // %d - domain name without first part, e.g. %d=mail.domain.tld, %m=domain.tld
+ $d = preg_replace('/^[^\.]+\./', '', $n);
+ // %h - IMAP host
+ $h = $_SESSION['imap_host'] ? $_SESSION['imap_host'] : $host;
+ // %z - IMAP domain without first part, e.g. %h=imap.domain.tld, %z=domain.tld
+ $z = preg_replace('/^[^\.]+\./', '', $h);
+
+ $name = str_replace(array('%n', '%d', '%h', '%z'), array($n, $d, $h, $z), $name);
+ return $name;
+}
+
+
+/**
+ * E-mail address validation
+ *
+ * @param string $email Email address
+ * @param boolean $dns_check True to check dns
+ * @return boolean
+ */
+function check_email($email, $dns_check=true)
+{
+ // Check for invalid characters
+ if (preg_match('/[\x00-\x1F\x7F-\xFF]/', $email))
+ return false;
+
+ // Check for length limit specified by RFC 5321 (#1486453)
+ if (strlen($email) > 254)
+ return false;
+
+ $email_array = explode('@', $email);
+
+ // Check that there's one @ symbol
+ if (count($email_array) < 2)
+ return false;
+
+ $domain_part = array_pop($email_array);
+ $local_part = implode('@', $email_array);
+
+ // from PEAR::Validate
+ $regexp = '&^(?:
+ ("\s*(?:[^"\f\n\r\t\v\b\s]+\s*)+")| #1 quoted name
+ ([-\w!\#\$%\&\'*+~/^`|{}=]+(?:\.[-\w!\#\$%\&\'*+~/^`|{}=]+)*)) #2 OR dot-atom (RFC5322)
+ $&xi';
+
+ if (!preg_match($regexp, $local_part))
+ return false;
+
+ // Check domain part
+ if (preg_match('/^\[*(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}\]*$/', $domain_part))
+ return true; // IP address
+ else {
+ // If not an IP address
+ $domain_array = explode('.', $domain_part);
+ if (sizeof($domain_array) < 2)
+ return false; // Not enough parts to be a valid domain
+
+ foreach ($domain_array as $part)
+ if (!preg_match('/^(([A-Za-z0-9][A-Za-z0-9-]{0,61}[A-Za-z0-9])|([A-Za-z0-9]))$/', $part))
+ return false;
+
+ if (!$dns_check || !rcmail::get_instance()->config->get('email_dns_check'))
+ return true;
+
+ if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN' && version_compare(PHP_VERSION, '5.3.0', '<')) {
+ $lookup = array();
+ @exec("nslookup -type=MX " . escapeshellarg($domain_part) . " 2>&1", $lookup);
+ foreach ($lookup as $line) {
+ if (strpos($line, 'MX preference'))
+ return true;
+ }
+ return false;
+ }
+
+ // find MX record(s)
+ if (getmxrr($domain_part, $mx_records))
+ return true;
+
+ // find any DNS record
+ if (checkdnsrr($domain_part, 'ANY'))
+ return true;
+ }
+
+ return false;
+}
+
+/*
+ * Idn_to_ascii wrapper.
+ * Intl/Idn modules version of this function doesn't work with e-mail address
+ */
+function rcube_idn_to_ascii($str)
+{
+ return rcube_idn_convert($str, true);
+}
+
+/*
+ * Idn_to_ascii wrapper.
+ * Intl/Idn modules version of this function doesn't work with e-mail address
+ */
+function rcube_idn_to_utf8($str)
+{
+ return rcube_idn_convert($str, false);
+}
+
+function rcube_idn_convert($input, $is_utf=false)
+{
+ if ($at = strpos($input, '@')) {
+ $user = substr($input, 0, $at);
+ $domain = substr($input, $at+1);
+ }
+ else {
+ $domain = $input;
+ }
+
+ $domain = $is_utf ? idn_to_ascii($domain) : idn_to_utf8($domain);
+
+ return $at ? $user . '@' . $domain : $domain;
+}
+
+
+/**
+ * Helper class to turn relative urls into absolute ones
+ * using a predefined base
+ */
+class rcube_base_replacer
+{
+ private $base_url;
+
+ public function __construct($base)
+ {
+ $this->base_url = $base;
+ }
+
+ public function callback($matches)
+ {
+ return $matches[1] . '="' . make_absolute_url($matches[3], $this->base_url) . '"';
+ }
+}
+
+
+/**
+ * Throw system error and show error page
+ *
+ * @param array Named parameters
+ * - code: Error code (required)
+ * - type: Error type [php|db|imap|javascript] (required)
+ * - message: Error message
+ * - file: File where error occured
+ * - line: Line where error occured
+ * @param boolean True to log the error
+ * @param boolean Terminate script execution
+ */
+// may be defined in Installer
+if (!function_exists('raise_error')) {
+function raise_error($arg=array(), $log=false, $terminate=false)
+{
+ global $__page_content, $CONFIG, $OUTPUT, $ERROR_CODE, $ERROR_MESSAGE;
+
+ // report bug (if not incompatible browser)
+ if ($log && $arg['type'] && $arg['message'])
+ log_bug($arg);
+
+ // display error page and terminate script
+ if ($terminate) {
+ $ERROR_CODE = $arg['code'];
+ $ERROR_MESSAGE = $arg['message'];
+ include('program/steps/utils/error.inc');
+ exit;
+ }