summaryrefslogtreecommitdiff
path: root/program/steps/mail
diff options
context:
space:
mode:
Diffstat (limited to 'program/steps/mail')
-rw-r--r--program/steps/mail/autocomplete.inc2
-rw-r--r--program/steps/mail/check_recent.inc5
-rw-r--r--program/steps/mail/compose.inc133
-rw-r--r--program/steps/mail/copy.inc8
-rw-r--r--program/steps/mail/func.inc298
-rw-r--r--program/steps/mail/get.inc136
-rw-r--r--program/steps/mail/import.inc105
-rw-r--r--program/steps/mail/list_contacts.inc43
-rw-r--r--program/steps/mail/mark.inc10
-rw-r--r--program/steps/mail/move_del.inc6
-rw-r--r--program/steps/mail/search_contacts.inc19
-rw-r--r--program/steps/mail/sendmail.inc53
-rw-r--r--program/steps/mail/show.inc18
13 files changed, 545 insertions, 291 deletions
diff --git a/program/steps/mail/autocomplete.inc b/program/steps/mail/autocomplete.inc
index 55579814c..f9e8d71a4 100644
--- a/program/steps/mail/autocomplete.inc
+++ b/program/steps/mail/autocomplete.inc
@@ -102,7 +102,7 @@ if (!empty($book_types) && strlen($search)) {
// also list matching contact groups
if ($abook->groups && count($contacts) < $MAXNUM) {
- foreach ($abook->list_groups($search) as $group) {
+ foreach ($abook->list_groups($search, $mode) as $group) {
$abook->reset();
$abook->set_group($group['ID']);
$group_prop = $abook->get_group($group['ID']);
diff --git a/program/steps/mail/check_recent.inc b/program/steps/mail/check_recent.inc
index 3649d148c..8c0b1ffc0 100644
--- a/program/steps/mail/check_recent.inc
+++ b/program/steps/mail/check_recent.inc
@@ -81,9 +81,10 @@ foreach ($a_mailboxes as $mbox_name) {
if (empty($_GET['_list']))
continue;
- // get overall message count; allow caching because rcube_storage::folder_status() did a refresh
+ // get overall message count; allow caching because rcube_storage::folder_status()
+ // did a refresh but only in list mode
$list_mode = $RCMAIL->storage->get_threading() ? 'THREADS' : 'ALL';
- $all_count = $RCMAIL->storage->count($mbox_name, $list_mode, false, false);
+ $all_count = $RCMAIL->storage->count($mbox_name, $list_mode, $list_mode == 'THREADS', false);
$page = $RCMAIL->storage->get_page();
$page_size = $RCMAIL->storage->get_pagesize();
diff --git a/program/steps/mail/compose.inc b/program/steps/mail/compose.inc
index c166eb74e..9ffde8a57 100644
--- a/program/steps/mail/compose.inc
+++ b/program/steps/mail/compose.inc
@@ -139,12 +139,11 @@ if (!empty($CONFIG['drafts_mbox'])) {
}
// set current mailbox in client environment
$OUTPUT->set_env('mailbox', $RCMAIL->storage->get_folder());
-$OUTPUT->set_env('sig_above', $RCMAIL->config->get('sig_above', false));
$OUTPUT->set_env('top_posting', intval($RCMAIL->config->get('reply_mode')) > 0);
$OUTPUT->set_env('recipients_separator', trim($RCMAIL->config->get('recipients_separator', ',')));
// default font for HTML editor
-$font = rcube_fontdefs($RCMAIL->config->get('default_font', 'Verdana'));
+$font = rcube_fontdefs($RCMAIL->config->get('default_font'));
if ($font && !is_array($font)) {
$OUTPUT->set_env('default_font', $font);
}
@@ -152,6 +151,7 @@ if ($font && !is_array($font)) {
// get reference message and set compose mode
if ($msg_uid = $COMPOSE['param']['draft_uid']) {
$compose_mode = RCUBE_COMPOSE_DRAFT;
+ $OUTPUT->set_env('draft_id', $msg_uid);
$RCMAIL->storage->set_folder($CONFIG['drafts_mbox']);
}
else if ($msg_uid = $COMPOSE['param']['reply_uid']) {
@@ -170,6 +170,9 @@ $OUTPUT->set_env('compose_mode', $compose_mode);
$config_show_sig = $RCMAIL->config->get('show_sig', 1);
if ($compose_mode == RCUBE_COMPOSE_EDIT || $compose_mode == RCUBE_COMPOSE_DRAFT) {
// don't add signature in draft/edit mode, we'll also not remove the old-one
+ // but only on page display, later we should be able to change identity/sig (#1489229)
+ if ($config_show_sig == 1 || $config_show_sig == 2)
+ $OUTPUT->set_env('show_sig_later', true);
}
else if ($config_show_sig == 1)
$OUTPUT->set_env('show_sig', true);
@@ -219,10 +222,10 @@ if (!empty($msg_uid) && empty($COMPOSE['as_attachment']))
$COMPOSE['param']['sent_mbox'] = $sent_folder;
}
}
- else if ($compose_mode == RCUBE_COMPOSE_DRAFT) {
- if ($MESSAGE->headers->others['x-draft-info']) {
+ else if ($compose_mode == RCUBE_COMPOSE_DRAFT || $compose_mode == RCUBE_COMPOSE_EDIT) {
+ if ($compose_mode == RCUBE_COMPOSE_DRAFT && ($draft_info = $MESSAGE->headers->get('x-draft-info'))) {
// get reply_uid/forward_uid to flag the original message when sending
- $info = rcmail_draftinfo_decode($MESSAGE->headers->others['x-draft-info']);
+ $info = rcmail_draftinfo_decode($draft_info);
if ($info['type'] == 'reply')
$COMPOSE['reply_uid'] = $info['uid'];
@@ -239,10 +242,10 @@ if (!empty($msg_uid) && empty($COMPOSE['as_attachment']))
}
}
- if ($MESSAGE->headers->in_reply_to)
- $COMPOSE['reply_msgid'] = '<'.$MESSAGE->headers->in_reply_to.'>';
+ if ($in_reply_to = $MESSAGE->headers->get('in-reply-to'))
+ $COMPOSE['reply_msgid'] = '<' . $in_reply_to . '>';
- $COMPOSE['references'] = $MESSAGE->headers->references;
+ $COMPOSE['references'] = $MESSAGE->headers->references;
}
}
else {
@@ -327,6 +330,20 @@ foreach ($parts as $header) {
$fvalue .= $v;
if ($v = $MESSAGE->headers->cc)
$fvalue .= (!empty($fvalue) ? $separator : '') . $v;
+ // Use Sender header (#1489011)
+ if (($v = $MESSAGE->headers->get('Sender', false)) && strpos($v, '-bounces@') === false)
+ $fvalue .= (!empty($fvalue) ? $separator : '') . $v;
+
+ // When To: and Reply-To: are the same we add From: address to the list (#1489037)
+ if ($v = $MESSAGE->headers->from) {
+ $from = rcube_mime::decode_address_list($v, null, false, $MESSAGE->headers->charset, true);
+ $to = rcube_mime::decode_address_list($MESSAGE->headers->to, null, false, $MESSAGE->headers->charset, true);
+ $replyto = rcube_mime::decode_address_list($MESSAGE->headers->replyto, null, false, $MESSAGE->headers->charset, true);
+
+ if (count($replyto) && !count(array_diff($to, $replyto)) && count(array_diff($from, $to))) {
+ $fvalue .= (!empty($fvalue) ? $separator : '') . $v;
+ }
+ }
}
}
else if (in_array($compose_mode, array(RCUBE_COMPOSE_DRAFT, RCUBE_COMPOSE_EDIT))) {
@@ -386,7 +403,7 @@ function rcmail_compose_headers($attrib)
{
global $MESSAGE;
- list($form_start, $form_end) = get_form_tags($attrib);
+ list($form_start,) = get_form_tags($attrib);
$out = '';
$part = strtolower($attrib['part']);
@@ -450,7 +467,7 @@ function rcmail_compose_headers($attrib)
function rcmail_compose_header_from($attrib)
{
- global $MESSAGE, $OUTPUT, $RCMAIL, $compose_mode;
+ global $MESSAGE, $OUTPUT, $RCMAIL, $COMPOSE, $compose_mode;
// pass the following attributes to the form class
$field_attrib = array('name' => '_from');
@@ -461,7 +478,8 @@ function rcmail_compose_header_from($attrib)
if (count($MESSAGE->identities))
{
$a_signatures = array();
- $separator = $RCMAIL->config->get('sig_above')
+ $identities = array();
+ $separator = intval($RCMAIL->config->get('reply_mode')) > 0
&& ($compose_mode == RCUBE_COMPOSE_REPLY || $compose_mode == RCUBE_COMPOSE_FORWARD) ? '---' : '-- ';
$field_attrib['onchange'] = JS_OBJECT_NAME.".change_identity(this)";
@@ -498,12 +516,21 @@ function rcmail_compose_header_from($attrib)
$a_signatures[$identity_id]['text'] = $text;
$a_signatures[$identity_id]['html'] = $html;
}
+
+ // add bcc and reply-to
+ if (!empty($sql_arr['reply-to'])) {
+ $identities[$identity_id]['replyto'] = $sql_arr['reply-to'];
+ }
+ if (!empty($sql_arr['bcc'])) {
+ $identities[$identity_id]['bcc'] = $sql_arr['bcc'];
+ }
}
- $out = $select_from->show($MESSAGE->compose['from']);
+ $out = $select_from->show((int)$MESSAGE->compose['from']);
// add signatures to client
$OUTPUT->set_env('signatures', $a_signatures);
+ $OUTPUT->set_env('identities', $identities);
}
// no identities, display text input field
else {
@@ -553,7 +580,7 @@ function rcmail_message_is_html()
function rcmail_prepare_message_body()
{
- global $RCMAIL, $MESSAGE, $COMPOSE, $compose_mode, $LINE_LENGTH, $HTML_MODE;
+ global $RCMAIL, $MESSAGE, $COMPOSE, $compose_mode, $HTML_MODE;
// use posted message body
if (!empty($_POST['_message'])) {
@@ -571,16 +598,33 @@ function rcmail_prepare_message_body()
rcmail_write_forward_attachments();
}
// reply/edit/draft/forward
- else if ($compose_mode && ($compose_mode != RCUBE_COMPOSE_REPLY || $RCMAIL->config->get('reply_mode') != -1)) {
- $isHtml = rcmail_compose_editor_mode();
+ else if ($compose_mode && ($compose_mode != RCUBE_COMPOSE_REPLY || intval($RCMAIL->config->get('reply_mode')) != -1)) {
+ $isHtml = rcmail_compose_editor_mode();
+ $messages = array();
if (!empty($MESSAGE->parts)) {
+ // collect IDs of message/rfc822 parts
+ if ($compose_mode == RCUBE_COMPOSE_EDIT || $compose_mode == RCUBE_COMPOSE_DRAFT) {
+ foreach ($MESSAGE->attachments as $part) {
+ if ($part->mimetype == 'message/rfc822') {
+ $messages[] = $part->mime_id;
+ }
+ }
+ }
+
foreach ($MESSAGE->parts as $part) {
// skip no-content and attachment parts (#1488557)
if ($part->type != 'content' || !$part->size || $MESSAGE->is_attachment($part)) {
continue;
}
+ // skip all content parts inside the message/rfc822 part in DRAFT/EDIT mode
+ foreach ($messages as $mimeid) {
+ if (strpos($part->mime_id, $mimeid . '.') === 0) {
+ continue 2;
+ }
+ }
+
if ($part_body = rcmail_compose_part_body($part, $isHtml)) {
$body .= ($body ? ($isHtml ? '<br/>' : "\n") : '') . $part_body;
}
@@ -626,7 +670,7 @@ function rcmail_prepare_message_body()
function rcmail_compose_part_body($part, $isHtml = false)
{
- global $RCMAIL, $MESSAGE, $compose_mode;
+ global $RCMAIL, $MESSAGE, $LINE_LENGTH, $compose_mode;
// Check if we have enough memory to handle the message in it
// #1487424: we need up to 10x more memory than the body
@@ -663,6 +707,11 @@ function rcmail_compose_part_body($part, $isHtml = false)
$body = rcmail_remove_signature($body);
}
}
+
+ if ($part->ctype_parameters['format'] == 'flowed') {
+ $body = rcube_mime::unfold_flowed($body);
+ }
+
// add HTML formatting
$body = rcmail_plain_body($body);
if ($body) {
@@ -702,7 +751,7 @@ function rcmail_compose_part_body($part, $isHtml = false)
function rcmail_compose_body($attrib)
{
- global $RCMAIL, $CONFIG, $OUTPUT, $MESSAGE, $compose_mode, $LINE_LENGTH, $HTML_MODE, $MESSAGE_BODY;
+ global $RCMAIL, $CONFIG, $OUTPUT, $MESSAGE, $compose_mode, $HTML_MODE, $MESSAGE_BODY;
list($form_start, $form_end) = get_form_tags($attrib);
unset($attrib['form']);
@@ -886,8 +935,7 @@ function rcmail_create_forward_body($body, $bodyIsHtml)
if (!isset($COMPOSE['forward_attachments']) && is_array($MESSAGE->mime_parts))
$cid_map = rcmail_write_compose_attachments($MESSAGE, $bodyIsHtml);
- $date = format_date($MESSAGE->headers->date, $RCMAIL->config->get('date_long'));
- $charset = $RCMAIL->output->get_charset();
+ $date = format_date($MESSAGE->headers->date, $RCMAIL->config->get('date_long'));
if (!$bodyIsHtml) {
$prefix = "\n\n\n-------- " . rcube_label('originalmessage') . " --------\n";
@@ -941,7 +989,7 @@ function rcmail_create_forward_body($body, $bodyIsHtml)
function rcmail_create_draft_body($body, $bodyIsHtml)
{
- global $MESSAGE, $OUTPUT, $COMPOSE;
+ global $MESSAGE, $COMPOSE;
/**
* add attachments
@@ -989,39 +1037,50 @@ function rcmail_write_compose_attachments(&$message, $bodyIsHtml)
global $RCMAIL, $COMPOSE, $compose_mode;
$loaded_attachments = array();
- foreach ((array)$COMPOSE['attachments'] as $id => $attachment) {
+ foreach ((array)$COMPOSE['attachments'] as $attachment) {
$loaded_attachments[$attachment['name'] . $attachment['mimetype']] = $attachment;
}
- $cid_map = $messages = array();
+ $cid_map = array();
+ $messages = array();
+
foreach ((array)$message->mime_parts as $pid => $part)
{
if ($part->disposition == 'attachment' || ($part->disposition == 'inline' && $bodyIsHtml) || $part->filename) {
- if (($part->ctype_primary == 'message' && $bodyIsHtml) || $part->ctype_primary == 'multipart') {
+ // skip parts that aren't valid attachments
+ if ($part->ctype_primary == 'multipart' || $part->mimetype == 'application/ms-tnef') {
continue;
}
- if ($part->mimetype == 'application/ms-tnef') {
+ // skip message attachments in reply mode
+ if ($part->ctype_primary == 'message' && $compose_mode == RCUBE_COMPOSE_REPLY) {
continue;
}
- // skip inline images when forwarding in plain text
- if ($part->content_id && !$bodyIsHtml && $compose_mode == RCUBE_COMPOSE_FORWARD) {
+ // skip inline images when forwarding in text mode
+ if ($part->content_id && $part->disposition == 'inline' && !$bodyIsHtml && $compose_mode == RCUBE_COMPOSE_FORWARD) {
continue;
}
- $skip = false;
+ // skip message/rfc822 attachments on forwards (#1489214)
+ // Thunderbird when forwarding in inline mode displays such attachments
+ // and skips any attachments from inside of such part, this however
+ // skipped e.g. images used in HTML body or other attachments. So,
+ // better to skip .eml attachments but not their content (included files).
if ($part->mimetype == 'message/rfc822') {
+ if ($compose_mode == RCUBE_COMPOSE_FORWARD) {
+ continue;
+ }
$messages[] = $part->mime_id;
- } else if ($messages) {
+ }
+ else if ($compose_mode != RCUBE_COMPOSE_FORWARD) {
// skip attachments included in message/rfc822 attachment (#1486487)
foreach ($messages as $mimeid)
- if (strpos($part->mime_id, $mimeid.'.') === 0) {
- $skip = true;
- break;
+ if (strpos($part->mime_id, $mimeid . '.') === 0) {
+ continue 2;
}
}
- if (!$skip && (($attachment = $loaded_attachments[rcmail_attachment_name($part) . $part->mimetype])
- || ($attachment = rcmail_save_attachment($message, $pid)))) {
+ if (($attachment = $loaded_attachments[rcmail_attachment_name($part) . $part->mimetype])
+ || ($attachment = rcmail_save_attachment($message, $pid))) {
$COMPOSE['attachments'][$attachment['id']] = $attachment;
if ($bodyIsHtml && ($part->content_id || $part->content_location)) {
$url = sprintf('%s&_id=%s&_action=display-attachment&_file=rcmfile%s',
@@ -1074,7 +1133,7 @@ function rcmail_write_forward_attachments()
$names = array();
$loaded_attachments = array();
- foreach ((array)$COMPOSE['attachments'] as $id => $attachment) {
+ foreach ((array)$COMPOSE['attachments'] as $attachment) {
$loaded_attachments[$attachment['name'] . $attachment['mimetype']] = $attachment;
}
@@ -1209,10 +1268,11 @@ function rcmail_save_image($path, $mimetype='')
// handle attachments in memory
$data = file_get_contents($path);
+ $name = rcmail_basename($path);
$attachment = array(
'group' => $COMPOSE['id'],
- 'name' => rcmail_basename($path),
+ 'name' => $name,
'mimetype' => $mimetype ? $mimetype : rc_mime_content_type($path, $name),
'data' => $data,
'size' => strlen($data),
@@ -1482,7 +1542,7 @@ function rcmail_editor_selector($attrib)
$select->add(Q(rcube_label('plaintoggle')), 'plain');
return $select->show($useHtml ? 'html' : 'plain');
-
+/*
foreach ($choices as $value => $text) {
$attrib['id'] = '_' . $value;
$attrib['value'] = $value;
@@ -1490,6 +1550,7 @@ function rcmail_editor_selector($attrib)
}
return $selector;
+*/
}
diff --git a/program/steps/mail/copy.inc b/program/steps/mail/copy.inc
index a72378b0e..876657485 100644
--- a/program/steps/mail/copy.inc
+++ b/program/steps/mail/copy.inc
@@ -24,10 +24,10 @@ if (!$OUTPUT->ajax_call)
return;
// move messages
-if (!empty($_POST['_uid']) && !empty($_POST['_target_mbox'])) {
- $uids = get_input_value('_uid', RCUBE_INPUT_POST);
+if (!empty($_POST['_uid']) && strlen($_POST['_target_mbox'])) {
+ $uids = get_input_value('_uid', RCUBE_INPUT_POST);
$target = get_input_value('_target_mbox', RCUBE_INPUT_POST, true);
- $mbox = get_input_value('_mbox', RCUBE_INPUT_POST, true);
+ $mbox = get_input_value('_mbox', RCUBE_INPUT_POST, true);
$copied = $RCMAIL->storage->copy_message($uids, $target, $mbox);
@@ -47,7 +47,7 @@ if (!empty($_POST['_uid']) && !empty($_POST['_target_mbox'])) {
}
// unknown action or missing query param
else {
- exit;
+ $OUTPUT->show_message('internalerror', 'error');
}
// send response
diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc
index da01e6cbf..ae23d4a6d 100644
--- a/program/steps/mail/func.inc
+++ b/program/steps/mail/func.inc
@@ -120,7 +120,7 @@ if (empty($RCMAIL->action) || $RCMAIL->action == 'list') {
if (!$OUTPUT->ajax_call)
$OUTPUT->add_label('checkingmail', 'deletemessage', 'movemessagetotrash',
'movingmessage', 'copyingmessage', 'deletingmessage', 'markingmessage',
- 'copy', 'move', 'quota');
+ 'copy', 'move', 'quota', 'replyall', 'replylist', 'importwait');
$pagetitle = $RCMAIL->localize_foldername($RCMAIL->storage->mod_folder($mbox_name), true);
$pagetitle = str_replace($delimiter, " \xC2\xBB ", $pagetitle);
@@ -128,6 +128,40 @@ if (empty($RCMAIL->action) || $RCMAIL->action == 'list') {
$OUTPUT->set_pagetitle($pagetitle);
}
+// register UI objects
+$OUTPUT->add_handlers(array(
+ 'mailboxlist' => 'rcmail_mailbox_list',
+ 'messages' => 'rcmail_message_list',
+ 'messagecountdisplay' => 'rcmail_messagecount_display',
+ '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',
+ 'messageimportform' => 'rcmail_message_import_form',
+ 'searchfilter' => 'rcmail_search_filter',
+ 'searchform' => array($OUTPUT, 'search_form'),
+));
+
+// register action aliases
+$RCMAIL->register_action_map(array(
+ 'refresh' => 'check_recent.inc',
+ 'preview' => 'show.inc',
+ 'print' => 'show.inc',
+ 'move' => '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',
+));
+
+
+
/**
* Returns 'to' if current folder is configured Sent or Drafts
* or their subfolders, otherwise returns 'from'.
@@ -224,7 +258,7 @@ function rcmail_message_list($attrib)
if (!in_array('threads', $a_show_cols))
array_unshift($a_show_cols, 'threads');
- $skin_path = $_SESSION['skin_path'] = $CONFIG['skin_path'];
+ $_SESSION['skin_path'] = $CONFIG['skin_path'];
// set client env
$OUTPUT->add_gui_object('messagelist', $attrib['id']);
@@ -236,15 +270,13 @@ function rcmail_message_list($attrib)
$OUTPUT->include_script('list.js');
- $thead = '';
- foreach (rcmail_message_list_head($attrib, $a_show_cols) as $cell)
- $thead .= html::tag('td', array('class' => $cell['className'], 'id' => $cell['id']), $cell['html']);
+ $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']);
+ }
- return html::tag('table',
- $attrib,
- html::tag('thead', null, html::tag('tr', null, $thead)) .
- html::tag('tbody', null, ''),
- array('style', 'class', 'id', 'cellpadding', 'cellspacing', 'border', 'summary'));
+ return $table->show();
}
@@ -291,7 +323,7 @@ function rcmail_js_message_list($a_headers, $insert_top=FALSE, $a_show_cols=null
$thead = $head_replace ? rcmail_message_list_head($_SESSION['list_attrib'], $a_show_cols) : NULL;
// get name of smart From/To column in folder context
- if (($f = array_search('fromto', $a_show_cols)) !== false) {
+ if (array_search('fromto', $a_show_cols) !== false) {
$smart_col = rcmail_message_list_smart_column_name();
}
@@ -307,7 +339,7 @@ function rcmail_js_message_list($a_headers, $insert_top=FALSE, $a_show_cols=null
}
// loop through message headers
- foreach ($a_headers as $n => $header) {
+ foreach ($a_headers as $header) {
if (empty($header))
continue;
@@ -381,7 +413,6 @@ function rcmail_message_list_head($attrib, $a_show_cols)
global $RCMAIL;
$skin_path = $_SESSION['skin_path'];
- $image_tag = html::img(array('src' => "%s%s", 'alt' => "%s"));
// check to see if we have some settings for sorting
$sort_col = $_SESSION['sort_col'];
@@ -417,7 +448,7 @@ function rcmail_message_list_head($attrib, $a_show_cols)
$cells = array();
// get name of smart From/To column in folder context
- if (($f = array_search('fromto', $a_show_cols)) !== false) {
+ if (array_search('fromto', $a_show_cols) !== false) {
$smart_col = rcmail_message_list_smart_column_name();
}
@@ -738,8 +769,13 @@ function rcmail_print_body($part, $p = array())
unset($data['body']);
// plaintext postprocessing
- if ($part->ctype_secondary == 'plain')
- $body = rcmail_plain_body($body, $part->ctype_parameters['format'] == 'flowed');
+ if ($part->ctype_secondary == 'plain') {
+ if ($part->ctype_secondary == 'plain' && $part->ctype_parameters['format'] == 'flowed') {
+ $body = rcube_mime::unfold_flowed($body);
+ }
+
+ $body = rcmail_plain_body($body);
+ }
// allow post-processing of the message body
$data = $RCMAIL->plugins->exec_hook('message_part_after',
@@ -753,11 +789,10 @@ function rcmail_print_body($part, $p = array())
* Handle links and citation marks in plain text message
*
* @param string Plain text string
- * @param boolean Text uses format=flowed
*
* @return string Formatted HTML string
*/
-function rcmail_plain_body($body, $flowed=false)
+function rcmail_plain_body($body)
{
global $RCMAIL;
@@ -782,53 +817,17 @@ function rcmail_plain_body($body, $flowed=false)
if ($q > $quote_level) {
$body[$n] = $replacer->get_replacement($replacer->add(
str_repeat('<blockquote>', $q - $quote_level))) . $body[$n];
+ $last = $n;
}
else if ($q < $quote_level) {
$body[$n] = $replacer->get_replacement($replacer->add(
str_repeat('</blockquote>', $quote_level - $q))) . $body[$n];
- }
- else if ($flowed) {
- // previous line is flowed
- if (isset($body[$last]) && $body[$n]
- && $body[$last][strlen($body[$last])-1] == ' ') {
- // merge lines
- $body[$last] .= $body[$n];
- unset($body[$n]);
- }
- else {
- $last = $n;
- }
+ $last = $n;
}
}
else {
$q = 0;
- if ($flowed) {
- // sig separator - line is fixed
- if ($body[$n] == '-- ') {
- $last = $last_sig = $n;
- }
- else {
- // remove space-stuffing
- if ($body[$n][0] == ' ')
- $body[$n] = substr($body[$n], 1);
-
- // previous line is flowed?
- if (isset($body[$last]) && $body[$n]
- && $last !== $last_sig
- && $body[$last][strlen($body[$last])-1] == ' '
- ) {
- $body[$last] .= $body[$n];
- unset($body[$n]);
- }
- else {
- $last = $n;
- }
- }
- if ($quote_level > 0)
- $body[$last] = $replacer->get_replacement($replacer->add(
- str_repeat('</blockquote>', $quote_level))) . $body[$last];
- }
- else if ($quote_level > 0)
+ if ($quote_level > 0)
$body[$n] = $replacer->get_replacement($replacer->add(
str_repeat('</blockquote>', $quote_level))) . $body[$n];
}
@@ -898,8 +897,8 @@ function rcmail_washtml_callback($tagname, $attrib, $content, $washtml)
* return table with message headers
*/
function rcmail_message_headers($attrib, $headers=null)
- {
- global $OUTPUT, $MESSAGE, $PRINT_MODE, $RCMAIL;
+{
+ global $MESSAGE, $PRINT_MODE, $RCMAIL;
static $sa_attrib;
// keep header table attrib
@@ -937,7 +936,7 @@ function rcmail_message_headers($attrib, $headers=null)
$value = $headers[$hkey];
else if ($headers['others'][$hkey])
$value = $headers['others'][$hkey];
- else
+ else if (!$attrib['valueof'])
continue;
if (in_array($hkey, $exclude_headers))
@@ -1084,7 +1083,7 @@ function rcmail_message_body($attrib)
$header_attrib[$regs[1]] = $value;
if (!empty($MESSAGE->parts)) {
- foreach ($MESSAGE->parts as $i => $part) {
+ foreach ($MESSAGE->parts as $part) {
if ($part->type == 'headers') {
$out .= html::div('message-partheaders', rcmail_message_headers(sizeof($header_attrib) ? $header_attrib : null, $part->headers));
}
@@ -1196,7 +1195,7 @@ function rcmail_message_body($attrib)
html::a($show_link + array('class' => 'image-link', 'style' => sprintf('width:%dpx', $thumbnail_size)),
html::img(array(
'class' => 'image-thumbnail',
- 'src' => $MESSAGE->get_part_url($attach_prop->mime_id, true) . '&_thumb=1',
+ 'src' => $MESSAGE->get_part_url($attach_prop->mime_id, 'image') . '&_thumb=1',
'title' => $attach_prop->filename,
'alt' => $attach_prop->filename,
'style' => sprintf('max-width:%dpx; max-height:%dpx', $thumbnail_size, $thumbnail_size),
@@ -1216,7 +1215,7 @@ function rcmail_message_body($attrib)
html::tag('legend', 'image-filename', Q($attach_prop->filename)) .
html::p(array('align' => "center"),
html::img(array(
- 'src' => $MESSAGE->get_part_url($attach_prop->mime_id, true),
+ 'src' => $MESSAGE->get_part_url($attach_prop->mime_id, 'image'),
'title' => $attach_prop->filename,
'alt' => $attach_prop->filename,
)))
@@ -1442,7 +1441,8 @@ function rcmail_address_string($input, $max=null, $linked=false, $addicon=null,
$c = count($a_parts);
$j = 0;
$out = '';
- $allvalues = array();
+ $allvalues = array();
+ $show_email = $RCMAIL->config->get('message_show_email');
if ($addicon && !isset($_SESSION['writeable_abook'])) {
$_SESSION['writeable_abook'] = $RCMAIL->get_address_sources(true) ? true : false;
@@ -1453,9 +1453,10 @@ function rcmail_address_string($input, $max=null, $linked=false, $addicon=null,
$name = $part['name'];
$mailto = $part['mailto'];
$string = $part['string'];
+ $valid = check_email($mailto, false);
// phishing email prevention (#1488981), e.g. "valid@email.addr <phishing@email.addr>"
- if ($name && $name != $mailto && strpos($name, '@')) {
+ if (!$show_email && $valid && $name && $name != $mailto && strpos($name, '@')) {
$name = '';
}
@@ -1471,15 +1472,23 @@ function rcmail_address_string($input, $max=null, $linked=false, $addicon=null,
// for printing we display all addresses
continue;
}
- else if (check_email($part['mailto'], false)) {
+ else if ($valid) {
if ($linked) {
- $address = html::a(array(
- 'href' => 'mailto:'.$mailto,
- 'onclick' => sprintf("return %s.command('compose','%s',this)", JS_OBJECT_NAME, JQ($mailto)),
- 'title' => $mailto,
- 'class' => "rcmContactAddress",
- ),
- Q($name ? $name : $mailto));
+ $attrs = array(
+ 'href' => 'mailto:' . $mailto,
+ 'onclick' => sprintf("return %s.command('compose','%s',this)", JS_OBJECT_NAME, JQ($mailto)),
+ 'class' => "rcmContactAddress",
+ );
+
+ if ($show_email && $name && $mailto) {
+ $content = Q($name ? sprintf('%s <%s>', $name, $mailto) : $mailto);
+ }
+ else {
+ $content = Q($name ? $name : $mailto);
+ $attrs['title'] = $mailto;
+ }
+
+ $address = html::a($attrs, $content);
}
else {
$address = html::span(array('title' => $mailto, 'class' => "rcmContactAddress"),
@@ -1504,7 +1513,7 @@ function rcmail_address_string($input, $max=null, $linked=false, $addicon=null,
if ($name)
$address .= Q($name);
if ($mailto)
- $address .= (strlen($address) ? ' ' : '') . sprintf('&lt;%s&gt;', Q($mailto));
+ $address = trim($address . ' ' . Q($name ? sprintf('<%s>', $mailto) : $mailto));
}
$address = html::span('adr', $address);
@@ -1543,11 +1552,11 @@ function rcmail_address_string($input, $max=null, $linked=false, $addicon=null,
/**
* Wrap text to a given number of characters per line
* but respect the mail quotation of replies messages (>).
- * Finally add another quotation level by prpending the lines
+ * Finally add another quotation level by prepending the lines
* with >
*
* @param string Text to wrap
- * @param int The line width
+ * @param int The line width
* @return string The wrapped text
*/
function rcmail_wrap_and_quote($text, $length = 72)
@@ -1563,7 +1572,7 @@ function rcmail_wrap_and_quote($text, $length = 72)
$line = '>' . rtrim($line);
else if (mb_strlen($line) > $max) {
$newline = '';
- foreach(explode("\n", rc_wordwrap($line, $length - 2)) as $l) {
+ foreach (explode("\n", rc_wordwrap($line, $length - 2)) as $l) {
if (strlen($l))
$newline .= '> ' . $l . "\n";
else
@@ -1606,45 +1615,6 @@ function rcmail_draftinfo_decode($str)
}
-function rcmail_message_part_controls($attrib)
-{
- global $MESSAGE, $RCMAIL;
-
- $part = asciiwords(get_input_value('_part', RCUBE_INPUT_GPC));
- if (!is_object($MESSAGE) || !is_array($MESSAGE->parts) || !($_GET['_uid'] && $_GET['_part']) || !$MESSAGE->mime_parts[$part])
- return '';
-
- $part = $MESSAGE->mime_parts[$part];
- $table = new html_table(array('cols' => 3));
-
- $filename = rcmail_attachment_name($part);
-
- if (!empty($filename)) {
- $table->add('title', Q(rcube_label('filename')));
- $table->add('header', Q($filename));
- $table->add('download-link', html::a(array('href' => './?'.str_replace('_frame=', '_download=', $_SERVER['QUERY_STRING'])), Q(rcube_label('download'))));
- }
-
- $table->add('title', Q(rcube_label('filesize')));
- $table->add('header', Q($RCMAIL->message_part_size($part)));
-
- return $table->show($attrib);
-}
-
-
-function rcmail_message_part_frame($attrib)
-{
- global $MESSAGE;
-
- $part = $MESSAGE->mime_parts[asciiwords(get_input_value('_part', RCUBE_INPUT_GPC))];
- $ctype_primary = strtolower($part->ctype_primary);
-
- $attrib['src'] = './?' . str_replace('_frame=', ($ctype_primary=='text' ? '_embed=' : '_preload='), $_SERVER['QUERY_STRING']);
-
- return html::iframe($attrib);
-}
-
-
/**
* clear message composing settings
*/
@@ -1732,8 +1702,7 @@ function rcmail_send_mdn($message, &$smtp_error)
$sent = rcmail_deliver_message($compose, $identity['email'], $mailto, $smtp_error, $body_file, $options);
- if ($sent)
- {
+ if ($sent) {
$RCMAIL->storage->set_flag($message->uid, 'MDNSENT');
return true;
}
@@ -1814,9 +1783,12 @@ function rcmail_identity_select($MESSAGE, $identities = null, $compose_mode = 'r
// Try Return-Path
if ($from_idx === null && ($return_path = $MESSAGE->headers->others['return-path'])) {
foreach ($identities as $idx => $ident) {
- if (strpos($return_path, str_replace('@', '=', $ident['email_ascii']).'@') !== false) {
- $from_idx = $idx;
- break;
+ $ident = str_replace('@', '=', $ident['email_ascii']) . '@';
+ foreach ((array)$return_path as $path) {
+ if (strpos($path, $ident) !== false) {
+ $from_idx = $idx;
+ break 2;
+ }
}
}
}
@@ -1851,8 +1823,7 @@ function rcmail_fix_mimetype($name)
// application/pdf.A520491B_3BF7_494D_8855_7FAC2C6C0608
if (preg_match('/^application\/pdf.+/', $name))
$name = 'application/pdf';
-
- // treat image/pjpeg as image/jpeg
+ // treat image/pjpeg (image/pjpg, image/jpg) as image/jpeg (#1489097)
else if (preg_match('/^image\/p?jpe?g$/', $name))
$name = 'image/jpeg';
@@ -1899,13 +1870,15 @@ function rcmail_search_filter($attrib)
$attrib['onchange'] = JS_OBJECT_NAME.'.filter_mailbox(this.value)';
- /*
- RFC3501 (6.4.4): 'ALL', 'RECENT',
- 'ANSWERED', 'DELETED', 'FLAGGED', 'SEEN',
- 'UNANSWERED', 'UNDELETED', 'UNFLAGGED', 'UNSEEN',
- 'NEW', // = (RECENT UNSEEN)
- 'OLD' // = NOT RECENT
- */
+ // Content-Type values of messages with attachments
+ // the same as in app.js:add_message_row()
+ $ctypes = array('application/', 'multipart/m', 'multipart/signed', 'multipart/report');
+
+ // Build search string of "with attachment" filter
+ $attachment = str_repeat(' OR', count($ctypes)-1);
+ foreach ($ctypes as $type) {
+ $attachment .= ' HEADER Content-Type ' . rcube_imap_generic::escape($type);
+ }
$select_filter = new html_select($attrib);
$select_filter->add(rcube_label('all'), 'ALL');
@@ -1916,6 +1889,7 @@ function rcmail_search_filter($attrib)
$select_filter->add(rcube_label('deleted'), 'DELETED');
$select_filter->add(rcube_label('undeleted'), 'UNDELETED');
}
+ $select_filter->add(rcube_label('withattachment'), $attachment);
$select_filter->add(rcube_label('priority').': '.rcube_label('highest'), 'HEADER X-PRIORITY 1');
$select_filter->add(rcube_label('priority').': '.rcube_label('high'), 'HEADER X-PRIORITY 2');
$select_filter->add(rcube_label('priority').': '.rcube_label('normal'), 'NOT HEADER X-PRIORITY 1 NOT HEADER X-PRIORITY 2 NOT HEADER X-PRIORITY 4 NOT HEADER X-PRIORITY 5');
@@ -1945,35 +1919,37 @@ function rcmail_message_error($uid=null)
$RCMAIL->output->send('messageerror');
}
-// register UI objects
-$OUTPUT->add_handlers(array(
- 'mailboxlist' => 'rcmail_mailbox_list',
- 'messages' => 'rcmail_message_list',
- 'messagecountdisplay' => 'rcmail_messagecount_display',
- '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',
- 'messagepartcontrols' => 'rcmail_message_part_controls',
- 'searchfilter' => 'rcmail_search_filter',
- 'searchform' => array($OUTPUT, 'search_form'),
-));
+function rcmail_message_import_form($attrib = array())
+{
+ global $OUTPUT;
-// register action aliases
-$RCMAIL->register_action_map(array(
- 'refresh' => 'check_recent.inc',
- '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',
-));
+ // set defaults
+ $attrib += array('id' => 'rcmImportform', 'buttons' => 'yes');
+
+ // Get filesize, enable upload progress bar
+ $max_filesize = rcube_upload_init();
+
+ $button = new html_inputfield(array('type' => 'button'));
+ $fileinput = new html_inputfield(array(
+ 'type' => 'file',
+ 'name' => '_file[]',
+ 'size' => $attrib['attachmentfieldsize'],
+ 'multiple' => 'multiple',
+ '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', rcube_label(array('name' => 'maxuploadsize', 'vars' => array('size' => $max_filesize)))) .
+ (get_boolean($attrib['buttons']) ? html::div('buttons',
+ $button->show(rcube_label('close'), array('class' => 'button', 'onclick' => "$('#$attrib[id]').hide()")) . ' ' .
+ $button->show(rcube_label('upload'), array('class' => 'button mainaction', 'onclick' => JS_OBJECT_NAME . ".command('import-messages', this.form)"))
+ ) : '')
+ )
+ );
+
+ $OUTPUT->add_gui_object('importform', $attrib['id'].'Frm');
+ return $out;
+}
diff --git a/program/steps/mail/get.inc b/program/steps/mail/get.inc
index 23dc22b7c..a27e788a3 100644
--- a/program/steps/mail/get.inc
+++ b/program/steps/mail/get.inc
@@ -22,7 +22,7 @@
// show loading page
if (!empty($_GET['_preload'])) {
- $url = preg_replace('/([&?]+)_preload=/', '\\1_embed=', $_SERVER['REQUEST_URI']);
+ $url = preg_replace('/([&?]+)_preload=/', '\\1_mimewarning=1&_embed=', $_SERVER['REQUEST_URI']);
$message = rcube_label('loadingdata');
header('Content-Type: text/html; charset=' . RCMAIL_CHARSET);
@@ -38,19 +38,34 @@ ob_end_clean();
// similar code as in program/steps/mail/show.inc
if (!empty($_GET['_uid'])) {
+ $uid = get_input_value('_uid', RCUBE_INPUT_GET);
$RCMAIL->config->set('prefer_html', true);
- $MESSAGE = new rcube_message(get_input_value('_uid', RCUBE_INPUT_GET));
+ $MESSAGE = new rcube_message($uid);
}
// check connection status
check_storage_status();
+$part_id = get_input_value('_part', RCUBE_INPUT_GPC);
+
// show part page
if (!empty($_GET['_frame'])) {
- if (($part_id = get_input_value('_part', RCUBE_INPUT_GPC)) && ($part = $MESSAGE->mime_parts[$part_id])) {
- $OUTPUT->set_pagetitle(rcmail_attachment_name($part));
+ if ($part_id && ($part = $MESSAGE->mime_parts[$part_id])) {
+ $filename = rcmail_attachment_name($part);
+ $OUTPUT->set_pagetitle($filename);
}
+ // register UI objects
+ $OUTPUT->add_handlers(array(
+ 'messagepartframe' => 'rcmail_message_part_frame',
+ 'messagepartcontrols' => 'rcmail_message_part_controls',
+ ));
+
+ $OUTPUT->set_env('mailbox', $RCMAIL->storage->get_folder());
+ $OUTPUT->set_env('uid', $uid);
+ $OUTPUT->set_env('part', $part_id);
+ $OUTPUT->set_env('filename', $filename);
+
$OUTPUT->send('messagepart');
exit;
}
@@ -62,9 +77,10 @@ else if ($_GET['_thumb']) {
$thumbnail_size = $RCMAIL->config->get('image_thumbnail_size', 240);
$temp_dir = $RCMAIL->config->get('temp_dir');
list(,$ext) = explode('/', $part->mimetype);
- $cache_basename = $temp_dir . '/' . md5($MESSAGE->headers->messageID . $part->mime_id . ':' . $RCMAIL->user->ID . ':' . $thumbnail_size);
- $cache_file = $cache_basename . '.' . $ext;
$mimetype = $part->mimetype;
+ $file_ident = $MESSAGE->headers->messageID . ':' . $part->mime_id . ':' . $part->size . ':' . $part->mimetype;
+ $cache_basename = $temp_dir . '/' . md5($file_ident . ':' . $RCMAIL->user->ID . ':' . $thumbnail_size);
+ $cache_file = $cache_basename . '.' . $ext;
// render thumbnail image if not done yet
if (!is_file($cache_file)) {
@@ -91,12 +107,9 @@ else if ($_GET['_thumb']) {
exit;
}
-else if (strlen($pid = get_input_value('_part', RCUBE_INPUT_GET))) {
-
- if ($part = $MESSAGE->mime_parts[$pid]) {
- $ctype_primary = strtolower($part->ctype_primary);
- $ctype_secondary = strtolower($part->ctype_secondary);
- $mimetype = sprintf('%s/%s', $ctype_primary, $ctype_secondary);
+else if (strlen($part_id)) {
+ if ($part = $MESSAGE->mime_parts[$part_id]) {
+ $mimetype = rcmail_fix_mimetype($part->mimetype);
// allow post-processing of the message body
$plugin = $RCMAIL->plugins->exec_hook('message_part_get',
@@ -106,7 +119,7 @@ else if (strlen($pid = get_input_value('_part', RCUBE_INPUT_GET))) {
exit;
// overwrite modified vars from plugin
- $mimetype = $plugin['mimetype'];
+ $mimetype = $plugin['mimetype'];
$extensions = rcube_mime::get_mime_extensions($mimetype);
if ($plugin['body'])
@@ -118,7 +131,7 @@ else if (strlen($pid = get_input_value('_part', RCUBE_INPUT_GET))) {
$file_extension = strtolower(pathinfo($part->filename, PATHINFO_EXTENSION));
// 1. compare filename suffix with expected suffix derived from mimetype
- $valid = $file_extension && in_array($file_extension, (array)$extensions);
+ $valid = $file_extension && in_array($file_extension, (array)$extensions) || !empty($_REQUEST['_mimeclass']);
// 2. detect the real mimetype of the attachment part and compare it with the stated mimetype and filename extension
if ($valid || !$file_extension || $mimetype == 'application/octet-stream' || $mimetype == 'text/plain') {
@@ -145,6 +158,10 @@ else if (strlen($pid = get_input_value('_part', RCUBE_INPUT_GET))) {
$extensions = rcube_mime::get_mime_extensions($real_mimetype);
$valid_extension = (!$file_extension || in_array($file_extension, (array)$extensions));
+ // ignore filename extension if mimeclass matches (#1489029)
+ if (!empty($_REQUEST['_mimeclass']) && $real_ctype_primary == $_REQUEST['_mimeclass'])
+ $valid_extension = true;
+
// fix mimetype for images wrongly declared as octet-stream
if ($mimetype == 'application/octet-stream' && strpos($real_mimetype, 'image/') === 0 && $valid_extension)
$mimetype = $real_mimetype;
@@ -157,22 +174,32 @@ else if (strlen($pid = get_input_value('_part', RCUBE_INPUT_GET))) {
// show warning if validity checks failed
if (!$valid) {
- $OUTPUT = new rcmail_html_page();
- $OUTPUT->write(html::tag('html', null, html::tag('body', 'embed',
- html::div(array('class' => 'rcmail-inline-message rcmail-inline-warning'),
- rcube_label(array(
- 'name' => 'attachmentvalidationerror',
- 'vars' => array(
- 'expected' => $mimetype . ($file_extension ? "(.$file_extension)" : ''),
- 'detected' => $real_mimetype . ($extensions[0] ? "(.$extensions[0])" : ''),
+ // send blocked.gif for expected images
+ if (empty($_REQUEST['_mimewarning']) && strpos($mimetype, 'image/') === 0) {
+ // Do not cache. Failure might be the result of a misconfiguration, thus real content should be returned once fixed.
+ $OUTPUT->nocacheing_headers();
+ header("Content-Type: image/gif");
+ header("Content-Transfer-Encoding: binary");
+ readfile(INSTALL_PATH . 'program/resources/blocked.gif');
+ }
+ else { // html warning with a button to load the file anyway
+ $OUTPUT = new rcmail_html_page();
+ $OUTPUT->write(html::tag('html', null, html::tag('body', 'embed',
+ html::div(array('class' => 'rcmail-inline-message rcmail-inline-warning'),
+ rcube_label(array(
+ 'name' => 'attachmentvalidationerror',
+ 'vars' => array(
+ 'expected' => $mimetype . ($file_extension ? "(.$file_extension)" : ''),
+ 'detected' => $real_mimetype . ($extensions[0] ? "(.$extensions[0])" : ''),
+ )
+ )) .
+ html::p(array('class' => 'rcmail-inline-buttons'),
+ html::tag('button',
+ array('onclick' => "location.href='" . $RCMAIL->url(array_merge($_GET, array('_nocheck' => 1))) . "'"),
+ rcube_label('showanyway')))
)
- )) .
- html::p(array('class' => 'rcmail-inline-buttons'),
- html::tag('button',
- array('onclick' => "location.href='" . $RCMAIL->url(array_merge($_GET, array('_nocheck' => 1))) . "'"),
- rcube_label('showanyway')))
- )
- )));
+ )));
+ }
exit;
}
}
@@ -202,7 +229,6 @@ else if (strlen($pid = get_input_value('_part', RCUBE_INPUT_GET))) {
header("Content-Type: text/$ctype_secondary; charset=" . ($part->charset ? $part->charset : RCMAIL_CHARSET));
}
else {
- $mimetype = rcmail_fix_mimetype($mimetype);
header("Content-Type: $mimetype");
header("Content-Transfer-Encoding: binary");
}
@@ -366,7 +392,9 @@ else {
header('HTTP/1.1 404 Not Found');
exit;
-
+/**
+ * Handles nicely storage connection errors
+ */
function check_storage_status()
{
$error = rcmail::get_instance()->storage->get_error_code();
@@ -398,3 +426,49 @@ function check_storage_status()
exit;
}
}
+
+/**
+ * Attachment properties table
+ */
+function rcmail_message_part_controls($attrib)
+{
+ global $MESSAGE, $RCMAIL;
+
+ $part = asciiwords(get_input_value('_part', RCUBE_INPUT_GPC));
+ if (!is_object($MESSAGE) || !is_array($MESSAGE->parts)
+ || !($_GET['_uid'] && $_GET['_part']) || !$MESSAGE->mime_parts[$part]
+ ) {
+ return '';
+ }
+
+ $part = $MESSAGE->mime_parts[$part];
+ $table = new html_table(array('cols' => 2));
+
+ $table->add('title', Q(rcube_label('namex')).':');
+ $table->add('header', Q(rcmail_attachment_name($part)));
+
+ $table->add('title', Q(rcube_label('type')).':');
+ $table->add('header', Q($part->mimetype));
+
+ $table->add('title', Q(rcube_label('size')).':');
+ $table->add('header', Q($RCMAIL->message_part_size($part)));
+
+ return $table->show($attrib);
+}
+
+/**
+ * Attachment preview frame
+ */
+function rcmail_message_part_frame($attrib)
+{
+ global $MESSAGE, $RCMAIL;
+
+ $part = $MESSAGE->mime_parts[asciiwords(get_input_value('_part', RCUBE_INPUT_GPC))];
+ $ctype_primary = strtolower($part->ctype_primary);
+
+ $attrib['src'] = './?' . str_replace('_frame=', ($ctype_primary=='text' ? '_embed=' : '_preload='), $_SERVER['QUERY_STRING']);
+
+ $RCMAIL->output->add_gui_object('messagepartframe', $attrib['id']);
+
+ return html::iframe($attrib);
+}
diff --git a/program/steps/mail/import.inc b/program/steps/mail/import.inc
new file mode 100644
index 000000000..f7e7a3eb8
--- /dev/null
+++ b/program/steps/mail/import.inc
@@ -0,0 +1,105 @@
+<?php
+
+/*
+ +-----------------------------------------------------------------------+
+ | program/steps/mail/import.inc |
+ | |
+ | This file is part of the Roundcube Webmail client |
+ | 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. |
+ | See the README file for a full license statement. |
+ | |
+ | PURPOSE: |
+ | Save the uploaded file(s) as messages to the current IMAP folder |
+ | |
+ +-----------------------------------------------------------------------+
+ | Author: Thomas Bruederli <roundcube@gmail.com> |
+ +-----------------------------------------------------------------------+
+*/
+
+// clear all stored output properties (like scripts and env vars)
+$OUTPUT->reset();
+
+if (is_array($_FILES['_file'])) {
+ $imported = 0;
+
+ foreach ((array)$_FILES['_file']['tmp_name'] as $i => $filepath) {
+ // Process uploaded file if there is no error
+ $err = $_FILES['_file']['error'][$i];
+
+ if (!$err) {
+ // check file content type first
+ list($mtype_primary,) = explode('/', rc_mime_content_type($filepath, $_FILES['_file']['name'][$i], $_FILES['_file']['type'][$i]));
+ if (!in_array($mtype_primary, array('text','message'))) {
+ $OUTPUT->show_message('importmessageerror', 'error');
+ continue;
+ }
+
+ // read the first few lines to detect header-like structure
+ $fp = fopen($filepath, 'r');
+ do { $line = fgets($fp); }
+ while ($line !== false && trim($line) == '');
+
+ if (!preg_match('/^From\s+-/', $line) && !preg_match('/^[a-z-_]+:\s+.+/i', $line)) {
+ $OUTPUT->show_message('importmessageerror', 'error');
+ continue;
+ }
+
+ $message = $lastline = '';
+ fseek($fp, 0);
+ while (($line = fgets($fp)) !== false) {
+ // importing mbox file, split by From - lines
+ if (preg_match('/^From\s+-/', $line) && $lastline == '') {
+ if (!empty($message)) {
+ if ($RCMAIL->storage->save_message(null, rtrim($message))) {
+ $imported++;
+ }
+ else {
+ rcube::raise_error("Failed to import message to " . $RCMAIL->storage->get_folder(), false, true);
+ }
+ $message = '';
+ }
+ continue;
+ }
+
+ $message .= $line;
+ $lastline = rtrim($line);
+ }
+
+ if (!empty($message) && $RCMAIL->storage->save_message(null, rtrim($message))) {
+ $imported++;
+ }
+ }
+
+ if ($err == UPLOAD_ERR_INI_SIZE || $err == UPLOAD_ERR_FORM_SIZE) {
+ $msg = rcube_label(array('name' => 'filesizeerror', 'vars' => array('size' => show_bytes(parse_bytes(ini_get('upload_max_filesize'))))));
+ }
+ else if ($err) {
+ $OUTPUT->show_message('fileuploaderror', 'error');
+ }
+ } // end foreach
+
+ if ($imported) {
+ $OUTPUT->show_message(rcube_label(array('name' => 'importmessagesuccess', 'nr' => $imported, 'vars' => array('nr' => $imported))), 'confirmation');
+ $OUTPUT->command('command', 'list');
+ }
+ else {
+ $OUTPUT->show_message('importmessageerror', 'error');
+ }
+}
+else if ($_SERVER['REQUEST_METHOD'] == 'POST') {
+ // if filesize exceeds post_max_size then $_FILES array is empty,
+ // show filesizeerror instead of fileuploaderror
+ if ($maxsize = ini_get('post_max_size'))
+ $msg = rcube_label(array('name' => 'filesizeerror', 'vars' => array('size' => show_bytes(parse_bytes($maxsize)))));
+ else
+ $msg = rcube_label('fileuploaderror');
+
+ $OUTPUT->command('display_message', $msg, 'error');
+}
+
+// send html page with JS calls as response
+$OUTPUT->send('iframe');
+
diff --git a/program/steps/mail/list_contacts.inc b/program/steps/mail/list_contacts.inc
index 7e3b349cd..dab146431 100644
--- a/program/steps/mail/list_contacts.inc
+++ b/program/steps/mail/list_contacts.inc
@@ -19,10 +19,10 @@
+-----------------------------------------------------------------------+
*/
-$afields = $RCMAIL->config->get('contactlist_fields');
-$sort_col = $RCMAIL->config->get('addressbook_sort_col', 'name');
-$page_size = $RCMAIL->config->get('addressbook_pagesize', $RCMAIL->config->get('pagesize', 50));
-$page = max(1, intval($_GET['_page']));
+$afields = $RCMAIL->config->get('contactlist_fields');
+$addr_sort_col = $RCMAIL->config->get('addressbook_sort_col', 'name');
+$page_size = $RCMAIL->config->get('addressbook_pagesize', $RCMAIL->config->get('pagesize', 50));
+$list_page = max(1, intval($_GET['_page']));
// Use search result
if (!empty($_REQUEST['_search']) && isset($_SESSION['search'][$_REQUEST['_search']])) {
@@ -42,7 +42,7 @@ if (!empty($_REQUEST['_search']) && isset($_SESSION['search'][$_REQUEST['_search
while ($row = $result->next()) {
$row['sourceid'] = $s;
- $key = rcube_addressbook::compose_contact_key($row, $sort_col);
+ $key = rcube_addressbook::compose_contact_key($row, $addr_sort_col);
$records[$key] = $row;
}
unset($result);
@@ -53,7 +53,7 @@ if (!empty($_REQUEST['_search']) && isset($_SESSION['search'][$_REQUEST['_search
// create resultset object
$count = count($records);
- $first = ($page-1) * $page_size;
+ $first = ($list_page-1) * $page_size;
$result = new rcube_result_set($count, $first);
// we need only records for current page
@@ -71,10 +71,13 @@ else {
if ($CONTACTS && $CONTACTS->ready) {
// set list properties
$CONTACTS->set_pagesize($page_size);
- $CONTACTS->set_page($page);
+ $CONTACTS->set_page($list_page);
+ if ($group_id = get_input_value('_gid', RCUBE_INPUT_GPC)) {
+ $CONTACTS->set_group($group_id);
+ }
// list groups of this source (on page one)
- if ($CONTACTS->groups && $CONTACTS->list_page == 1) {
+ else if ($CONTACTS->groups && $CONTACTS->list_page == 1) {
foreach ($CONTACTS->list_groups() as $group) {
$CONTACTS->reset();
$CONTACTS->set_group($group['ID']);
@@ -89,6 +92,19 @@ else {
'contactgroup' => html::span(array('title' => $email), Q($group['name']))), 'group');
}
}
+ // make virtual groups clickable to list their members
+ else if ($group_prop['virtual']) {
+ $row_id = 'G'.$group['ID'];
+ $OUTPUT->command('add_contact_row', $row_id, array(
+ 'contactgroup' => html::a(array(
+ 'href' => '#list',
+ 'rel' => $row['ID'],
+ 'title' => rcube_label('listgroup'),
+ 'onclick' => sprintf("return %s.command('pushgroup',{'source':'%s','id':'%s'},this,event)", JS_OBJECT_NAME, $source, $group['ID']),
+ ), Q($group['name']) . '&nbsp;' . html::span('action', '&raquo;'))),
+ 'group',
+ array('ID' => $group['ID'], 'name' => $group['name'], 'virtual' => true));
+ }
// show group with count
else if (($result = $CONTACTS->count()) && $result->count) {
$row_id = 'E'.$group['ID'];
@@ -97,10 +113,12 @@ else {
'contactgroup' => Q($group['name'] . ' (' . intval($result->count) . ')')), 'group');
}
}
+
+ $CONTACTS->reset();
+ $CONTACTS->set_group(0);
}
// get contacts for this user
- $CONTACTS->set_group(0);
$result = $CONTACTS->list_records($afields);
}
}
@@ -118,10 +136,13 @@ else if (!empty($result) && $result->count > 0) {
foreach ($emails as $i => $email) {
$row_id = $row['ID'].$i;
$jsresult[$row_id] = format_email_recipient($email, $name);
+ $classname = $row['_type'] == 'group' ? 'group' : 'person';
+ $keyname = $row['_type'] == 'group' ? 'contactgroup' : 'contact';
+
$OUTPUT->command('add_contact_row', $row_id, array(
- 'contact' => html::span(array('title' => $email), Q($name ? $name : $email) .
+ $keyname => html::span(array('title' => $email), Q($name ? $name : $email) .
($name && count($emails) > 1 ? '&nbsp;' . html::span('email', Q($email)) : '')
- )), 'person');
+ )), $classname);
}
}
}
diff --git a/program/steps/mail/mark.inc b/program/steps/mail/mark.inc
index c220fc5c4..dfc892ea1 100644
--- a/program/steps/mail/mark.inc
+++ b/program/steps/mail/mark.inc
@@ -113,7 +113,7 @@ if (($uids = get_input_value('_uid', RCUBE_INPUT_POST)) && ($flag = get_input_va
$OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($msg_count), $mbox);
if ($threading) {
- $count = get_input_value('_count', RCUBE_INPUT_POST);
+ $count = get_input_value('_count', RCUBE_INPUT_POST);
}
// add new rows from next page (if any)
@@ -125,9 +125,9 @@ if (($uids = get_input_value('_uid', RCUBE_INPUT_POST)) && ($flag = get_input_va
}
}
}
-
- $OUTPUT->send();
+}
+else {
+ $OUTPUT->show_message('internalerror', 'error');
}
-exit;
-
+$OUTPUT->send();
diff --git a/program/steps/mail/move_del.inc b/program/steps/mail/move_del.inc
index 3fc6ac5a7..f15cd2460 100644
--- a/program/steps/mail/move_del.inc
+++ b/program/steps/mail/move_del.inc
@@ -29,7 +29,7 @@ $old_count = $RCMAIL->storage->count(NULL, $threading ? 'THREADS' : 'ALL');
$old_pages = ceil($old_count / $RCMAIL->storage->get_pagesize());
// move messages
-if ($RCMAIL->action == 'moveto' && !empty($_POST['_uid']) && strlen($_POST['_target_mbox'])) {
+if ($RCMAIL->action == 'move' && !empty($_POST['_uid']) && strlen($_POST['_target_mbox'])) {
$count = sizeof(explode(',', ($uids = get_input_value('_uid', RCUBE_INPUT_POST))));
$target = get_input_value('_target_mbox', RCUBE_INPUT_POST, true);
$mbox = get_input_value('_mbox', RCUBE_INPUT_POST, true);
@@ -74,6 +74,8 @@ else if ($RCMAIL->action=='delete' && !empty($_POST['_uid'])) {
}
// unknown action or missing query param
else {
+ $OUTPUT->show_message('internalerror', 'error');
+ $OUTPUT->send();
exit;
}
@@ -124,7 +126,7 @@ else
rcmail_set_unseen_count($mbox, $unseen_count);
}
- if ($RCMAIL->action == 'moveto' && strlen($target)) {
+ if ($RCMAIL->action == 'move' && strlen($target)) {
rcmail_send_unread_count($target, true);
}
diff --git a/program/steps/mail/search_contacts.inc b/program/steps/mail/search_contacts.inc
index 2e6bb12f8..6a30ad1f5 100644
--- a/program/steps/mail/search_contacts.inc
+++ b/program/steps/mail/search_contacts.inc
@@ -19,16 +19,15 @@
+-----------------------------------------------------------------------+
*/
-$search = get_input_value('_q', RCUBE_INPUT_GPC, true);
-$sources = $RCMAIL->get_address_sources();
-$search_mode = (int) $RCMAIL->config->get('addressbook_search_mode');
-$sort_col = $RCMAIL->config->get('addressbook_sort_col', 'name');
-$afields = $RCMAIL->config->get('contactlist_fields');
+$search = get_input_value('_q', RCUBE_INPUT_GPC, true);
+$sources = $RCMAIL->get_address_sources();
+$search_mode = (int) $RCMAIL->config->get('addressbook_search_mode');
+$addr_sort_col = $RCMAIL->config->get('addressbook_sort_col', 'name');
+$afields = $RCMAIL->config->get('contactlist_fields');
+$page_size = $RCMAIL->config->get('addressbook_pagesize', $RCMAIL->config->get('pagesize', 50));
+$records = array();
+$search_set = array();
-$page = 1;
-$page_size = $RCMAIL->config->get('addressbook_pagesize', $RCMAIL->config->get('pagesize', 50));
-
-$records = $search_set = array();
foreach ($sources as $s) {
$source = $RCMAIL->get_address_book($s['id']);
$source->set_page(1);
@@ -46,7 +45,7 @@ foreach ($sources as $s) {
while ($row = $result->next()) {
$row['sourceid'] = $s['id'];
- $key = rcube_addressbook::compose_contact_key($row, $sort_col);
+ $key = rcube_addressbook::compose_contact_key($row, $addr_sort_col);
$records[$key] = $row;
}
diff --git a/program/steps/mail/sendmail.inc b/program/steps/mail/sendmail.inc
index eb0ba89c6..cf22a2af9 100644
--- a/program/steps/mail/sendmail.inc
+++ b/program/steps/mail/sendmail.inc
@@ -255,6 +255,33 @@ function rcmail_email_input_format($mailto, $count=false, $check=true)
}
+function rcmail_generic_message_footer($isHtml)
+{
+ global $CONFIG;
+
+ if ($isHtml && !empty($CONFIG['generic_message_footer_html'])) {
+ $file = $CONFIG['generic_message_footer_html'];
+ $html_footer = true;
+ }
+ else {
+ $file = $CONFIG['generic_message_footer'];
+ $html_footer = false;
+ }
+
+ if ($file && realpath($file)) {
+ // sanity check
+ if (!preg_match('/\.(php|ini|conf)$/', $file) && strpos($file, '/etc/') === false) {
+ $footer = file_get_contents($file);
+ if ($isHtml && !$html_footer)
+ $footer = '<pre>' . $footer . '</pre>';
+ return $footer;
+ }
+ }
+
+ return false;
+}
+
+
/****** compose message ********/
if (strlen($_POST['_draft_saveid']) > 3)
@@ -364,10 +391,6 @@ if (!empty($mailcc)) {
if (!empty($mailbcc)) {
$headers['Bcc'] = $mailbcc;
}
-if (!empty($identity_arr['bcc']) && stripos($headers['Bcc'], $identity_arr['bcc']) === false) {
- $headers['Bcc'] = ($headers['Bcc'] ? $headers['Bcc'].', ' : '') . $identity_arr['bcc'];
- $RECIPIENT_COUNT ++;
-}
if (($max_recipients = (int) $RCMAIL->config->get('max_recipients')) > 0) {
if ($RECIPIENT_COUNT > $max_recipients) {
@@ -385,9 +408,6 @@ if (!empty($identity_arr['organization'])) {
if (!empty($_POST['_replyto'])) {
$headers['Reply-To'] = rcmail_email_input_format(get_input_value('_replyto', RCUBE_INPUT_POST, TRUE, $message_charset));
}
-else if (!empty($identity_arr['reply-to'])) {
- $headers['Reply-To'] = rcmail_email_input_format($identity_arr['reply-to'], false, true);
-}
if (!empty($headers['Reply-To'])) {
$headers['Mail-Reply-To'] = $headers['Reply-To'];
}
@@ -452,7 +472,7 @@ $isHtml = (bool) get_input_value('_is_html', RCUBE_INPUT_POST);
$message_body = get_input_value('_message', RCUBE_INPUT_POST, TRUE, $message_charset);
if ($isHtml) {
- $font = rcube_fontdefs($RCMAIL->config->get('default_font', 'Verdana'));
+ $font = rcube_fontdefs($RCMAIL->config->get('default_font'));
$bstyle = $font && is_string($font) ? " style='font-family: $font'" : '';
// append doctype and html/body wrappers
@@ -466,7 +486,7 @@ if (!$savedraft) {
$message_body = preg_replace('/\s*id="_rc_sig"/', '', $message_body);
// add inline css for blockquotes
- $bstyle = 'padding-left:5px; border-left:#1010ff 2px solid; margin-left:5px; width:100%';
+ $bstyle = 'padding-left:5px; border-left:#1010ff 2px solid; margin-left:5px';
$message_body = preg_replace('/<blockquote>/',
'<blockquote type="cite" style="'.$bstyle.'">', $message_body);
}
@@ -490,19 +510,10 @@ if (!$savedraft) {
}
// generic footer for all messages
- if ($isHtml && !empty($CONFIG['generic_message_footer_html'])) {
- $footer = file_get_contents(realpath($CONFIG['generic_message_footer_html']));
- $footer = rcube_charset_convert($footer, RCMAIL_CHARSET, $message_charset);
- }
- else if (!empty($CONFIG['generic_message_footer'])) {
- $footer = file_get_contents(realpath($CONFIG['generic_message_footer']));
+ if ($footer = rcmail_generic_message_footer($isHtml)) {
$footer = rcube_charset_convert($footer, RCMAIL_CHARSET, $message_charset);
- if ($isHtml)
- $footer = '<pre>'.$footer.'</pre>';
- }
-
- if ($footer)
$message_body .= "\r\n" . $footer;
+ }
}
if ($isHtml) {
@@ -820,6 +831,6 @@ else {
if ($store_folder && !$saved)
$OUTPUT->command('sent_successfully', 'error', rcube_label('errorsavingsent'));
else
- $OUTPUT->command('sent_successfully', 'confirmation', rcube_label('messagesent'));
+ $OUTPUT->command('sent_successfully', 'confirmation', rcube_label('messagesent'), $store_target);
$OUTPUT->send('iframe');
}
diff --git a/program/steps/mail/show.inc b/program/steps/mail/show.inc
index 552c180f5..59f4d55e1 100644
--- a/program/steps/mail/show.inc
+++ b/program/steps/mail/show.inc
@@ -109,14 +109,14 @@ if ($uid) {
$OUTPUT->set_env('skip_deleted', true);
if ($CONFIG['display_next'])
$OUTPUT->set_env('display_next', true);
- if ($MESSAGE->headers->others['list-post'])
+ if ($MESSAGE->headers->get('list-post', false))
$OUTPUT->set_env('list_post', true);
if ($CONFIG['forward_attachment'])
$OUTPUT->set_env('forward_attachment', true);
if (!$OUTPUT->ajax_call)
$OUTPUT->add_label('checkingmail', 'deletemessage', 'movemessagetotrash',
- 'movingmessage', 'deletingmessage', 'markingmessage');
+ 'movingmessage', 'deletingmessage', 'markingmessage', 'replyall', 'replylist');
$prefer_html = $RCMAIL->config->get('prefer_html');
if ($MESSAGE->has_html_part()) {
@@ -228,11 +228,11 @@ function rcmail_remote_objects_msg()
function rcmail_message_buttons()
{
- global $MESSAGE, $RCMAIL, $CONFIG;
+ global $RCMAIL;
$mbox = $RCMAIL->storage->get_folder();
$delim = $RCMAIL->storage->get_hierarchy_delimiter();
- $dbox = $CONFIG['drafts_mbox'];
+ $dbox = $RCMAIL->config->get('drafts_mbox');
// the message is not a draft
if ($mbox != $dbox && strpos($mbox, $dbox.$delim) !== 0) {
@@ -275,9 +275,13 @@ function rcmail_contact_exists($email)
if ($email) {
// @TODO: search in all address books?
$CONTACTS = $RCMAIL->get_address_book(-1, true);
- $existing = $CONTACTS->search('email', $email, true, false);
- if ($existing->count)
- return true;
+
+ if (is_object($CONTACTS)) {
+ $existing = $CONTACTS->search('email', $email, true, false);
+ if ($existing->count) {
+ return true;
+ }
+ }
}
return false;