Merge branch 'master' of github.com:roundcube/roundcubemail

pull/175/head
Aleksander Machniak 11 years ago
commit eddaf0b5f6

@ -1,6 +1,7 @@
CHANGELOG Roundcube Webmail CHANGELOG Roundcube Webmail
=========================== ===========================
- Search across multiple folders (#1485234)
- Improve UI integration of ACL settings - Improve UI integration of ACL settings
- Drop support for PHP < 5.3.7 - Drop support for PHP < 5.3.7
- Set In-Reply-To and References for forwarded messages (#1489593) - Set In-Reply-To and References for forwarded messages (#1489593)

@ -169,6 +169,8 @@ class zipdownload extends rcube_plugin
*/ */
public function download_folder() public function download_folder()
{ {
@set_time_limit(0);
$imap = rcmail::get_instance()->get_storage(); $imap = rcmail::get_instance()->get_storage();
$mbox_name = $imap->get_folder(); $mbox_name = $imap->get_folder();

@ -2028,8 +2028,9 @@ class rcmail extends rcube
$_uid = $uids ?: rcube_utils::get_input_value('_uid', RCUBE_INPUT_GPC); $_uid = $uids ?: rcube_utils::get_input_value('_uid', RCUBE_INPUT_GPC);
$_mbox = $mbox ?: (string)rcube_utils::get_input_value('_mbox', RCUBE_INPUT_GPC); $_mbox = $mbox ?: (string)rcube_utils::get_input_value('_mbox', RCUBE_INPUT_GPC);
if (is_array($uid)) { // already a hash array
return $uid; if (is_array($_uid) && !isset($_uid[0])) {
return $_uid;
} }
$result = array(); $result = array();
@ -2043,8 +2044,11 @@ class rcmail extends rcube
} }
} }
else { else {
if (is_string($_uid))
$_uid = explode(',', $_uid);
// create a per-folder UIDs array // create a per-folder UIDs array
foreach (explode(',', $_uid) as $uid) { foreach ((array)$_uid as $uid) {
list($uid, $mbox) = explode('-', $uid, 2); list($uid, $mbox) = explode('-', $uid, 2);
if (empty($mbox)) if (empty($mbox))
$mbox = $_mbox; $mbox = $_mbox;

@ -3,8 +3,8 @@
| Roundcube Webmail Client Script | | Roundcube Webmail Client Script |
| | | |
| This file is part of the Roundcube Webmail client | | This file is part of the Roundcube Webmail client |
| Copyright (C) 2005-2013, The Roundcube Dev Team | | Copyright (C) 2005-2014, The Roundcube Dev Team |
| Copyright (C) 2011-2013, Kolab Systems AG | | Copyright (C) 2011-2014, Kolab Systems AG |
| | | |
| Licensed under the GNU General Public License version 3 or | | Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. | | any later version with exceptions for skins & plugins. |
@ -222,7 +222,7 @@ function rcube_webmail()
this.gui_objects.messagelist.parentNode.onmousedown = function(e){ return p.click_on_list(e); }; this.gui_objects.messagelist.parentNode.onmousedown = function(e){ return p.click_on_list(e); };
this.enable_command('toggle_status', 'toggle_flag', 'sort', true); this.enable_command('toggle_status', 'toggle_flag', 'sort', true);
this.enable_command('set-listmode', this.env.threads && !this.env.search_request); this.enable_command('set-listmode', this.env.threads && !this.is_multifolder_listing());
// load messages // load messages
this.command('list'); this.command('list');
@ -707,7 +707,7 @@ function rcube_webmail()
break; break;
case 'list': case 'list':
// re-send for the selected folder // re-send search query for the selected folder
if (props && props != '' && this.env.search_request && this.gui_objects.qsearchbox.value) { if (props && props != '' && this.env.search_request && this.gui_objects.qsearchbox.value) {
var oldmbox = this.env.search_scope == 'all' ? '*' : this.env.mailbox; var oldmbox = this.env.search_scope == 'all' ? '*' : this.env.mailbox;
this.env.search_mods[props] = this.env.search_mods[oldmbox]; // copy search mods from active search this.env.search_mods[props] = this.env.search_mods[oldmbox]; // copy search mods from active search
@ -1113,7 +1113,7 @@ function rcube_webmail()
case 'forward': case 'forward':
var uids = this.env.uid ? [this.env.uid] : (this.message_list ? this.message_list.get_selection() : []); var uids = this.env.uid ? [this.env.uid] : (this.message_list ? this.message_list.get_selection() : []);
if (uids.length) { if (uids.length) {
url = { _forward_uid: this.uids_to_list(uids), _mbox: this.env.mailbox }; url = { _forward_uid: this.uids_to_list(uids), _mbox: this.env.mailbox, _search: this.env.search_request };
if (command == 'forward-attachment' || (!props && this.env.forward_attachment) || uids.length > 1) 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);
@ -1713,7 +1713,9 @@ function rcube_webmail()
{ {
switch (this.task) { switch (this.task) {
case 'mail': case 'mail':
return (this.env.mailboxes[id] && this.env.mailboxes[id].id != this.env.mailbox && !this.env.mailboxes[id].virtual) ? 1 : 0; return (this.env.mailboxes[id]
&& !this.env.mailboxes[id].virtual
&& (this.env.mailboxes[id].id != this.env.mailbox || this.is_multifolder_listing())) ? 1 : 0;
case 'settings': case 'settings':
return id != this.env.mailbox ? 1 : 0; return id != this.env.mailbox ? 1 : 0;
@ -2191,8 +2193,16 @@ function rcube_webmail()
this.http_request('search', this.search_params(false, filter), lock); this.http_request('search', this.search_params(false, filter), lock);
}; };
// reload the current message listing
this.refresh_list = function()
{
this.list_mailbox(this.env.mailbox, this.env.current_page || 1, null, { _clear:1 }, true);
if (this.message_list)
this.message_list.clear_selection();
};
// list messages of a specific mailbox // list messages of a specific mailbox
this.list_mailbox = function(mbox, page, sort, url) this.list_mailbox = function(mbox, page, sort, url, update_only)
{ {
var win, target = window; var win, target = window;
@ -2217,15 +2227,17 @@ function rcube_webmail()
this.select_all_mode = false; this.select_all_mode = false;
} }
// unselect selected messages and clear the list and message data if (!update_only) {
this.clear_message_list(); // unselect selected messages and clear the list and message data
this.clear_message_list();
if (mbox != this.env.mailbox || (mbox == this.env.mailbox && !page && !sort)) if (mbox != this.env.mailbox || (mbox == this.env.mailbox && !page && !sort))
url._refresh = 1; url._refresh = 1;
this.select_folder(mbox, '', true); this.select_folder(mbox, '', true);
this.unmark_folder(mbox, 'recent', '', true); this.unmark_folder(mbox, 'recent', '', true);
this.env.mailbox = mbox; this.env.mailbox = mbox;
}
// load message list remotely // load message list remotely
if (this.gui_objects.messagelist) { if (this.gui_objects.messagelist) {
@ -2259,20 +2271,17 @@ function rcube_webmail()
}; };
// send remote request to load message list // send remote request to load message list
this.list_mailbox_remote = function(mbox, page, post_data) this.list_mailbox_remote = function(mbox, page, url)
{ {
// clear message list first
this.message_list.clear();
var lock = this.set_busy(true, 'loading'); var lock = this.set_busy(true, 'loading');
if (typeof post_data != 'object') if (typeof url != 'object')
post_data = {}; url = {};
post_data._mbox = mbox; url._mbox = mbox;
if (page) if (page)
post_data._page = page; url._page = page;
this.http_request('list', post_data, lock); this.http_request('list', url, lock);
}; };
// removes messages that doesn't exists from list selection array // removes messages that doesn't exists from list selection array
@ -2689,7 +2698,7 @@ function rcube_webmail()
return this.folder_selector(obj, function(folder) { ref.command('move', folder); }); return this.folder_selector(obj, function(folder) { ref.command('move', folder); });
// exit if current or no mailbox specified // exit if current or no mailbox specified
if (!mbox || (mbox == this.env.mailbox && (!this.env.search_request || this.env.search_scope == 'base'))) if (!mbox || (mbox == this.env.mailbox && !this.is_multifolder_listing()))
return; return;
var lock = false, post_data = this.selection_post_data({_target_mbox: mbox}); var lock = false, post_data = this.selection_post_data({_target_mbox: mbox});
@ -2757,7 +2766,8 @@ function rcube_webmail()
// @private // @private
this._with_selected_messages = function(action, post_data, lock) this._with_selected_messages = function(action, post_data, lock)
{ {
var count = 0, msg; var count = 0, msg,
remove = (action == 'delete' || !this.is_multifolder_listing());
// update the list (remove rows, clear selection) // update the list (remove rows, clear selection)
if (this.message_list) { if (this.message_list) {
@ -2774,10 +2784,11 @@ function rcube_webmail()
roots.push(root); roots.push(root);
} }
} }
this.message_list.remove_row(id, (this.env.display_next && n == selection.length-1)); if (remove)
this.message_list.remove_row(id, (this.env.display_next && n == selection.length-1));
} }
// make sure there are no selected rows // make sure there are no selected rows
if (!this.env.display_next) if (!this.env.display_next && remove)
this.message_list.clear_selection(); this.message_list.clear_selection();
// update thread tree icons // update thread tree icons
for (n=0, len=roots.length; n<len; n++) { for (n=0, len=roots.length; n<len; n++) {
@ -2788,9 +2799,12 @@ function rcube_webmail()
if (count < 0) if (count < 0)
post_data._count = (count*-1); post_data._count = (count*-1);
// remove threads from the end of the list // remove threads from the end of the list
else if (count > 0) else if (count > 0 && remove)
this.delete_excessive_thread_rows(); this.delete_excessive_thread_rows();
if (!remove)
post_data._refresh = 1;
if (!lock) { if (!lock) {
msg = action == 'move' ? 'movingmessage' : 'deletingmessage'; msg = action == 'move' ? 'movingmessage' : 'deletingmessage';
lock = this.display_message(this.get_label(msg), 'loading'); lock = this.display_message(this.get_label(msg), 'loading');
@ -3000,7 +3014,8 @@ function rcube_webmail()
var icn_src, uid, i, len, var icn_src, uid, i, len,
rows = this.message_list ? this.message_list.rows : {}; rows = this.message_list ? this.message_list.rows : {};
uids = String(uids).split(','); if (typeof uids == 'string')
uids = String(uids).split(',');
for (i=0, len=uids.length; i<len; i++) { for (i=0, len=uids.length; i<len; i++) {
uid = uids[i]; uid = uids[i];
@ -3013,7 +3028,7 @@ function rcube_webmail()
// with select_all mode checking // with select_all mode checking
this.uids_to_list = function(uids) this.uids_to_list = function(uids)
{ {
return this.select_all_mode ? '*' : uids.join(','); return this.select_all_mode ? '*' : (uids.length <= 1 ? uids.join(',') : uids);
}; };
// Sets title of the delete button // Sets title of the delete button
@ -4259,6 +4274,12 @@ function rcube_webmail()
this.env.search_mods[mbox] = mods; this.env.search_mods[mbox] = mods;
}; };
this.is_multifolder_listing = function()
{
return typeof this.env.multifolder_listing != 'undefined' ? this.env.multifolder_listing :
(this.env.search_request && (this.env.search_scope || 'base') != 'base');
}
this.sent_successfully = function(type, msg, folders) this.sent_successfully = function(type, msg, folders)
{ {
this.display_message(msg, type); this.display_message(msg, type);
@ -7041,6 +7062,7 @@ function rcube_webmail()
this.enable_command('expunge', this.env.exists); this.enable_command('expunge', this.env.exists);
this.enable_command('purge', this.purge_mailbox_test()); this.enable_command('purge', this.purge_mailbox_test());
this.enable_command('expand-all', 'expand-unread', 'collapse-all', this.env.threading && this.env.messagecount); this.enable_command('expand-all', 'expand-unread', 'collapse-all', this.env.threading && this.env.messagecount);
this.enable_command('set-listmode', this.env.threads && !this.is_multifolder_listing());
if ((response.action == 'list' || response.action == 'search') && this.message_list) { if ((response.action == 'list' || response.action == 'search') && this.message_list) {
this.msglist_select(this.message_list); this.msglist_select(this.message_list);

@ -285,7 +285,7 @@ class html
// ignore not allowed attributes // ignore not allowed attributes
if (!empty($allowed)) { if (!empty($allowed)) {
$is_data_attr = substr_compare($key, 'data-', 0, 5) === 0; $is_data_attr = @substr_compare($key, 'data-', 0, 5) === 0;
if (!isset($allowed_f[$key]) && (!$is_data_attr || !isset($allowed_f['data-*']))) { if (!isset($allowed_f[$key]) && (!$is_data_attr || !isset($allowed_f['data-*']))) {
continue; continue;
} }

@ -988,6 +988,10 @@ class rcube_imap extends rcube_storage
$a_msg_headers = array_slice(array_values($a_msg_headers), $from, $slice_length); $a_msg_headers = array_slice(array_values($a_msg_headers), $from, $slice_length);
} }
else { else {
if ($this->sort_order != $search_set->get_parameters('ORDER')) {
$search_set->revert();
}
// slice resultset first... // slice resultset first...
$fetch = array(); $fetch = array();
foreach (array_slice($search_set->get(), $from, $slice_length) as $msg_id) { foreach (array_slice($search_set->get(), $from, $slice_length) as $msg_id) {
@ -1708,7 +1712,7 @@ class rcube_imap extends rcube_storage
} }
// decode combined UID-folder identifier // decode combined UID-folder identifier
if (preg_match('/^\d+-[^,]+$/', $uid)) { if (preg_match('/^\d+-.+/', $uid)) {
list($uid, $folder) = explode('-', $uid, 2); list($uid, $folder) = explode('-', $uid, 2);
} }
@ -1744,7 +1748,7 @@ class rcube_imap extends rcube_storage
} }
// decode combined UID-folder identifier // decode combined UID-folder identifier
if (preg_match('/^\d+-[^,]+$/', $uid)) { if (preg_match('/^\d+-.+/', $uid)) {
list($uid, $folder) = explode('-', $uid, 2); list($uid, $folder) = explode('-', $uid, 2);
} }

@ -95,8 +95,8 @@ class rcube_ldap extends rcube_addressbook
if (empty($this->prop['groups']['scope'])) if (empty($this->prop['groups']['scope']))
$this->prop['groups']['scope'] = 'sub'; $this->prop['groups']['scope'] = 'sub';
// extend group objectclass => member attribute mapping // extend group objectclass => member attribute mapping
if (!empty($this->prop['groups']['event-panel-summary'])) if (!empty($this->prop['groups']['class_member_attr']))
$this->group_types = array_merge($this->group_types, $this->prop['groups']['event-panel-summary']); $this->group_types = array_merge($this->group_types, $this->prop['groups']['class_member_attr']);
// add group name attrib to the list of attributes to be fetched // add group name attrib to the list of attributes to be fetched
$fetch_attributes[] = $this->prop['groups']['name_attr']; $fetch_attributes[] = $this->prop['groups']['name_attr'];
@ -377,10 +377,11 @@ class rcube_ldap extends rcube_addressbook
// replace placeholders in filter settings // replace placeholders in filter settings
if (!empty($this->prop['filter'])) if (!empty($this->prop['filter']))
$this->prop['filter'] = strtr($this->prop['filter'], $replaces); $this->prop['filter'] = strtr($this->prop['filter'], $replaces);
if (!empty($this->prop['groups']['filter']))
$this->prop['groups']['filter'] = strtr($this->prop['groups']['filter'], $replaces); foreach (array('base_dn','filter','member_filter') as $k) {
if (!empty($this->prop['groups']['member_filter'])) if (!empty($this->prop['groups'][$k]))
$this->prop['groups']['member_filter'] = strtr($this->prop['groups']['member_filter'], $replaces); $this->prop['groups'][$k] = strtr($this->prop['groups'][$k], $replaces);
}
if (!empty($this->prop['group_filters'])) { if (!empty($this->prop['group_filters'])) {
foreach ($this->prop['group_filters'] as $i => $gf) { foreach ($this->prop['group_filters'] as $i => $gf) {

@ -75,7 +75,7 @@ class rcube_message
function __construct($uid, $folder = null) function __construct($uid, $folder = null)
{ {
// decode combined UID-folder identifier // decode combined UID-folder identifier
if (preg_match('/^\d+-[^,]+$/', $uid)) { if (preg_match('/^\d+-.+/', $uid)) {
list($uid, $folder) = explode('-', $uid, 2); list($uid, $folder) = explode('-', $uid, 2);
} }

@ -130,6 +130,17 @@ class rcube_result_multifolder
public function revert() public function revert()
{ {
$this->order = $this->order == 'ASC' ? 'DESC' : 'ASC'; $this->order = $this->order == 'ASC' ? 'DESC' : 'ASC';
$this->index = array();
// revert order in all sub-sets
foreach ($this->sets as $set) {
if ($this->order != $set->get_parameters('ORDER')) {
$set->revert();
}
$folder = $set->get_parameters('MAILBOX');
$index = array_map(function($uid) use ($folder) { return $uid . '-' . $folder; }, $set->get());
$this->index = array_merge($this->index, $index);
}
} }

@ -463,6 +463,11 @@ function rcmail_process_compose_params(&$COMPOSE)
} }
} }
// resolve _forward_uid=* to an absolute list of messages from a search result
if ($COMPOSE['param']['forward_uid'] == '*' && is_object($_SESSION['search'][1])) {
$COMPOSE['param']['forward_uid'] = $_SESSION['search'][1]->get();
}
// clean HTML message body which can be submitted by URL // clean HTML message body which can be submitted by URL
if (!empty($COMPOSE['param']['body'])) { if (!empty($COMPOSE['param']['body'])) {
$COMPOSE['param']['body'] = rcmail_wash_html($COMPOSE['param']['body'], array('safe' => false, 'inline_html' => true), array()); $COMPOSE['param']['body'] = rcmail_wash_html($COMPOSE['param']['body'], array('safe' => false, 'inline_html' => true), array());
@ -1259,10 +1264,10 @@ function rcmail_write_forward_attachments()
$index = $storage->index(null, rcmail_sort_column(), rcmail_sort_order()); $index = $storage->index(null, rcmail_sort_column(), rcmail_sort_order());
$COMPOSE['forward_uid'] = $index->get(); $COMPOSE['forward_uid'] = $index->get();
} }
else if (strpos($COMPOSE['forward_uid'], ':')) { else if (!is_array($COMPOSE['forward_uid']) && strpos($COMPOSE['forward_uid'], ':')) {
$COMPOSE['forward_uid'] = rcube_imap_generic::uncompressMessageSet($COMPOSE['forward_uid']); $COMPOSE['forward_uid'] = rcube_imap_generic::uncompressMessageSet($COMPOSE['forward_uid']);
} }
else { else if (is_string($COMPOSE['forward_uid'])) {
$COMPOSE['forward_uid'] = explode(',', $COMPOSE['forward_uid']); $COMPOSE['forward_uid'] = explode(',', $COMPOSE['forward_uid']);
} }

@ -5,7 +5,7 @@
| program/steps/mail/copy.inc | | program/steps/mail/copy.inc |
| | | |
| This file is part of the Roundcube Webmail client | | This file is part of the Roundcube Webmail client |
| Copyright (C) 2005-2013, The Roundcube Dev Team | | Copyright (C) 2005-2014, The Roundcube Dev Team |
| | | |
| Licensed under the GNU General Public License version 3 or | | Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. | | any later version with exceptions for skins & plugins. |
@ -29,7 +29,10 @@ if (!empty($_POST['_uid']) && strlen($_POST['_target_mbox'])) {
$target = rcube_utils::get_input_value('_target_mbox', rcube_utils::INPUT_POST, true); $target = rcube_utils::get_input_value('_target_mbox', rcube_utils::INPUT_POST, true);
foreach (rcmail::get_uids() as $mbox => $uids) { foreach (rcmail::get_uids() as $mbox => $uids) {
$copied += (int)$RCMAIL->storage->copy_message($uids, $target, $mbox); if ($mbox == $target)
$copied++;
else
$copied += (int)$RCMAIL->storage->copy_message($uids, $target, $mbox);
} }
if (!$copied) { if (!$copied) {

@ -69,7 +69,7 @@ if (!empty($_REQUEST['_search']) && isset($_SESSION['search'])
} }
// remove mbox part from _uid // remove mbox part from _uid
if (($_uid = get_input_value('_uid', RCUBE_INPUT_GPC)) && preg_match('/^\d+-[^,]+$/', $_uid)) { if (($_uid = rcube_utils::get_input_value('_uid', RCUBE_INPUT_GPC)) && !is_array($_uid) && preg_match('/^\d+-.+/', $_uid)) {
list($_uid, $mbox) = explode('-', $_uid, 2); list($_uid, $mbox) = explode('-', $_uid, 2);
if (isset($_GET['_uid'])) $_GET['_uid'] = $_uid; if (isset($_GET['_uid'])) $_GET['_uid'] = $_uid;
if (isset($_POST['_uid'])) $_POST['_uid'] = $_uid; if (isset($_POST['_uid'])) $_POST['_uid'] = $_uid;
@ -393,6 +393,8 @@ function rcmail_js_message_list($a_headers, $insert_top=false, $a_show_cols=null
$OUTPUT->command('select_folder', ''); $OUTPUT->command('select_folder', '');
} }
$OUTPUT->set_env('multifolder_listing', $multifolder);
if (empty($a_headers)) { if (empty($a_headers)) {
return; return;
} }

@ -101,6 +101,11 @@ $OUTPUT->set_env('current_page', $count ? $RCMAIL->storage->get_page() : 1);
$OUTPUT->set_env('exists', $exists); $OUTPUT->set_env('exists', $exists);
$OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($count), $mbox_name); $OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($count), $mbox_name);
// remove old message rows if commanded by the client
if (!empty($_REQUEST['_clear'])) {
$OUTPUT->command('clear_message_list');
}
// add message rows // add message rows
rcmail_js_message_list($a_headers, false, $cols); rcmail_js_message_list($a_headers, false, $cols);

@ -68,7 +68,9 @@ if (($_uids = rcube_utils::get_input_value('_uid', rcube_utils::INPUT_POST))
if ($flag == 'DELETED' && $read_deleted && !empty($_POST['_ruid'])) { if ($flag == 'DELETED' && $read_deleted && !empty($_POST['_ruid'])) {
$ruids = rcube_utils::get_input_value('_ruid', rcube_utils::INPUT_POST); $ruids = rcube_utils::get_input_value('_ruid', rcube_utils::INPUT_POST);
$read = $RCMAIL->storage->set_flag($ruids, 'SEEN'); foreach (rcmail::get_uids($ruids) as $mbox => $uids) {
$read += (int)$RCMAIL->storage->set_flag($uids, 'SEEN', $mbox);
}
if ($read && !$skip_deleted) { if ($read && !$skip_deleted) {
$OUTPUT->command('flag_deleted_as_read', $ruids); $OUTPUT->command('flag_deleted_as_read', $ruids);

@ -60,7 +60,13 @@ if ($RCMAIL->action == 'move' && !empty($_POST['_uid']) && strlen($_POST['_targe
$OUTPUT->show_message('messagemoved', 'confirmation'); $OUTPUT->show_message('messagemoved', 'confirmation');
} }
$addrows = true; if (!empty($_POST['_refresh'])) {
// FIXME: send updated message rows instead of releading the entire list
$OUTPUT->command('refresh_list');
}
else {
$addrows = true;
}
} }
// delete messages // delete messages
else if ($RCMAIL->action=='delete' && !empty($_POST['_uid'])) { else if ($RCMAIL->action=='delete' && !empty($_POST['_uid'])) {

Loading…
Cancel
Save