Browse Source

IMAP: Partial support for ANNOTATE-EXPERIMENT-1 extension (RFC 5257)

validate-url-parameter-for-upload-v1.6
Aleksander Machniak 8 months ago
parent
commit
b206cbc87a
  1. 1
      CHANGELOG.md
  2. 36
      program/lib/Roundcube/rcube_imap.php
  3. 84
      program/lib/Roundcube/rcube_imap_generic.php
  4. 7
      program/lib/Roundcube/rcube_message_header.php

1
CHANGELOG.md

@ -2,6 +2,7 @@
## Unreleased
- IMAP: Partial support for ANNOTATE-EXPERIMENT-1 extension (RFC 5257)
- OAuth: Support standard authentication with short-living password received with OIDC token (#9530)
- Fix PHP warnings (#9616, #9611)
- Fix whitespace handling in vCard line continuation (#9637)

36
program/lib/Roundcube/rcube_imap.php

@ -1302,7 +1302,7 @@ class rcube_imap extends rcube_storage
else {
// fetch requested headers from server
$headers = $this->conn->fetchHeaders(
$folder, $msgs, true, false, $this->get_fetch_headers());
$folder, $msgs, true, false, $this->get_fetch_headers(), $this->get_fetch_items());
}
if (empty($headers)) {
@ -1892,7 +1892,7 @@ class rcube_imap extends rcube_storage
}
else {
$headers = $this->conn->fetchHeader(
$folder, $uid, true, true, $this->get_fetch_headers());
$folder, $uid, true, true, $this->get_fetch_headers(), $this->get_fetch_items());
if (is_object($headers)) {
$headers->folder = $folder;
@ -2884,6 +2884,29 @@ class rcube_imap extends rcube_storage
return $result;
}
/**
* Annotate a message.
*
* @param array $annotation Message annotation key-value array
* @param mixed $uids Message UIDs as array or comma-separated string, or '*'
* @param string $folder Folder name
*
* @return bool True on success, False on failure
*/
public function annotate_message($annotation, $uids, $folder = null)
{
[$uids] = $this->parse_uids($uids);
if (!is_string($folder) || !strlen($folder)) {
$folder = $this->folder;
}
if (!$this->check_connection()) {
return false;
}
return $this->conn->storeMessageAnnotation($folder, $uids, $annotation);
}
/* --------------------------------
* folder management
@ -3922,6 +3945,15 @@ class rcube_imap extends rcube_storage
return $headers;
}
/**
* Get additional FETCH items for rcube_imap_generic::fetchHeader(s)
*
* @return array List of items
*/
protected function get_fetch_items()
{
return $this->options['fetch_items'] ?? [];
}
/* -----------------------------------------
* ACL and METADATA/ANNOTATEMORE methods

84
program/lib/Roundcube/rcube_imap_generic.php

@ -2520,6 +2520,7 @@ class rcube_imap_generic
$result[$id]->id = $id;
$result[$id]->subject = '';
$result[$id]->messageID = 'mid:' . $id;
$result[$id]->folder = $mailbox;
$headers = null;
$line = substr($line, strlen($m[0]) + 2);
@ -2551,6 +2552,21 @@ class rcube_imap_generic
}
}
}
else if ($name == 'ANNOTATION') {
$result[$id]->annotations = [];
if (!empty($value) && is_array($value)) {
$n = 0;
while (!empty($value[$n]) && is_string($value[$n])) {
$name = $value[$n++];
$list = $value[$n++];
$result[$id]->annotations[$name] = [];
$c = 0;
while (!empty($list[$c]) && is_string($list[$c])) {
$result[$id]->annotations[$name][$list[$c++]] = $list[$c++];
}
}
}
}
else if ($name == 'MODSEQ') {
$result[$id]->modseq = $value[0];
}
@ -2686,14 +2702,15 @@ class rcube_imap_generic
* @param mixed $message_set Message(s) sequence identifier(s) or UID(s)
* @param bool $is_uid True if $message_set contains UIDs
* @param bool $bodystr Enable to add BODYSTRUCTURE data to the result
* @param array $add_headers List of additional headers
* @param array $add_headers List of additional headers to fetch
* @param array $query_items List of additional items to fetch
*
* @return bool|array List of rcube_message_header elements, False on error
*/
public function fetchHeaders($mailbox, $message_set, $is_uid = false, $bodystr = false, $add_headers = [])
public function fetchHeaders($mailbox, $message_set, $is_uid = false, $bodystr = false, $add_headers = [], $query_items = [])
{
$query_items = ['UID', 'RFC822.SIZE', 'FLAGS', 'INTERNALDATE'];
$headers = ['DATE', 'FROM', 'TO', 'SUBJECT', 'CONTENT-TYPE', 'CC', 'REPLY-TO',
$query_items = array_unique(array_merge($query_items, ['UID', 'RFC822.SIZE', 'FLAGS', 'INTERNALDATE']));
$headers = ['DATE', 'FROM', 'TO', 'SUBJECT', 'CONTENT-TYPE', 'CC', 'REPLY-TO',
'LIST-POST', 'DISPOSITION-NOTIFICATION-TO', 'X-PRIORITY'];
if (!empty($add_headers)) {
@ -2718,12 +2735,13 @@ class rcube_imap_generic
* @param bool $is_uid True if $id is an UID
* @param bool $bodystr Enable to add BODYSTRUCTURE data to the result
* @param array $add_headers List of additional headers
* @param array $query_items List of additional items to fetch
*
* @return bool|rcube_message_header Message data, False on error
*/
public function fetchHeader($mailbox, $id, $is_uid = false, $bodystr = false, $add_headers = [])
public function fetchHeader($mailbox, $id, $is_uid = false, $bodystr = false, $add_headers = [], $query_items = [])
{
$a = $this->fetchHeaders($mailbox, $id, $is_uid, $bodystr, $add_headers);
$a = $this->fetchHeaders($mailbox, $id, $is_uid, $bodystr, $add_headers, $query_items);
if (is_array($a)) {
return array_first($a);
@ -3751,6 +3769,60 @@ class rcube_imap_generic
}
}
/**
* Send the STORE X ANNOTATION command (RFC5257)
*
* @param string $mailbox Mailbox name
* @param array $entries
*
* @return bool True on success, False on failure
*
* @since 1.6.10
*/
public function storeMessageAnnotation($mailbox, $uids, $entries)
{
if (!$this->hasCapability('ANNOTATE-EXPERIMENT-1')) {
return false;
}
if (empty($entries) || empty($uids)) {
$this->setError(self::ERROR_COMMAND, 'Wrong argument for STORE ANNOTATION command');
return false;
}
if (!$this->select($mailbox)) {
return false;
}
/* Example input compatible with rcube_message_header::$annotations:
$entries = [
'/comment' => [
'value.priv' => 'test1',
'value.shared' => null,
],
];
*/
$request = [];
foreach ($entries as $name => $annotation) {
if (!empty($annotation)) {
foreach ($annotation as $key => $value) {
$annotation[$key] = $this->escape($key) . ' ' . $this->escape($value, true);
}
$request[] = $this->escape($name);
$request[] = $annotation;
}
}
$result = $this->execute(
'UID STORE',
[$this->compressMessageSet($uids), 'ANNOTATION', $request],
self::COMMAND_NORESPONSE
);
return $result == self::ERROR_OK;
}
/**
* Returns BODYSTRUCTURE for the specified message.
*

7
program/lib/Roundcube/rcube_message_header.php

@ -208,6 +208,13 @@ class rcube_message_header
*/
public $flags = [];
/**
* Message annotations (RFC 5257)
*
* @var ?array
*/
public $annotations;
/**
* Extra flags (for the messages list)
*

Loading…
Cancel
Save