Aleksander Machniak
2013-12-31 f5d2eef55c89b7f1a5549704705c25fd7f0c0185
program/steps/mail/func.inc
@@ -5,7 +5,7 @@
 | program/steps/mail/func.inc                                           |
 |                                                                       |
 | This file is part of the Roundcube Webmail client                     |
 | Copyright (C) 2005-2012, The Roundcube Dev Team                       |
 | Copyright (C) 2005-2013, The Roundcube Dev Team                       |
 |                                                                       |
 | Licensed under the GNU General Public License version 3 or            |
 | any later version with exceptions for skins & plugins.                |
@@ -16,43 +16,44 @@
 |                                                                       |
 +-----------------------------------------------------------------------+
 | Author: Thomas Bruederli <roundcube@gmail.com>                        |
 | Author: Aleksander Machniak <alec@alec.pl>                            |
 +-----------------------------------------------------------------------+
*/
// setup some global vars used by mail steps
$SENT_MBOX = $RCMAIL->config->get('sent_mbox');
$DRAFTS_MBOX = $RCMAIL->config->get('drafts_mbox');
$SEARCH_MODS_DEFAULT = array(
    '*'         => array('subject'=>1, 'from'=>1),
    $SENT_MBOX  => array('subject'=>1, 'to'=>1),
    $DRAFTS_MBOX => array('subject'=>1, 'to'=>1)
);
// always instantiate storage object (but not connect to server yet)
$RCMAIL->storage_init();
// set imap properties and session vars
if (strlen(trim($mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_GPC, true))))
if (strlen(trim($mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_GPC, true)))) {
  $RCMAIL->storage->set_folder(($_SESSION['mbox'] = $mbox));
else if ($RCMAIL->storage)
}
else if ($RCMAIL->storage) {
  $_SESSION['mbox'] = $RCMAIL->storage->get_folder();
}
if (!empty($_GET['_page']))
if (!empty($_GET['_page'])) {
  $RCMAIL->storage->set_page(($_SESSION['page'] = intval($_GET['_page'])));
}
$a_threading        = $RCMAIL->config->get('message_threading', array());
$message_sort_col   = $RCMAIL->config->get('message_sort_col');
$message_sort_order = $RCMAIL->config->get('message_sort_col');
// set default sort col/order to session
if (!isset($_SESSION['sort_col']))
  $_SESSION['sort_col'] = !empty($CONFIG['message_sort_col']) ? $CONFIG['message_sort_col'] : '';
if (!isset($_SESSION['sort_order']))
  $_SESSION['sort_order'] = strtoupper($CONFIG['message_sort_order']) == 'ASC' ? 'ASC' : 'DESC';
if (!isset($_SESSION['sort_col'])) {
    $_SESSION['sort_col'] = $message_sort_col ? $message_sort_col : '';
}
if (!isset($_SESSION['sort_order'])) {
  $_SESSION['sort_order'] = strtoupper($message_sort_order) == 'ASC' ? 'ASC' : 'DESC';
}
// set threads mode
$a_threading = $RCMAIL->config->get('message_threading', array());
if (isset($_GET['_threads'])) {
  if ($_GET['_threads'])
    $a_threading[$_SESSION['mbox']] = true;
  else
    unset($a_threading[$_SESSION['mbox']]);
  $RCMAIL->user->save_prefs(array('message_threading' => $a_threading));
}
$RCMAIL->storage->set_threading($a_threading[$_SESSION['mbox']]);
@@ -62,6 +63,7 @@
    && $_SESSION['search_request'] == $_REQUEST['_search']
) {
  $RCMAIL->storage->set_search_set($_SESSION['search']);
  $OUTPUT->set_env('search_request', $_REQUEST['_search']);
  $OUTPUT->set_env('search_text', $_SESSION['last_text_search']);
}
@@ -76,16 +78,16 @@
  if (empty($RCMAIL->action)) {
    // initialize searching result if search_filter is used
    if ($_SESSION['search_filter'] && $_SESSION['search_filter'] != 'ALL') {
      $search_request = md5($mbox_name.$_SESSION['search_filter']);
      $RCMAIL->storage->search($mbox_name, $_SESSION['search_filter'], RCUBE_CHARSET, rcmail_sort_column());
            $search_request             = md5($mbox_name.$_SESSION['search_filter']);
      $_SESSION['search'] = $RCMAIL->storage->get_search_set();
      $_SESSION['search_request'] = $search_request;
      $OUTPUT->set_env('search_request', $search_request);
    }
    $search_mods = $RCMAIL->config->get('search_mods', $SEARCH_MODS_DEFAULT);
    $OUTPUT->set_env('search_mods', $search_mods);
        $OUTPUT->set_env('search_mods', rcmail_search_mods());
  }
  $threading = (bool) $RCMAIL->storage->get_threading();
@@ -99,29 +101,31 @@
  $OUTPUT->set_env('threads', $threading || $RCMAIL->storage->get_capability('THREAD'));
  $OUTPUT->set_env('reply_all_mode', (int) $RCMAIL->config->get('reply_all_mode'));
  $OUTPUT->set_env('preview_pane_mark_read', $RCMAIL->config->get('preview_pane_mark_read', 0));
  if ($RCMAIL->storage->get_capability('QUOTA')) {
    $OUTPUT->set_env('quota', true);
  }
  foreach (array('delete_junk','flag_for_deletion','read_when_deleted','skip_deleted','display_next','message_extwin','compose_extwin','forward_attachment') as $prop) {
    if ($CONFIG[$prop])
      $OUTPUT->set_env($prop, true);
    // set special folders
    foreach (array('drafts', 'trash', 'junk') as $mbox) {
        if ($folder = $RCMAIL->config->get($mbox . '_mbox')) {
            $OUTPUT->set_env($mbox . '_mailbox', $folder);
        }
  }
  if ($CONFIG['trash_mbox'])
    $OUTPUT->set_env('trash_mailbox', $CONFIG['trash_mbox']);
  if ($CONFIG['drafts_mbox'])
    $OUTPUT->set_env('drafts_mailbox', $CONFIG['drafts_mbox']);
  if ($CONFIG['junk_mbox'])
    $OUTPUT->set_env('junk_mailbox', $CONFIG['junk_mbox']);
    // set configuration
    $RCMAIL->set_env_config(array('delete_junk', 'flag_for_deletion', 'read_when_deleted',
        'skip_deleted', 'display_next', 'message_extwin', 'compose_extwin', 'forward_attachment'));
  if (!empty($_SESSION['browser_caps']))
    if (!empty($_SESSION['browser_caps'])) {
    $OUTPUT->set_env('browser_capabilities', $_SESSION['browser_caps']);
    }
  if (!$OUTPUT->ajax_call)
    if (!$OUTPUT->ajax_call) {
    $OUTPUT->add_label('checkingmail', 'deletemessage', 'movemessagetotrash',
      'movingmessage', 'copyingmessage', 'deletingmessage', 'markingmessage',
      'copy', 'move', 'quota', 'replyall', 'replylist', 'importwait');
    }
  $pagetitle = $RCMAIL->localize_foldername($RCMAIL->storage->mod_folder($mbox_name), true);
  $pagetitle = str_replace($delimiter, " \xC2\xBB ", $pagetitle);
@@ -132,9 +136,9 @@
// register UI objects
$OUTPUT->add_handlers(array(
  'mailboxlist'         => array($RCMAIL, 'folder_list'),
    'quotadisplay'        => array($RCMAIL, 'quota_display'),
  'messages'            => 'rcmail_message_list',
  'messagecountdisplay' => 'rcmail_messagecount_display',
  'quotadisplay'        => array($RCMAIL, 'quota_display'),
  'mailboxname'         => 'rcmail_mailbox_name_display',
  'messageheaders'      => 'rcmail_message_headers',
  'messagefullheaders'  => 'rcmail_message_full_headers',
@@ -162,6 +166,28 @@
));
/**
 * Returns default search mods
 */
function rcmail_search_mods()
{
    global $RCMAIL;
    $mods = $RCMAIL->config->get('search_mods');
    if (empty($mods)) {
        $mods = array('*' => array('subject' => 1, 'from' => 1));
        foreach (array('sent', 'drafts') as $mbox) {
            if ($mbox = $RCMAIL->config->get($mbox . '_mbox')) {
                $mods[$mbox] = array('subject' => 1, 'to' => 1);
            }
        }
    }
    return $mods;
}
/**
 * Returns 'to' if current folder is configured Sent or Drafts
@@ -234,7 +260,7 @@
 */
function rcmail_message_list($attrib)
{
  global $CONFIG, $OUTPUT;
    global $RCMAIL, $OUTPUT;
  // add some labels to client
  $OUTPUT->add_label('from', 'to');
@@ -245,8 +271,10 @@
  // define list of cols to be displayed based on parameter or config
  if (empty($attrib['columns'])) {
    $a_show_cols = is_array($CONFIG['list_cols']) ? $CONFIG['list_cols'] : array('subject');
    $OUTPUT->set_env('col_movable', !in_array('list_cols', (array)$CONFIG['dont_override']));
        $list_cols   = $RCMAIL->config->get('list_cols');
        $a_show_cols = !empty($list_cols) && is_array($list_cols) ? $list_cols : array('subject');
        $OUTPUT->set_env('col_movable', !in_array('list_cols', (array)$RCMAIL->config->get('dont_override')));
  }
  else {
    $a_show_cols = preg_split('/[\s,;]+/', str_replace(array("'", '"'), '', $attrib['columns']));
@@ -255,17 +283,18 @@
  // save some variables for use in ajax list
  $_SESSION['list_attrib'] = $attrib;
  // make sure 'threads' and 'subject' columns are present
  if (!in_array('subject', $a_show_cols))
    array_unshift($a_show_cols, 'subject');
  if (!in_array('threads', $a_show_cols))
    array_unshift($a_show_cols, 'threads');
  $_SESSION['skin_path'] = $CONFIG['skin_path'];
    $_SESSION['skin_path'] = $RCMAIL->config->get('skin_path');
  // set client env
  $OUTPUT->add_gui_object('messagelist', $attrib['id']);
  $OUTPUT->set_env('autoexpand_threads', intval($CONFIG['autoexpand_threads']));
    $OUTPUT->set_env('autoexpand_threads', intval($RCMAIL->config->get('autoexpand_threads')));
  $OUTPUT->set_env('sort_col', $_SESSION['sort_col']);
  $OUTPUT->set_env('sort_order', $_SESSION['sort_order']);
  $OUTPUT->set_env('messages', array());
@@ -274,6 +303,7 @@
  $OUTPUT->include_script('list.js');
  $table = new html_table($attrib);
  if (!$attrib['noheader']) {
    foreach (rcmail_message_list_head($attrib, $a_show_cols) as $cell)
      $table->add_header(array('class' => $cell['className'], 'id' => $cell['id']), $cell['html']);
@@ -282,23 +312,25 @@
  return $table->show();
}
/**
 * return javascript commands to add rows to the message list
 */
function rcmail_js_message_list($a_headers, $insert_top=FALSE, $a_show_cols=null)
{
  global $CONFIG, $RCMAIL, $OUTPUT;
    global $RCMAIL, $OUTPUT;
  if (empty($a_show_cols)) {
    if (!empty($_SESSION['list_attrib']['columns']))
      $a_show_cols = $_SESSION['list_attrib']['columns'];
    else
      $a_show_cols = is_array($CONFIG['list_cols']) ? $CONFIG['list_cols'] : array('subject');
        else {
            $list_cols   = $RCMAIL->config->get('list_cols');
            $a_show_cols = !empty($list_cols) && is_array($list_cols) ? $list_cols : array('subject');
        }
  }
  else {
    if (!is_array($a_show_cols))
        if (!is_array($a_show_cols)) {
      $a_show_cols = preg_split('/[\s,;]+/', str_replace(array("'", '"'), '', $a_show_cols));
        }
    $head_replace = true;
  }
@@ -332,13 +364,15 @@
  $OUTPUT->command('set_message_coltypes', $a_show_cols, $thead, $smart_col);
  if (empty($a_headers))
    if (empty($a_headers)) {
    return;
    }
  // remove 'threads', 'attachment', 'flag', 'status' columns, we don't need them here
  foreach (array('threads', 'attachment', 'flag', 'status', 'priority') as $col) {
    if (($key = array_search($col, $a_show_cols)) !== FALSE)
        if (($key = array_search($col, $a_show_cols)) !== FALSE) {
      unset($a_show_cols[$key]);
        }
  }
  // loop through message headers
@@ -407,7 +441,6 @@
  }
}
/*
 * Creates <THEAD> for message list table
 */
@@ -442,11 +475,11 @@
    else
      $list_menu = html::a(array('href' => '#', 'onclick' => $onclick),
        html::img(array('src' => $skin_path . $attrib['optionsmenuicon'],
          'id' => 'listmenulink', 'title' => $RCMAIL->gettext('listoptions')))
      );
                    'id' => 'listmenulink', 'title' => $RCMAIL->gettext('listoptions'))));
  }
  else
    else {
    $list_menu = '';
    }
  $cells = array();
@@ -477,10 +510,16 @@
    }
    // make sort links
    if (in_array($col, $a_sort_cols))
      $col_name = html::a(array('href'=>"./#sort", 'onclick' => 'return '.rcmail_output::JS_OBJECT_NAME.".command('sort','".$col."',this)", 'title' => $RCMAIL->gettext('sortby')), $col_name);
    else if ($col_name[0] != '<')
        if (in_array($col, $a_sort_cols)) {
            $col_name = html::a(array(
                    'href'    => "./#sort",
                    'onclick' => 'return '.rcmail_output::JS_OBJECT_NAME.".command('sort','".$col."',this)",
                    'title'   => $RCMAIL->gettext('sortby')
                ), $col_name);
        }
        else if ($col_name[0] != '<') {
      $col_name = '<span class="' . $col .'">' . $col_name . '</span>';
        }
    $sort_class = $col == $sort_col && !$disabled_order ? " sorted$sort_order" : '';
    $class_name = $col.$sort_class;
@@ -491,7 +530,6 @@
  return $cells;
}
/**
 * return an HTML iframe for loading mail content
@@ -505,13 +543,14 @@
  $attrib['name'] = $attrib['id'];
  if ($RCMAIL->config->get('preview_pane'))
    if ($RCMAIL->config->get('preview_pane')) {
    $OUTPUT->set_env('contentframe', $attrib['id']);
    }
  $OUTPUT->set_env('blankpage', $attrib['src'] ? $OUTPUT->abs_url($attrib['src']) : 'program/resources/blank.gif');
  return $OUTPUT->frame($attrib, true);
}
function rcmail_messagecount_display($attrib)
{
@@ -527,19 +566,18 @@
  return html::span($attrib, $content);
}
function rcmail_get_messagecount_text($count=NULL, $page=NULL)
function rcmail_get_messagecount_text($count = null, $page = null)
{
  global $RCMAIL;
  if ($page === NULL) {
    if ($page === null) {
    $page = $RCMAIL->storage->get_page();
  }
  $page_size = $RCMAIL->storage->get_pagesize();
  $start_msg = ($page-1) * $page_size + 1;
  if ($count!==NULL)
    if ($count !== null)
    $max = $count;
  else if ($RCMAIL->action)
    $max = $RCMAIL->storage->count(NULL, $RCMAIL->storage->get_threading() ? 'THREADS' : 'ALL');
@@ -555,7 +593,6 @@
  return rcube::Q($out);
}
function rcmail_mailbox_name_display($attrib)
{
  global $RCMAIL;
@@ -568,13 +605,11 @@
  return html::span($attrib, rcmail_get_mailbox_name_text());
}
function rcmail_get_mailbox_name_text()
{
  global $RCMAIL;
  return $RCMAIL->localize_foldername($RCMAIL->storage->get_folder());
}
function rcmail_send_unread_count($mbox_name, $force=false, $count=null, $mark='')
{
@@ -596,27 +631,24 @@
  return $unseen;
}
function rcmail_set_unseen_count($mbox_name, $count)
{
  // @TODO: this data is doubled (session and cache tables) if caching is enabled
  // Make sure we have an array here (#1487066)
  if (!is_array($_SESSION['unseen_count']))
    if (!is_array($_SESSION['unseen_count'])) {
    $_SESSION['unseen_count'] = array();
    }
  $_SESSION['unseen_count'][$mbox_name] = $count;
}
function rcmail_get_unseen_count($mbox_name)
{
  if (is_array($_SESSION['unseen_count']) && array_key_exists($mbox_name, $_SESSION['unseen_count']))
    if (is_array($_SESSION['unseen_count']) && array_key_exists($mbox_name, $_SESSION['unseen_count'])) {
    return $_SESSION['unseen_count'][$mbox_name];
  else
    return null;
}
}
/**
 * Sets message is_safe flag according to 'show_images' option value
@@ -652,7 +684,6 @@
    }
  }
}
/**
 * Cleans up the given message HTML Body (for displaying)
@@ -708,12 +739,14 @@
  // initialize HTML washer
  $washer = new rcube_washtml($wash_opts);
  if (!$p['skip_washer_form_callback'])
    if (!$p['skip_washer_form_callback']) {
    $washer->add_callback('form', 'rcmail_washtml_callback');
    }
  // allow CSS styles, will be sanitized by rcmail_washtml_callback()
  if (!$p['skip_washer_style_callback'])
    if (!$p['skip_washer_style_callback']) {
    $washer->add_callback('style', 'rcmail_washtml_callback');
    }
  // Remove non-UTF8 characters (#1487813)
  $html = rcube_charset::clean($html);
@@ -723,7 +756,6 @@
  return $html;
}
/**
 * Convert the given message part to proper HTML
@@ -747,6 +779,7 @@
    if ($data['type'] == 'enriched') {
      $data['body'] = rcube_enriched::to_html($data['body']);
    }
    $txt = new rcube_html2text($data['body'], false, true);
    $body = $txt->get_text();
    $part->ctype_secondary = 'plain';
@@ -786,7 +819,6 @@
  return $data['type'] == 'html' ? $data['body'] : html::tag('pre', array(), $data['body']);
}
/**
 * Handle links and citation marks in plain text message
@@ -848,12 +880,15 @@
  // colorize signature (up to <sig_max_lines> lines)
  $len = strlen($body);
  $sig_max_lines = $RCMAIL->config->get('sig_max_lines', 15);
  while (($sp = strrpos($body, "-- \n", $sp ? -$len+$sp-1 : 0)) !== false) {
    if ($sp == 0 || $body[$sp-1] == "\n") {
      // do not touch blocks with more that X lines
      if (substr_count($body, "\n", $sp) < $sig_max_lines)
            if (substr_count($body, "\n", $sp) < $sig_max_lines) {
        $body = substr($body, 0, max(0, $sp))
          .'<span class="sig">'.substr($body, $sp).'</span>';
            }
      break;
    }
  }
@@ -863,7 +898,6 @@
  return $body;
}
/**
 * Callback function for washtml cleaning class
@@ -895,7 +929,6 @@
  return $out;
}
/**
 * return table with message headers
 */
@@ -910,8 +943,9 @@
  else if (!is_array($attrib) && is_array($sa_attrib))
    $attrib = $sa_attrib;
  if (!isset($MESSAGE))
    return FALSE;
    if (!isset($MESSAGE)) {
        return false;
    }
  // get associative array of headers object
  if (!$headers) {
@@ -962,7 +996,8 @@
    }
    else if ($hkey == 'replyto') {
      if ($headers['replyto'] != $headers['from']) {
        $header_value = rcmail_address_string($value, $attrib['max'], true, $attrib['addicon'], $headers['charset'], $header_title);
                $header_value = rcmail_address_string($value, $attrib['max'], true,
                    $attrib['addicon'], $headers['charset'], $header_title);
        $ishtml = true;
      }
      else
@@ -972,7 +1007,8 @@
      if ($headers['mail-replyto'] != $headers['reply-to']
        && $headers['reply-to'] != $headers['from']
      ) {
        $header_value = rcmail_address_string($value, $attrib['max'], true, $attrib['addicon'], $headers['charset'], $header_title);
                $header_value = rcmail_address_string($value, $attrib['max'], true,
                    $attrib['addicon'], $headers['charset'], $header_title);
        $ishtml = true;
      }
      else
@@ -980,18 +1016,21 @@
    }
    else if ($hkey == 'sender') {
      if ($headers['sender'] != $headers['from']) {
        $header_value = rcmail_address_string($value, $attrib['max'], true, $attrib['addicon'], $headers['charset'], $header_title);
                $header_value = rcmail_address_string($value, $attrib['max'], true,
                    $attrib['addicon'], $headers['charset'], $header_title);
        $ishtml = true;
      }
      else
        continue;
    }
    else if ($hkey == 'mail-followup-to') {
      $header_value = rcmail_address_string($value, $attrib['max'], true, $attrib['addicon'], $headers['charset'], $header_title);
            $header_value = rcmail_address_string($value, $attrib['max'], true,
                $attrib['addicon'], $headers['charset'], $header_title);
      $ishtml = true;
    }
    else if (in_array($hkey, array('from', 'to', 'cc', 'bcc'))) {
      $header_value = rcmail_address_string($value, $attrib['max'], true, $attrib['addicon'], $headers['charset'], $header_title);
            $header_value = rcmail_address_string($value, $attrib['max'], true,
                $attrib['addicon'], $headers['charset'], $header_title);
      $ishtml = true;
    }
    else if ($hkey == 'subject' && empty($value))
@@ -1007,19 +1046,25 @@
    );
  }
  $plugin = $RCMAIL->plugins->exec_hook('message_headers_output',
    array('output' => $output_headers, 'headers' => $headers_obj, 'exclude' => $exclude_headers));
    $plugin = $RCMAIL->plugins->exec_hook('message_headers_output', array(
        'output'  => $output_headers,
        'headers' => $headers_obj,
        'exclude' => $exclude_headers
    ));
  // single header value is requested
  if (!empty($attrib['valueof']))
    if (!empty($attrib['valueof'])) {
    return rcube::Q($plugin['output'][$attrib['valueof']]['value'], ($attrib['valueof'] == 'subject' ? 'strict' : 'show'));
    }
  // compose html table
  $table = new html_table(array('cols' => 2));
  foreach ($plugin['output'] as $hkey => $row) {
        $val = $row['html'] ? $row['value'] : rcube::Q($row['value'], ($hkey == 'subject' ? 'strict' : 'show'));
    $table->add(array('class' => 'header-title'), rcube::Q($row['title']));
    $table->add(array('class' => 'header '.$hkey), $row['html'] ? $row['value'] : rcube::Q($row['value'], ($hkey == 'subject' ? 'strict' : 'show')));
        $table->add(array('class' => 'header '.$hkey), $val);
  }
  return $table->show($attrib);
@@ -1040,8 +1085,9 @@
    '5' => 'lowest',
  );
  if ($value && $labels_map[$value])
    if ($value && $labels_map[$value]) {
    return $RCMAIL->gettext($labels_map[$value]);
    }
  return '';
}
@@ -1054,14 +1100,17 @@
  global $OUTPUT, $RCMAIL;
  $html = html::div(array('id' => "all-headers", 'class' => "all", 'style' => 'display:none'), html::div(array('id' => 'headers-source'), ''));
  $html .= html::div(array('class' => "more-headers show-headers", 'onclick' => "return ".rcmail_output::JS_OBJECT_NAME.".command('show-headers','',this)", 'title' => $RCMAIL->gettext('togglefullheaders')), '');
    $html .= html::div(array(
            'class'   => "more-headers show-headers",
            'onclick' => "return ".rcmail_output::JS_OBJECT_NAME.".command('show-headers','',this)",
            'title'   => $RCMAIL->gettext('togglefullheaders')
        ), '');
  $OUTPUT->add_gui_object('all_headers_row', 'all-headers');
  $OUTPUT->add_gui_object('all_headers_box', 'headers-source');
  return html::div($attrib, $html);
}
/**
 * Handler for the 'messagebody' GUI object
@@ -1071,10 +1120,11 @@
 */
function rcmail_message_body($attrib)
{
  global $CONFIG, $OUTPUT, $MESSAGE, $RCMAIL, $REMOTE_OBJECTS;
    global $OUTPUT, $MESSAGE, $RCMAIL, $REMOTE_OBJECTS;
  if (!is_array($MESSAGE->parts) && empty($MESSAGE->body))
    if (!is_array($MESSAGE->parts) && empty($MESSAGE->body)) {
    return '';
    }
  if (!$attrib['id'])
    $attrib['id'] = 'rcmailMsgBody';
@@ -1083,9 +1133,11 @@
  $out = '';
  $header_attrib = array();
  foreach ($attrib as $attr => $value)
    if (preg_match('/^headertable([a-z]+)$/i', $attr, $regs))
    foreach ($attrib as $attr => $value) {
        if (preg_match('/^headertable([a-z]+)$/i', $attr, $regs)) {
      $header_attrib[$regs[1]] = $value;
        }
    }
  if (!empty($MESSAGE->parts)) {
    foreach ($MESSAGE->parts as $part) {
@@ -1103,6 +1155,7 @@
        else if (!$part->size) {
          continue;
        }
        // Check if we have enough memory to handle the message in it
        // #1487424: we need up to 10x more memory than the body
        else if (!rcube_utils::mem_check($part->size * 10)) {
@@ -1112,12 +1165,14 @@
          continue;
        }
        if (empty($part->ctype_parameters) || empty($part->ctype_parameters['charset']))
                if (empty($part->ctype_parameters) || empty($part->ctype_parameters['charset'])) {
          $part->ctype_parameters['charset'] = $MESSAGE->headers->charset;
                }
        // fetch part if not available
        if (!isset($part->body))
                if (!isset($part->body)) {
          $part->body = $MESSAGE->get_part_content($part->mime_id);
                }
        // extract headers from message/rfc822 parts
        if ($part->mimetype == 'message/rfc822') {
@@ -1133,10 +1188,10 @@
          rcmail_message_error($MESSAGE->uid);
        }
        $plugin = $RCMAIL->plugins->exec_hook('message_body_prefix', array(
          'part' => $part, 'prefix' => ''));
                $plugin = $RCMAIL->plugins->exec_hook('message_body_prefix',
                    array('part' => $part, 'prefix' => ''));
        $body = rcmail_print_body($part, array('safe' => $safe_mode, 'plain' => !$CONFIG['prefer_html']));
                $body = rcmail_print_body($part, array('safe' => $safe_mode, 'plain' => !$RCMAIL->config->get('prefer_html')));
        if ($part->ctype_secondary == 'html') {
          $body = rcmail_html4inline($body, $attrib['id'], 'rcmBody', $attrs, $safe_mode);
@@ -1166,8 +1221,8 @@
          .'&_mbox='. urlencode($RCMAIL->storage->get_folder()), $RCMAIL->gettext('download')));
    }
    else {
      $plugin = $RCMAIL->plugins->exec_hook('message_body_prefix', array(
        'part' => $MESSAGE, 'prefix' => ''));
            $plugin = $RCMAIL->plugins->exec_hook('message_body_prefix',
                array('part' => $MESSAGE, 'prefix' => ''));
      $out .= html::div('message-part', $plugin['prefix'] . html::tag('pre', array(),
        rcmail_plain_body(rcube::Q($MESSAGE->body, 'strict', false))));
@@ -1218,7 +1273,7 @@
        else {
          $out .= html::tag('fieldset', 'image-attachment',
            html::tag('legend', 'image-filename', rcube::Q($attach_prop->filename)) .
            html::p(array('align' => "center"),
                        html::p(array('align' => 'center'),
              html::img(array(
                'src'   => $MESSAGE->get_part_url($attach_prop->mime_id, 'image'),
                'title' => $attach_prop->filename,
@@ -1231,8 +1286,9 @@
  }
  // tell client that there are blocked remote objects
  if ($REMOTE_OBJECTS && !$safe_mode)
    if ($REMOTE_OBJECTS && !$safe_mode) {
    $OUTPUT->set_env('blockedobjects', true);
    }
  return html::div($attrib, $out);
}
@@ -1280,7 +1336,6 @@
  }
}
/**
 * modify a HTML message that it can be displayed inside a HTML page
 */
@@ -1290,8 +1345,7 @@
  $cont_id = $container_id.($body_id ? ' div.'.$body_id : '');
  // find STYLE tags
  while (($pos = stripos($body, '<style', $last_style_pos)) && ($pos2 = stripos($body, '</style>', $pos)))
  {
    while (($pos = stripos($body, '<style', $last_style_pos)) && ($pos2 = stripos($body, '</style>', $pos))) {
    $pos = strpos($body, '>', $pos) + 1;
    $len = $pos2 - $pos;
@@ -1343,16 +1397,19 @@
  $regexp = '/<div class="' . preg_quote($body_id, '/') . '"([^>]*)/';
  if (preg_match($regexp, $body, $m)) {
    $attrs = $m[0];
    // Get bgcolor, we'll set it as background-color of the message container
    if ($m[1] && preg_match('/bgcolor=["\']*([a-z0-9#]+)["\']*/i', $attrs, $mb)) {
      $attributes['background-color'] = $mb[1];
      $attrs = preg_replace('/bgcolor=["\']*[a-z0-9#]+["\']*/i', '', $attrs);
    }
    // Get background, we'll set it as background-image of the message container
    if ($m[1] && preg_match('/background=["\']*([^"\'>\s]+)["\']*/', $attrs, $mb)) {
      $attributes['background-image'] = 'url('.$mb[1].')';
      $attrs = preg_replace('/background=["\']*([^"\'>\s]+)["\']*/', '', $attrs);
    }
    if (!empty($attributes)) {
      $body = preg_replace($regexp, rtrim($attrs), $body, 1);
    }
@@ -1362,9 +1419,11 @@
      // get body style
      if (preg_match('/#'.preg_quote($cont_id, '/').'\s+\{([^}]+)}/i', $body, $m)) {
        // get background related style
        if (preg_match_all('/(background-position|background-repeat)\s*:\s*([^;]+);/i', $m[1], $ma, PREG_SET_ORDER)) {
          foreach ($ma as $style)
                $regexp = '/(background-position|background-repeat)\s*:\s*([^;]+);/i';
                if (preg_match_all($regexp, $m[1], $ma, PREG_SET_ORDER)) {
                    foreach ($ma as $style) {
            $attributes[$style[1]] = $style[2];
                    }
        }
      }
    }
@@ -1377,7 +1436,6 @@
  return $body;
}
/**
 * parse link (a, link, area) attributes and set correct target
@@ -1451,18 +1509,18 @@
  return "<$tag" . html::attrib_string($attrib, $allow) . $end;
}
/**
 * decode address string and re-format it as HTML links
 */
function rcmail_address_string($input, $max=null, $linked=false, $addicon=null, $default_charset=null, $title=null)
{
  global $RCMAIL, $PRINT_MODE, $CONFIG;
    global $RCMAIL, $PRINT_MODE;
  $a_parts = rcube_mime::decode_address_list($input, null, true, $default_charset);
  if (!sizeof($a_parts))
    if (!sizeof($a_parts)) {
    return $input;
    }
  $c = count($a_parts);
  $j = 0;
@@ -1476,6 +1534,7 @@
  foreach ($a_parts as $part) {
    $j++;
    $name   = $part['name'];
    $mailto = $part['mailto'];
    $string = $part['string'];
@@ -1500,8 +1559,9 @@
      if ($linked) {
        $attrs = array(
           'href' => 'mailto:' . $mailto,
           'onclick' => sprintf("return %s.command('compose','%s',this)", rcmail_output::JS_OBJECT_NAME, rcube::JQ(format_email_recipient($mailto, $name))),
           'class' => "rcmContactAddress",
                    'class'   => 'rcmContactAddress',
                    'onclick' => sprintf("return %s.command('compose','%s',this)",
                        rcmail_output::JS_OBJECT_NAME, rcube::JQ(format_email_recipient($mailto, $name))),
        );
        if ($show_email && $name && $mailto) {
@@ -1522,12 +1582,13 @@
      if ($addicon && $_SESSION['writeable_abook']) {
        $address .= html::a(array(
            'href' => "#add",
            'onclick' => sprintf("return %s.command('add-contact','%s',this)", rcmail_output::JS_OBJECT_NAME, rcube::JQ($string)),
            'title' => $RCMAIL->gettext('addtoaddressbook'),
            'class' => 'rcmaddcontact',
                        'onclick' => sprintf("return %s.command('add-contact','%s',this)",
                            rcmail_output::JS_OBJECT_NAME, rcube::JQ($string)),
          ),
          html::img(array(
            'src' => $CONFIG['skin_path'] . $addicon,
                        'src' => $RCMAIL->config->get('skin_path') . $addicon,
            'alt' => "Add contact",
          )));
      }
@@ -1563,8 +1624,9 @@
        'href' => '#more',
        'class' => 'morelink',
        'onclick' => '$(this).hide().next().show()',
      ), rcube::Q($RCMAIL->gettext(array('name' => 'andnmore', 'vars' => array('nr' => $moreadrs))))) .
      html::span(array('style' => 'display:none'), join(', ', $allvalues));
                ),
                rcube::Q($RCMAIL->gettext(array('name' => 'andnmore', 'vars' => array('nr' => $moreadrs)))))
                . html::span(array('style' => 'display:none'), join(', ', $allvalues));
    }
    else {
      $out .= ' ' . html::a(array(
@@ -1581,7 +1643,6 @@
  return $out;
}
/**
 * Wrap text to a given number of characters per line
@@ -1602,20 +1663,24 @@
  foreach ($lines as $line) {
    // don't wrap already quoted lines
    if ($line[0] == '>')
        if ($line[0] == '>') {
      $line = '>' . rtrim($line);
        }
    else if (mb_strlen($line) > $max) {
      $newline = '';
      foreach (explode("\n", rcube_mime::wordwrap($line, $length - 2)) as $l) {
        if (strlen($l))
          $newline .= '> ' . $l . "\n";
        else
          $newline .= ">\n";
      }
      $line = rtrim($newline);
    }
    else
        else {
      $line = '> ' . $line;
        }
    // Append the line
    $out .= $line . "\n";
@@ -1624,44 +1689,45 @@
  return rtrim($out, "\n");
}
function rcmail_draftinfo_encode($p)
{
  $parts = array();
  foreach ($p as $key => $val)
    foreach ($p as $key => $val) {
    $parts[] = $key . '=' . ($key == 'folder' ? base64_encode($val) : $val);
    }
  return join('; ', $parts);
}
function rcmail_draftinfo_decode($str)
{
  $info = array();
  foreach (preg_split('/;\s+/', $str) as $part) {
    list($key, $val) = explode('=', $part, 2);
    if ($key == 'folder')
        if ($key == 'folder') {
      $val = base64_decode($val);
        }
    $info[$key] = $val;
  }
  return $info;
}
/**
 * clear message composing settings
 */
function rcmail_compose_cleanup($id)
{
  if (!isset($_SESSION['compose_data_'.$id]))
    if (!isset($_SESSION['compose_data_'.$id])) {
    return;
    }
  $rcmail = rcmail::get_instance();
  $rcmail->plugins->exec_hook('attachments_cleanup', array('group' => $id));
  $rcmail->session->remove('compose_data_'.$id);
}
/**
 * Send the MDN response
@@ -1675,12 +1741,13 @@
{
  global $RCMAIL;
  if (!is_object($message) || !is_a($message, 'rcube_message'))
    if (!is_object($message) || !is_a($message, 'rcube_message')) {
    $message = new rcube_message($message);
    }
  if ($message->headers->mdn_to && empty($message->headers->flags['MDNSENT']) &&
    ($RCMAIL->storage->check_permflag('MDNSENT') || $RCMAIL->storage->check_permflag('*')))
  {
        ($RCMAIL->storage->check_permflag('MDNSENT') || $RCMAIL->storage->check_permflag('*'))
    ) {
    $identity  = rcmail_identity_select($message);
    $sender    = format_email_recipient($identity['email'], $identity['name']);
    $recipient = array_shift(rcube_mime::decode_address_list(
@@ -1707,9 +1774,9 @@
      'References' => trim($message->headers->references . ' ' . $message->headers->messageID),
    );
    $report = "Final-Recipient: rfc822; {$identity['email']}\r\n" .
               "Original-Message-ID: {$message->headers->messageID}\r\n" .
               "Disposition: manual-action/MDN-sent-manually; displayed\r\n";
        $report = "Final-Recipient: rfc822; {$identity['email']}\r\n"
            . "Original-Message-ID: {$message->headers->messageID}\r\n"
            . "Disposition: manual-action/MDN-sent-manually; displayed\r\n";
    if ($message->headers->to) {
        $report .= "Original-Recipient: {$message->headers->to}\r\n";
@@ -1731,8 +1798,9 @@
    $compose->setTXTBody(rcube_mime::wordwrap($body, 75, "\r\n"));
    $compose->addAttachment($report, 'message/disposition-notification', 'MDNPart2.txt', false, '7bit', 'inline');
    if ($RCMAIL->config->get('mdn_use_from'))
        if ($RCMAIL->config->get('mdn_use_from')) {
      $options['mdn_use_from'] = true;
        }
    $sent = $RCMAIL->deliver_message($compose, $identity['email'], $mailto, $smtp_error, $body_file, $options);
@@ -1858,11 +1926,13 @@
{
  // Some versions of Outlook create garbage Content-Type:
  // application/pdf.A520491B_3BF7_494D_8855_7FAC2C6C0608
  if (preg_match('/^application\/pdf.+/', $name))
    if (preg_match('/^application\/pdf.+/', $name)) {
    $name = 'application/pdf';
    }
  // treat image/pjpeg (image/pjpg, image/jpg) as image/jpeg (#1489097)
  else if (preg_match('/^image\/p?jpe?g$/', $name))
    else if (preg_match('/^image\/p?jpe?g$/', $name)) {
    $name = 'image/jpeg';
    }
  return $name;
}
@@ -1902,7 +1972,7 @@
function rcmail_search_filter($attrib)
{
  global $RCMAIL, $OUTPUT, $CONFIG;
    global $RCMAIL;
  if (!strlen($attrib['id']))
    $attrib['id'] = 'rcmlistfilter';
@@ -1924,7 +1994,7 @@
  $select_filter->add($RCMAIL->gettext('unread'), 'UNSEEN');
  $select_filter->add($RCMAIL->gettext('flagged'), 'FLAGGED');
  $select_filter->add($RCMAIL->gettext('unanswered'), 'UNANSWERED');
  if (!$CONFIG['skip_deleted']) {
    if (!$RCMAIL->config->get('skip_deleted')) {
    $select_filter->add($RCMAIL->gettext('deleted'), 'DELETED');
    $select_filter->add($RCMAIL->gettext('undeleted'), 'UNDELETED');
  }
@@ -1937,7 +2007,7 @@
  $out = $select_filter->show($_SESSION['search_filter']);
  $OUTPUT->add_gui_object('search_filter', $attrib['id']);
    $RCMAIL->output->add_gui_object('search_filter', $attrib['id']);
  return $out;
}
@@ -1949,9 +2019,11 @@
  // Set env variables for messageerror.html template
  if ($RCMAIL->action == 'show') {
    $mbox_name = $RCMAIL->storage->get_folder();
    $RCMAIL->output->set_env('mailbox', $mbox_name);
    $RCMAIL->output->set_env('uid', null);
  }
  // display error message
  $RCMAIL->output->show_message('messageopenerror', 'error');
  // ... display message error page
@@ -1960,7 +2032,7 @@
function rcmail_message_import_form($attrib = array())
{
  global $OUTPUT, $RCMAIL;
    global $RCMAIL;
  // set defaults
  $attrib += array('id' => 'rcmImportform', 'buttons' => 'yes');
@@ -1976,18 +2048,28 @@
      'accept' => ".eml, .mbox, message/rfc822, text/*",
  ));
  $out = html::div($attrib,
    $OUTPUT->form_tag(array('id' => $attrib['id'].'Frm', 'method' => 'post', 'enctype' => 'multipart/form-data'),
      html::tag('input', array('type' => 'hidden', 'name' => '_unlock', 'value' => '')) .
      html::div(null, $fileinput->show()) .
      html::div('hint', $RCMAIL->gettext(array('name' => 'maxuploadsize', 'vars' => array('size' => $max_filesize)))) .
      (rcube_utils::get_boolean($attrib['buttons']) ? html::div('buttons',
        $button->show($RCMAIL->gettext('close'), array('class' => 'button', 'onclick' => "$('#$attrib[id]').hide()")) . ' ' .
        $button->show($RCMAIL->gettext('upload'), array('class' => 'button mainaction', 'onclick' => rcmail_output::JS_OBJECT_NAME . ".command('import-messages', this.form)"))
      ) : '')
    )
  );
    $content = html::tag('input', array('type' => 'hidden', 'name' => '_unlock', 'value' => ''))
        . html::div(null, $fileinput->show())
        . html::div('hint', $RCMAIL->gettext(array('name' => 'maxuploadsize', 'vars' => array('size' => $max_filesize))));
  $OUTPUT->add_gui_object('importform', $attrib['id'].'Frm');
  return $out;
    if (rcube_utils::get_boolean($attrib['buttons'])) {
        $content .= html::div('buttons',
            $button->show($RCMAIL->gettext('close'), array('class' => 'button', 'onclick' => "$('#$attrib[id]').hide()"))
            . ' ' .
            $button->show($RCMAIL->gettext('upload'), array(
                'class'   => 'button mainaction',
                'onclick' => rcmail_output::JS_OBJECT_NAME . ".command('import-messages', this.form)"
            )));
    }
    $out = $RCMAIL->output->form_tag(array(
            'id'      => $attrib['id'].'Frm',
            'method'  => 'post',
            'enctype' => 'multipart/form-data'
        ),
        $content);
    $RCMAIL->output->add_gui_object('importform', $attrib['id'].'Frm');
    return html::div($attrib, $out);
}