thomascube
2011-12-09 2b017e7f79be26563ab767bb9e97fee5d88a01f4
program/include/main.inc
@@ -97,9 +97,9 @@
 *
 * @see rcmail::text_exists()
 */
function rcube_label_exists($name, $domain=null)
function rcube_label_exists($name, $domain=null, &$ref_domain = null)
{
  return rcmail::get_instance()->text_exists($name, $domain);
  return rcmail::get_instance()->text_exists($name, $domain, $ref_domain);
}
@@ -169,11 +169,17 @@
  // get target timestamp
  $ts = get_offset_time($rcmail->config->get('message_cache_lifetime', '30d'), -1);
  $db->query("DELETE FROM ".get_table_name('messages')."
             WHERE  created < " . $db->fromunixtime($ts));
  $db->query("DELETE FROM ".get_table_name('cache_messages')
        ." WHERE changed < " . $db->fromunixtime($ts));
  $db->query("DELETE FROM ".get_table_name('cache')."
              WHERE  created < " . $db->fromunixtime($ts));
  $db->query("DELETE FROM ".get_table_name('cache_index')
        ." WHERE changed < " . $db->fromunixtime($ts));
  $db->query("DELETE FROM ".get_table_name('cache_thread')
        ." WHERE changed < " . $db->fromunixtime($ts));
  $db->query("DELETE FROM ".get_table_name('cache')
        ." WHERE created < " . $db->fromunixtime($ts));
}
@@ -634,20 +640,23 @@
function get_input_value($fname, $source, $allow_html=FALSE, $charset=NULL)
{
  $value = NULL;
  if ($source==RCUBE_INPUT_GET && isset($_GET[$fname]))
    $value = $_GET[$fname];
  else if ($source==RCUBE_INPUT_POST && isset($_POST[$fname]))
    $value = $_POST[$fname];
  else if ($source==RCUBE_INPUT_GPC)
    {
  if ($source == RCUBE_INPUT_GET) {
    if (isset($_GET[$fname]))
      $value = $_GET[$fname];
  }
  else if ($source == RCUBE_INPUT_POST) {
    if (isset($_POST[$fname]))
      $value = $_POST[$fname];
  }
  else if ($source == RCUBE_INPUT_GPC) {
    if (isset($_POST[$fname]))
      $value = $_POST[$fname];
    else if (isset($_GET[$fname]))
      $value = $_GET[$fname];
    else if (isset($_COOKIE[$fname]))
      $value = $_COOKIE[$fname];
    }
  }
  return parse_input_value($value, $allow_html, $charset);
}
@@ -655,7 +664,7 @@
/**
 * Parse/validate input value. See get_input_value()
 * Performs stripslashes() and charset conversion if necessary
 *
 *
 * @param  string   Input value
 * @param  boolean  Allow HTML tags in field value
 * @param  string   Charset to convert into
@@ -681,15 +690,21 @@
  else if (get_magic_quotes_gpc() || get_magic_quotes_runtime())
    $value = stripslashes($value);
  // remove HTML tags if not allowed
  // remove HTML tags if not allowed
  if (!$allow_html)
    $value = strip_tags($value);
  $output_charset = is_object($OUTPUT) ? $OUTPUT->get_charset() : null;
  // remove invalid characters (#1488124)
  if ($output_charset == 'UTF-8')
    $value = rc_utf8_clean($value);
  // convert to internal charset
  if (is_object($OUTPUT) && $charset)
    return rcube_charset_convert($value, $OUTPUT->get_charset(), $charset);
  else
    return $value;
  if ($charset && $output_charset)
    $value = rcube_charset_convert($value, $output_charset, $charset);
  return $value;
}
/**
@@ -699,15 +714,16 @@
 * @param  int   Source to get value from (GPC)
 * @return array Hash array with all request parameters
 */
function request2param($mode = RCUBE_INPUT_GPC)
function request2param($mode = RCUBE_INPUT_GPC, $ignore = 'task|action')
{
  $out = array();
  $src = $mode == RCUBE_INPUT_GET ? $_GET : ($mode == RCUBE_INPUT_POST ? $_POST : $_REQUEST);
  foreach ($src as $key => $value) {
    $fname = $key[0] == '_' ? substr($key, 1) : $key;
    $out[$fname] = get_input_value($key, $mode);
    if ($ignore && !preg_match('/^(' . $ignore . ')$/', $fname))
      $out[$fname] = get_input_value($key, $mode);
  }
  return $out;
}
@@ -723,12 +739,14 @@
/**
 * Convert the given string into a valid HTML identifier
 * Same functionality as done in app.js with this.identifier_expr
 *
 * Same functionality as done in app.js with rcube_webmail.html_identifier()
 */
function html_identifier($str)
function html_identifier($str, $encode=false)
{
  return asciiwords($str, true, '_');
  if ($encode)
    return rtrim(strtr(base64_encode($str), '+/', '-_'), '=');
  else
    return asciiwords($str, true, '_');
}
/**
@@ -765,52 +783,48 @@
 * @return string HTML table code
 */
function rcube_table_output($attrib, $table_data, $a_show_cols, $id_col)
  {
{
  global $RCMAIL;
  $table = new html_table(/*array('cols' => count($a_show_cols))*/);
  // add table header
  if (!$attrib['noheader'])
    foreach ($a_show_cols as $col)
      $table->add_header($col, Q(rcube_label($col)));
  $c = 0;
  if (!is_array($table_data))
  if (!is_array($table_data))
  {
    $db = $RCMAIL->get_dbh();
    while ($table_data && ($sql_arr = $db->fetch_assoc($table_data)))
    {
      $zebra_class = $c % 2 ? 'even' : 'odd';
      $table->add_row(array('id' => 'rcmrow' . html_identifier($sql_arr[$id_col]), 'class' => $zebra_class));
      $table->add_row(array('id' => 'rcmrow' . html_identifier($sql_arr[$id_col])));
      // format each col
      foreach ($a_show_cols as $col)
        $table->add($col, Q($sql_arr[$col]));
      $c++;
    }
  }
  else
  {
  else {
    foreach ($table_data as $row_data)
    {
      $zebra_class = $c % 2 ? 'even' : 'odd';
      if (!empty($row_data['class']))
        $zebra_class .= ' '.$row_data['class'];
      $class = !empty($row_data['class']) ? $row_data['class'] : '';
      $table->add_row(array('id' => 'rcmrow' . html_identifier($row_data[$id_col]), 'class' => $zebra_class));
      $table->add_row(array('id' => 'rcmrow' . html_identifier($row_data[$id_col]), 'class' => $class));
      // format each col
      foreach ($a_show_cols as $col)
        $table->add($col, Q(is_array($row_data[$col]) ? $row_data[$col][0] : $row_data[$col]));
      $c++;
    }
  }
  return $table->show($attrib);
  }
}
/**
@@ -869,18 +883,18 @@
 * @param string Container ID to use as prefix
 * @return string Modified CSS source
 */
function rcmail_mod_css_styles($source, $container_id)
function rcmail_mod_css_styles($source, $container_id, $allow_remote=false)
  {
  $last_pos = 0;
  $replacements = new rcube_string_replacer;
  // ignore the whole block if evil styles are detected
  $stripped = preg_replace('/[^a-z\(:;]/', '', rcmail_xss_entity_decode($source));
  if (preg_match('/expression|behavior|url\(|import[^a]/', $stripped))
  $source = rcmail_xss_entity_decode($source);
  $stripped = preg_replace('/[^a-z\(:;]/i', '', $source);
  $evilexpr = 'expression|behavior' . (!$allow_remote ? '|url\(|import[^a]' : '');
  if (preg_match("/$evilexpr/i", $stripped) // don't accept No-Gos
      || (strpos($stripped, 'url(') && !preg_match('!url\s*\([ "\'](https?:)//[a-z0-9/._+-]+["\' ]\)!Ui', $source))) // only allow clean urls
    return '/* evil! */';
  // remove css comments (sometimes used for some ugly hacks)
  $source = preg_replace('!/\*(.+)\*/!Ums', '', $source);
  // cut out all contents between { and }
  while (($pos = strpos($source, '{', $last_pos)) && ($pos2 = strpos($source, '}', $pos)))
@@ -923,7 +937,7 @@
{
  $out = html_entity_decode(html_entity_decode($content));
  $out = preg_replace_callback('/\\\([0-9a-f]{4})/i', 'rcmail_xss_entity_decode_callback', $out);
  $out = preg_replace('#/\*.*\*/#Um', '', $out);
  $out = preg_replace('#/\*.*\*/#Ums', '', $out);
  return $out;
}
@@ -1015,15 +1029,15 @@
 * Convert the given date to a human readable form
 * This uses the date formatting properties from config
 *
 * @param mixed Date representation (string or timestamp)
 * @param mixed  Date representation (string or timestamp)
 * @param string Date format to use
 * @param bool   Enables date convertion according to user timezone
 *
 * @return string Formatted date string
 */
function format_date($date, $format=NULL)
function format_date($date, $format=NULL, $convert=true)
{
  global $CONFIG;
  $ts = NULL;
  global $RCMAIL, $CONFIG;
  if (!empty($date))
    $ts = rcube_strtotime($date);
@@ -1031,37 +1045,37 @@
  if (empty($ts))
    return '';
  // get user's timezone
  if ($CONFIG['timezone'] === 'auto')
    $tz = isset($_SESSION['timezone']) ? $_SESSION['timezone'] : date('Z')/3600;
  else {
    $tz = $CONFIG['timezone'];
    if ($CONFIG['dst_active'])
      $tz++;
  if ($convert) {
    // get user's timezone offset
    $tz = $RCMAIL->config->get_timezone();
    // convert time to user's timezone
    $timestamp = $ts - date('Z', $ts) + ($tz * 3600);
    // get current timestamp in user's timezone
    $now = time();  // local time
    $now -= (int)date('Z'); // make GMT time
    $now += ($tz * 3600); // user's time
  }
  // convert time to user's timezone
  $timestamp = $ts - date('Z', $ts) + ($tz * 3600);
  // get current timestamp in user's timezone
  $now = time();  // local time
  $now -= (int)date('Z'); // make GMT time
  $now += ($tz * 3600); // user's time
  $now_date = getdate($now);
  $today_limit = mktime(0, 0, 0, $now_date['mon'], $now_date['mday'], $now_date['year']);
  $week_limit  = mktime(0, 0, 0, $now_date['mon'], $now_date['mday']-6, $now_date['year']);
  else {
    $now       = time();
    $timestamp = $ts;
  }
  // define date format depending on current time
  if (!$format) {
    $now_date    = getdate($now);
    $today_limit = mktime(0, 0, 0, $now_date['mon'], $now_date['mday'], $now_date['year']);
    $week_limit  = mktime(0, 0, 0, $now_date['mon'], $now_date['mday']-6, $now_date['year']);
    if ($CONFIG['prettydate'] && $timestamp > $today_limit && $timestamp < $now) {
      $format = $CONFIG['date_today'] ? $CONFIG['date_today'] : 'H:i';
      $format = $RCMAIL->config->get('date_today', $RCMAIL->config->get('time_format', 'H:i'));
      $today  = true;
    }
    else if ($CONFIG['prettydate'] && $timestamp > $week_limit && $timestamp < $now)
      $format = $CONFIG['date_short'] ? $CONFIG['date_short'] : 'D H:i';
      $format = $RCMAIL->config->get('date_short', 'D H:i');
    else
      $format = $CONFIG['date_long'] ? $CONFIG['date_long'] : 'd.m.Y H:i';
      $format = $RCMAIL->config->get('date_long', 'Y-m-d H:i');
  }
  // strftime() format
@@ -1213,9 +1227,9 @@
    $p['folder_name'] = '*';
  if ($p['unsubscribed'])
    $list = $RCMAIL->imap->list_unsubscribed('', $p['folder_name'], $p['folder_filter']);
    $list = $RCMAIL->imap->list_unsubscribed('', $p['folder_name'], $p['folder_filter'], $p['folder_rights']);
  else
    $list = $RCMAIL->imap->list_mailboxes('', $p['folder_name'], $p['folder_filter']);
    $list = $RCMAIL->imap->list_mailboxes('', $p['folder_name'], $p['folder_filter'], $p['folder_rights']);
  $delimiter = $RCMAIL->imap->get_hierarchy_delimiter();
@@ -1229,7 +1243,7 @@
  if ($p['noselection'])
    $select->add($p['noselection'], '');
  rcmail_render_folder_tree_select($a_mailboxes, $mbox, $p['maxlength'], $select, $p['realnames']);
  rcmail_render_folder_tree_select($a_mailboxes, $mbox, $p['maxlength'], $select, $p['realnames'], 0, $p);
  return $select;
}
@@ -1278,11 +1292,6 @@
  $path .= $prefix.$currentFolder;
  if (!isset($arrFolders[$currentFolder])) {
    // Check \Noselect option (if options are in cache)
    if (!$virtual && ($opts = $RCMAIL->imap->mailbox_options($path))) {
      $virtual = in_array('\\Noselect', $opts);
    }
    $arrFolders[$currentFolder] = array(
      'id' => $path,
      'name' => rcube_charset_convert($currentFolder, 'UTF7-IMAP'),
@@ -1310,13 +1319,14 @@
  $realnames = (bool)$attrib['realnames'];
  $msgcounts = $RCMAIL->imap->get_cache('messagecount');
  $idx = 0;
  $out = '';
  foreach ($arrFolders as $key => $folder) {
    $zebra_class = (($nestLevel+1)*$idx) % 2 == 0 ? 'even' : 'odd';
    $title = null;
    $title        = null;
    $folder_class = rcmail_folder_classname($folder['id']);
    $collapsed    = strpos($CONFIG['collapsed_folders'], '&'.rawurlencode($folder['id']).'&') !== false;
    $unread       = $msgcounts ? intval($msgcounts[$folder['id']]['UNSEEN']) : 0;
    if (($folder_class = rcmail_folder_classname($folder['id'])) && !$realnames) {
    if ($folder_class && !$realnames) {
      $foldername = rcube_label($folder_class);
    }
    else {
@@ -1332,30 +1342,15 @@
    }
    // make folder name safe for ids and class names
    $folder_id = html_identifier($folder['id']);
    $folder_id = html_identifier($folder['id'], true);
    $classes = array('mailbox');
    // set special class for Sent, Drafts, Trash and Junk
    if ($folder['id'] == $CONFIG['sent_mbox'])
      $classes[] = 'sent';
    else if ($folder['id'] == $CONFIG['drafts_mbox'])
      $classes[] = 'drafts';
    else if ($folder['id'] == $CONFIG['trash_mbox'])
      $classes[] = 'trash';
    else if ($folder['id'] == $CONFIG['junk_mbox'])
      $classes[] = 'junk';
    else if ($folder['id'] == 'INBOX')
      $classes[] = 'inbox';
    else
      $classes[] = '_'.asciiwords($folder_class ? $folder_class : strtolower($folder['id']), true);
    $classes[] = $zebra_class;
    if ($folder_class)
      $classes[] = $folder_class;
    if ($folder['id'] == $mbox_name)
      $classes[] = 'selected';
    $collapsed = strpos($CONFIG['collapsed_folders'], '&'.rawurlencode($folder['id']).'&') !== false;
    $unread = $msgcounts ? intval($msgcounts[$folder['id']]['UNSEEN']) : 0;
    if ($folder['virtual'])
      $classes[] = 'virtual';
@@ -1390,7 +1385,6 @@
    }
    $out .= "</li>\n";
    $idx++;
  }
  return $out;
@@ -1402,11 +1396,25 @@
 * @access private
 * @return string
 */
function rcmail_render_folder_tree_select(&$arrFolders, &$mbox_name, $maxlength, &$select, $realnames=false, $nestLevel=0)
function rcmail_render_folder_tree_select(&$arrFolders, &$mbox_name, $maxlength, &$select, $realnames=false, $nestLevel=0, $opts=array())
{
  global $RCMAIL;
  $out = '';
  foreach ($arrFolders as $key=>$folder) {
  foreach ($arrFolders as $key => $folder) {
    // skip exceptions (and its subfolders)
    if (!empty($opts['exceptions']) && in_array($folder['id'], $opts['exceptions'])) {
      continue;
    }
    // skip folders in which it isn't possible to create subfolders
    if (!empty($opts['skip_noinferiors']) && ($attrs = $RCMAIL->imap->mailbox_attributes($folder['id']))
        && in_array('\\Noinferiors', $attrs)
    ) {
      continue;
    }
    if (!$realnames && ($folder_class = rcmail_folder_classname($folder['id'])))
      $foldername = rcube_label($folder_class);
    else {
@@ -1420,7 +1428,8 @@
    $select->add(str_repeat('&nbsp;', $nestLevel*4) . $foldername, $folder['id']);
    if (!empty($folder['folders']))
      $out .= rcmail_render_folder_tree_select($folder['folders'], $mbox_name, $maxlength, $select, $realnames, $nestLevel+1);
      $out .= rcmail_render_folder_tree_select($folder['folders'], $mbox_name, $maxlength,
        $select, $realnames, $nestLevel+1, $opts);
  }
  return $out;
@@ -1461,6 +1470,31 @@
    return rcube_label($folder_class);
  else
    return rcube_charset_convert($name, 'UTF7-IMAP');
}
function rcmail_localize_folderpath($path)
{
    global $RCMAIL;
    $protect_folders = $RCMAIL->config->get('protect_default_folders');
    $default_folders = (array) $RCMAIL->config->get('default_imap_folders');
    $delimiter       = $RCMAIL->imap->get_hierarchy_delimiter();
    $path            = explode($delimiter, $path);
    $result          = array();
    foreach ($path as $idx => $dir) {
        $directory = implode($delimiter, array_slice($path, 0, $idx+1));
        if ($protect_folders && in_array($directory, $default_folders)) {
            unset($result);
            $result[] = rcmail_localize_foldername($directory);
        }
        else {
            $result[] = rcube_charset_convert($dir, 'UTF7-IMAP');
        }
    }
    return implode($delimiter, $result);
}
@@ -1544,7 +1578,11 @@
        $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));
        // try to detect access rights problem and display appropriate message
        if (stripos($err_str, 'Permission denied') !== false)
            $RCMAIL->output->show_message('errornoperm', 'error');
        else
            $RCMAIL->output->show_message('servererrormsg', 'error', array('msg' => $err_str));
    }
    else if ($fallback) {
        $RCMAIL->output->show_message($fallback, 'error', $fallback_args);
@@ -1562,26 +1600,34 @@
 */
function rcube_html_editor($mode='')
{
  global $RCMAIL, $CONFIG;
  global $RCMAIL;
  $hook = $RCMAIL->plugins->exec_hook('html_editor', array('mode' => $mode));
  if ($hook['abort'])
    return;
    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);
  // TinyMCE uses two-letter lang codes, with exception of Chinese
  if (strpos($lang, 'zh_') === 0)
    $lang = str_replace('_', '-', $lang);
  else
    $lang = 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');
  $RCMAIL->output->add_script(sprintf("rcmail_editor_init(%s)",
    json_encode(array(
        'mode'       => $mode,
        'skin_path'  => '$__skin_path',
        'lang'       => $lang,
        'spellcheck' => intval($RCMAIL->config->get('enable_spellcheck')),
        'spelldict'  => intval($RCMAIL->config->get('spellcheck_dictionary')),
    ))), 'foot');
}
@@ -1619,6 +1665,207 @@
  }
  return preg_replace($search, $replace, $html);
}
/**
 * Send the given message using the configured method
 *
 * @param object $message    Reference to Mail_MIME object
 * @param string $from       Sender address string
 * @param array  $mailto     Array of recipient address strings
 * @param array  $smtp_error SMTP error array (reference)
 * @param string $body_file  Location of file with saved message body (reference),
 *                           used when delay_file_io is enabled
 * @param array  $smtp_opts  SMTP options (e.g. DSN request)
 *
 * @return boolean Send status.
 */
function rcmail_deliver_message(&$message, $from, $mailto, &$smtp_error, &$body_file=null, $smtp_opts=null)
{
  global $CONFIG, $RCMAIL;
  $headers = $message->headers();
  // send thru SMTP server using custom SMTP library
  if ($CONFIG['smtp_server']) {
    // generate list of recipients
    $a_recipients = array($mailto);
    if (strlen($headers['Cc']))
      $a_recipients[] = $headers['Cc'];
    if (strlen($headers['Bcc']))
      $a_recipients[] = $headers['Bcc'];
    // clean Bcc from header for recipients
    $send_headers = $headers;
    unset($send_headers['Bcc']);
    // here too, it because txtHeaders() below use $message->_headers not only $send_headers
    unset($message->_headers['Bcc']);
    $smtp_headers = $message->txtHeaders($send_headers, true);
    if ($message->getParam('delay_file_io')) {
      // use common temp dir
      $temp_dir = $RCMAIL->config->get('temp_dir');
      $body_file = tempnam($temp_dir, 'rcmMsg');
      if (PEAR::isError($mime_result = $message->saveMessageBody($body_file))) {
        raise_error(array('code' => 650, 'type' => 'php',
            'file' => __FILE__, 'line' => __LINE__,
            'message' => "Could not create message: ".$mime_result->getMessage()),
            TRUE, FALSE);
        return false;
      }
      $msg_body = fopen($body_file, 'r');
    } else {
      $msg_body = $message->get();
    }
    // send message
    if (!is_object($RCMAIL->smtp))
      $RCMAIL->smtp_init(true);
    $sent = $RCMAIL->smtp->send_mail($from, $a_recipients, $smtp_headers, $msg_body, $smtp_opts);
    $smtp_response = $RCMAIL->smtp->get_response();
    $smtp_error = $RCMAIL->smtp->get_error();
    // log error
    if (!$sent)
      raise_error(array('code' => 800, 'type' => 'smtp', 'line' => __LINE__, 'file' => __FILE__,
                        'message' => "SMTP error: ".join("\n", $smtp_response)), TRUE, FALSE);
  }
  // send mail using PHP's mail() function
  else {
    // unset some headers because they will be added by the mail() function
    $headers_enc = $message->headers($headers);
    $headers_php = $message->_headers;
    unset($headers_php['To'], $headers_php['Subject']);
    // reset stored headers and overwrite
    $message->_headers = array();
    $header_str = $message->txtHeaders($headers_php);
    // #1485779
    if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
      if (preg_match_all('/<([^@]+@[^>]+)>/', $headers_enc['To'], $m)) {
        $headers_enc['To'] = implode(', ', $m[1]);
      }
    }
    $msg_body = $message->get();
    if (PEAR::isError($msg_body))
      raise_error(array('code' => 650, 'type' => 'php',
            'file' => __FILE__, 'line' => __LINE__,
            'message' => "Could not create message: ".$msg_body->getMessage()),
            TRUE, FALSE);
    else {
      $delim   = $RCMAIL->config->header_delimiter();
      $to      = $headers_enc['To'];
      $subject = $headers_enc['Subject'];
      $header_str = rtrim($header_str);
      if ($delim != "\r\n") {
        $header_str = str_replace("\r\n", $delim, $header_str);
        $msg_body   = str_replace("\r\n", $delim, $msg_body);
        $to         = str_replace("\r\n", $delim, $to);
        $subject    = str_replace("\r\n", $delim, $subject);
      }
      if (ini_get('safe_mode'))
        $sent = mail($to, $subject, $msg_body, $header_str);
      else
        $sent = mail($to, $subject, $msg_body, $header_str, "-f$from");
    }
  }
  if ($sent) {
    $RCMAIL->plugins->exec_hook('message_sent', array('headers' => $headers, 'body' => $msg_body));
    // remove MDN headers after sending
    unset($headers['Return-Receipt-To'], $headers['Disposition-Notification-To']);
    // get all recipients
    if ($headers['Cc'])
      $mailto .= $headers['Cc'];
    if ($headers['Bcc'])
      $mailto .= $headers['Bcc'];
    if (preg_match_all('/<([^@]+@[^>]+)>/', $mailto, $m))
      $mailto = implode(', ', array_unique($m[1]));
    if ($CONFIG['smtp_log']) {
      write_log('sendmail', sprintf("User %s [%s]; Message for %s; %s",
        $RCMAIL->user->get_username(),
        $_SERVER['REMOTE_ADDR'],
        $mailto,
        !empty($smtp_response) ? join('; ', $smtp_response) : ''));
    }
  }
  if (is_resource($msg_body)) {
    fclose($msg_body);
  }
  $message->_headers = array();
  $message->headers($headers);
  return $sent;
}
// Returns unique Message-ID
function rcmail_gen_message_id()
{
  global $RCMAIL;
  $local_part  = md5(uniqid('rcmail'.mt_rand(),true));
  $domain_part = $RCMAIL->user->get_username('domain');
  // Try to find FQDN, some spamfilters doesn't like 'localhost' (#1486924)
  if (!preg_match('/\.[a-z]+$/i', $domain_part)) {
    if (($host = preg_replace('/:[0-9]+$/', '', $_SERVER['HTTP_HOST']))
      && preg_match('/\.[a-z]+$/i', $host)) {
        $domain_part = $host;
    }
    else if (($host = preg_replace('/:[0-9]+$/', '', $_SERVER['SERVER_NAME']))
      && preg_match('/\.[a-z]+$/i', $host)) {
        $domain_part = $host;
    }
  }
  return sprintf('<%s@%s>', $local_part, $domain_part);
}
// Returns RFC2822 formatted current date in user's timezone
function rcmail_user_date()
{
  global $RCMAIL, $CONFIG;
  // get user's timezone
  $tz = $RCMAIL->config->get_timezone();
  $date = time() + $tz * 60 * 60;
  $date = gmdate('r', $date);
  $tz   = sprintf('%+05d', intval($tz) * 100 + ($tz - intval($tz)) * 60);
  $date = preg_replace('/[+-][0-9]{4}$/', $tz, $date);
  return $date;
}
/**
 * Check if we can process not exceeding memory_limit
 *
 * @param integer Required amount of memory
 * @return boolean
 */
function rcmail_mem_check($need)
{
  $mem_limit = parse_bytes(ini_get('memory_limit'));
  $memory    = function_exists('memory_get_usage') ? memory_get_usage() : 16*1024*1024; // safe value: 16MB
  return $mem_limit && $memory + $need > $mem_limit ? false : true;
}
@@ -1921,8 +2168,8 @@
  if (!$RCMAIL->config->get('log_logins') || !$RCMAIL->user)
    return;
  write_log('userlogins', sprintf('Successful login for %s (ID: %d) from %s',
    $RCMAIL->user->get_username(), $RCMAIL->user->ID, rcmail_remote_ip()));
  write_log('userlogins', sprintf('Successful login for %s (ID: %d) from %s in session %s',
    $RCMAIL->user->get_username(), $RCMAIL->user->ID, rcmail_remote_ip(), session_id()));
}
@@ -2094,7 +2341,7 @@
        $status = apc_fetch($prefix . $params['name']);
        if (!empty($status)) {
            $status['percent'] = $status['current']/$status['total']*100;
            $status['percent'] = round($status['current']/$status['total']*100);
            $params = array_merge($status, $params);
        }
    }
@@ -2105,12 +2352,12 @@
            'current' => show_bytes($params['current']),
            'total'   => show_bytes($params['total'])
        )));
console($params);
    $RCMAIL->output->command('upload_progress_update', $params);
    $RCMAIL->output->send();
}
function rcube_upload_progress_init()
function rcube_upload_init()
{
    global $RCMAIL;
@@ -2121,4 +2368,67 @@
            $RCMAIL->output->set_env('upload_progress_time', (int) $seconds);
        }
    }
    // find max filesize value
    $max_filesize = parse_bytes(ini_get('upload_max_filesize'));
    $max_postsize = parse_bytes(ini_get('post_max_size'));
    if ($max_postsize && $max_postsize < $max_filesize)
        $max_filesize = $max_postsize;
    $RCMAIL->output->set_env('max_filesize', $max_filesize);
    $max_filesize = show_bytes($max_filesize);
    $RCMAIL->output->set_env('filesizeerror', rcube_label(array(
        'name' => 'filesizeerror', 'vars' => array('size' => $max_filesize))));
    return $max_filesize;
}
/**
 * Initializes client-side autocompletion
 */
function rcube_autocomplete_init()
{
    global $RCMAIL;
    static $init;
    if ($init)
        return;
    $init = 1;
    if (($threads = (int)$RCMAIL->config->get('autocomplete_threads')) > 0) {
      $book_types = (array) $RCMAIL->config->get('autocomplete_addressbooks', 'sql');
      if (count($book_types) > 1) {
        $RCMAIL->output->set_env('autocomplete_threads', $threads);
        $RCMAIL->output->set_env('autocomplete_sources', $book_types);
      }
    }
    $RCMAIL->output->set_env('autocomplete_max', (int)$RCMAIL->config->get('autocomplete_max', 15));
    $RCMAIL->output->set_env('autocomplete_min_length', $RCMAIL->config->get('autocomplete_min_length'));
    $RCMAIL->output->add_label('autocompletechars', 'autocompletemore');
}
function rcube_fontdefs($font = null)
{
  $fonts = array(
    'Andale Mono'   => '"Andale Mono",Times,monospace',
    'Arial'         => 'Arial,Helvetica,sans-serif',
    'Arial Black'   => '"Arial Black","Avant Garde",sans-serif',
    'Book Antiqua'  => '"Book Antiqua",Palatino,serif',
    'Courier New'   => '"Courier New",Courier,monospace',
    'Georgia'       => 'Georgia,Palatino,serif',
    'Helvetica'     => 'Helvetica,Arial,sans-serif',
    'Impact'        => 'Impact,Chicago,sans-serif',
    'Tahoma'        => 'Tahoma,Arial,Helvetica,sans-serif',
    'Terminal'      => 'Terminal,Monaco,monospace',
    'Times New Roman' => '"Times New Roman",Times,serif',
    'Trebuchet MS'  => '"Trebuchet MS",Geneva,sans-serif',
    'Verdana'       => 'Verdana,Geneva,sans-serif',
  );
  if ($font)
    return $fonts[$font];
  return $fonts;
}