summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Machniak <alec@alec.pl>2012-12-11 08:30:49 +0100
committerAleksander Machniak <alec@alec.pl>2012-12-11 08:30:49 +0100
commitd9f109b56af2015eae7aadc5e87c06365854eda0 (patch)
tree4241470bba72fcc8dcab37db50a7a08786978234
parent1aaa4bc3937187c54039a8459409a2efd9cb3cd7 (diff)
Allow forwarding of multiple emails (#1486854)
-rw-r--r--CHANGELOG1
-rw-r--r--program/js/app.js19
-rw-r--r--program/steps/mail/compose.inc147
-rw-r--r--program/steps/mail/sendmail.inc3
-rw-r--r--skins/classic/includes/messagetoolbar.html2
-rw-r--r--skins/larry/includes/mailtoolbar.html2
6 files changed, 101 insertions, 73 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 79f19b904..ebc279622 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,7 @@
CHANGELOG Roundcube Webmail
===========================
+- 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)
- Fix XSS vulnerability in vbscript: and data:text links handling (#1488850)
diff --git a/program/js/app.js b/program/js/app.js
index 955c77ff5..4db7fa0c8 100644
--- a/program/js/app.js
+++ b/program/js/app.js
@@ -224,9 +224,10 @@ function rcube_webmail()
this.set_button_titles();
- this.env.message_commands = ['show', 'reply', 'reply-all', 'reply-list', 'forward',
- 'moveto', 'copy', 'delete', 'open', 'mark', 'edit', 'viewsource', 'download',
- 'print', 'load-attachment', 'show-headers', 'hide-headers', 'forward-attachment'];
+ this.env.message_commands = ['show', 'reply', 'reply-all', 'reply-list',
+ 'moveto', 'copy', 'delete', 'open', 'mark', 'edit', 'viewsource',
+ 'print', 'load-attachment', 'show-headers', 'hide-headers', 'download',
+ 'forward', 'forward-inline', 'forward-attachment'];
if (this.env.action == 'show' || this.env.action == 'preview') {
this.enable_command(this.env.message_commands, this.env.uid);
@@ -999,10 +1000,12 @@ function rcube_webmail()
break;
case 'forward-attachment':
+ case 'forward-inline':
case 'forward':
- if (uid = this.get_single_uid()) {
- url = { _forward_uid: uid, _mbox: this.env.mailbox };
- if (command == 'forward-attachment' || (!props && this.env.forward_attachment))
+ var uids = this.env.uid ? [this.env.uid] : (this.message_list ? this.message_list.get_selection() : []);
+ if (uids.length) {
+ 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;
this.open_compose_step(url);
}
@@ -1526,7 +1529,7 @@ function rcube_webmail()
if (selected) {
// Hide certain command buttons when Drafts folder is selected
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
else {
var msg = this.env.messages[list.get_single_selection()];
@@ -1535,7 +1538,7 @@ function rcube_webmail()
}
}
// 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
if (selected || (list.selection.length && list.selection.length != list.rowcount))
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,
diff --git a/skins/classic/includes/messagetoolbar.html b/skins/classic/includes/messagetoolbar.html
index eebb55708..371c83fd9 100644
--- a/skins/classic/includes/messagetoolbar.html
+++ b/skins/classic/includes/messagetoolbar.html
@@ -27,7 +27,7 @@
<div id="forwardmenu" class="popupmenu">
<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>
<roundcube:container name="forwardmenu" id="forwardmenu" />
</ul>
diff --git a/skins/larry/includes/mailtoolbar.html b/skins/larry/includes/mailtoolbar.html
index 31472cbb3..8efcc762c 100644
--- a/skins/larry/includes/mailtoolbar.html
+++ b/skins/larry/includes/mailtoolbar.html
@@ -17,7 +17,7 @@
<div id="forwardmenu" class="popupmenu">
<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>
<roundcube:container name="forwardmenu" id="forwardmenu" />
</ul>