zipdownload: Added option to define size limit for multiple messages download (#5696)

Default limit set to 50MB.
pull/6220/head
Aleksander Machniak 7 years ago
parent 2428be488e
commit a02fafa542

@ -25,6 +25,7 @@ CHANGELOG Roundcube Webmail
- Managesieve: Support filter action with custom IMAP flags (#6011)
- Managesieve: Support 'mime' extension tests - RFC5703 (#5832)
- Managesieve: Support GSSAPI authentication with krb_authentication plugin (#5779)
- zipdownload: Added option to define size limit for multiple messages download (#5696)
- Changed defaults for smtp_user (%u), smtp_pass (%p) and smtp_port (587)
- Composer: Fix certificate validation errors by using packagist only (#5148)
- Enigma: Add button to send mail unencrypted if no key was found (#5913)

@ -3,7 +3,7 @@
"type": "roundcube-plugin",
"description": "Adds an option to download all attachments to a message in one zip file, when a message has multiple attachments. Also allows the download of a selection of messages in one zip file. Supports mbox and maildir format.",
"license": "GPLv3+",
"version": "3.3",
"version": "3.4",
"authors": [
{
"name": "Thomas Bruederli",

@ -9,8 +9,11 @@
// -1 to prevent downloading of attachments as zip
$config['zipdownload_attachments'] = 1;
// Zip selection of messages
$config['zipdownload_selection'] = false;
// Zip selection of mail messages
// This option enables downloading of multiple messages as one zip archive.
// The number or string value specifies maximum total size of all messages
// in the archive (not the size of the archive itself).
$config['zipdownload_selection'] = '50MB';
// Charset to use for filenames inside the zip
$config['zipdownload_charset'] = 'ISO-8859-1';

@ -22,3 +22,4 @@ $labels['download'] = 'Download...';
$labels['downloadmbox'] = 'Mbox format (.zip)';
$labels['downloadmaildir'] = 'Maildir format (.zip)';
$labels['downloademl'] = 'Source (.eml)';
$labels['sizelimiterror'] = 'Total size of selected messages exceeds the limit ($size)';

@ -4,7 +4,7 @@
* @licstart The following is the entire license notice for the
* JavaScript code in this file.
*
* Copyright (c) 2013-2014, The Roundcube Dev Team
* Copyright (c) 2013-2018, The Roundcube Dev Team
*
* The JavaScript code in this page is free software: you can redistribute it
* and/or modify it under the terms of the GNU General Public License
@ -62,8 +62,16 @@ function rcmail_zipdownload(mode)
// multi-message download, use hidden form to POST selection
if (rcmail.message_list && rcmail.message_list.get_selection().length > 1) {
var inputs = [], form = $('#zipdownload-form'),
post = rcmail.selection_post_data();
var inputs = [],
post = rcmail.selection_post_data(),
id = 'zipdownload-' + new Date().getTime(),
iframe = $('<iframe>').attr({name: id, style: 'display:none'}),
form = $('<form>').attr({
target: id,
style: 'display: none',
method: 'post',
action: '?_task=mail&_action=plugin.zipdownload.messages'
});
post._mode = mode;
post._token = rcmail.env.request_token;
@ -78,15 +86,8 @@ function rcmail_zipdownload(mode)
}
});
if (!form.length)
form = $('<form>').attr({
style: 'display: none',
method: 'POST',
action: '?_task=mail&_action=plugin.zipdownload.messages'
})
.appendTo('body');
form.html('').append(inputs).submit();
iframe.appendTo(document.body);
form.append(inputs).appendTo(document.body).submit();
}
}

@ -17,8 +17,8 @@ class zipdownload extends rcube_plugin
public $task = 'mail';
private $charset = 'ASCII';
private $names = [];
private $default_limit = '50MB';
// RFC4155: mbox date format
const MBOX_DATE_FORMAT = 'D M d H:i:s Y';
@ -42,16 +42,17 @@ class zipdownload extends rcube_plugin
$this->load_config();
$this->charset = $rcmail->config->get('zipdownload_charset', RCUBE_CHARSET);
$this->add_texts('localization');
if ($rcmail->config->get('zipdownload_attachments', 1) > -1 && ($rcmail->action == 'show' || $rcmail->action == 'preview')) {
$this->add_texts('localization');
$this->add_hook('template_object_messageattachments', array($this, 'attachment_ziplink'));
}
$this->register_action('plugin.zipdownload.attachments', array($this, 'download_attachments'));
$this->register_action('plugin.zipdownload.messages', array($this, 'download_messages'));
if (!$rcmail->action && $rcmail->config->get('zipdownload_selection')) {
if (!$rcmail->action && $rcmail->config->get('zipdownload_selection', $this->default_limit)) {
$this->add_texts('localization');
$this->download_menu();
}
}
@ -177,7 +178,7 @@ class zipdownload extends rcube_plugin
{
$rcmail = rcmail::get_instance();
if ($rcmail->config->get('zipdownload_selection') && !empty($_POST['_uid'])) {
if ($rcmail->config->get('zipdownload_selection', $this->default_limit) && !empty($_POST['_uid'])) {
$messageset = rcmail::get_uids();
if (count($messageset)) {
$this->_download_messages($messageset);
@ -231,27 +232,25 @@ class zipdownload extends rcube_plugin
*/
private function _download_messages($messageset)
{
$this->add_texts('localization');
$rcmail = rcmail::get_instance();
$imap = $rcmail->get_storage();
$mode = rcube_utils::get_input_value('_mode', rcube_utils::INPUT_POST);
$temp_dir = $rcmail->config->get('temp_dir');
$limit = $rcmail->config->get('zipdownload_selection', $this->default_limit);
$limit = $limit !== true ? parse_bytes($limit) : -1;
$delimiter = $imap->get_hierarchy_delimiter();
$tmpfname = tempnam($temp_dir, 'zipdownload');
$tempfiles = array($tmpfname);
$folders = count($messageset) > 1;
$timezone = new DateTimeZone('UTC');
$messages = array();
$size = 0;
// @TODO: file size limit
// open zip file
$zip = new ZipArchive();
$zip->open($tmpfname, ZIPARCHIVE::OVERWRITE);
if ($mode == 'mbox') {
$tmpfp = fopen($tmpfname . '.mbox', 'w');
}
// collect messages metadata (and check size limit)
foreach ($messageset as $mbox => $uids) {
$imap->set_folder($mbox);
$path = $folders ? str_replace($imap->get_hierarchy_delimiter(), '/', $mbox) . '/' : '';
if ($uids === '*') {
$index = $imap->index($mbox, null, null, true);
@ -268,9 +267,8 @@ class zipdownload extends rcube_plugin
$from = preg_replace('/\s/', '-', $from);
// Received (internal) date
$date = rcube_utils::anytodatetime($headers->internaldate);
$date = rcube_utils::anytodatetime($headers->internaldate, $timezone);
if ($date) {
$date->setTimezone(new DateTimeZone('UTC'));
$date = $date->format(self::MBOX_DATE_FORMAT);
}
@ -280,7 +278,50 @@ class zipdownload extends rcube_plugin
$date ?: ''
);
fwrite($tmpfp, $header);
$messages[$uid . ':' . $mbox] = $header;
}
else { // maildir
$subject = rcube_mime::decode_header($headers->subject, $headers->charset);
$subject = $this->_filename_from_subject(mb_substr($subject, 0, 16));
$subject = $this->_convert_filename($subject);
$path = $folders ? str_replace($delimiter, '/', $mbox) . '/' : '';
$disp_name = $path . $uid . ($subject ? " $subject" : '') . '.eml';
$messages[$uid . ':' . $mbox] = $disp_name;
}
$size += $headers->size;
if ($limit > 0 && $size > $limit) {
unlink($tmpfname);
$msg = $this->gettext(array(
'name' => 'sizelimiterror',
'vars' => array('$size' => $rcmail->show_bytes($limit))
));
$rcmail->output->show_message($msg, 'error');
$rcmail->output->send('iframe');
exit;
}
}
}
// open zip file
$zip = new ZipArchive();
$zip->open($tmpfname, ZIPARCHIVE::OVERWRITE);
if ($mode == 'mbox') {
$tmpfp = fopen($tmpfname . '.mbox', 'w');
}
foreach ($messages as $key => $value) {
list($uid, $mbox) = explode(':', $key, 2);
$imap->set_folder($mbox);
if ($mode == 'mbox') {
fwrite($tmpfp, $value);
// Use stream filter to quote "From " in the message body
stream_filter_register('mbox_filter', 'zipdownload_mbox_filter');
@ -290,19 +331,12 @@ class zipdownload extends rcube_plugin
fwrite($tmpfp, "\r\n");
}
else { // maildir
$subject = rcube_mime::decode_header($headers->subject, $headers->charset);
$subject = $this->_filename_from_subject(mb_substr($subject, 0, 16));
$subject = $this->_convert_filename($subject);
$disp_name = $path . $uid . ($subject ? " $subject" : '') . '.eml';
$tmpfn = tempnam($temp_dir, 'zipmessage');
$tmpfp = fopen($tmpfn, 'w');
$imap->get_raw_body($uid, $tmpfp);
$tempfiles[] = $tmpfn;
fclose($tmpfp);
$zip->addFile($tmpfn, $disp_name);
}
$zip->addFile($tmpfn, $value);
}
}

Loading…
Cancel
Save