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