#include "str.h"
#include "istream.h"
#include "ostream.h"
+#include "mailbox-list-iter.h"
#include "imap-quote.h"
#include "imap-metadata.h"
struct mailbox *box;
struct mailbox_transaction_context *trans;
+ struct mailbox_list_iterate_context *list_iter;
ARRAY_TYPE(const_string) entries;
uint32_t maxsize;
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)
}
}
-static void cmd_getmetadata_deinit(struct imap_getmetadata_context *ctx)
+static void cmd_getmetadata_mailbox_deinit(struct imap_getmetadata_context *ctx)
{
- ctx->cmd->client->output_cmd_lock = NULL;
-
if (ctx->iter != NULL)
(void)mailbox_attribute_iter_deinit(&ctx->iter);
- (void)mailbox_transaction_commit(&ctx->trans);
- mailbox_free(&ctx->box);
+ 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)
+{
+ struct client_command_context *cmd = ctx->cmd;
+
+ 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)
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;
/* 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;
}