From d9f109b56af2015eae7aadc5e87c06365854eda0 Mon Sep 17 00:00:00 2001 From: Aleksander Machniak Date: Tue, 11 Dec 2012 08:30:49 +0100 Subject: Allow forwarding of multiple emails (#1486854) --- program/steps/mail/compose.inc | 147 +++++++++++++++++++++++----------------- program/steps/mail/sendmail.inc | 3 +- 2 files changed, 87 insertions(+), 63 deletions(-) (limited to 'program/steps/mail') diff --git a/program/steps/mail/compose.inc b/program/steps/mail/compose.inc index 908de950e..d181a72e6 100644 --- a/program/steps/mail/compose.inc +++ b/program/steps/mail/compose.inc @@ -151,15 +151,22 @@ if ($font && !is_array($font)) { // get reference message and set compose mode if ($msg_uid = $COMPOSE['param']['draft_uid']) { - $RCMAIL->storage->set_folder($CONFIG['drafts_mbox']); $compose_mode = RCUBE_COMPOSE_DRAFT; + $RCMAIL->storage->set_folder($CONFIG['drafts_mbox']); } -else if ($msg_uid = $COMPOSE['param']['reply_uid']) +else if ($msg_uid = $COMPOSE['param']['reply_uid']) { $compose_mode = RCUBE_COMPOSE_REPLY; -else if ($msg_uid = $COMPOSE['param']['forward_uid']) + $OUTPUT->set_env('compose_mode', 'reply'); +} +else if ($msg_uid = $COMPOSE['param']['forward_uid']) { $compose_mode = RCUBE_COMPOSE_FORWARD; -else if ($msg_uid = $COMPOSE['param']['uid']) + $OUTPUT->set_env('compose_mode', 'forward'); + $COMPOSE['forward_uid'] = $msg_uid; + $COMPOSE['as_attachment'] = !empty($COMPOSE['param']['attachment']); +} +else if ($msg_uid = $COMPOSE['param']['uid']) { $compose_mode = RCUBE_COMPOSE_EDIT; +} $config_show_sig = $RCMAIL->config->get('show_sig', 1); if ($config_show_sig == 1) @@ -174,7 +181,7 @@ else // set line length for body wrapping $LINE_LENGTH = $RCMAIL->config->get('line_length', 72); -if (!empty($msg_uid)) +if (!empty($msg_uid) && empty($COMPOSE['as_attachment'])) { // similar as in program/steps/mail/show.inc // re-set 'prefer_html' to have possibility to use html part for compose @@ -188,8 +195,7 @@ if (!empty($msg_uid)) if (!empty($MESSAGE->headers->charset)) $RCMAIL->storage->set_charset($MESSAGE->headers->charset); - if ($compose_mode == RCUBE_COMPOSE_REPLY) - { + if ($compose_mode == RCUBE_COMPOSE_REPLY) { $COMPOSE['reply_uid'] = $msg_uid; $COMPOSE['reply_msgid'] = $MESSAGE->headers->messageID; $COMPOSE['references'] = trim($MESSAGE->headers->references . " " . $MESSAGE->headers->messageID); @@ -197,8 +203,6 @@ if (!empty($msg_uid)) if (!empty($COMPOSE['param']['all'])) $MESSAGE->reply_all = $COMPOSE['param']['all']; - $OUTPUT->set_env('compose_mode', 'reply'); - // Save the sent message in the same folder of the message being replied to if ($RCMAIL->config->get('reply_same_folder') && ($sent_folder = $COMPOSE['mailbox']) && rcmail_check_sent_folder($sent_folder, false) @@ -206,10 +210,8 @@ if (!empty($msg_uid)) $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) { + if ($MESSAGE->headers->others['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']); @@ -233,14 +235,6 @@ if (!empty($msg_uid)) $COMPOSE['references'] = $MESSAGE->headers->references; } - else if ($compose_mode == RCUBE_COMPOSE_FORWARD) - { - $COMPOSE['forward_uid'] = $msg_uid; - $OUTPUT->set_env('compose_mode', 'forward'); - - if (!empty($COMPOSE['param']['attachment'])) - $MESSAGE->forward_attachment = true; - } } else { $MESSAGE = new stdClass(); @@ -643,11 +637,11 @@ function rcmail_prepare_message_body() $isHtml = false; } // forward as attachment - else if ($compose_mode == RCUBE_COMPOSE_FORWARD && $MESSAGE->forward_attachment) { + else if ($compose_mode == RCUBE_COMPOSE_FORWARD && $COMPOSE['as_attachment']) { $isHtml = rcmail_compose_editor_mode(); $body = ''; if (empty($COMPOSE['attachments'])) - rcmail_write_forward_attachment($MESSAGE); + rcmail_write_forward_attachments(); } // reply/edit/draft/forward else if ($compose_mode && ($compose_mode != RCUBE_COMPOSE_REPLY || $RCMAIL->config->get('reply_mode') != -1)) { @@ -1135,55 +1129,86 @@ function rcmail_write_inline_attachments(&$message) return $cid_map; } -// Creates an attachment from the forwarded message -function rcmail_write_forward_attachment(&$message) +// Creates attachment(s) from the forwarded message(s) +function rcmail_write_forward_attachments() { - global $RCMAIL, $COMPOSE; + global $RCMAIL, $COMPOSE, $MESSAGE; + + $storage = $RCMAIL->get_storage(); + $mem_limit = parse_bytes(ini_get('memory_limit')); + $curr_mem = function_exists('memory_get_usage') ? memory_get_usage() : 16*1024*1024; // safe value: 16MB + $names = array(); - if (strlen($message->subject)) { - $name = mb_substr($message->subject, 0, 64) . '.eml'; + if ($COMPOSE['forward_uid'] == '*') { + $index = $storage->index(null, rcmail_sort_column(), rcmail_sort_order()); + $COMPOSE['forward_uid'] = $index->get(); } else { - $name = 'message_rfc822.eml'; + $COMPOSE['forward_uid'] = explode(',', $COMPOSE['forward_uid']); } - $mem_limit = parse_bytes(ini_get('memory_limit')); - $curr_mem = function_exists('memory_get_usage') ? memory_get_usage() : 16*1024*1024; // safe value: 16MB - $data = $path = null; + foreach ((array)$COMPOSE['forward_uid'] as $uid) { + $message = new rcube_message($uid); - // don't load too big attachments into memory - if ($mem_limit > 0 && $message->size > $mem_limit - $curr_mem) { - $temp_dir = unslashify($RCMAIL->config->get('temp_dir')); - $path = tempnam($temp_dir, 'rcmAttmnt'); - if ($fp = fopen($path, 'w')) { - $RCMAIL->storage->get_raw_body($message->uid, $fp); - fclose($fp); - } else - return false; - } else { - $data = $RCMAIL->storage->get_raw_body($message->uid); - } + if (empty($message->headers)) { + continue; + } - $attachment = array( - 'group' => $COMPOSE['id'], - 'name' => $name, - 'mimetype' => 'message/rfc822', - 'data' => $data, - 'path' => $path, - 'size' => $path ? filesize($path) : strlen($data), - ); + if (!empty($message->headers->charset)) { + $storage->set_charset($message->headers->charset); + } - $attachment = $RCMAIL->plugins->exec_hook('attachment_save', $attachment); + if (empty($MESSAGE->subject)) { + $MESSAGE->subject = $message->subject; + } - if ($attachment['status']) { - unset($attachment['data'], $attachment['status'], $attachment['content_id'], $attachment['abort']); - $COMPOSE['attachments'][$attachment['id']] = $attachment; - return true; - } else if ($path) { - @unlink($path); - } + // generate (unique) attachment name + $name = strlen($message->subject) ? mb_substr($message->subject, 0, 64) : 'message_rfc822'; + if (!empty($names[$name])) { + $names[$name]++; + $name .= '_' . $names[$name]; + } + $names[$name] = 1; + $name .= '.eml'; + + $data = $path = null; + + // don't load too big attachments into memory + if ($mem_limit > 0 && $message->size > $mem_limit - $curr_mem) { + $temp_dir = unslashify($RCMAIL->config->get('temp_dir')); + $path = tempnam($temp_dir, 'rcmAttmnt'); + if ($fp = fopen($path, 'w')) { + $storage->get_raw_body($message->uid, $fp); + fclose($fp); + } + else { + return false; + } + } + else { + $data = $storage->get_raw_body($message->uid); + $curr_mem += $message->size; + } - return false; + $attachment = array( + 'group' => $COMPOSE['id'], + 'name' => $name, + 'mimetype' => 'message/rfc822', + 'data' => $data, + 'path' => $path, + 'size' => $path ? filesize($path) : strlen($data), + ); + + $attachment = $RCMAIL->plugins->exec_hook('attachment_save', $attachment); + + if ($attachment['status']) { + unset($attachment['data'], $attachment['status'], $attachment['content_id'], $attachment['abort']); + $COMPOSE['attachments'][$attachment['id']] = $attachment; + } + else if ($path) { + @unlink($path); + } + } } diff --git a/program/steps/mail/sendmail.inc b/program/steps/mail/sendmail.inc index c26d774a2..d48834bb4 100644 --- a/program/steps/mail/sendmail.inc +++ b/program/steps/mail/sendmail.inc @@ -617,13 +617,12 @@ if (is_array($COMPOSE['attachments'])) $ctype = str_replace('image/pjpeg', 'image/jpeg', $attachment['mimetype']); // #1484914 $file = $attachment['data'] ? $attachment['data'] : $attachment['path']; - // .eml attachments send inline $MAIL_MIME->addAttachment($file, $ctype, $attachment['name'], ($attachment['data'] ? false : true), ($ctype == 'message/rfc822' ? '8bit' : 'base64'), - ($ctype == 'message/rfc822' ? 'inline' : 'attachment'), + 'attachment', '', '', '', $CONFIG['mime_param_folding'] ? 'quoted-printable' : NULL, $CONFIG['mime_param_folding'] == 2 ? 'quoted-printable' : NULL, -- cgit v1.2.3 From bb5d7282855dd83ccdd211cb77d0776dce71468e Mon Sep 17 00:00:00 2001 From: Aleksander Machniak Date: Wed, 12 Dec 2012 08:54:33 +0100 Subject: Use also Envelope-To for identity selection (#1488553) --- CHANGELOG | 2 +- program/lib/Roundcube/rcube_storage.php | 1 + program/steps/mail/compose.inc | 10 ++++++++++ 3 files changed, 12 insertions(+), 1 deletion(-) (limited to 'program/steps/mail') diff --git a/CHANGELOG b/CHANGELOG index ebc279622..8fd17b407 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -8,7 +8,7 @@ CHANGELOG Roundcube Webmail - Fix broken message/part bodies when FETCH response contains more untagged lines (#1488836) - Fix empty email on identities list after identity update (#1488834) - Add new identities_level: (4) one identity with possibility to edit only signature -- Use Delivered-To header as a last resort for identity selection (#1488840) +- Use Delivered-To and Envelope-To headers for identity selection (#1488840, #1488553) - Fix XSS vulnerability using Flash files (#1488828) - Fix absolute positioning in HTML messages (#1488819) - Fix cache (in)validation after setting \Deleted flag diff --git a/program/lib/Roundcube/rcube_storage.php b/program/lib/Roundcube/rcube_storage.php index 245d911c0..7ec05b7af 100644 --- a/program/lib/Roundcube/rcube_storage.php +++ b/program/lib/Roundcube/rcube_storage.php @@ -65,6 +65,7 @@ abstract class rcube_storage 'MAIL-REPLY-TO', 'RETURN-PATH', 'DELIVERED-TO', + 'ENVELOPE-TO', ); const UNKNOWN = 0; diff --git a/program/steps/mail/compose.inc b/program/steps/mail/compose.inc index d181a72e6..d764f5289 100644 --- a/program/steps/mail/compose.inc +++ b/program/steps/mail/compose.inc @@ -455,6 +455,16 @@ function rcmail_identity_select($MESSAGE, $identities, $compose_mode) } } + // Fallback using Envelope-To + if ($from_idx === null && ($envelope_to = $MESSAGE->headers->others['envelope-to'])) { + foreach ($identities as $idx => $ident) { + if (in_array($ident['email_ascii'], (array)$envelope_to)) { + $from_idx = $idx; + break; + } + } + } + return $identities[$from_idx !== null ? $from_idx : $default_identity]; } -- cgit v1.2.3 From 04689fa7ee89c29b57278a354b39d9ee5397a442 Mon Sep 17 00:00:00 2001 From: Aleksander Machniak Date: Wed, 12 Dec 2012 19:59:08 +0100 Subject: Fix so compacting of non-empty folder is possible also when messages list is empty (#1488858) --- CHANGELOG | 1 + program/js/app.js | 11 ++++++----- program/steps/mail/check_recent.inc | 4 +++- program/steps/mail/folders.inc | 1 + program/steps/mail/list.inc | 1 + program/steps/mail/move_del.inc | 7 +++---- program/steps/mail/search.inc | 1 + 7 files changed, 16 insertions(+), 10 deletions(-) (limited to 'program/steps/mail') diff --git a/CHANGELOG b/CHANGELOG index 8fd17b407..095a240d4 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ CHANGELOG Roundcube Webmail =========================== +- Fix so compacting of non-empty folder is possible also when messages list is empty (#1488858) - Allow forwarding of multiple emails (#1486854) - Fix big memory consumption of DB layer (#1488856) - Add workaround for IE<=8 bug where Content-Disposition:inline was ignored (#1488844) diff --git a/program/js/app.js b/program/js/app.js index 4094a67ad..b5bf1840a 100644 --- a/program/js/app.js +++ b/program/js/app.js @@ -651,13 +651,13 @@ function rcube_webmail() break; case 'expunge': - if (this.env.messagecount) + if (this.env.exists) this.expunge_mailbox(this.env.mailbox); break; case 'purge': case 'empty-mailbox': - if (this.env.messagecount) + if (this.env.exists) this.purge_mailbox(this.env.mailbox); break; @@ -2971,7 +2971,7 @@ function rcube_webmail() // test if purge command is allowed this.purge_mailbox_test = function() { - return (this.env.messagecount && (this.env.mailbox == this.env.trash_mailbox || this.env.mailbox == this.env.junk_mailbox + return (this.env.exists && (this.env.mailbox == this.env.trash_mailbox || this.env.mailbox == this.env.junk_mailbox || this.env.mailbox.match('^' + RegExp.escape(this.env.trash_mailbox) + RegExp.escape(this.env.delimiter)) || this.env.mailbox.match('^' + RegExp.escape(this.env.junk_mailbox) + RegExp.escape(this.env.delimiter)))); }; @@ -6228,7 +6228,7 @@ function rcube_webmail() case 'purge': case 'expunge': if (this.task == 'mail') { - if (!this.env.messagecount) { + if (!this.env.exists) { // clear preview pane content if (this.env.contentframe) this.show_contentframe(false); @@ -6248,7 +6248,8 @@ function rcube_webmail() this.env.qsearch = null; case 'list': if (this.task == 'mail') { - this.enable_command('show', 'expunge', 'select-all', 'select-none', (this.env.messagecount > 0)); + this.enable_command('show', 'select-all', 'select-none', this.env.messagecount > 0); + this.enable_command('expunge', this.env.exists); this.enable_command('purge', this.purge_mailbox_test()); this.enable_command('expand-all', 'expand-unread', 'collapse-all', this.env.threading && this.env.messagecount); diff --git a/program/steps/mail/check_recent.inc b/program/steps/mail/check_recent.inc index 61693b4ed..4befbf275 100644 --- a/program/steps/mail/check_recent.inc +++ b/program/steps/mail/check_recent.inc @@ -75,13 +75,15 @@ foreach ($a_mailboxes as $mbox_name) { if (!empty($_GET['_quota'])) $OUTPUT->command('set_quota', rcmail_quota_content()); + $OUTPUT->set_env('exists', $RCMAIL->storage->count($mbox_name, 'EXISTS')); + // "No-list" mode, don't get messages if (empty($_GET['_list'])) continue; // get overall message count; allow caching because rcube_storage::folder_status() did a refresh $list_mode = $RCMAIL->storage->get_threading() ? 'THREADS' : 'ALL'; - $all_count = $RCMAIL->storage->count(null, $list_mode, false, false); + $all_count = $RCMAIL->storage->count($mbox_name, $list_mode, false, false); $page = $RCMAIL->storage->get_page(); $page_size = $RCMAIL->storage->get_pagesize(); diff --git a/program/steps/mail/folders.inc b/program/steps/mail/folders.inc index c56c914cd..574d6e975 100644 --- a/program/steps/mail/folders.inc +++ b/program/steps/mail/folders.inc @@ -65,6 +65,7 @@ else if ($RCMAIL->action == 'purge') if (!empty($_REQUEST['_reload'])) { $OUTPUT->set_env('messagecount', 0); $OUTPUT->set_env('pagecount', 0); + $OUTPUT->set_env('exists', 0); $OUTPUT->command('message_list.clear'); $OUTPUT->command('set_rowcount', rcmail_get_messagecount_text(), $mbox); $OUTPUT->command('set_unread_count', $mbox, 0); diff --git a/program/steps/mail/list.inc b/program/steps/mail/list.inc index b433f81fc..b8c3ee021 100644 --- a/program/steps/mail/list.inc +++ b/program/steps/mail/list.inc @@ -95,6 +95,7 @@ $OUTPUT->set_env('messagecount', $count); $OUTPUT->set_env('pagecount', $pages); $OUTPUT->set_env('threading', $threading); $OUTPUT->set_env('current_page', $count ? $RCMAIL->storage->get_page() : 1); +$OUTPUT->set_env('exists', $RCMAIL->storage->count($mbox_name, 'EXISTS')); $OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($count), $mbox_name); $OUTPUT->command('set_mailboxname', rcmail_get_mailbox_name_text()); diff --git a/program/steps/mail/move_del.inc b/program/steps/mail/move_del.inc index da43b4000..3e2252683 100644 --- a/program/steps/mail/move_del.inc +++ b/program/steps/mail/move_del.inc @@ -38,7 +38,7 @@ if ($RCMAIL->action=='moveto' && !empty($_POST['_uid']) && strlen($_POST['_targe if (!$moved) { // send error message - if ($_POST['_from'] != 'show') + if ($_POST['_from'] != 'show') $OUTPUT->command('list_mailbox'); rcmail_display_server_error('errormoving'); $OUTPUT->send(); @@ -59,7 +59,7 @@ else if ($RCMAIL->action=='delete' && !empty($_POST['_uid'])) { if (!$del) { // send error message - if ($_POST['_from'] != 'show') + if ($_POST['_from'] != 'show') $OUTPUT->command('list_mailbox'); rcmail_display_server_error('errordeleting'); $OUTPUT->send(); @@ -111,6 +111,7 @@ else $OUTPUT->set_env('messagecount', $msg_count); $OUTPUT->set_env('current_page', $page); $OUTPUT->set_env('pagecount', $pages); + $OUTPUT->set_env('exists', $RCMAIL->storage->count($mbox, 'EXISTS', true)); // update mailboxlist $mbox = $RCMAIL->storage->get_folder(); @@ -144,5 +145,3 @@ else // send response $OUTPUT->send(); - - diff --git a/program/steps/mail/search.inc b/program/steps/mail/search.inc index db5424b3b..f9b8f9e67 100644 --- a/program/steps/mail/search.inc +++ b/program/steps/mail/search.inc @@ -143,5 +143,6 @@ else { $OUTPUT->set_env('search_request', $search_str ? $search_request : ''); $OUTPUT->set_env('messagecount', $count); $OUTPUT->set_env('pagecount', ceil($count/$RCMAIL->storage->get_pagesize())); +$OUTPUT->set_env('exists', $RCMAIL->storage->count($mbox_name, 'EXISTS')); $OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($count, 1), $mbox); $OUTPUT->send(); -- cgit v1.2.3 From a9bb50d8045e5a119ca5f66ec03753ca80aa4d4a Mon Sep 17 00:00:00 2001 From: Aleksander Machniak Date: Thu, 13 Dec 2012 15:14:56 +0100 Subject: Fix handling of signatures on draft edit: Don't add new signature and don't remove the old-one, the same for Edit as new (#1488798) --- CHANGELOG | 1 + program/steps/mail/compose.inc | 21 +++++++++++++-------- 2 files changed, 14 insertions(+), 8 deletions(-) (limited to 'program/steps/mail') diff --git a/CHANGELOG b/CHANGELOG index 095a240d4..840c34901 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ CHANGELOG Roundcube Webmail =========================== +- Fix handling of signatures on draft edit (#1488798) - Fix so compacting of non-empty folder is possible also when messages list is empty (#1488858) - Allow forwarding of multiple emails (#1486854) - Fix big memory consumption of DB layer (#1488856) diff --git a/program/steps/mail/compose.inc b/program/steps/mail/compose.inc index d764f5289..b4dbd8d9c 100644 --- a/program/steps/mail/compose.inc +++ b/program/steps/mail/compose.inc @@ -169,14 +169,15 @@ else if ($msg_uid = $COMPOSE['param']['uid']) { } $config_show_sig = $RCMAIL->config->get('show_sig', 1); -if ($config_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 +} +else if ($config_show_sig == 1) $OUTPUT->set_env('show_sig', true); -else if ($config_show_sig == 2 && (empty($compose_mode) || $compose_mode == RCUBE_COMPOSE_EDIT || $compose_mode == RCUBE_COMPOSE_DRAFT)) +else if ($config_show_sig == 2 && empty($compose_mode)) $OUTPUT->set_env('show_sig', true); else if ($config_show_sig == 3 && ($compose_mode == RCUBE_COMPOSE_REPLY || $compose_mode == RCUBE_COMPOSE_FORWARD)) $OUTPUT->set_env('show_sig', true); -else - $OUTPUT->set_env('show_sig', false); // set line length for body wrapping $LINE_LENGTH = $RCMAIL->config->get('line_length', 72); @@ -741,8 +742,10 @@ function rcmail_compose_part_body($part, $isHtml = false) } else { // try to remove the signature - if ($RCMAIL->config->get('strip_existing_sig', true)) { - $body = rcmail_remove_signature($body); + if ($compose_mode != RCUBE_COMPOSE_DRAFT && $compose_mode != RCUBE_COMPOSE_EDIT) { + if ($RCMAIL->config->get('strip_existing_sig', true)) { + $body = rcmail_remove_signature($body); + } } // add HTML formatting $body = rcmail_plain_body($body); @@ -773,8 +776,10 @@ function rcmail_compose_part_body($part, $isHtml = false) } // try to remove the signature - if ($RCMAIL->config->get('strip_existing_sig', true)) { - $body = rcmail_remove_signature($body); + if ($compose_mode != RCUBE_COMPOSE_DRAFT && $compose_mode != RCUBE_COMPOSE_EDIT) { + if ($RCMAIL->config->get('strip_existing_sig', true)) { + $body = rcmail_remove_signature($body); + } } } } -- cgit v1.2.3