dovecot-2.2: imap: Allow wildcards in GETMETADATA mailbox-name.
dovecot at dovecot.org
dovecot at dovecot.org
Thu Dec 19 23:08:10 EET 2013
details: http://hg.dovecot.org/dovecot-2.2/rev/0c3071ebe44b
changeset: 17077:0c3071ebe44b
user: Timo Sirainen <tss at iki.fi>
date: Thu Dec 19 23:08:03 2013 +0200
description:
imap: Allow wildcards in GETMETADATA mailbox-name.
RFC 5464 doesn't specify this, but its earlier draft did, and Kolab uses it.
diffstat:
src/imap/cmd-getmetadata.c | 122 ++++++++++++++++++++++++++++++++------------
1 files changed, 89 insertions(+), 33 deletions(-)
diffs (172 lines):
diff -r f64810b00b7f -r 0c3071ebe44b src/imap/cmd-getmetadata.c
--- a/src/imap/cmd-getmetadata.c Thu Dec 19 23:07:15 2013 +0200
+++ b/src/imap/cmd-getmetadata.c Thu Dec 19 23:08:03 2013 +0200
@@ -4,6 +4,7 @@
#include "str.h"
#include "istream.h"
#include "ostream.h"
+#include "mailbox-list-iter.h"
#include "imap-quote.h"
#include "imap-metadata.h"
@@ -12,6 +13,7 @@
struct mailbox *box;
struct mailbox_transaction_context *trans;
+ struct mailbox_list_iterate_context *list_iter;
ARRAY_TYPE(const_string) entries;
uint32_t maxsize;
@@ -30,6 +32,8 @@
bool failed;
};
+static bool cmd_getmetadata_iter_next(struct imap_getmetadata_context *ctx);
+
static bool
cmd_getmetadata_parse_options(struct imap_getmetadata_context *ctx,
const struct imap_arg *options)
@@ -267,14 +271,37 @@
}
}
+static void cmd_getmetadata_mailbox_deinit(struct imap_getmetadata_context *ctx)
+{
+ if (ctx->iter != NULL)
+ (void)mailbox_attribute_iter_deinit(&ctx->iter);
+ if (ctx->box != NULL) {
+ (void)mailbox_transaction_commit(&ctx->trans);
+ mailbox_free(&ctx->box);
+ }
+ ctx->first_entry_sent = FALSE;
+ ctx->entry_idx = 0;
+}
+
static void cmd_getmetadata_deinit(struct imap_getmetadata_context *ctx)
{
- ctx->cmd->client->output_cmd_lock = NULL;
+ struct client_command_context *cmd = ctx->cmd;
- if (ctx->iter != NULL)
- (void)mailbox_attribute_iter_deinit(&ctx->iter);
- (void)mailbox_transaction_commit(&ctx->trans);
- mailbox_free(&ctx->box);
+ cmd_getmetadata_mailbox_deinit(ctx);
+ cmd->client->output_cmd_lock = NULL;
+
+ if (ctx->list_iter != NULL &&
+ mailbox_list_iter_deinit(&ctx->list_iter) < 0)
+ client_send_list_error(cmd, cmd->client->user->namespaces->list);
+ else if (ctx->failed) {
+ client_send_tagline(cmd, "NO Getmetadata failed to send some entries");
+ } else if (ctx->largest_seen_size != 0) {
+ client_send_tagline(cmd, t_strdup_printf(
+ "OK [METADATA LONGENTRIES %"PRIuUOFF_T"] "
+ "Getmetadata completed.", ctx->largest_seen_size));
+ } else {
+ client_send_tagline(cmd, "OK Getmetadata completed.");
+ }
}
static bool cmd_getmetadata_continue(struct client_command_context *cmd)
@@ -308,14 +335,47 @@
if (ctx->first_entry_sent)
o_stream_nsend_str(cmd->client->output, ")\r\n");
- if (ctx->failed) {
- client_send_tagline(cmd, "NO Getmetadata failed to send some entries");
- } else if (ctx->largest_seen_size != 0) {
- client_send_tagline(cmd, t_strdup_printf(
- "OK [METADATA LONGENTRIES %"PRIuUOFF_T"] "
- "Getmetadata completed.", ctx->largest_seen_size));
- } else {
- client_send_tagline(cmd, "OK Getmetadata completed.");
+ cmd_getmetadata_mailbox_deinit(ctx);
+ if (ctx->list_iter != NULL)
+ return cmd_getmetadata_iter_next(ctx);
+ cmd_getmetadata_deinit(ctx);
+ return TRUE;
+}
+
+static bool
+cmd_getmetadata_mailbox(struct imap_getmetadata_context *ctx,
+ struct mail_namespace *ns, const char *mailbox)
+{
+ struct client_command_context *cmd = ctx->cmd;
+
+ ctx->box = mailbox_alloc(ns->list, mailbox, MAILBOX_FLAG_READONLY);
+ if (mailbox_open(ctx->box) < 0) {
+ client_send_box_error(cmd, ctx->box);
+ mailbox_free(&ctx->box);
+ return TRUE;
+ }
+ ctx->trans = mailbox_transaction_begin(ctx->box, 0);
+
+ if (ctx->depth > 0)
+ ctx->iter_entry_prefix = str_new(cmd->pool, 128);
+
+ if (!cmd_getmetadata_continue(cmd)) {
+ cmd->state = CLIENT_COMMAND_STATE_WAIT_OUTPUT;
+ cmd->func = cmd_getmetadata_continue;
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static bool cmd_getmetadata_iter_next(struct imap_getmetadata_context *ctx)
+{
+ const struct mailbox_info *info;
+
+ while ((info = mailbox_list_iter_next(ctx->list_iter)) != NULL) {
+ if ((info->flags & (MAILBOX_NOSELECT | MAILBOX_NONEXISTENT)) != 0)
+ continue;
+ /* we'll get back here recursively */
+ return cmd_getmetadata_mailbox(ctx, info->ns, info->vname);
}
cmd_getmetadata_deinit(ctx);
return TRUE;
@@ -365,28 +425,24 @@
/* server attribute */
ctx->key_prefix = MAILBOX_ATTRIBUTE_PREFIX_DOVECOT_PVT_SERVER;
ns = mail_namespace_find_inbox(cmd->client->user->namespaces);
- mailbox = "INBOX";
- } else {
+ return cmd_getmetadata_mailbox(ctx, ns, "INBOX");
+ } else if (strchr(mailbox, '*') == NULL &&
+ strchr(mailbox, '%') == NULL) {
ns = client_find_namespace(cmd, &mailbox);
if (ns == NULL)
return TRUE;
+ return cmd_getmetadata_mailbox(ctx, ns, mailbox);
+ } else {
+ /* wildcards in mailbox name. this isn't supported by RFC 5464,
+ but it was in the earlier drafts and is already used by
+ some software (Kolab). */
+ const char *patterns[2];
+ patterns[0] = mailbox; patterns[1] = NULL;
+
+ ctx->list_iter =
+ mailbox_list_iter_init_namespaces(
+ cmd->client->user->namespaces,
+ patterns, MAIL_NAMESPACE_TYPE_MASK_ALL, 0);
+ return cmd_getmetadata_iter_next(ctx);
}
-
- ctx->box = mailbox_alloc(ns->list, mailbox, MAILBOX_FLAG_READONLY);
- if (mailbox_open(ctx->box) < 0) {
- client_send_box_error(cmd, ctx->box);
- mailbox_free(&ctx->box);
- return TRUE;
- }
- ctx->trans = mailbox_transaction_begin(ctx->box, 0);
-
- if (ctx->depth > 0)
- ctx->iter_entry_prefix = str_new(cmd->pool, 128);
-
- if (!cmd_getmetadata_continue(cmd)) {
- cmd->state = CLIENT_COMMAND_STATE_WAIT_OUTPUT;
- cmd->func = cmd_getmetadata_continue;
- return FALSE;
- }
- return TRUE;
}
More information about the dovecot-cvs
mailing list