plugins/zipdownload/README | ●●●●● patch | view | raw | blame | history | |
plugins/zipdownload/composer.json | ●●●●● patch | view | raw | blame | history | |
plugins/zipdownload/config.inc.php.dist | ●●●●● patch | view | raw | blame | history | |
plugins/zipdownload/localization/en_US.inc | ●●●●● patch | view | raw | blame | history | |
plugins/zipdownload/package.xml | ●●●●● patch | view | raw | blame | history | |
plugins/zipdownload/zipdownload.js | ●●●●● patch | view | raw | blame | history | |
plugins/zipdownload/zipdownload.php | ●●●●● patch | view | raw | blame | history |
plugins/zipdownload/README
@@ -2,8 +2,7 @@ ============================= This plugin adds an option to download all attachments to a message in one zip file, when a message has multiple attachments. The plugin also allows the download of a selection of messages in 1 zip file and the download of entire folders. download of a selection of messages in 1 zip file. Requirements ============ plugins/zipdownload/composer.json
@@ -1,14 +1,19 @@ { "name": "roundcube/zipdownload", "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 and the download of entire folders.", "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": "GNU GPLv3+", "version": "2.1", "version": "3.0", "authors": [ { "name": "Thomas Bruederli", "email": "roundcube@gmail.com", "role": "Lead" }, { "name": "Aleksander Machniak", "email": "alec@alec.pl", "role": "Lead" } ], "repositories": [ plugins/zipdownload/config.inc.php.dist
@@ -9,9 +9,6 @@ // -1 to prevent downloading of attachments as zip $config['zipdownload_attachments'] = 1; // Zip entire folders $config['zipdownload_folder'] = false; // Zip selection of messages $config['zipdownload_selection'] = false; plugins/zipdownload/localization/en_US.inc
@@ -5,7 +5,7 @@ | plugins/zipdownload/localization/<lang>.inc | | | | Localization file of the Roundcube Webmail Zipdownload plugin | | Copyright (C) 2012-2013, The Roundcube Dev Team | | Copyright (C) 2012-2014, The Roundcube Dev Team | | | | Licensed under the GNU General Public License version 3 or | | any later version with exceptions for skins & plugins. | @@ -18,6 +18,7 @@ $labels = array(); $labels['downloadall'] = 'Download all attachments'; $labels['downloadfolder'] = 'Download folder'; ?> $labels['download'] = 'Download...'; $labels['downloadmbox'] = 'Mbox format (.zip)'; $labels['downloadmaildir'] = 'Maildir format (.zip)'; $labels['downloademl'] = 'Source (.eml)'; plugins/zipdownload/package.xml
@@ -6,7 +6,8 @@ <name>zipdownload</name> <channel>pear.roundcube.net</channel> <summary>Download multiple attachments or messages in one zip file</summary> <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 and the download of entire folders.</description> <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 formats.</description> <lead> <name>Philip Weir</name> <user>JohnDoh</user> @@ -19,11 +20,17 @@ <email>roundcube@gmail.com</email> <active>yes</active> </lead> <date>2014-04-07</date> <time>17:28:00</time> <lead> <name>Aleksander Machniak</name> <user>alec</user> <email>alec@alec.pl</email> <active>yes</active> </lead> <date>2014-04-18</date> <time>09:00:00</time> <version> <release>2.1</release> <api>2.0</api> <release>3.0</release> <api>3.0</api> </version> <stability> <release>stable</release> plugins/zipdownload/zipdownload.js
@@ -2,32 +2,94 @@ * ZipDownload plugin script */ function rcmail_zipmessages() { if (rcmail.message_list && rcmail.message_list.get_selection().length > 1) { rcmail.goto_url('plugin.zipdownload.zip_messages', '_mbox=' + urlencode(rcmail.env.mailbox) + '&_uid=' + rcmail.message_list.get_selection().join(',')); } window.rcmail && rcmail.addEventListener('init', function(evt) { // register additional actions rcmail.register_command('download-eml', function() { rcmail_zipdownload('eml'); }); rcmail.register_command('download-mbox', function() { rcmail_zipdownload('mbox'); }); rcmail.register_command('download-maildir', function() { rcmail_zipdownload('maildir'); }); // commands status rcmail.message_list.addEventListener('select', function(list) { var selected = list.get_selection().length; rcmail.enable_command('download', selected > 0); rcmail.enable_command('download-eml', selected == 1); rcmail.enable_command('download-mbox', 'download-maildir', selected > 1); }); // hook before default download action rcmail.addEventListener('beforedownload', rcmail_zipdownload_menu); // find and modify default download link/button $.each(rcmail.buttons['download'] || [], function() { var link = $('#' + this.id), span = $('span', link); if (!span.length) { span = $('<span>'); link.html('').append(span); } span.addClass('folder-selector-link').text(rcmail.gettext('zipdownload.download')); rcmail.env.download_link = link; }); // hide menu on click out of menu element var fn = function(e) { var menu = $('#zipdownload-menu'); if (e.target != menu.get(0)) menu.hide(); }; $(document.body).on('mouseup', fn); $('iframe').contents().on('mouseup', fn) .load(function(e) { try { $(this).contents().on('mouseup', fn); } catch(e) {}; }); }); function rcmail_zipdownload(mode) { // default .eml download of single message if (mode == 'eml') { var uid = rcmail.get_single_uid(); rcmail.goto_url('viewsource', {_uid: uid, _mbox: rcmail.get_message_mailbox(uid), _save: 1}); return; } // 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(); post._mode = mode; post._token = rcmail.env.request_token; $.each(post, function(k, v) { inputs.push($('<input>').attr({type: 'hidden', name: k, value: v})); }); 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(); } } $(document).ready(function() { if (window.rcmail) { rcmail.addEventListener('init', function(evt) { // register command (directly enable in message view mode) rcmail.register_command('plugin.zipdownload.zip_folder', function() { rcmail.goto_url('plugin.zipdownload.zip_folder', '_mbox=' + urlencode(rcmail.env.mailbox)); }, rcmail.env.messagecount > 0); // display download options menu function rcmail_zipdownload_menu() { // fix menu style and display menu var z_index = rcmail.env.download_link.parents('.popupmenu').css('z-index'), menu = $('#zipdownload-menu').css({'max-height': 'none', 'z-index': z_index + 1}).show(); if (rcmail.message_list && rcmail.env.zipdownload_selection) { rcmail.message_list.addEventListener('select', function(list) { rcmail.enable_command('download', list.get_selection().length > 0); }); // position menu on the screen rcmail.element_position(menu, rcmail.env.download_link); // check in contextmenu plugin exists and if so allow multiple message download if (rcmail.contextmenu_disable_multi) rcmail.contextmenu_disable_multi.splice($.inArray('#download', rcmail.contextmenu_disable_multi), 1); } }); rcmail.addEventListener('listupdate', function(props) { rcmail.enable_command('plugin.zipdownload.zip_folder', rcmail.env.messagecount > 0); } ); rcmail.addEventListener('beforedownload', function(props) { rcmail_zipmessages(); } ); } }); // abort default download action return false; } plugins/zipdownload/zipdownload.php
@@ -4,11 +4,13 @@ * ZipDownload * * Plugin to allow the download of all message attachments in one zip file * and downloading of many messages in one go. * * @version 2.1 * @version 3.0 * @requires php_zip extension (including ZipArchive class) * @author Philip Weir * @author Thomas Bruderli * @author Aleksander Machniak */ class zipdownload extends rcube_plugin { @@ -40,18 +42,11 @@ $this->add_hook('template_object_messageattachments', array($this, 'attachment_ziplink')); } $this->register_action('plugin.zipdownload.zip_attachments', array($this, 'download_attachments')); $this->register_action('plugin.zipdownload.zip_messages', array($this, 'download_selection')); $this->register_action('plugin.zipdownload.zip_folder', array($this, 'download_folder')); $this->register_action('plugin.zipdownload.attachments', array($this, 'download_attachments')); $this->register_action('plugin.zipdownload.messages', array($this, 'download_messages')); if (($selection = $rcmail->config->get('zipdownload_selection')) || $rcmail->config->get('zipdownload_folder')) { $this->include_script('zipdownload.js'); $this->api->output->set_env('zipdownload_selection', $selection); if ($rcmail->config->get('zipdownload_folder', false) && ($rcmail->action == '' || $rcmail->action == 'show')) { $zipdownload = $this->api->output->button(array('command' => 'plugin.zipdownload.zip_folder', 'type' => 'link', 'classact' => 'active', 'content' => $this->gettext('downloadfolder'))); $this->api->add_content(html::tag('li', array('class' => 'separator_above'), $zipdownload), 'mailboxoptions'); } if (!$rcmail->action && $rcmail->config->get('zipdownload_selection')) { $this->download_menu(); } } @@ -65,7 +60,7 @@ // only show the link if there is more than the configured number of attachments if (substr_count($p['content'], '<li') > $rcmail->config->get('zipdownload_attachments', 1)) { $href = $rcmail->url(array( '_action' => 'plugin.zipdownload.zip_attachments', '_action' => 'plugin.zipdownload.attachments', '_mbox' => $rcmail->output->env['mailbox'], '_uid' => $rcmail->output->env['uid'], )); @@ -89,6 +84,30 @@ } return $p; } /** * Adds download options menu to the page */ public function download_menu() { $this->include_script('zipdownload.js'); $this->add_label('download'); $rcmail = rcmail::get_instance(); $menu = array(); $ul_attr = $rcmail->config->get('skin') == 'classic' ? null : array('class' => 'toolbarmenu'); foreach (array('eml', 'mbox', 'maildir') as $type) { $menu[] = html::tag('li', null, $rcmail->output->button(array( 'command' => "download-$type", 'label' => "zipdownload.download$type", 'classact' => 'active', ))); } $rcmail->output->add_footer(html::div(array('id' => 'zipdownload-menu', 'class' => 'popupmenu'), html::tag('ul', $ul_attr, implode('', $menu)))); } /** @@ -153,49 +172,16 @@ /** * Handler for message download action */ public function download_selection() public function download_messages() { if (isset($_REQUEST['_uid'])) { $messageset = rcmail::get_uids(); $rcmail = rcmail::get_instance(); if (sizeof($messageset) > 0) { if ($rcmail->config->get('zipdownload_selection') && !empty($_POST['_uid'])) { $messageset = rcmail::get_uids(); if (sizeof($messageset)) { $this->_download_messages($messageset); } } } /** * Handler for folder download action */ public function download_folder() { @set_time_limit(0); $imap = rcmail::get_instance()->get_storage(); $mbox_name = $imap->get_folder(); // initialize searching result if search_filter is used if ($_SESSION['search_filter'] && $_SESSION['search_filter'] != 'ALL') { $imap->search($mbox_name, $_SESSION['search_filter'], RCUBE_CHARSET); } // fetch message headers for all pages $uids = array(); if ($count = $imap->count($mbox_name, $imap->get_threading() ? 'THREADS' : 'ALL', FALSE)) { for ($i = 0; ($i * $imap->get_pagesize()) <= $count; $i++) { $a_headers = $imap->list_messages($mbox_name, ($i + 1)); foreach ($a_headers as $header) { if (empty($header)) continue; array_push($uids, $header->uid); } } } if (sizeof($uids) > 0) $this->_download_messages(array($mbox_name => $uids)); } /** @@ -207,40 +193,80 @@ { $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'); $tmpfname = tempnam($temp_dir, 'zipdownload'); $tempfiles = array($tmpfname); $folders = count($messageset) > 1; // @TODO: file size limit // open zip file $zip = new ZipArchive(); $zip->open($tmpfname, ZIPARCHIVE::OVERWRITE); foreach ($messageset as $mbox => $uids){ if ($mode == 'mbox') { $tmpfp = fopen($tmpfname . '.mbox', 'w'); } foreach ($messageset as $mbox => $uids) { $imap->set_folder($mbox); $path = $folders ? str_replace($imap->get_hierarchy_delimiter(), '/', $mbox) . '/' : ''; foreach ($uids as $uid){ foreach ($uids as $uid) { $headers = $imap->get_message_headers($uid); $subject = rcube_mime::decode_mime_string((string)$headers->subject); $subject = $this->_convert_filename($subject); $subject = substr($subject, 0, 16); $disp_name = ($subject ? $subject : 'message_rfc822') . ".eml"; $disp_name = $path . $uid . "_" . $disp_name; if ($mode == 'mbox') { $from = rcube_mime::decode_address_list($headers->from, null, true, $headers->charset, true); $from = array_shift($from); $tmpfn = tempnam($temp_dir, 'zipmessage'); $tmpfp = fopen($tmpfn, 'w'); $imap->get_raw_body($uid, $tmpfp); $tempfiles[] = $tmpfn; fclose($tmpfp); $zip->addFile($tmpfn, $disp_name); // Mbox format header // @FIXME: \r\n or \n // @FIXME: date format $header = sprintf("From %s %s\r\n", // replace spaces with hyphens $from ? preg_replace('/\s/', '-', $from) : 'MAILER-DAEMON', // internaldate $headers->internaldate ); fwrite($tmpfp, $header); // Use stream filter to quote "From " in the message body stream_filter_register('mbox_filter', 'zipdownload_mbox_filter'); $filter = stream_filter_append($tmpfp, 'mbox_filter'); $imap->get_raw_body($uid, $tmpfp); stream_filter_remove($filter); fwrite($tmpfp, "\r\n"); } else { // maildir $subject = rcube_mime::decode_mime_string((string)$headers->subject); $subject = $this->_convert_filename($subject); $subject = substr($subject, 0, 16); $disp_name = ($subject ? $subject : 'message_rfc822') . ".eml"; $disp_name = $path . $uid . "_" . $disp_name; $tmpfn = tempnam($temp_dir, 'zipmessage'); $tmpfp = fopen($tmpfn, 'w'); $imap->get_raw_body($uid, $tmpfp); $tempfiles[] = $tmpfn; fclose($tmpfp); $zip->addFile($tmpfn, $disp_name); } } } $filename = $folders ? 'messages' : $imap->get_folder(); if ($mode == 'mbox') { $tempfiles[] = $tmpfname . '.mbox'; fclose($tmpfp); $zip->addFile($tmpfname . '.mbox', $filename . '.mbox'); } $zip->close(); $filename = $folders ? 'messages' : $imap->get_folder(); $this->_deliver_zipfile($tmpfname, $filename . '.zip'); // delete temporary files from disk @@ -261,9 +287,7 @@ $rcmail->output->nocacheing_headers(); if ($browser->ie && $browser->ver < 7) $filename = rawurlencode(abbreviate_string($filename, 55)); else if ($browser->ie) if ($browser->ie) $filename = rawurlencode($filename); else $filename = addcslashes($filename, '"'); @@ -288,6 +312,25 @@ { $str = rcube_charset::convert($str, RCUBE_CHARSET, $this->charset); return strtr($str, array(':'=>'', '/'=>'-')); return strtr($str, array(':' => '', '/' => '-')); } } class zipdownload_mbox_filter extends php_user_filter { function filter($in, $out, &$consumed, $closing) { while ($bucket = stream_bucket_make_writeable($in)) { // messages are read line by line if (preg_match('/^>*From /', $bucket->data)) { $bucket->data = '>' . $bucket->data; $bucket->datalen += 1; } $consumed += $bucket->datalen; stream_bucket_append($out, $bucket); } return PSFS_PASS_ON; } }