File 0001-Correctly-proxy-GETMETADATA-with-DEPTH-0.patch of Package cyrus-imapd-3
From 572a42859211d810af65fb4e40962115831b21fa Mon Sep 17 00:00:00 2001
From: Christian Mollekopf <mollekopf@apheleia-it.ch>
Date: Thu, 7 Sep 2023 22:04:38 +0200
Subject: [PATCH] Correctly proxy GETMETADATA with DEPTH != 0
Not that the backend handles DEPTH infinity correctly, but we try.
---
imap/imap_proxy.c | 40 ++++++++++++++++++++++++++++++++++------
1 file changed, 34 insertions(+), 6 deletions(-)
diff --git a/imap/imap_proxy.c b/imap/imap_proxy.c
index 7d6dc4335..aca1ab4df 100644
--- a/imap/imap_proxy.c
+++ b/imap/imap_proxy.c
@@ -1409,7 +1409,7 @@ int annotate_fetch_proxy(const char *server, const char *mbox_pat,
const strarray_t *attribute_pat)
{
struct backend *be;
- int i;
+ int i, increment;
char mytag[128];
assert(server && mbox_pat && entry_pat && attribute_pat);
@@ -1421,15 +1421,43 @@ int annotate_fetch_proxy(const char *server, const char *mbox_pat,
/* Send command to remote */
proxy_gentag(mytag, sizeof(mytag));
- prot_printf(be->out, "%s GETMETADATA \"%s\" (", mytag, mbox_pat);
+ prot_printf(be->out, "%s GETMETADATA (", mytag);
+
+ //For depth infinity/1 we get an extra entry (per pattern), with a suffix we can check (* for infinity, % for 1).
+ // entry /vendor/kolab/folder-type
+ // entry /vendor/kolab/folder-type/*
+ //
+ // We only check the first, because there is just one depth in GETMETADATA
+ // FIXME: we completely ignore other options
+ if (entry_pat->count == attribute_pat->count) {
+ prot_printf(be->out, "DEPTH 0) \"%s\" (", mbox_pat);
+ } else if (entry_pat->count > 1) {
+ const char *entry = strarray_nth(entry_pat, 1);
+ const char suffix = entry[strlen(entry) - 1];
+ if (suffix == '%') {
+ prot_printf(be->out, "DEPTH 1) \"%s\" (", mbox_pat);
+ } else if (suffix == '*') {
+ prot_printf(be->out, "DEPTH infinity) \"%s\" (", mbox_pat);
+ } else {
+ syslog(LOG_ERR, "Unknown entry suffix %s %c", entry, suffix);
+ return IMAP_INTERNAL;
+ }
+ }
- if (entry_pat->count != attribute_pat->count) {
- syslog(LOG_ERR, "Number of scopes and entries must match");
+ //With DEPTH 0, we get one entry pattern. With DEPTH infinity an extra pattern with /*, and with DEPTH 1 and extra pattern of /%
+ if (entry_pat->count == attribute_pat->count) {
+ increment = 1;
+ } else {
+ increment = 2;
+ }
+ //The count matches if depth = 0, otherwise we have twice the number of entries.
+ if ((entry_pat->count / increment) != attribute_pat->count) {
+ syslog(LOG_ERR, "Number of scopes and entries must match %i %i", entry_pat->count, attribute_pat->count);
return IMAP_INTERNAL;
}
- for (i = 0; i < entry_pat->count; i++) {
- const char *entry = strarray_nth(entry_pat, i);
+ for (i = 0; (i * increment) < entry_pat->count; i++) {
+ const char *entry = strarray_nth(entry_pat, i * increment);
const char *scope, *attr = strarray_nth(attribute_pat, i);
if (!strcmp(attr, "value.shared")) {
scope = "/shared";
--
2.41.0