/* Constants for listMailboxes() */
const MBOX_SUBSCRIBED = 1;
- const MBOX_UNSUBSCRIBED = 2;
- const MBOX_ALL = 3;
+ const MBOX_SUBSCRIBED_EXISTS = 2;
+ const MBOX_UNSUBSCRIBED = 3;
+ const MBOX_ALL = 4;
/* Constants for status() */
const STATUS_MESSAGES = 1;
/**
* Obtain a list of mailboxes matching a pattern.
*
- * @todo RFC 5258 extensions
- *
- * @param string $pattern The mailbox search pattern (see RFC 3501
- * [6.3.8] for the format). Either in UTF7-IMAP or
+ * @param mixed $pattern The mailbox search pattern(s) (see RFC 3501
+ * [6.3.8] for the format). Either a string or an
+ * array of strings. Either in UTF7-IMAP or
* UTF-8.
* @param integer $mode Which mailboxes to return. Either
* Horde_Imap_Client::MBOX_SUBSCRIBED,
+ * Horde_Imap_Client::MBOX_SUBSCRIBED_EXISTS,
* Horde_Imap_Client::MBOX_UNSUBSCRIBED, or
* Horde_Imap_Client::MBOX_ALL.
* @param array $options Additional options:
* the 'attributes' key. The attributes will be returned
* in an array with each attribute in lowercase.
* DEFAULT: Do not return this information.
- * 'utf8' - (boolean) True to return mailbox names in UTF-8.
- * DEFAULT: Names are returned in UTF7-IMAP.
+ * 'children' - (boolean) Tell server to return children attribute
+ * information. Requires the LIST-EXTENDED extension. Server
+ * MAY return this autribute without this option, but it
+ * is not guaranteed.
+ * DEFAULT: false
* 'delimiter' - (boolean) If true, return delimiter information under
* the 'delimiter' key.
* DEFAULT: Do not return this information.
* 'flat' - (boolean) If true, return a flat list of mailbox names only.
* Overrides both the 'attributes' and 'delimiter' options.
* DEFAULT: Do not return flat list.
+ * 'recursivematch' - (boolean) Force the server to return information
+ * about parent mailboxes that don't match other
+ * selection options, but have some submailboxes that
+ * do. Information about children is returned in the
+ * CHILDINFO extended data item ('extended'). Requires
+ * the LIST-EXTENDED extension.
+ * DEFAULT: false
+ * 'remote' - (boolean) Tell server to return mailboxes that reside on
+ * another server. Requires the LIST-EXTENDED extension.
+ * DEFAULT: false
* 'sort' - (boolean) If true, return a sorted list of mailboxes?
* DEFAULT: Do not sort the list.
* 'sort_delimiter' - (string) If 'sort' is true, this is the delimiter
* used to sort the mailboxes.
* DEFAULT: '.'
+ * 'utf8' - (boolean) True to return mailbox names in UTF-8.
+ * DEFAULT: Names are returned in UTF7-IMAP.
* </pre>
*
* @return array If 'flat' option is true, the array values are the list
* of mailboxes. Otherwise, the array values are arrays
* with the following keys: 'mailbox', 'attributes' (only
- * if 'attributes' option is true), and 'delimiter' (only
- * if 'delimiter' option is true).
+ * if 'attributes' option is true), 'delimiter' (only
+ * if 'delimiter' option is true), and 'extended' (only
+ * if 'recursivematch' option is true and LIST-EXTENDED
+ * extension is supported on the server).
* @throws Horde_Imap_Client_Exception
*/
public function listMailboxes($pattern, $mode = Horde_Imap_Client::MBOX_ALL,
/**
* Obtain a list of mailboxes matching a pattern.
*
- * @param string $pattern The mailbox search pattern (UTF7-IMAP).
- * @param integer $mode Which mailboxes to return.
- * @param array $options Additional options.
+ * @param mixed $pattern The mailbox search pattern(s) (UTF7-IMAP).
+ * @param integer $mode Which mailboxes to return.
+ * @param array $options Additional options.
*
* @return array See self::listMailboxes().
* @throws Horde_Imap_Client_Exception
/**
* Obtain a list of mailboxes matching a pattern.
*
- * @param string $pattern The mailbox search pattern.
- * @param integer $mode Which mailboxes to return.
- * @param array $options Additional options.
+ * @param mixed $pattern The mailbox search pattern(s).
+ * @param integer $mode Which mailboxes to return.
+ * @param array $options Additional options.
* <pre>
* For the 'attributes' option, this driver will return only these
* attributes:
case Horde_Imap_Client::MBOX_SUBSCRIBED:
case Horde_Imap_Client::MBOX_UNSUBSCRIBED:
+ case Horde_Imap_Client::MBOX_SUBSCRIBED_EXISTS:
$sub = $this->_getMailboxList($pattern, Horde_Imap_Client::MBOX_SUBSCRIBED);
+ if ($mode == Horde_Imap_Client::MBOX_SUBSCRIBED_EXISTS) {
+ $mboxes = $this->_getMailboxList($pattern, Horde_Imap_Client::MBOX_ALL);
+ $sub = array_intersect($sub, $mboxes);
+ }
+
if (!empty($options['flat'])) {
if (!empty($options['utf8'])) {
$sub = array_map(array('Horde_Imap_Client_Utf7imap', 'Utf7ImapToUtf8'), $sub);
}
- if ($mode == Horde_Imap_Client::MBOX_SUBSCRIBED) {
- return $sub;
+
+ if (($mode == Horde_Imap_Client::MBOX_SUBSCRIBED) ||
+ ($mode == Horde_Imap_Client::MBOX_SUBSCRIBED_EXISTS)) {
+ return array_values($sub);
}
$mboxes = $this->_getMailboxList($pattern, Horde_Imap_Client::MBOX_ALL);
+
if (!empty($options['utf8'])) {
- $sub = array_map(array('Horde_Imap_Client_Utf7imap', 'Utf7ImapToUtf8'), $sub);
+ $mboxes = array_map(array('Horde_Imap_Client_Utf7imap', 'Utf7ImapToUtf8'), $mboxes);
}
return array_values(array_diff($mboxes, $sub));
}
$sub = array_flip($sub);
$check = true;
+ break;
}
$attr = array(
/**
* Obtain a list of mailboxes matching a pattern.
*
- * @param string $pattern The mailbox search pattern.
- * @param integer $mode Which mailboxes to return. Either
- * Horde_Imap_Client::MBOX_SUBSCRIBED or
- * Horde_Imap_Client::MBOX_ALL.
+ * @param mixed $pattern The mailbox search patterns.
+ * @param integer $mode Which mailboxes to return. Either
+ * Horde_Imap_Client::MBOX_SUBSCRIBED or
+ * Horde_Imap_Client::MBOX_ALL.
*
* @return array A list of mailboxes in UTF7-IMAP format.
*/
protected function _getMailboxList($pattern, $mode)
{
+ if (is_array($pattern)) {
+ $res = array();
+ foreach ($pattern as $val) {
+ if (strlen($val)) {
+ $res = array_merge($res, $this->_getMailboxList($val, $mode);
+ }
+ }
+ return array_unique($res);
+ }
+
$mboxes = array();
$old_error = error_reporting(0);
* RFC 5182 - SEARCHRES
* RFC 5255 - LANGUAGE/I18NLEVEL
* RFC 5256 - THREAD/SORT
+ * RFC 5258 - LIST-EXTENDED
* RFC 5267 - ESORT
* RFC 5464 - METADATA
*
* RFC 4469/5550 - CATENATE
* RFC 4978 - COMPRESS=DEFLATE
* See: http://bugs.php.net/bug.php?id=48725
- * RFC 3348/5258 - LIST-EXTENDED
* RFC 5257 - ANNOTATE
* RFC 5259 - CONVERT
* RFC 5267 - CONTEXT
/**
* Obtain a list of mailboxes matching a pattern.
*
- * @param string $pattern The mailbox search pattern.
- * @param integer $mode Which mailboxes to return.
- * @param array $options Additional options.
+ * @param mixed $pattern The mailbox search pattern(s).
+ * @param integer $mode Which mailboxes to return.
+ * @param array $options Additional options.
*
* @return array See self::listMailboxes().
* @throws Horde_Imap_Client_Exception
// Get the list of subscribed/unsubscribed mailboxes. Since LSUB is
// not guaranteed to have correct attributes, we must use LIST to
// ensure we receive the correct information.
- if ($mode != Horde_Imap_Client::MBOX_ALL) {
+ // TODO: Use LSUB for MBOX_SUBSCRIBED if no other options are
+ // set (RFC 5258 3.1)
+ if (($mode != Horde_Imap_Client::MBOX_ALL) &&
+ !$this->queryCapability('LIST-EXTENDED')) {
$subscribed = $this->_getMailboxList($pattern, Horde_Imap_Client::MBOX_SUBSCRIBED, array('flat' => true));
+
// If mode is subscribed, and 'flat' option is true, we can
// return now.
if (($mode == Horde_Imap_Client::MBOX_SUBSCRIBED) && !empty($options['flat'])) {
}
/**
- * Obtain a list of mailboxes matching a pattern.
+ * Obtain a list of mailboxes.
*
- * @param string $pattern The mailbox search pattern.
+ * @param mixed $pattern The mailbox search pattern(s).
* @param integer $mode Which mailboxes to return.
* @param array $options Additional options.
* @param array $subscribed A list of subscribed mailboxes.
$t = &$this->_temp;
$t['mailboxlist'] = array(
'check' => $check,
- 'subscribed' => $check ? array_flip($subscribed) : null,
- 'options' => $options
+ 'options' => $options,
+ 'subexist' => ($mode == Horde_Imap_Client::MBOX_SUBSCRIBED_EXISTS),
+ 'subscribed' => ($check ? array_flip($subscribed) : null)
);
$t['listresponse'] = array();
- $this->_sendLine((($mode == Horde_Imap_Client::MBOX_SUBSCRIBED) ? 'LSUB' : 'LIST') . ' "" ' . $this->utils->escape($pattern));
+ if ($this->queryCapability('LIST-EXTENDED')) {
+ $cmd = 'LIST';
+
+ $return_opts = $select_opts = array();
+
+ if (($mode == Horde_Imap_Client::MBOX_SUBSCRIBED) ||
+ ($mode == Horde_Imap_Client::MBOX_SUBSCRIBED_EXISTS)) {
+ $select_opts[] = 'SUBSCRIBED';
+ $return_opts[] = 'SUBSCRIBED';
+ }
+
+ if (!empty($options['remote'])) {
+ $select_opts[] = 'REMOTE';
+ }
+
+ if (!empty($options['recursivematch'])) {
+ $select_opts[] = 'RECURSIVEMATCH';
+ }
+
+ if (!empty($select_opts)) {
+ $cmd .= ' (' . implode(' ', $select_opts) . ')';
+ }
+
+ $cmd .= ' "" ';
+
+ if (is_array($pattern)) {
+ $cmd .= '(';
+ foreach ($pattern as $val) {
+ $cmd .= $this->utils->escape($pattern) . ' ';
+ }
+ $cmd = rtrim($cmd) . ')';
+ } else {
+ $cmd .= $this->utils->escape($pattern);
+ }
+
+ if (!empty($options['children'])) {
+ $return_opts[] = 'CHILDREN';
+ }
- return (empty($options['flat'])) ? $t['listresponse'] : array_values($t['listresponse']);
+ if (!empty($return_opts)) {
+ $cmd .= ' RETURN (' . implode(' ', $return_opts) . ')';
+ }
+ } else {
+ $cmd = (($mode == Horde_Imap_Client::MBOX_SUBSCRIBED) ? 'LSUB' : 'LIST') . ' "" ' . $this->utils->escape($pattern);
+ }
+
+ $this->_sendLine($cmd);
+
+ return empty($options['flat'])
+ ? $t['listresponse']
+ : array_values($t['listresponse']);
}
/**
$mbox = Horde_Imap_Client_Utf7imap::Utf7ImapToUtf8($mbox);
}
+ if ($ml['subexist'] ||
+ (empty($mlo['flat']) && !empty($mlo['attributes']))) {
+ $attr = array_map('strtolower', $data[1]);
+ if ($ml['subexist'] && in_array('\\nonexistent', $attr)) {
+ return;
+ }
+ }
+
if (empty($mlo['flat'])) {
$tmp = array('mailbox' => $mbox);
if (!empty($mlo['attributes'])) {
- $tmp['attributes'] = array_map('strtolower', $data[1]);
+ $tmp['attributes'] = $attr;
}
if (!empty($mlo['delimiter'])) {
$tmp['delimiter'] = $data[2];
}
+ if (isset($data[4])) {
+ $tmp['extended'] = $data[4];
+ }
$lr[$mbox] = $tmp;
} else {
$lr[] = $mbox;
<api>alpha</api>
</stability>
<license uri="http://www.gnu.org/copyleft/lesser.html">LGPL</license>
- <notes>* Add Horde_Imap_Client_Utils::createUrl().
+ <notes>* Add support for RFC 5258 (LIST-EXTENDED).
+ * Add Horde_Imap_Client_Utils::createUrl().
* Support SORT=DISPLAY extension.
* Added search and thread (message list) caching.
* Added PHP socket based POP3 driver.