alecpl
2011-02-28 29c54229cfbc104930e7743cecc212f53aed8a15
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-2010, Roundcube Dev. - Switzerland                 |
 | Copyright (C) 2005-2010, The Roundcube Dev Team                       |
 | Licensed under the GNU GPL                                            |
 |                                                                       |
 | PURPOSE:                                                              |
@@ -46,7 +46,7 @@
}
// set imap properties and session vars
if ($mbox = get_input_value('_mbox', RCUBE_INPUT_GPC))
if (strlen(trim($mbox = get_input_value('_mbox', RCUBE_INPUT_GPC, true))))
  $IMAP->set_mailbox(($_SESSION['mbox'] = $mbox));
else if ($IMAP)
  $_SESSION['mbox'] = $IMAP->get_mailbox_name();
@@ -56,9 +56,9 @@
// set default sort col/order to session
if (!isset($_SESSION['sort_col']))
  $_SESSION['sort_col'] = $CONFIG['message_sort_col'];
  $_SESSION['sort_col'] = !empty($CONFIG['message_sort_col']) ? $CONFIG['message_sort_col'] : '';
if (!isset($_SESSION['sort_order']))
  $_SESSION['sort_order'] = $CONFIG['message_sort_order'];
  $_SESSION['sort_order'] = strtoupper($CONFIG['message_sort_order']) == 'ASC' ? 'ASC' : 'DESC';
// set threads mode
$a_threading = $RCMAIL->config->get('message_threading', array());
@@ -72,45 +72,40 @@
$IMAP->set_threading($a_threading[$_SESSION['mbox']]);
// set message set for search result
if (!empty($_REQUEST['_search']) && isset($_SESSION['search'][$_REQUEST['_search']]))
  {
  $IMAP->set_search_set($_SESSION['search'][$_REQUEST['_search']]);
if (!empty($_REQUEST['_search']) && isset($_SESSION['search'])
    && $_SESSION['search_request'] == $_REQUEST['_search']
) {
  $IMAP->set_search_set($_SESSION['search']);
  $OUTPUT->set_env('search_request', $_REQUEST['_search']);
  $OUTPUT->set_env('search_text', $_SESSION['last_text_search']);
  }
}
// set main env variables, labels and page title
if (empty($RCMAIL->action) || $RCMAIL->action == 'list')
  {
if (empty($RCMAIL->action) || $RCMAIL->action == 'list') {
  $mbox_name = $IMAP->get_mailbox_name();
  if (empty($RCMAIL->action))
    {
  if (empty($RCMAIL->action)) {
    // initialize searching result if search_filter is used
    if ($_SESSION['search_filter'] && $_SESSION['search_filter'] != 'ALL')
      {
    if ($_SESSION['search_filter'] && $_SESSION['search_filter'] != 'ALL') {
      $search_request = md5($mbox_name.$_SESSION['search_filter']);
      $IMAP->search($mbox_name, $_SESSION['search_filter'], RCMAIL_CHARSET, $_SESSION['sort_col']);
      $_SESSION['search'][$search_request] = $IMAP->get_search_set();
      $_SESSION['search'] = $IMAP->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);
    }
  }
  // set current mailbox and some other vars in client environment
  $OUTPUT->set_env('mailbox', $mbox_name);
  $OUTPUT->set_env('pagesize', $IMAP->page_size);
  $OUTPUT->set_env('quota', $IMAP->get_capability('quota'));
  $OUTPUT->set_env('quota', $IMAP->get_capability('QUOTA'));
  $OUTPUT->set_env('delimiter', $IMAP->get_hierarchy_delimiter());
  $OUTPUT->set_env('threading', (bool) $IMAP->threading);
  $OUTPUT->set_env('threads', $IMAP->threading
   || $IMAP->get_capability('thread=references')
        || $IMAP->get_capability('thread=orderedsubject')
        || $IMAP->get_capability('thread=refs')
  );
  $OUTPUT->set_env('threads', $IMAP->threading || $IMAP->get_capability('THREAD'));
  if ($CONFIG['flag_for_deletion'])
    $OUTPUT->set_env('flag_for_deletion', true);
@@ -132,10 +127,11 @@
  if (!$OUTPUT->ajax_call)
    $OUTPUT->add_label('checkingmail', 'deletemessage', 'movemessagetotrash',
      'movingmessage', 'copyingmessage', 'copy', 'move', 'quota');
      'movingmessage', 'copyingmessage', 'deletingmessage', 'markingmessage',
      'copy', 'move', 'quota');
  $OUTPUT->set_pagetitle(rcmail_localize_foldername($mbox_name));
  }
}
/**
@@ -256,17 +252,14 @@
  if (empty($a_headers))
    return;
  // remove 'threads', 'attachment', 'flag' columns, we don't need them here
  if (($key = array_search('attachment', $a_show_cols)) !== FALSE)
    unset($a_show_cols[$key]);
  if (($key = array_search('flag', $a_show_cols)) !== FALSE)
    unset($a_show_cols[$key]);
  if (($key = array_search('threads', $a_show_cols)) !== FALSE)
    unset($a_show_cols[$key]);
  // loop through message headers
  // remove 'threads', 'attachment', 'flag', 'status' columns, we don't need them here
  foreach (array('threads', 'attachment', 'flag', 'status') as $col) {
    if (($key = array_search($col, $a_show_cols)) !== FALSE)
      unset($a_show_cols[$key]);
  }
  foreach ($a_headers as $n => $header)
    {
  // loop through message headers
  foreach ($a_headers as $n => $header) {
    if (empty($header))
      continue;
@@ -276,16 +269,14 @@
    $IMAP->set_charset(!empty($header->charset) ? $header->charset : $CONFIG['default_charset']);
    // format each col; similar as in rcmail_message_list()
    foreach ($a_show_cols as $col)
      {
    foreach ($a_show_cols as $col) {
      if (in_array($col, array('from', 'to', 'cc', 'replyto')))
        $cont = Q(rcmail_address_string($header->$col, 3), 'show');
      else if ($col=='subject')
        {
        $cont = abbreviate_string(trim($IMAP->decode_header($header->$col)), 160);
      else if ($col=='subject') {
        $cont = trim($IMAP->decode_header($header->$col));
        if (!$cont) $cont = rcube_label('nosubject');
        $cont = Q($cont);
        }
      }
      else if ($col=='size')
        $cont = show_bytes($header->$col);
      else if ($col=='date')
@@ -294,7 +285,7 @@
        $cont = Q($header->$col);
      $a_msg_cols[$col] = $cont;
      }
    }
    if ($header->depth)
      $a_msg_flags['depth'] = $header->depth;
@@ -318,8 +309,8 @@
      $a_msg_flags['flagged'] = 1;
    if ($header->others['list-post'])
      $a_msg_flags['ml'] = 1;
    if (preg_match("/(application\/|multipart\/m)/i", $header->ctype))
      $a_msg_flags['attachment'] = 1;
    $a_msg_flags['ctype'] = Q($header->ctype);
    $a_msg_flags['mbox'] = $mbox;
    // merge with plugin result
@@ -333,11 +324,11 @@
      $a_msg_cols,
      $a_msg_flags,
      $insert_top);
    }
  }
    if ($IMAP->threading) {
      $OUTPUT->command('init_threads', (array) $roots);
    }
  if ($IMAP->threading) {
    $OUTPUT->command('init_threads', (array) $roots);
  }
}
@@ -381,7 +372,8 @@
        $col_name = '<span class="flagged">&nbsp;</span>';
        break;
      case 'attachment':
        $col_name = '<span class="attachment">&nbsp;</span>';
      case 'status':
        $col_name = '<span class="' . $col .'">&nbsp;</span>';
        break;
      case 'threads':
        $col_name = $list_menu;
@@ -427,86 +419,22 @@
function rcmail_messagecount_display($attrib)
  {
  global $IMAP, $OUTPUT;
  global $RCMAIL;
  if (!$attrib['id'])
    $attrib['id'] = 'rcmcountdisplay';
  $OUTPUT->add_gui_object('countdisplay', $attrib['id']);
  $RCMAIL->output->add_gui_object('countdisplay', $attrib['id']);
  return html::span($attrib, rcmail_get_messagecount_text());
  }
  $content =  $RCMAIL->action != 'show' ? rcmail_get_messagecount_text() : rcube_label('loading');
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 $COMM_PATH, $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;
  return html::span($attrib, $content);
  }
function rcmail_get_messagecount_text($count=NULL, $page=NULL)
  {
  global $RCMAIL, $IMAP, $MESSAGE;
  if (isset($MESSAGE->index))
    {
    return rcube_label(array('name' => 'messagenrof',
        'vars' => array('nr'  => $MESSAGE->index+1,
        'count' => $count!==NULL ? $count : $IMAP->messagecount(NULL, 'ALL')))); // Only messages, no threads here
    }
  global $RCMAIL, $IMAP;
  if ($page===NULL)
    $page = $IMAP->list_page;
@@ -554,7 +482,7 @@
{
  global $RCMAIL;
  $old_unseen = $_SESSION['unseen_count'][$mbox_name];
  $old_unseen = rcmail_get_unseen_count($mbox_name);
  if ($count === null)
    $unseen = $RCMAIL->imap->messagecount($mbox_name, 'UNSEEN', $force);
@@ -564,10 +492,30 @@
  if ($unseen != $old_unseen || ($mbox_name == 'INBOX'))
    $RCMAIL->output->command('set_unread_count', $mbox_name, $unseen, ($mbox_name == 'INBOX'));
  // @TODO: this data is doubled (session and cache tables) if caching is enabled
  $_SESSION['unseen_count'][$mbox_name] = $unseen;
  rcmail_set_unseen_count($mbox_name, $unseen);
  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']))
    $_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']))
    return $_SESSION['unseen_count'][$mbox_name];
  else
    return null;
}
@@ -717,7 +665,8 @@
  // trigger plugin hook
  $data = $RCMAIL->plugins->exec_hook('message_part_before',
    array('type' => $part->ctype_secondary, 'body' => $part->body) + $p + array('safe' => false, 'plain' => false, 'inline_html' => true));
    array('type' => $part->ctype_secondary, 'body' => $part->body, 'id' => $part->mime_id)
        + $p + array('safe' => false, 'plain' => false, 'inline_html' => true));
  // convert html to text/plain
  if ($data['type'] == 'html' && $data['plain']) {
@@ -750,7 +699,8 @@
    $body = rcmail_plain_body($body, $part->ctype_parameters['format'] == 'flowed');
  // allow post-processing of the message body
  $data = $RCMAIL->plugins->exec_hook('message_part_after', array('type' => $part->ctype_secondary, 'body' => $body) + $data);
  $data = $RCMAIL->plugins->exec_hook('message_part_after',
    array('type' => $part->ctype_secondary, 'body' => $body, 'id' => $part->mime_id) + $data);
  return $data['type'] == 'html' ? $data['body'] : html::tag('pre', array(), $data['body']);
}
@@ -840,15 +790,20 @@
    $quote_level = $q;
  }
  // quote plain text
  $body = Q(join("\n", $a_lines), 'dummy', false);
  $body = join("\n", $a_lines);
  // colorize signature
  // quote plain text (don't use Q() here, to display entities "as is")
  $table = get_html_translation_table(HTML_SPECIALCHARS);
  unset($table['?']);
  $body = strtr($body, $table);
  // 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) < $RCMAIL->config->get('sig_max_lines', 15))
      if (substr_count($body, "\n", $sp) < $sig_max_lines)
        $body = substr($body, 0, max(0, $sp))
          .'<span class="sig">'.substr($body, $sp).'</span>';
      break;
@@ -874,10 +829,10 @@
    case 'style':
      // decode all escaped entities and reduce to ascii strings
      $stripped = preg_replace('/[^a-zA-Z\(:]/', '', rcmail_xss_entity_decode($content));
      $stripped = preg_replace('/[^a-zA-Z\(:;]/', '', rcmail_xss_entity_decode($content));
      // now check for evil strings like expression, behavior or url()
      if (!preg_match('/expression|behavior|url\(|import/', $stripped)) {
      if (!preg_match('/expression|behavior|url\(|import[^a]/', $stripped)) {
        $out = html::tag('style', array('type' => 'text/css'), $content);
        break;
      }
@@ -970,29 +925,42 @@
    else
      $header_value = trim($IMAP->decode_header($value));
    $output_headers[$hkey] = array('title' => rcube_label($hkey), 'value' => $header_value, 'raw' => $value);
    $output_headers[$hkey] = array(
        'title' => rcube_label(preg_replace('/(^mail-|-)/', '', $hkey)),
        'value' => $header_value, 'raw' => $value
    );
  }
  $plugin = $RCMAIL->plugins->exec_hook('message_headers_output', array('output' => $output_headers, 'headers' => $MESSAGE->headers));
  $plugin = $RCMAIL->plugins->exec_hook('message_headers_output',
    array('output' => $output_headers, 'headers' => $MESSAGE->headers));
  // compose html table
  $table = new html_table(array('cols' => 2));
  foreach ($plugin['output'] as $hkey => $row) {
    $table->add(array('class' => 'header-title'), Q($row['title']));
    $table->add(array('class' => $hkey, 'width' => "90%"), Q($row['value'], ($hkey == 'subject' ? 'strict' : 'show')));
    $table->add(array('class' => 'header '.$hkey), Q($row['value'], ($hkey == 'subject' ? 'strict' : 'show')));
  }
  // all headers division
  $table->add(array('colspan' => 2, 'class' => "more-headers show-headers", 'onclick' => "return ".JS_OBJECT_NAME.".command('load-headers','',this)"), '');
  $table->add_row(array('id' => "all-headers"));
  $table->add(array('colspan' => 2, 'class' => "all"), html::div(array('id' => 'headers-source'), ''));
  return $table->show($attrib);
}
/**
 * return block to show full message headers
 */
function rcmail_message_full_headers($attrib, $headers=NULL)
{
  global $OUTPUT;
  $html = html::div(array('class' => "more-headers show-headers", 'onclick' => "return ".JS_OBJECT_NAME.".command('load-headers','',this)"), '');
  $html .= html::div(array('id' => "all-headers", 'class' => "all", 'style' => 'display:none'), html::div(array('id' => 'headers-source'), ''));
  
  $OUTPUT->add_gui_object('all_headers_row', 'all-headers');
  $OUTPUT->add_gui_object('all_headers_box', 'headers-source');
  return $table->show($attrib);
  }
  return html::div($attrib, $html);
}
/**
@@ -1182,20 +1150,22 @@
  $attributes = array();
  // Handle body attributes that doesn't play nicely with div elements
  if (preg_match('/<div class="' . preg_quote($body_id, '/') . '" ([^>]+)/', $body, $m)) {
  $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 (preg_match('/bgcolor=["\']*([a-z0-9#]+)["\']*/', $attrs, $mb)) {
    if ($m[1] && preg_match('/bgcolor=["\']*([a-z0-9#]+)["\']*/', $attrs, $mb)) {
      $attributes['background-color'] = $mb[1];
      $attrs = preg_replace('/bgcolor=["\']*([a-z0-9#]+)["\']*/', '', $attrs);
    }
    // Get background, we'll set it as background-image of the message container
    if (preg_match('/background=["\']*([^"\'>\s]+)["\']*/', $attrs, $mb)) {
    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('/<div class="' . preg_quote($body_id, '/') . '" [^>]+/', rtrim($attrs), $body, 1);
    if (!empty($attributes)) {
      $body = preg_replace($regexp, rtrim($attrs), $body, 1);
    }
    // handle body styles related to background image
    if ($attributes['background-image']) {
@@ -1211,8 +1181,9 @@
  }
  // make sure there's 'rcmBody' div, we need it for proper css modification
  // its name is hardcoded in rcmail_message_body() also
  else
  else {
    $body = '<div class="' . $body_id . '">' . $body . '</div>';
  }
  return $body;
}
@@ -1223,15 +1194,19 @@
 */
function rcmail_alter_html_link($matches)
{
  global $EMAIL_ADDRESS_PATTERN;
  global $RCMAIL, $EMAIL_ADDRESS_PATTERN;
  $tag = $matches[1];
  $attrib = parse_attrib_string($matches[2]);
  $end = '>';
  // Remove non-printable characters in URL (#1487805)
  $attrib['href'] = preg_replace('/[\x00-\x1F]/', '', $attrib['href']);
  if ($tag == 'link' && preg_match('/^https?:\/\//i', $attrib['href'])) {
    $attrib['href'] = "?_task=utils&amp;_action=modcss&amp;u=" . urlencode($attrib['href'])
        . "&amp;c=" . urlencode($GLOBALS['rcmail_html_container_id']);
    $tempurl = 'tmp-' . md5($attrib['href']) . '.css';
    $_SESSION['modcssurls'][$tempurl] = $attrib['href'];
    $attrib['href'] = $RCMAIL->url(array('task' => 'utils', 'action' => 'modcss', 'u' => $tempurl, 'c' => $GLOBALS['rcmail_html_container_id']));
    $end = ' />';
  }
  else if (preg_match('/^mailto:'.$EMAIL_ADDRESS_PATTERN.'(\?[^"\'>]+)?/i', $attrib['href'], $mailto)) {
@@ -1279,17 +1254,17 @@
    // IDNA ASCII to Unicode
    if ($name == $mailto)
      $name = idn_to_utf8($name);
      $name = rcube_idn_to_utf8($name);
    if ($string == $mailto)
      $string = idn_to_utf8($string);
    $mailto = idn_to_utf8($mailto);
      $string = rcube_idn_to_utf8($string);
    $mailto = rcube_idn_to_utf8($mailto);
    if ($PRINT_MODE) {
      $out .= sprintf('%s &lt;%s&gt;', Q($name), $mailto);
    }
    else if (check_email($part['mailto'], false)) {
      if ($linked) {
        $out .= html::a(array(
        $address = html::a(array(
            'href' => 'mailto:'.$mailto,
            'onclick' => sprintf("return %s.command('compose','%s',this)", JS_OBJECT_NAME, JQ($mailto)),
            'title' => $mailto,
@@ -1298,12 +1273,12 @@
        Q($name ? $name : $mailto));
      }
      else {
        $out .= html::span(array('title' => $mailto, 'class' => "rcmContactAddress"),
        $address = html::span(array('title' => $mailto, 'class' => "rcmContactAddress"),
          Q($name ? $name : $mailto));
      }
      if ($addicon && $got_writable_abook) {
        $out .= '&nbsp;' . html::a(array(
        $address = html::span(null, $address . html::a(array(
            'href' => "#add",
            'onclick' => sprintf("return %s.command('add-contact','%s',this)", JS_OBJECT_NAME, urlencode($string)),
            'title' => rcube_label('addtoaddressbook'),
@@ -1311,8 +1286,9 @@
          html::img(array(
            'src' => $CONFIG['skin_path'] . $addicon,
            'alt' => "Add contact",
          )));
          ))));
      }
      $out .= $address;
    }
    else {
      if ($name)
@@ -1548,6 +1524,7 @@
      $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);
@@ -1721,6 +1698,16 @@
  return $date;
}
// Fixes some content-type names
function rcmail_fix_mimetype($name)
{
  // Some versions of Outlook create garbage Content-Type:
  // application/pdf.A520491B_3BF7_494D_8855_7FAC2C6C0608
  if (preg_match('/^application\/pdf.+/', $name))
    $name = 'application/pdf';
  return $name;
}
function rcmail_search_filter($attrib)
{
@@ -1778,6 +1765,7 @@
  'quotadisplay' => 'rcmail_quota_display',
  'mailboxname' => 'rcmail_mailbox_name_display',
  'messageheaders' => 'rcmail_message_headers',
  'messagefullheaders' => 'rcmail_message_full_headers',
  'messagebody' => 'rcmail_message_body',
  'messagecontentframe' => 'rcmail_messagecontent_frame',
  'messagepartframe' => 'rcmail_message_part_frame',
@@ -1786,4 +1774,17 @@
  'searchform' => array($OUTPUT, 'search_form'),
));
// register action aliases
$RCMAIL->register_action_map(array(
    'preview' => 'show.inc',
    'print'   => 'show.inc',
    'moveto'  => 'move_del.inc',
    'delete'  => 'move_del.inc',
    'send'    => 'sendmail.inc',
    'expunge' => 'folders.inc',
    'purge'   => 'folders.inc',
    'remove-attachment'  => 'attachments.inc',
    'display-attachment' => 'attachments.inc',
    'upload'             => 'attachments.inc',
    'group-expand'       => 'autocomplete.inc',
));