Allow forwarding of multiple emails (#1486854)

pull/52/head
Aleksander Machniak 12 years ago
parent 1aaa4bc393
commit d9f109b56a

@ -1,6 +1,7 @@
CHANGELOG Roundcube Webmail CHANGELOG Roundcube Webmail
=========================== ===========================
- Allow forwarding of multiple emails (#1486854)
- Fix big memory consumption of DB layer (#1488856) - Fix big memory consumption of DB layer (#1488856)
- Add workaround for IE<=8 bug where Content-Disposition:inline was ignored (#1488844) - Add workaround for IE<=8 bug where Content-Disposition:inline was ignored (#1488844)
- Fix XSS vulnerability in vbscript: and data:text links handling (#1488850) - Fix XSS vulnerability in vbscript: and data:text links handling (#1488850)

@ -224,9 +224,10 @@ function rcube_webmail()
this.set_button_titles(); this.set_button_titles();
this.env.message_commands = ['show', 'reply', 'reply-all', 'reply-list', 'forward', this.env.message_commands = ['show', 'reply', 'reply-all', 'reply-list',
'moveto', 'copy', 'delete', 'open', 'mark', 'edit', 'viewsource', 'download', 'moveto', 'copy', 'delete', 'open', 'mark', 'edit', 'viewsource',
'print', 'load-attachment', 'show-headers', 'hide-headers', 'forward-attachment']; 'print', 'load-attachment', 'show-headers', 'hide-headers', 'download',
'forward', 'forward-inline', 'forward-attachment'];
if (this.env.action == 'show' || this.env.action == 'preview') { if (this.env.action == 'show' || this.env.action == 'preview') {
this.enable_command(this.env.message_commands, this.env.uid); this.enable_command(this.env.message_commands, this.env.uid);
@ -999,10 +1000,12 @@ function rcube_webmail()
break; break;
case 'forward-attachment': case 'forward-attachment':
case 'forward-inline':
case 'forward': case 'forward':
if (uid = this.get_single_uid()) { var uids = this.env.uid ? [this.env.uid] : (this.message_list ? this.message_list.get_selection() : []);
url = { _forward_uid: uid, _mbox: this.env.mailbox }; if (uids.length) {
if (command == 'forward-attachment' || (!props && this.env.forward_attachment)) url = { _forward_uid: this.uids_to_list(uids), _mbox: this.env.mailbox };
if (command == 'forward-attachment' || (!props && this.env.forward_attachment) || uids.length > 1)
url._attachment = 1; url._attachment = 1;
this.open_compose_step(url); this.open_compose_step(url);
} }
@ -1526,7 +1529,7 @@ function rcube_webmail()
if (selected) { if (selected) {
// Hide certain command buttons when Drafts folder is selected // Hide certain command buttons when Drafts folder is selected
if (this.env.mailbox == this.env.drafts_mailbox) if (this.env.mailbox == this.env.drafts_mailbox)
this.enable_command('reply', 'reply-all', 'reply-list', 'forward', 'forward-attachment', false); this.enable_command('reply', 'reply-all', 'reply-list', 'forward', 'forward-attachment', 'forward-inline', false);
// Disable reply-list when List-Post header is not set // Disable reply-list when List-Post header is not set
else { else {
var msg = this.env.messages[list.get_single_selection()]; var msg = this.env.messages[list.get_single_selection()];
@ -1535,7 +1538,7 @@ function rcube_webmail()
} }
} }
// Multi-message commands // Multi-message commands
this.enable_command('delete', 'moveto', 'copy', 'mark', (list.selection.length > 0 ? true : false)); this.enable_command('delete', 'moveto', 'copy', 'mark', 'forward', 'forward-attachment', list.selection.length > 0);
// reset all-pages-selection // reset all-pages-selection
if (selected || (list.selection.length && list.selection.length != list.rowcount)) if (selected || (list.selection.length && list.selection.length != list.rowcount))

@ -151,15 +151,22 @@ if ($font && !is_array($font)) {
// get reference message and set compose mode // get reference message and set compose mode
if ($msg_uid = $COMPOSE['param']['draft_uid']) { if ($msg_uid = $COMPOSE['param']['draft_uid']) {
$RCMAIL->storage->set_folder($CONFIG['drafts_mbox']);
$compose_mode = RCUBE_COMPOSE_DRAFT; $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; $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; $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; $compose_mode = RCUBE_COMPOSE_EDIT;
}
$config_show_sig = $RCMAIL->config->get('show_sig', 1); $config_show_sig = $RCMAIL->config->get('show_sig', 1);
if ($config_show_sig == 1) if ($config_show_sig == 1)
@ -174,7 +181,7 @@ else
// set line length for body wrapping // set line length for body wrapping
$LINE_LENGTH = $RCMAIL->config->get('line_length', 72); $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 // similar as in program/steps/mail/show.inc
// re-set 'prefer_html' to have possibility to use html part for compose // 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)) if (!empty($MESSAGE->headers->charset))
$RCMAIL->storage->set_charset($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_uid'] = $msg_uid;
$COMPOSE['reply_msgid'] = $MESSAGE->headers->messageID; $COMPOSE['reply_msgid'] = $MESSAGE->headers->messageID;
$COMPOSE['references'] = trim($MESSAGE->headers->references . " " . $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'])) if (!empty($COMPOSE['param']['all']))
$MESSAGE->reply_all = $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 // 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']) if ($RCMAIL->config->get('reply_same_folder') && ($sent_folder = $COMPOSE['mailbox'])
&& rcmail_check_sent_folder($sent_folder, false) && rcmail_check_sent_folder($sent_folder, false)
@ -206,10 +210,8 @@ if (!empty($msg_uid))
$COMPOSE['param']['sent_mbox'] = $sent_folder; $COMPOSE['param']['sent_mbox'] = $sent_folder;
} }
} }
else if ($compose_mode == RCUBE_COMPOSE_DRAFT) else if ($compose_mode == RCUBE_COMPOSE_DRAFT) {
{ if ($MESSAGE->headers->others['x-draft-info']) {
if ($MESSAGE->headers->others['x-draft-info'])
{
// get reply_uid/forward_uid to flag the original message when sending // 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($MESSAGE->headers->others['x-draft-info']);
@ -233,14 +235,6 @@ if (!empty($msg_uid))
$COMPOSE['references'] = $MESSAGE->headers->references; $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 { else {
$MESSAGE = new stdClass(); $MESSAGE = new stdClass();
@ -643,11 +637,11 @@ function rcmail_prepare_message_body()
$isHtml = false; $isHtml = false;
} }
// forward as attachment // 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(); $isHtml = rcmail_compose_editor_mode();
$body = ''; $body = '';
if (empty($COMPOSE['attachments'])) if (empty($COMPOSE['attachments']))
rcmail_write_forward_attachment($MESSAGE); rcmail_write_forward_attachments();
} }
// reply/edit/draft/forward // reply/edit/draft/forward
else if ($compose_mode && ($compose_mode != RCUBE_COMPOSE_REPLY || $RCMAIL->config->get('reply_mode') != -1)) { else if ($compose_mode && ($compose_mode != RCUBE_COMPOSE_REPLY || $RCMAIL->config->get('reply_mode') != -1)) {
@ -1135,20 +1129,48 @@ function rcmail_write_inline_attachments(&$message)
return $cid_map; return $cid_map;
} }
// Creates an attachment from the forwarded message // Creates attachment(s) from the forwarded message(s)
function rcmail_write_forward_attachment(&$message) 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)) { if ($COMPOSE['forward_uid'] == '*') {
$name = mb_substr($message->subject, 0, 64) . '.eml'; $index = $storage->index(null, rcmail_sort_column(), rcmail_sort_order());
$COMPOSE['forward_uid'] = $index->get();
} }
else { else {
$name = 'message_rfc822.eml'; $COMPOSE['forward_uid'] = explode(',', $COMPOSE['forward_uid']);
} }
$mem_limit = parse_bytes(ini_get('memory_limit')); foreach ((array)$COMPOSE['forward_uid'] as $uid) {
$curr_mem = function_exists('memory_get_usage') ? memory_get_usage() : 16*1024*1024; // safe value: 16MB $message = new rcube_message($uid);
if (empty($message->headers)) {
continue;
}
if (!empty($message->headers->charset)) {
$storage->set_charset($message->headers->charset);
}
if (empty($MESSAGE->subject)) {
$MESSAGE->subject = $message->subject;
}
// 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; $data = $path = null;
// don't load too big attachments into memory // don't load too big attachments into memory
@ -1156,12 +1178,16 @@ function rcmail_write_forward_attachment(&$message)
$temp_dir = unslashify($RCMAIL->config->get('temp_dir')); $temp_dir = unslashify($RCMAIL->config->get('temp_dir'));
$path = tempnam($temp_dir, 'rcmAttmnt'); $path = tempnam($temp_dir, 'rcmAttmnt');
if ($fp = fopen($path, 'w')) { if ($fp = fopen($path, 'w')) {
$RCMAIL->storage->get_raw_body($message->uid, $fp); $storage->get_raw_body($message->uid, $fp);
fclose($fp); fclose($fp);
} else }
else {
return false; return false;
} else { }
$data = $RCMAIL->storage->get_raw_body($message->uid); }
else {
$data = $storage->get_raw_body($message->uid);
$curr_mem += $message->size;
} }
$attachment = array( $attachment = array(
@ -1178,12 +1204,11 @@ function rcmail_write_forward_attachment(&$message)
if ($attachment['status']) { if ($attachment['status']) {
unset($attachment['data'], $attachment['status'], $attachment['content_id'], $attachment['abort']); unset($attachment['data'], $attachment['status'], $attachment['content_id'], $attachment['abort']);
$COMPOSE['attachments'][$attachment['id']] = $attachment; $COMPOSE['attachments'][$attachment['id']] = $attachment;
return true; }
} else if ($path) { else if ($path) {
@unlink($path); @unlink($path);
} }
}
return false;
} }

@ -617,13 +617,12 @@ if (is_array($COMPOSE['attachments']))
$ctype = str_replace('image/pjpeg', 'image/jpeg', $attachment['mimetype']); // #1484914 $ctype = str_replace('image/pjpeg', 'image/jpeg', $attachment['mimetype']); // #1484914
$file = $attachment['data'] ? $attachment['data'] : $attachment['path']; $file = $attachment['data'] ? $attachment['data'] : $attachment['path'];
// .eml attachments send inline
$MAIL_MIME->addAttachment($file, $MAIL_MIME->addAttachment($file,
$ctype, $ctype,
$attachment['name'], $attachment['name'],
($attachment['data'] ? false : true), ($attachment['data'] ? false : true),
($ctype == 'message/rfc822' ? '8bit' : 'base64'), ($ctype == 'message/rfc822' ? '8bit' : 'base64'),
($ctype == 'message/rfc822' ? 'inline' : 'attachment'), 'attachment',
'', '', '', '', '', '',
$CONFIG['mime_param_folding'] ? 'quoted-printable' : NULL, $CONFIG['mime_param_folding'] ? 'quoted-printable' : NULL,
$CONFIG['mime_param_folding'] == 2 ? 'quoted-printable' : NULL, $CONFIG['mime_param_folding'] == 2 ? 'quoted-printable' : NULL,

@ -27,7 +27,7 @@
<div id="forwardmenu" class="popupmenu"> <div id="forwardmenu" class="popupmenu">
<ul> <ul>
<li><roundcube:button command="forward" label="forwardinline" prop="sub" classAct="forwardlink active" class="forwardlink" /></li> <li><roundcube:button command="forward-inline" label="forwardinline" prop="sub" classAct="forwardlink active" class="forwardlink" /></li>
<li><roundcube:button command="forward-attachment" label="forwardattachment" prop="sub" classAct="forwardattachmentlink active" class="forwardattachmentlink" /></li> <li><roundcube:button command="forward-attachment" label="forwardattachment" prop="sub" classAct="forwardattachmentlink active" class="forwardattachmentlink" /></li>
<roundcube:container name="forwardmenu" id="forwardmenu" /> <roundcube:container name="forwardmenu" id="forwardmenu" />
</ul> </ul>

@ -17,7 +17,7 @@
<div id="forwardmenu" class="popupmenu"> <div id="forwardmenu" class="popupmenu">
<ul class="toolbarmenu"> <ul class="toolbarmenu">
<li><roundcube:button command="forward" label="forwardinline" prop="sub" classAct="forwardlink active" class="forwardlink" /></li> <li><roundcube:button command="forward-inline" label="forwardinline" prop="sub" classAct="forwardlink active" class="forwardlink" /></li>
<li><roundcube:button command="forward-attachment" label="forwardattachment" prop="sub" classAct="forwardattachmentlink active" class="forwardattachmentlink" /></li> <li><roundcube:button command="forward-attachment" label="forwardattachment" prop="sub" classAct="forwardattachmentlink active" class="forwardattachmentlink" /></li>
<roundcube:container name="forwardmenu" id="forwardmenu" /> <roundcube:container name="forwardmenu" id="forwardmenu" />
</ul> </ul>

Loading…
Cancel
Save