summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoralecpl <alec@alec.pl>2010-10-26 13:44:39 +0000
committeralecpl <alec@alec.pl>2010-10-26 13:44:39 +0000
commit3870bec7ff891677fd848df8d027171acf921420 (patch)
tree6ecb2eb47f02cf8f8685125cf41e4a132122bac6
parent10a6fc58e6e8a40388ffda43f949f69f5ec804dc (diff)
- Add support for selection options from LIST-EXTENDED extension (RFC 5258)
- Don't list subscribed but non-existent folders (#1486225) - Fix \Noselect handling performance (#1487082)
-rw-r--r--CHANGELOG2
-rw-r--r--program/include/main.inc5
-rw-r--r--program/include/rcube_imap.php36
-rw-r--r--program/include/rcube_imap_generic.php37
4 files changed, 63 insertions, 17 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 30868f1f6..9478fc0f5 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -49,6 +49,8 @@ CHANGELOG Roundcube Webmail
- Add support for AUTH=DIGEST-MD5 in IMAP (RFC 2831)
- Fix parent folder with unread subfolder not bold when message is open (#1487078)
- Add basic IMAP LIST's \Noselect option support
+- Add support for selection options from LIST-EXTENDED extension (RFC 5258)
+- Don't list subscribed but non-existent folders (#1486225)
RELEASE 0.4.2
-------------
diff --git a/program/include/main.inc b/program/include/main.inc
index 7e96233bc..242fb1ac3 100644
--- a/program/include/main.inc
+++ b/program/include/main.inc
@@ -1356,9 +1356,8 @@ function rcmail_build_folder_tree(&$arrFolders, $folder, $delm='/', $path='')
$path .= $currentFolder;
- // Check \Noselect option
- if (!$virtual) {
- $opts = $RCMAIL->imap->mailbox_options($path);
+ // Check \Noselect option (if options are in cache)
+ if (!$virtual && ($opts = $RCMAIL->imap->mailbox_options($path))) {
$virtual = in_array('\\Noselect', $opts);
}
diff --git a/program/include/rcube_imap.php b/program/include/rcube_imap.php
index 556441dcb..a4b18c970 100644
--- a/program/include/rcube_imap.php
+++ b/program/include/rcube_imap.php
@@ -2816,8 +2816,27 @@ class rcube_imap
$a_folders = $data['folders'];
}
else {
- // retrieve list of folders from IMAP server
- $a_folders = $this->conn->listSubscribed($this->mod_mailbox($root), $filter);
+ // Server supports LIST-EXTENDED, we can use selection options
+ if ($this->get_capability('LIST-EXTENDED')) {
+ // This will also set mailbox options, LSUB doesn't do that
+ $a_folders = $this->conn->listMailboxes($this->mod_mailbox($root), $filter,
+ NULL, array('SUBSCRIBED'));
+
+ // remove non-existent folders
+ if (is_array($a_folders)) {
+ foreach ($a_folders as $idx => $folder) {
+ if ($this->conn->data['LIST'] && ($opts = $this->conn->data['LIST'][$folder])
+ && in_array('\\NonExistent', $opts)
+ ) {
+ unset($a_folders[$idx]);
+ }
+ }
+ }
+ }
+ // retrieve list of folders from IMAP server using LSUB
+ else {
+ $a_folders = $this->conn->listSubscribed($this->mod_mailbox($root), $filter);
+ }
}
if (!is_array($a_folders) || !sizeof($a_folders))
@@ -3121,13 +3140,15 @@ class rcube_imap
/**
- * Gets folder options from LIST/LSUB response, e.g. \Noselect, \Noinferiors
+ * Gets folder options from LIST response, e.g. \Noselect, \Noinferiors
*
* @param string $mbox_name Folder name
+ * @param bool $force Set to True if options should be refreshed
+ * Options are available after LIST command only
*
* @return array Options list
*/
- function mailbox_options($mbox_name)
+ function mailbox_options($mbox_name, $force=false)
{
$mbox = $this->mod_mailbox($mbox_name);
@@ -3136,7 +3157,12 @@ class rcube_imap
}
if (!is_array($this->conn->data['LIST']) || !is_array($this->conn->data['LIST'][$mbox])) {
- $this->conn->listMailboxes($this->mod_mailbox(''), $mbox_name);
+ if ($force) {
+ $this->conn->listMailboxes($this->mod_mailbox(''), $mbox_name);
+ }
+ else {
+ return array();
+ }
}
$opts = $this->conn->data['LIST'][$mbox];
diff --git a/program/include/rcube_imap_generic.php b/program/include/rcube_imap_generic.php
index c79124bec..41240a2d1 100644
--- a/program/include/rcube_imap_generic.php
+++ b/program/include/rcube_imap_generic.php
@@ -1826,14 +1826,15 @@ class rcube_imap_generic
* @param string $ref Reference name
* @param string $mailbox Mailbox name
* @param array $status_opts (see self::_listMailboxes)
+ * @param array $select_opts (see self::_listMailboxes)
*
* @return array List of mailboxes or hash of options if $status_opts argument
* is non-empty.
* @access public
*/
- function listMailboxes($ref, $mailbox, $status_opts=array())
+ function listMailboxes($ref, $mailbox, $status_opts=array(), $select_opts=array())
{
- return $this->_listMailboxes($ref, $mailbox, false, $status_opts);
+ return $this->_listMailboxes($ref, $mailbox, false, $status_opts, $select_opts);
}
/**
@@ -1843,13 +1844,13 @@ class rcube_imap_generic
* @param string $mailbox Mailbox name
* @param array $status_opts (see self::_listMailboxes)
*
- * @return array List of mailboxes or hash of options if $status_ops argument
+ * @return array List of mailboxes or hash of options if $status_opts argument
* is non-empty.
* @access public
*/
function listSubscribed($ref, $mailbox, $status_opts=array())
{
- return $this->_listMailboxes($ref, $mailbox, true, $status_opts);
+ return $this->_listMailboxes($ref, $mailbox, true, $status_opts, NULL);
}
/**
@@ -1860,12 +1861,15 @@ class rcube_imap_generic
* @param bool $subscribed Enables returning subscribed mailboxes only
* @param array $status_opts List of STATUS options (RFC5819: LIST-STATUS)
* Possible: MESSAGES, RECENT, UIDNEXT, UIDVALIDITY, UNSEEN
+ * @param array $select_opts List of selection options (RFC5258: LIST-EXTENDED)
+ * Possible: SUBSCRIBED, RECURSIVEMATCH, REMOTE
*
* @return array List of mailboxes or hash of options if $status_ops argument
* is non-empty.
* @access private
*/
- private function _listMailboxes($ref, $mailbox, $subscribed=false, $status_opts=array())
+ private function _listMailboxes($ref, $mailbox, $subscribed=false,
+ $status_opts=array(), $select_opts=array())
{
if (empty($mailbox)) {
$mailbox = '*';
@@ -1875,10 +1879,19 @@ class rcube_imap_generic
$ref = $this->prefs['rootdir'];
}
- $args = array($this->escape($ref), $this->escape($mailbox));
+ $args = array();
+
+ if (!empty($select_opts) && $this->getCapability('LIST-EXTENDED')) {
+ $select_opts = (array) $select_opts;
+
+ $args[] = '(' . implode(' ', $select_opts) . ')';
+ }
+
+ $args[] = $this->escape($ref);
+ $args[] = $this->escape($mailbox);
if (!empty($status_opts) && $this->getCapability('LIST-STATUS')) {
- $status_opts = array($status_opts);
+ $status_opts = (array) $status_opts;
$lstatus = true;
$args[] = 'RETURN (STATUS (' . implode(' ', $status_opts) . '))';
@@ -1894,6 +1907,7 @@ class rcube_imap_generic
if (!$lstatus || $cmd == 'LIST' || $cmd == 'LSUB') {
list($opts, $delim, $folder) = $this->tokenizeResponse($response, 3);
+ // Add to result array
if (!$lstatus) {
$folders[] = $folder;
}
@@ -1901,8 +1915,13 @@ class rcube_imap_generic
$folders[$folder] = array();
}
- if ($cmd == 'LIST') {
- $this->data['LIST'][$folder] = $opts;
+ // Add to options array
+ if (!empty($opts)) {
+ if (empty($this->data['LIST'][$folder]))
+ $this->data['LIST'][$folder] = $opts;
+ else
+ $this->data['LIST'][$folder] = array_unique(array_merge(
+ $this->data['LIST'][$folder], $opts));
}
}
// * STATUS <mailbox> (<result>)