From 463ce6848da1d699031ea0cbd892e00a62fac979 Mon Sep 17 00:00:00 2001 From: Aleksander Machniak Date: Tue, 11 Dec 2012 14:43:15 +0100 Subject: Fix bug where all messages in a folder were copied on copy action, if search was active and user choose select-all feature. Code improvements. --- program/js/app.js | 110 +++++++++++++++++++++++++++--------------------------- 1 file changed, 55 insertions(+), 55 deletions(-) (limited to 'program') diff --git a/program/js/app.js b/program/js/app.js index 4db7fa0c8..f599f7a64 100644 --- a/program/js/app.js +++ b/program/js/app.js @@ -2553,27 +2553,18 @@ function rcube_webmail() if (mbox && typeof mbox === 'object') mbox = mbox.id; - // exit if current or no mailbox specified or if selection is empty - if (!mbox || mbox == this.env.mailbox || (!this.env.uid && (!this.message_list || !this.message_list.get_selection().length))) + // exit if current or no mailbox specified + if (!mbox || mbox == this.env.mailbox) return; - var a_uids = [], n, selection, - lock = this.display_message(this.get_label('copyingmessage'), 'loading'), - post_data = {_mbox: this.env.mailbox, _target_mbox: mbox, _from: (this.env.action ? this.env.action : '')}; + var post_data = this.selection_post_data({_target_mbox: mbox}); - if (this.env.uid) - a_uids[0] = this.env.uid; - else { - selection = this.message_list.get_selection(); - for (n in selection) { - a_uids.push(selection[n]); - } - } - - post_data._uid = this.uids_to_list(a_uids); + // exit if selection is empty + if (!post_data._uid) + return; // send request to server - this.http_post('copy', post_data, lock); + this.http_post('copy', post_data, this.display_message(this.get_label('copyingmessage'), 'loading')); }; // move selected messages to the specified mailbox @@ -2582,12 +2573,15 @@ function rcube_webmail() if (mbox && typeof mbox === 'object') mbox = mbox.id; - // exit if current or no mailbox specified or if selection is empty - if (!mbox || mbox == this.env.mailbox || (!this.env.uid && (!this.message_list || !this.message_list.get_selection().length))) + // exit if current or no mailbox specified + if (!mbox || mbox == this.env.mailbox) return; - var lock = false, - add_post = {_target_mbox: mbox, _from: (this.env.action ? this.env.action : '')}; + var lock = false, post_data = this.selection_post_data({_target_mbox: mbox}); + + // exit if selection is empty + if (!post_data._uid) + return; // show wait message if (this.env.action == 'show') @@ -2598,7 +2592,7 @@ function rcube_webmail() // Hide message command buttons until a message is selected this.enable_command(this.env.message_commands, false); - this._with_selected_messages('moveto', lock, add_post); + this._with_selected_messages('moveto', post_data, lock); }; // delete selected messages from the current mailbox @@ -2606,7 +2600,7 @@ function rcube_webmail() { var uid, i, len, trash = this.env.trash_mailbox, list = this.message_list, - selection = list ? $.merge([], list.get_selection()) : []; + selection = list.get_selection(); // exit if no mailbox specified or if selection is empty if (!this.env.uid && !selection.length) @@ -2625,7 +2619,6 @@ function rcube_webmail() return false; } // if there isn't a defined trash mailbox or we are in it - // @TODO: we should check if defined trash mailbox exists else if (!trash || this.env.mailbox == trash) this.permanently_remove_messages(); // we're in Junk folder and delete_junk is enabled @@ -2648,32 +2641,29 @@ function rcube_webmail() // delete the selected messages permanently this.permanently_remove_messages = function() { - // exit if no mailbox specified or if selection is empty - if (!this.env.uid && (!this.message_list || !this.message_list.get_selection().length)) + var post_data = this.selection_post_data(); + + // exit if selection is empty + if (!post_data._uid) return; this.show_contentframe(false); - this._with_selected_messages('delete', false, {_from: this.env.action ? this.env.action : ''}); + this._with_selected_messages('delete', post_data); }; // Send a specifc moveto/delete request with UIDs of all selected messages // @private - this._with_selected_messages = function(action, lock, post_data) + this._with_selected_messages = function(action, post_data, lock) { - var a_uids = [], count = 0, msg, lock; + var count = 0, msg; - if (typeof(post_data) != 'object') - post_data = {}; - - if (this.env.uid) - a_uids[0] = this.env.uid; - else { + // update the list (remove rows, clear selection) + if (this.message_list) { var n, id, root, roots = [], selection = this.message_list.get_selection(); for (n=0, len=selection.length; n 0) this.delete_excessive_thread_rows(); - post_data._uid = this.uids_to_list(a_uids); - post_data._mbox = this.env.mailbox; - if (!lock) { msg = action == 'moveto' ? 'movingmessage' : 'deletingmessage'; lock = this.display_message(this.get_label(msg), 'loading'); @@ -2718,22 +2701,39 @@ function rcube_webmail() this.http_post(action, post_data, lock); }; + // build post data for message delete/move/copy requests + this.selection_post_data = function(data) + { + var a_uids = this.env.uid ? this.env.uid : this.message_list.get_selection(); + + if (typeof(data) != 'object') + data = {}; + + data._uid = this.uids_to_list(a_uids); + data._mbox = this.env.mailbox; + + if (this.env.action) + data._from = this.env.action; + + // also send search request to get the right messages + if (this.env.search_request) + data._search = this.env.search_request; + + return data; + }; + // set a specific flag to one or more messages this.mark_message = function(flag, uid) { - var a_uids = [], r_uids = [], len, n, id, selection, + var a_uids = [], r_uids = [], len, n, id, list = this.message_list; if (uid) a_uids[0] = uid; else if (this.env.uid) a_uids[0] = this.env.uid; - else if (list) { - selection = list.get_selection(); - for (n=0, len=selection.length; n Date: Tue, 11 Dec 2012 15:12:59 +0100 Subject: More code unification using selection_post_data() --- program/js/app.js | 45 +++++++++++++-------------------------------- 1 file changed, 13 insertions(+), 32 deletions(-) (limited to 'program') diff --git a/program/js/app.js b/program/js/app.js index f599f7a64..4094a67ad 100644 --- a/program/js/app.js +++ b/program/js/app.js @@ -2701,17 +2701,19 @@ function rcube_webmail() this.http_post(action, post_data, lock); }; - // build post data for message delete/move/copy requests + // build post data for message delete/move/copy/flag requests this.selection_post_data = function(data) { - var a_uids = this.env.uid ? this.env.uid : this.message_list.get_selection(); - if (typeof(data) != 'object') data = {}; - data._uid = this.uids_to_list(a_uids); data._mbox = this.env.mailbox; + if (!data._uid) { + var uids = this.env.uid ? this.env.uid : this.message_list.get_selection(); + data._uid = this.uids_to_list(uids); + } + if (this.env.action) data._from = this.env.action; @@ -2777,16 +2779,12 @@ function rcube_webmail() this.toggle_read_status = function(flag, a_uids) { var i, len = a_uids.length, - post_data = {_uid: this.uids_to_list(a_uids), _flag: flag}, + post_data = this.selection_post_data({_uid: this.uids_to_list(a_uids), _flag: flag}), lock = this.display_message(this.get_label('markingmessage'), 'loading'); // mark all message rows as read/unread for (i=0; i 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') 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 0435f40999564586dd9bd9669696ec04c16f2e32 Mon Sep 17 00:00:00 2001 From: Aleksander Machniak Date: Wed, 12 Dec 2012 13:32:24 +0100 Subject: Add EXISTS mode to count() method - return number of all messages in a folder, event if skip_deleted is enabled and/or search is active. --- program/lib/Roundcube/rcube_imap.php | 14 +++++++++----- program/lib/Roundcube/rcube_storage.php | 2 +- 2 files changed, 10 insertions(+), 6 deletions(-) (limited to 'program') diff --git a/program/lib/Roundcube/rcube_imap.php b/program/lib/Roundcube/rcube_imap.php index a2495462a..ab90fa23f 100644 --- a/program/lib/Roundcube/rcube_imap.php +++ b/program/lib/Roundcube/rcube_imap.php @@ -571,7 +571,7 @@ class rcube_imap extends rcube_storage * Get message count for a specific folder * * @param string $folder Folder name - * @param string $mode Mode for count [ALL|THREADS|UNSEEN|RECENT] + * @param string $mode Mode for count [ALL|THREADS|UNSEEN|RECENT|EXISTS] * @param boolean $force Force reading from server and update cache * @param boolean $status Enables storing folder status info (max UID/count), * required for folder_status() @@ -592,7 +592,7 @@ class rcube_imap extends rcube_storage * protected method for getting nr of messages * * @param string $folder Folder name - * @param string $mode Mode for count [ALL|THREADS|UNSEEN|RECENT] + * @param string $mode Mode for count [ALL|THREADS|UNSEEN|RECENT|EXISTS] * @param boolean $force Force reading from server and update cache * @param boolean $status Enables storing folder status info (max UID/count), * required for folder_status() @@ -614,6 +614,10 @@ class rcube_imap extends rcube_storage } } + // EXISTS is a special alias for ALL, it allows to get the number + // of all messages in a folder also when search is active and with + // any skip_deleted setting + $a_folder_cache = $this->get_cache('messagecount'); // return cached value @@ -644,7 +648,7 @@ class rcube_imap extends rcube_storage $count = $this->conn->countRecent($folder); } // use SEARCH for message counting - else if (!empty($this->options['skip_deleted'])) { + else if ($mode != 'EXISTS' && !empty($this->options['skip_deleted'])) { $search_str = "ALL UNDELETED"; $keys = array('COUNT'); @@ -683,8 +687,8 @@ class rcube_imap extends rcube_storage } else { $count = $this->conn->countMessages($folder); - if ($status) { - $this->set_folder_stats($folder,'cnt', $count); + if ($status && $mode == 'ALL') { + $this->set_folder_stats($folder, 'cnt', $count); $this->set_folder_stats($folder, 'maxuid', $count ? $this->id2uid($count, $folder) : 0); } } diff --git a/program/lib/Roundcube/rcube_storage.php b/program/lib/Roundcube/rcube_storage.php index 7ec05b7af..763b9155e 100644 --- a/program/lib/Roundcube/rcube_storage.php +++ b/program/lib/Roundcube/rcube_storage.php @@ -354,7 +354,7 @@ abstract class rcube_storage * Get messages count for a specific folder. * * @param string $folder Folder name - * @param string $mode Mode for count [ALL|THREADS|UNSEEN|RECENT] + * @param string $mode Mode for count [ALL|THREADS|UNSEEN|RECENT|EXISTS] * @param boolean $force Force reading from server and update cache * @param boolean $status Enables storing folder status info (max UID/count), * required for folder_status() -- 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') 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