]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
imap: Restructure handling of the STATUS response so that it uses its own flags for...
authorStephan Bosch <stephan.bosch@dovecot.fi>
Mon, 27 Aug 2018 21:28:58 +0000 (23:28 +0200)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Thu, 6 Feb 2020 13:21:47 +0000 (13:21 +0000)
Before, it used mailbox status and metadata item flags for this purpose.
This is needed to allow the existing X-SIZE and the newly standardized SIZE flag to coexist.

src/imap/cmd-notify.c
src/imap/imap-notify.c
src/imap/imap-status.c
src/imap/imap-status.h

index d9ff27315b6671458d337c9e029ec4ed22afde6a..a378e39d72cb9211355bb350f48f2030a846280b 100644 (file)
@@ -429,11 +429,11 @@ imap_notify_box_send_status(struct client_command_context *cmd,
        i_zero(&items);
        i_zero(&result);
 
-       items.status = STATUS_UIDVALIDITY | STATUS_UIDNEXT |
-               STATUS_MESSAGES | STATUS_UNSEEN;
+       items.flags = IMAP_STATUS_ITEM_UIDVALIDITY | IMAP_STATUS_ITEM_UIDNEXT |
+               IMAP_STATUS_ITEM_MESSAGES | IMAP_STATUS_ITEM_UNSEEN;
        if ((ctx->global_used_events & (IMAP_NOTIFY_EVENT_FLAG_CHANGE |
                                        IMAP_NOTIFY_EVENT_ANNOTATION_CHANGE)) != 0)
-               items.status |= STATUS_HIGHESTMODSEQ;
+               items.flags |= IMAP_STATUS_ITEM_HIGHESTMODSEQ;
 
        box = mailbox_alloc(info->ns->list, info->vname, MAILBOX_FLAG_READONLY);
        mailbox_set_reason(box, "NOTIFY send STATUS");
index 13f8a4c805890182181b0a10c991aa51c6d44272..7f47aa40b233a104944b64c11b10d256171f3052 100644 (file)
@@ -52,25 +52,27 @@ static int imap_notify_status(struct imap_notify_namespace *notify_ns,
 
        i_zero(&items);
        if (client_has_enabled(client, imap_feature_condstore))
-               items.status |= STATUS_HIGHESTMODSEQ;
+               items.flags |= IMAP_STATUS_ITEM_HIGHESTMODSEQ;
 
        box = mailbox_alloc(notify_ns->ns->list, rec->vname, 0);
        mailbox_set_reason(box, "NOTIFY STATUS");
        if ((rec->events & MAILBOX_LIST_NOTIFY_UIDVALIDITY) != 0) {
-               items.status |= STATUS_UIDVALIDITY | STATUS_UIDNEXT |
-                       STATUS_MESSAGES | STATUS_UNSEEN;
+               items.flags |= IMAP_STATUS_ITEM_UIDVALIDITY |
+                       IMAP_STATUS_ITEM_UIDNEXT | IMAP_STATUS_ITEM_MESSAGES |
+                       IMAP_STATUS_ITEM_UNSEEN;
        }
        if ((rec->events & (MAILBOX_LIST_NOTIFY_APPENDS |
                            MAILBOX_LIST_NOTIFY_EXPUNGES)) != 0)
-               items.status |= STATUS_UIDNEXT | STATUS_MESSAGES | STATUS_UNSEEN;
+               items.flags |= IMAP_STATUS_ITEM_UIDNEXT |
+                       IMAP_STATUS_ITEM_MESSAGES | IMAP_STATUS_ITEM_UNSEEN;
        if ((rec->events & MAILBOX_LIST_NOTIFY_SEEN_CHANGES) != 0)
-               items.status |= STATUS_UNSEEN;
+               items.flags |= IMAP_STATUS_ITEM_UNSEEN;
        if ((rec->events & MAILBOX_LIST_NOTIFY_MODSEQ_CHANGES) != 0) {
                /* if HIGHESTMODSEQ isn't being sent, don't send anything */
        }
-       if (items.status == 0) {
+       if (imap_status_items_is_empty(&items)) {
                /* don't send anything */
-       } else if (mailbox_get_status(box, items.status, &result.status) < 0) {
+       } else if (imap_status_get_result(client, box, &items, &result) < 0) {
                /* hide permission errors from client. we don't want to leak
                   information about existence of mailboxes where user doesn't
                   have access to */
index 93a2b372f34c2428a16a08db276b61e14795e61d..4bdf3097446e4681bb12334a3cfde17458c7f30e 100644 (file)
@@ -10,9 +10,8 @@ int imap_status_parse_items(struct client_command_context *cmd,
                            const struct imap_arg *args,
                            struct imap_status_items *items_r)
 {
+       enum imap_status_item_flags flags = 0;
        const char *item;
-       enum mailbox_status_items status = 0;
-       enum mailbox_metadata_items metadata = 0;
 
        if (IMAP_ARG_IS_EOL(args)) {
                client_send_command_error(cmd, "Empty status list.");
@@ -30,21 +29,21 @@ int imap_status_parse_items(struct client_command_context *cmd,
 
                item = t_str_ucase(item);
                if (strcmp(item, "MESSAGES") == 0)
-                       status |= STATUS_MESSAGES;
+                       flags |= IMAP_STATUS_ITEM_MESSAGES;
                else if (strcmp(item, "RECENT") == 0)
-                       status |= STATUS_RECENT;
+                       flags |= IMAP_STATUS_ITEM_RECENT;
                else if (strcmp(item, "UIDNEXT") == 0)
-                       status |= STATUS_UIDNEXT;
+                       flags |= IMAP_STATUS_ITEM_UIDNEXT;
                else if (strcmp(item, "UIDVALIDITY") == 0)
-                       status |= STATUS_UIDVALIDITY;
+                       flags |= IMAP_STATUS_ITEM_UIDVALIDITY;
                else if (strcmp(item, "UNSEEN") == 0)
-                       status |= STATUS_UNSEEN;
+                       flags |= IMAP_STATUS_ITEM_UNSEEN;
                else if (strcmp(item, "HIGHESTMODSEQ") == 0)
-                       status |= STATUS_HIGHESTMODSEQ;
+                       flags |= IMAP_STATUS_ITEM_HIGHESTMODSEQ;
                else if (strcmp(item, "X-SIZE") == 0)
-                       metadata |= MAILBOX_METADATA_VIRTUAL_SIZE;
+                       flags |= IMAP_STATUS_ITEM_X_SIZE;
                else if (strcmp(item, "X-GUID") == 0)
-                       metadata |= MAILBOX_METADATA_GUID;
+                       flags |= IMAP_STATUS_ITEM_X_GUID;
                else {
                        client_send_command_error(cmd, t_strconcat(
                                "Invalid status item ", item, NULL));
@@ -52,11 +51,44 @@ int imap_status_parse_items(struct client_command_context *cmd,
                }
        }
 
-       items_r->status = status;
-       items_r->metadata = metadata;
+       items_r->flags = flags;
        return 0;
 }
 
+int imap_status_get_result(struct client *client, struct mailbox *box,
+                          const struct imap_status_items *items,
+                          struct imap_status_result *result_r)
+{
+       enum mailbox_status_items status = 0;
+       enum mailbox_metadata_items metadata = 0;
+       int ret;
+
+       if (HAS_ALL_BITS(items->flags, IMAP_STATUS_ITEM_MESSAGES))
+               status |= STATUS_MESSAGES;
+       if (HAS_ALL_BITS(items->flags, IMAP_STATUS_ITEM_RECENT))
+               status |= STATUS_RECENT;
+       if (HAS_ALL_BITS(items->flags, IMAP_STATUS_ITEM_UIDNEXT))
+               status |= STATUS_UIDNEXT;
+       if (HAS_ALL_BITS(items->flags, IMAP_STATUS_ITEM_UIDVALIDITY))
+               status |= STATUS_UIDVALIDITY;
+       if (HAS_ALL_BITS(items->flags, IMAP_STATUS_ITEM_UNSEEN))
+               status |= STATUS_UNSEEN;
+       if (HAS_ALL_BITS(items->flags, IMAP_STATUS_ITEM_HIGHESTMODSEQ)) {
+               client_enable(client, imap_feature_condstore);
+               status |= STATUS_HIGHESTMODSEQ;
+       }
+       if (HAS_ALL_BITS(items->flags, IMAP_STATUS_ITEM_X_SIZE))
+               metadata |= MAILBOX_METADATA_VIRTUAL_SIZE;
+       if (HAS_ALL_BITS(items->flags, IMAP_STATUS_ITEM_X_GUID))
+               metadata |= MAILBOX_METADATA_GUID;
+
+       ret = mailbox_get_status(box, status, &result_r->status);
+       if (metadata != 0 && ret == 0)
+               ret = mailbox_get_metadata(box, metadata, &result_r->metadata);
+
+       return ret;
+}
+
 int imap_status_get(struct client_command_context *cmd,
                    struct mail_namespace *ns, const char *mailbox,
                    const struct imap_status_items *items,
@@ -78,15 +110,7 @@ int imap_status_get(struct client_command_context *cmd,
                (void)mailbox_enable(box, client_enabled_mailbox_features(client));
        }
 
-       if ((items->status & STATUS_HIGHESTMODSEQ) != 0)
-               client_enable(client, imap_feature_condstore);
-
-       ret = mailbox_get_status(box, items->status, &result_r->status);
-       if (items->metadata != 0 && ret == 0) {
-               ret = mailbox_get_metadata(box, items->metadata,
-                                          &result_r->metadata);
-       }
-
+       ret = imap_status_get_result(client, box, items, result_r);
        if (ret < 0) {
                errstr = mailbox_get_last_error(box, &result_r->error);
                result_r->errstr = imap_get_error_string(cmd, errstr,
@@ -111,25 +135,25 @@ int imap_status_send(struct client *client, const char *mailbox_mutf7,
        str_append(str, " (");
 
        prefix_len = str_len(str);
-       if ((items->status & STATUS_MESSAGES) != 0)
+       if (HAS_ALL_BITS(items->flags, IMAP_STATUS_ITEM_MESSAGES))
                str_printfa(str, "MESSAGES %u ", status->messages);
-       if ((items->status & STATUS_RECENT) != 0)
+       if (HAS_ALL_BITS(items->flags, IMAP_STATUS_ITEM_RECENT))
                str_printfa(str, "RECENT %u ", status->recent);
-       if ((items->status & STATUS_UIDNEXT) != 0)
+       if (HAS_ALL_BITS(items->flags, IMAP_STATUS_ITEM_UIDNEXT))
                str_printfa(str, "UIDNEXT %u ", status->uidnext);
-       if ((items->status & STATUS_UIDVALIDITY) != 0)
+       if (HAS_ALL_BITS(items->flags, IMAP_STATUS_ITEM_UIDVALIDITY))
                str_printfa(str, "UIDVALIDITY %u ", status->uidvalidity);
-       if ((items->status & STATUS_UNSEEN) != 0)
+       if (HAS_ALL_BITS(items->flags, IMAP_STATUS_ITEM_UNSEEN))
                str_printfa(str, "UNSEEN %u ", status->unseen);
-       if ((items->status & STATUS_HIGHESTMODSEQ) != 0) {
+       if (HAS_ALL_BITS(items->flags, IMAP_STATUS_ITEM_HIGHESTMODSEQ)) {
                str_printfa(str, "HIGHESTMODSEQ %"PRIu64" ",
                            status->highest_modseq);
        }
-       if ((items->metadata & MAILBOX_METADATA_VIRTUAL_SIZE) != 0) {
+       if (HAS_ALL_BITS(items->flags, IMAP_STATUS_ITEM_X_SIZE)) {
                str_printfa(str, "X-SIZE %"PRIu64" ",
                            result->metadata.virtual_size);
        }
-       if ((items->metadata & MAILBOX_METADATA_GUID) != 0) {
+       if (HAS_ALL_BITS(items->flags, IMAP_STATUS_ITEM_X_GUID)) {
                str_printfa(str, "X-GUID %s ",
                            guid_128_to_string(result->metadata.guid));
        }
index fd54c68aa9c27d5bc1b2b590cb3cba6993731858..07ec8c487b8f0a7085ae7723c9beaabb447ce2c1 100644 (file)
@@ -1,9 +1,20 @@
 #ifndef IMAP_STATUS_H
 #define IMAP_STATUS_H
 
+enum imap_status_item_flags {
+       IMAP_STATUS_ITEM_MESSAGES = BIT(0),
+       IMAP_STATUS_ITEM_RECENT = BIT(1),
+       IMAP_STATUS_ITEM_UIDNEXT = BIT(2),
+       IMAP_STATUS_ITEM_UIDVALIDITY = BIT(3),
+       IMAP_STATUS_ITEM_UNSEEN = BIT(4),
+       IMAP_STATUS_ITEM_HIGHESTMODSEQ = BIT(5),
+
+       IMAP_STATUS_ITEM_X_SIZE = BIT(16),
+       IMAP_STATUS_ITEM_X_GUID = BIT(17),
+};
+
 struct imap_status_items {
-       enum mailbox_status_items status;
-       enum mailbox_metadata_items metadata;
+       enum imap_status_item_flags flags;
 };
 
 struct imap_status_result {
@@ -13,13 +24,24 @@ struct imap_status_result {
        const char *errstr;
 };
 
+static inline bool
+imap_status_items_is_empty(const struct imap_status_items *items)
+{
+       return (items->flags == 0);
+}
+
 int imap_status_parse_items(struct client_command_context *cmd,
                            const struct imap_arg *args,
                            struct imap_status_items *items_r);
+
+int imap_status_get_result(struct client *client, struct mailbox *box,
+                          const struct imap_status_items *items,
+                          struct imap_status_result *result_r);
 int imap_status_get(struct client_command_context *cmd,
                    struct mail_namespace *ns, const char *mailbox,
                    const struct imap_status_items *items,
                    struct imap_status_result *result_r);
+
 int imap_status_send(struct client *client, const char *mailbox_mutf7,
                     const struct imap_status_items *items,
                     const struct imap_status_result *result)