abstract protected function _getMyACLRights($mailbox);
/**
- * Get metadata for a given mailbox. The server must support the
- * IMAP METADATA extension (RFC 5464).
+ * Get metadata for a given mailbox. The server must support either the
+ * IMAP METADATA extension (RFC 5464) or the ANNOTATEMORE extension
+ * (http://ietfreport.isoc.org/idref/draft-daboo-imap-annotatemore/).
*
- * @param string $mailbox A mailbox. Either in UTF7-IMAP or UTF-8.
- * @param array $entries The entries to fetch.
- * @param array $options Additional options:
+ * @param string $mailbox A mailbox. Either in UTF7-IMAP or UTF-8.
+ * @param array $entries The entries to fetch.
+ * @param array $options Additional options:
* <pre>
- * 'maxsize' - (int) The maximal size the returned values may have.
- * This option is only available if 'annotatemore' has
- * not been set.
- * DEFAULT: No maximal size.
- * 'depth' - (string) Either "0", "1" or "infinity". Returns only
- * the given value ("0"), only values one level below
- * the specified value ("1") or all entries below the
- * specified value ("infinity").
- * This option is only available if 'annotatemore' has
- * not been set.
- * DEFAULT: Unset which is equivalent to "0".
- * 'nocapability' - (boolean) Do not check for the METADATA capability of
- * the server ("true"). Otherwise the call will fail if
- * the server does not announce the METADATA capability
- * ("false").
- * DEFAULT: false - Check the capability.
- * 'annotatemore' - (boolean) Use the ANNOTATION command rather than the
- * METADATA command ("true"). This corresponds to
- * an old version of the RFC 5464 that is available for
- * some servers (cyrus, dovecot).
- * DEFAULT: Use the newer METADATA command.
+ * 'depth' - (string) Either "0", "1" or "infinity". Returns only the
+ * given value ("0"), only values one level below the specified
+ * value (1) or all entries below the specified value
+ * ("infinity").
+ * 'maxsize' - (integer) The maximal size the returned values may have.
+ * DEFAULT: No maximal size.
+ * DEFAULT: 0
* </pre>
*
- * @return array
+ * @return array An array with metadata names as the keys and metadata
+ * values as the values.
* @throws Horde_Imap_Client_Exception
*/
public function getMetadata($mailbox, $entries, $options = array())
{
- if (empty($options['nocapability'])) {
- if (empty($options['annotatemore'])) {
- $capability = 'METADATA';
- } else {
- $capability = 'ANNOTATEMORE';
- }
- if (!$this->queryCapability($capability)) {
- throw new Horde_Imap_Client_Exception('Server does not support the METADATA extension.',
- Horde_Imap_Client_Exception::NOSUPPORTIMAPEXT);
- }
- }
-
if (!is_array($entries)) {
$entries = array($entries);
}
- $entries_utf7 = array();
- foreach ($entries as $entry) {
- $entries_utf7[] = Horde_Imap_Client_Utf7imap::Utf8ToUtf7Imap($entry);
- }
-
- return $this->_getMetadata(Horde_Imap_Client_Utf7imap::Utf8ToUtf7Imap($mailbox),
- $entries_utf7,
- $options);
+ return $this->_getMetadata(Horde_Imap_Client_Utf7imap::Utf8ToUtf7Imap($mailbox), array_map(array('Horde_Imap_Client_Utf7imap', 'Utf8ToUtf7Imap'), $entries), $options);
}
/**
* Get metadata for a given mailbox.
*
- * @param string $mailbox A mailbox (UTF7-IMAP).
- * @param array $entries The entries to fetch.
- * @param array $options Additional options.
+ * @param string $mailbox A mailbox (UTF7-IMAP).
+ * @param array $entries The entries to fetch.
+ * @param array $options Additional options.
*
- * @return array An array with metadata names as the keys and
- * metadata values as the values.
+ * @return array An array with metadata names as the keys and metadata
+ * values as the values.
* @throws Horde_Imap_Client_Exception
*/
abstract protected function _getMetadata($mailbox, $entries, $options);
/**
* Set metadata for a given mailbox/identifier.
*
- * @param string $mailbox A mailbox. Either in UTF7-IMAP or UTF-8.
- * @param array $data A set of data values. The metadata values
- * corresponding to the keys of the array will
- * be set to the values in the array.
- * @param array $options Additional options:
- * <pre>
- * 'nocapability' - (boolean) Do not check for the METADATA capability of
- * the server ("true"). Otherwise the call will fail if
- * the server does not announce the METADATA capability
- * ("false").
- * DEFAULT: false - Check the capability.
- * 'annotatemore' - (boolean) Use the ANNOTATION command rather than the
- * METADATA command ("true"). This corresponds to
- * an older draft version of the RFC 5464 that has been
- * implemented in some servers (cyrus, dovecot).
- * http://ietfreport.isoc.org/idref/draft-daboo-imap-annotatemore/
- * DEFAULT: Use the newer METADATA command.
- * </pre>
- *
+ * @param string $mailbox A mailbox. Either in UTF7-IMAP or UTF-8. If
+ * empty, sets a server annotation.
+ * @param array $data A set of data values. The metadata values
+ * corresponding to the keys of the array will
+ * be set to the values in the array.
*
* @throws Horde_Imap_Client_Exception
*/
- public function setMetadata($mailbox, $data, $options = array())
+ public function setMetadata($mailbox, $data)
{
- if (empty($options['nocapability'])) {
- if (empty($options['annotatemore'])) {
- $capability = 'METADATA';
- } else {
- $capability = 'ANNOTATEMORE';
- }
- if (!$this->queryCapability($capability)) {
- throw new Horde_Imap_Client_Exception('Server does not support the METADATA extension.',
- Horde_Imap_Client_Exception::NOSUPPORTIMAPEXT);
- }
- }
-
- return $this->_setMetadata(Horde_Imap_Client_Utf7imap::Utf8ToUtf7Imap($mailbox), $data, $options);
+ $this->_setMetadata(Horde_Imap_Client_Utf7imap::Utf8ToUtf7Imap($mailbox), $data);
}
/**
* Set metadata for a given mailbox/identifier.
*
- * @param string $mailbox A mailbox (UTF7-IMAP).
- * @param array $data A set of data values. The metadata values
- * corresponding to the keys of the array will
- * be set to the values in the array.
- * @param array $options Additional options.
- *
- * @throws Horde_Imap_Client_Exception
- */
- abstract protected function _setMetadata($mailbox, $data, $options);
-
- /**
- * Split a name for the METADATA extension into the correct syntax for the
- * older ANNOTATEMORE version (it is a predecessor of RFC 5464.
- *
- * @param string $name A name for a metadata entry.
- *
- * @return array A list of two elements: The entry name and the value type.
+ * @param string $mailbox A mailbox (UTF7-IMAP).
+ * @param array $data A set of data values. The metadata values
+ * corresponding to the keys of the array will
+ * be set to the values in the array.
*
* @throws Horde_Imap_Client_Exception
*/
- protected function _getAnnotateMoreEntry($name)
- {
- if (substr($name, 0, 7) == '/shared') {
- $entry = substr($name, 7);
- $type = 'value.shared';
- } else if (substr($name, 0, 8) == '/private') {
- $entry = substr($name, 8);
- $type = 'value.priv';
- } else {
- throw new Horde_Imap_Client_Exception('Invalid METADATA entry: ' . $name);
- }
- return array($entry, $type);
- }
+ abstract protected function _setMetadata($mailbox, $data);
/* Utility functions. */
/**
* Get metadata for a given mailbox.
*
- * @param string $mailbox A mailbox (UTF7-IMAP).
- * @param array $entries The entries to fetch.
- * @param array $options Additional options.
+ * @param string $mailbox A mailbox (UTF7-IMAP).
+ * @param array $entries The entries to fetch.
+ * @param array $options Additional options.
*
- * @return array An array with identifiers as the keys and the
- * metadata as the values.
+ * @return array An array with identifiers as the keys and the
+ * metadata as the values.
* @throws Horde_Imap_Client_Exception
*/
protected function _getMetadata($mailbox, $entries, $options)
{
- if (!empty($options['annotatemore'])
- && function_exists('imap_getannotation')) {
- $result = array();
- foreach ($entries as $md_entry) {
- list($entry, $type) = $this->_getAnnotateMoreEntry($md_entry);
- $old_error = error_reporting(0);
- $res = imap_getannotation($this->_stream, $mailbox, $entry, $type);
- error_reporting($old_error);
- if (!$res) {
- throw new Horde_Imap_Client_Exception('Error when fetching METADATA: ' . imap_last_error());
- }
- foreach ($res as $key => $value) {
- switch ($type) {
- case 'value.priv':
- $result[$mailbox]['/private' . $entry] = $value;
- break;
- case 'value.shared':
- $result[$mailbox]['/shared' . $entry] = $value;
- break;
- }
- }
- }
- return $result;
- } else {
- return $this->_getSocket()->getMetadata($mailbox, $entry, $options);
- }
+ return $this->_getSocket()->getMetadata($mailbox, $entry, $options);
}
/**
* Set metadata for a given mailbox/identifier.
*
- * @param string $mailbox A mailbox (UTF7-IMAP).
- * @param array $data A set of data values. The metadata values
- * corresponding to the keys of the array will
- * be set to the values in the array.
- * @param array $options Additional options.
+ * @param string $mailbox A mailbox (UTF7-IMAP).
+ * @param array $data A set of data values. The metadata values
+ * corresponding to the keys of the array will
+ * be set to the values in the array.
*
* @throws Horde_Imap_Client_Exception
*/
- protected function _setMetadata($mailbox, $data, $options)
+ protected function _setMetadata($mailbox, $data)
{
- if (!empty($options['annotatemore'])
- && function_exists('imap_setannotation')) {
- foreach ($data as $key => $value) {
- list($entry, $type) = $this->_getAnnotateMoreEntry($key);
- $old_error = error_reporting(0);
- $res = imap_setannotation($this->_stream, $mailbox, $entry, $type, $value);
- error_reporting($old_error);
- if (!$res) {
- throw new Horde_Imap_Client_Exception('Error when setting METADATA: ' . imap_last_error());
- }
- }
- } else {
- return $this->_getSocket()->setMetadata($mailbox, $data, $options);
- }
+ $this->_getSocket()->setMetadata($mailbox, $data);
}
/* Internal functions */
throw new Horde_Imap_Client_Exception('IMAP ACLs not supported on POP3 servers.', Horde_Imap_Client_Exception::POP3_NOTSUPPORTED);
}
+ /**
+ * Get metadata for a given mailbox.
+ *
+ * @param string $mailbox A mailbox (UTF7-IMAP).
+ * @param array $entries The entries to fetch.
+ * @param array $options Additional options.
+ *
+ * @return array An array with identifiers as the keys and the
+ * metadata as the values.
+ * @throws Horde_Imap_Client_Exception
+ */
+ protected function _getMetadata($mailbox, $entries, $options)
+ {
+ throw new Horde_Imap_Client_Exception('IMAP metadata not supported on POP3 servers.', Horde_Imap_Client_Exception::POP3_NOTSUPPORTED);
+ }
+
+ /**
+ * Set metadata for a given mailbox/identifier.
+ *
+ * @param string $mailbox A mailbox (UTF7-IMAP).
+ * @param array $data A set of data values. The metadata values
+ * corresponding to the keys of the array will
+ * be set to the values in the array.
+ *
+ * @throws Horde_Imap_Client_Exception
+ */
+ protected function _setMetadata($mailbox, $data)
+ {
+ throw new Horde_Imap_Client_Exception('IMAP metadata not supported on POP3 servers.', Horde_Imap_Client_Exception::POP3_NOTSUPPORTED);
+ }
+
}
/**
* Get metadata for a given mailbox.
*
- * @param string $mailbox A mailbox (UTF7-IMAP).
- * @param array $entries The entries to fetch.
- * @param array $options Additional options.
+ * @param string $mailbox A mailbox (UTF7-IMAP).
+ * @param array $entries The entries to fetch.
+ * @param array $options Additional options.
*
* @return array An array with identifiers as the keys and the
* metadata as the values.
*/
protected function _getMetadata($mailbox, $entries, $options)
{
- $folder = $this->_getMailbox($mailbox);
+ $folder = $this->_getMailbox($mailbox);
$metadata = array();
+
foreach ($entries as $entry) {
$result = false;
if (isset(self::$storage[$folder]['annotations'])) {
- $ref = &self::$storage[$folder]['annotations'];
+ $ref = &self::$storage[$folder]['annotations'];
$path = split('/', $entry);
foreach ($path as $element) {
if (!isset($ref[$element])) {
$result = false;
break;
} else {
- $ref = &$ref[$element];
+ $ref = &$ref[$element];
$result = true;
}
}
}
$metadata[$entry] = $result;
}
+
return $metadata;
}
/**
* Set metadata for a given mailbox/identifier.
*
- * @param string $mailbox A mailbox (UTF7-IMAP).
- * @param array $data A set of data values. The metadata values
- * corresponding to the keys of the array will
- * be set to the values in the array.
- * @param array $options Additional options.
+ * @param string $mailbox A mailbox (UTF7-IMAP).
+ * @param array $data A set of data values. The metadata values
+ * corresponding to the keys of the array will
+ * be set to the values in the array.
*
* @throws Horde_Imap_Client_Exception
*/
- protected function _setMetadata($mailbox, $data, $options)
+ protected function _setMetadata($mailbox, $data)
{
$folder = $this->_getMailbox($mailbox);
+
foreach ($data as $key => $value) {
$path = split('/', $key);
$ref = &self::$storage[$folder]['annotations'];
foreach ($path as $element) {
if (!isset($ref[$element])) {
$ref[$element] = array();
-
$ref = &$ref[$element];
}
}
$ref['/'] = $value;
}
+
return true;
}
-}
\ No newline at end of file
+}
/**
* Get metadata for a given mailbox.
*
- * @param string $mailbox A mailbox (UTF7-IMAP).
- * @param array $entries The entries to fetch.
- * @param array $options Additional options.
+ * @param string $mailbox A mailbox (UTF7-IMAP).
+ * @param array $entries The entries to fetch.
+ * @param array $options Additional options.
*
- * @return array An array with identifiers as the keys and the
- * metadata as the values.
+ * @return array An array with metadata names as the keys and metadata
+ * values as the values.
* @throws Horde_Imap_Client_Exception
*/
protected function _getMetadata($mailbox, $entries, $options)
$this->_temp['metadata'] = array();
$cmd_options = array();
- $single_type = '';
+ $option_string = $single_type = '';
+ $use_rfc5464 = false;
+
+ if ($this->queryCapability('METADATA') ||
+ ((strlen($mailbox) == 0) &&
+ $this->queryCapability('METADATA-SERVER'))) {
+ $use_rfc5464 = true;
+ } elseif (!$this->queryCapability('ANNOTATEMORE') &&
+ !$this->queryCapability('ANNOTATEMORE2')) {
+ throw new Horde_Imap_Client_Exception('Server does not support the METADATA extension.', Horde_Imap_Client_Exception::NOSUPPORTIMAPEXT);
+ }
- if (!empty($options['annotatemore'])) {
- if (!empty($options['maxsize']) || !empty($options['depth'])) {
- throw new Horde_Imap_Client_Exception('ANNOTATEMORE does not support the "depth" and "maxsize" option.');
+ if ($use_rfc5464) {
+ $cmd = 'GETMETADATA ';
+
+ if (!empty($options['maxsize'])) {
+ $cmd_options[] = '(MAXSIZE ' . intval($options['maxsize']) . ')';
}
+ if (!empty($options['depth'])) {
+ $cmd_options[] = '(DEPTH ' . $options['depth'] . ')';
+ }
+ } else {
$cmd = 'GETANNOTATION ';
$result = array();
if (empty($single_type)) {
$single_type = $type;
} else if ($single_type != $type) {
+ // TODO: Recursive calls to _getMetadata()
throw new Horde_Imap_Client_Exception('Multiple value types may not be retrieved in one call when using ANNOTATEMORE.');
}
$result[] = $entry;
}
$entries = $result;
- } else {
- $cmd = 'GETMETADATA ';
-
- if (!empty($options['maxsize'])) {
- $cmd_options[] = '(MAXSIZE ' . $options['maxsize'] . ')';
- }
- if (!empty($options['depth'])) {
- $cmd_options[] = '(DEPTH ' . $options['depth'] . ')';
- }
}
- if (count($entries) == 1) {
- $entry_string = $this->utils->escape($entries[0]) . ' ' . $this->utils->escape($single_type);
+ if (count($cmd_options) == 1) {
+ $option_string = $cmd_options[0];
} else {
- $entry_string = '(' . join(' ', $entries) . ') ' . $single_type;
+ $option_string = '(' . join(' ', $cmd_options) . ')';
}
- if (count($cmd_options) == 0) {
- $option_string = ' ';
- } else if (count($cmd_options) == 1) {
- $option_string = ' ' . $cmd_options[0] . ' ';
- } else {
- $option_string = ' (' . join(' ', $cmd_options) . ') ';
+ $entry_string = (count($entries) == 1)
+ ? $this->utils->escape($entries[0]) . ' ' . $this->utils->escape($single_type)
+ : '(' . join(' ', $entries) . ') ' . $single_type;
+
+ $this->_sendLine($cmd . $this->utils->escape($mailbox) . ' ' . $option_string . ' ' . $entry_string);
+
+ if (!$use_rfc5464) {
+ // TODO: Honor maxsize and depth options.
}
- $this->_sendLine($cmd . $this->utils->escape($mailbox) . $option_string . $entry_string);
return $this->_temp['metadata'];
}
/**
+ * Split a name for the METADATA extension into the correct syntax for the
+ * older ANNOTATEMORE version.
+ *
+ * @param string $name A name for a metadata entry.
+ *
+ * @return array A list of two elements: The entry name and the value
+ * type.
+ * @throws Horde_Imap_Client_Exception
+ */
+ protected function _getAnnotateMoreEntry($name)
+ {
+ if (substr($name, 0, 7) == '/shared') {
+ return array(substr($name, 7), 'value.shared');
+ } else if (substr($name, 0, 8) == '/private') {
+ return array(substr($name, 8), 'value.priv');
+ }
+
+ throw new Horde_Imap_Client_Exception('Invalid METADATA entry: ' . $name);
+ }
+
+ /**
* Set metadata for a given mailbox/identifier.
*
- * @param string $mailbox A mailbox (UTF7-IMAP).
- * @param array $data A set of data values. The metadata values
- * corresponding to the keys of the array will
- * be set to the values in the array.
- * @param array $options Additional options.
+ * @param string $mailbox A mailbox (UTF7-IMAP).
+ * @param array $data A set of data values. The metadata values
+ * corresponding to the keys of the array will
+ * be set to the values in the array.
*
* @throws Horde_Imap_Client_Exception
*/
- protected function _setMetadata($mailbox, $data, $options)
+ protected function _setMetadata($mailbox, $data)
{
- if (!empty($options['annotatemore'])) {
- $cmd = 'SETANNOTATION ';
+ $data_elements = array();
+ $use_rfc5464 = false;
- $data_elements = array();
- foreach ($data as $md_entry => $value) {
- list($entry, $type) = $this->_getAnnotateMoreEntry($md_entry);
- $i_value = ($value === null) ? 'NIL' : $this->utils->escape($value);
- $data_elements[] = $this->utils->escape($entry) . ' (' . $this->utils->escape($type) . ' ' . $i_value . ')';
- }
- } else {
+ if ($this->queryCapability('METADATA') ||
+ ((strlen($mailbox) == 0) &&
+ $this->queryCapability('METADATA-SERVER'))) {
+ $use_rfc5464 = true;
+ } elseif (!$this->queryCapability('ANNOTATEMORE') &&
+ !$this->queryCapability('ANNOTATEMORE2')) {
+ throw new Horde_Imap_Client_Exception('Server does not support the METADATA extension.', Horde_Imap_Client_Exception::NOSUPPORTIMAPEXT);
+ }
+
+ if ($use_rfc5464) {
$cmd = 'SETMETADATA ';
foreach ($data as $key => $value) {
- $i_value = ($value === null) ? 'NIL' : $this->utils->escape($value);
+ $i_value = is_null($value)
+ ? 'NIL'
+ : $this->utils->escape($value);
$data_elements[] = $this->utils->escape($key) . ' ' . $i_value;
}
- }
-
- if (count($data_elements) == 1) {
- $data_string = $data_elements[0];
} else {
- $data_string = '(' . join(' ', $data_elements) . ')';
+ $cmd = 'SETANNOTATION ';
+
+ foreach ($data as $md_entry => $value) {
+ list($entry, $type) = $this->_getAnnotateMoreEntry($md_entry);
+ $i_value = is_null($value)
+ ? 'NIL'
+ : $this->utils->escape($value);
+ $data_elements[] = $this->utils->escape($entry) . ' (' . $this->utils->escape($type) . ' ' . $i_value . ')';
+ }
}
- /**
- * Disallow multi-line data for now.
- * @todo: Support this with sending literal data.
- */
+ $data_string = (count($data_elements) == 1)
+ ? $data_elements[0]
+ : '(' . join(' ', $data_elements) . ')';
+
+ /* Disallow multi-line data for now.
+ * @todo: Support this with sending literal data. */
$data_string = str_replace("\n", '', $data_string);
$this->_sendLine($cmd . $this->utils->escape($mailbox) . ' ' . $data_string);
* Parse a METADATA response (RFC 5464 [4.4]).
*
* @param array $data The server response.
+ *
+ * @throws Horde_Imap_Client_Exception
*/
protected function _parseMetadata($data)
{
case 'value.priv':
$this->_temp['metadata'][$data[1]]['/private' . $data[2]] = array_shift($values);
break;
+
case 'value.shared':
$this->_temp['metadata'][$data[1]]['/shared' . $data[2]] = array_shift($values);
break;
+
default:
throw new Horde_Imap_Client_Exception('Invalid METADATA value type ' . $type);
}
}
break;
+
case 'METADATA':
$values = $data[2];
while (!empty($values)) {
case 'ANNOTATION':
case 'METADATA':
- // Parse a ANNOTATEMORE/METADATA response (RFC 5464).
+ // Parse a ANNOTATEMORE/METADATA response.
$this->_parseMetadata($ob['token']);
break;
throw new Horde_Imap_Client_Exception('IMAP ACLs not supported on POP3 servers.', Horde_Imap_Client_Exception::POP3_NOTSUPPORTED);
}
+ /**
+ * Get metadata for a given mailbox.
+ *
+ * @param string $mailbox A mailbox (UTF7-IMAP).
+ * @param array $entries The entries to fetch.
+ * @param array $options Additional options.
+ *
+ * @return array An array with identifiers as the keys and the
+ * metadata as the values.
+ * @throws Horde_Imap_Client_Exception
+ */
+ protected function _getMetadata($mailbox, $entries, $options)
+ {
+ throw new Horde_Imap_Client_Exception('IMAP metadata not supported on POP3 servers.', Horde_Imap_Client_Exception::POP3_NOTSUPPORTED);
+ }
+
+ /**
+ * Set metadata for a given mailbox/identifier.
+ *
+ * @param string $mailbox A mailbox (UTF7-IMAP).
+ * @param array $data A set of data values. The metadata values
+ * corresponding to the keys of the array will
+ * be set to the values in the array.
+ *
+ * @throws Horde_Imap_Client_Exception
+ */
+ protected function _setMetadata($mailbox, $data)
+ {
+ throw new Horde_Imap_Client_Exception('IMAP metadata not supported on POP3 servers.', Horde_Imap_Client_Exception::POP3_NOTSUPPORTED);
+ }
+
/* Internal functions. */
/**
print "\nSet METADATA on " . $test_mbox . ".\n";
try {
- $imap_client->setMetadata($test_mbox,
- array('/shared/comment' => 'test'),
- array('annotatemore' => true,
- 'nocapability' => true));
+ $imap_client->setMetadata($test_mbox, array('/shared/comment' => 'test'));
print "Set Metadata: OK\n";
} catch (Horde_Imap_Client_Exception $e) {
print 'ERROR: ' . $e->getMessage() . "\n";
print "\nGet METADATA from " . $test_mbox . ".\n";
try {
- print_r($imap_client->getMetadata($test_mbox,
- '/shared/comment',
- array('annotatemore' => true,
- 'nocapability' => true)));
+ print_r($imap_client->getMetadata($test_mbox, '/shared/comment'));
print "Get Metadata: OK\n";
} catch (Horde_Imap_Client_Exception $e) {
print 'ERROR: ' . $e->getMessage() . "\n";