diff options
Diffstat (limited to 'src/doveadm/doveadm-mail-flags.c')
-rw-r--r-- | src/doveadm/doveadm-mail-flags.c | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/src/doveadm/doveadm-mail-flags.c b/src/doveadm/doveadm-mail-flags.c new file mode 100644 index 0000000..7c252a7 --- /dev/null +++ b/src/doveadm/doveadm-mail-flags.c @@ -0,0 +1,178 @@ +/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "imap-util.h" +#include "mail-storage.h" +#include "doveadm-mailbox-list-iter.h" +#include "doveadm-mail-iter.h" +#include "doveadm-mail.h" + +#include <stdio.h> + +struct flags_cmd_context { + struct doveadm_mail_cmd_context ctx; + enum modify_type modify_type; + enum mail_flags flags; + const char *const *keywords; +}; + +static int +cmd_flags_run_box(struct flags_cmd_context *ctx, + const struct mailbox_info *info) +{ + struct doveadm_mail_iter *iter; + struct mailbox *box; + struct mail *mail; + struct mail_keywords *kw = NULL; + + if (doveadm_mail_iter_init(&ctx->ctx, info, ctx->ctx.search_args, + 0, NULL, 0, &iter) < 0) + return -1; + box = doveadm_mail_iter_get_mailbox(iter); + + if (ctx->keywords != NULL) { + if (mailbox_keywords_create(box, ctx->keywords, &kw) < 0) { + i_error("Invalid keywords: %s", + mailbox_get_last_internal_error(box, NULL)); + (void)doveadm_mail_iter_deinit(&iter); + ctx->ctx.exit_code = DOVEADM_EX_NOTPOSSIBLE; + return -1; + } + } + + while (doveadm_mail_iter_next(iter, &mail)) { + mail_update_flags(mail, ctx->modify_type, ctx->flags); + if (kw != NULL) + mail_update_keywords(mail, ctx->modify_type, kw); + } + if (kw != NULL) + mailbox_keywords_unref(&kw); + return doveadm_mail_iter_deinit_sync(&iter); +} + +static int +cmd_flags_run(struct doveadm_mail_cmd_context *_ctx, struct mail_user *user) +{ + struct flags_cmd_context *ctx = (struct flags_cmd_context *)_ctx; + const enum mailbox_list_iter_flags iter_flags = + MAILBOX_LIST_ITER_NO_AUTO_BOXES | + MAILBOX_LIST_ITER_RETURN_NO_FLAGS; + struct doveadm_mailbox_list_iter *iter; + const struct mailbox_info *info; + int ret = 0; + + iter = doveadm_mailbox_list_iter_init(_ctx, user, _ctx->search_args, + iter_flags); + while ((info = doveadm_mailbox_list_iter_next(iter)) != NULL) T_BEGIN { + if (cmd_flags_run_box(ctx, info) < 0) + ret = -1; + } T_END; + if (doveadm_mailbox_list_iter_deinit(&iter) < 0) + ret = -1; + return ret; +} + +static void cmd_flags_init(struct doveadm_mail_cmd_context *_ctx, + const char *const args[]) +{ + struct flags_cmd_context *ctx = (struct flags_cmd_context *)_ctx; + const char *const *tmp; + enum mail_flags flag; + ARRAY_TYPE(const_string) keywords; + + if (args[0] == NULL || args[1] == NULL) { + switch (ctx->modify_type) { + case MODIFY_ADD: + doveadm_mail_help_name("flags add"); + case MODIFY_REMOVE: + doveadm_mail_help_name("flags remove"); + case MODIFY_REPLACE: + doveadm_mail_help_name("flags replace"); + } + i_unreached(); + } + + p_array_init(&keywords, _ctx->pool, 8); + for (tmp = t_strsplit(args[0], " "); *tmp != NULL; tmp++) { + const char *str = *tmp; + + if (str[0] == '\\') { + flag = imap_parse_system_flag(str); + if (flag == 0) + i_fatal("Invalid system flag: %s", str); + ctx->flags |= flag; + } else { + str = p_strdup(_ctx->pool, str); + array_push_back(&keywords, &str); + } + } + if (array_count(&keywords) > 0 || ctx->modify_type == MODIFY_REPLACE) { + array_append_zero(&keywords); + ctx->keywords = array_front(&keywords); + } + + _ctx->search_args = doveadm_mail_build_search_args(args+1); +} + +static struct doveadm_mail_cmd_context * +cmd_flag_alloc(enum modify_type modify_type) +{ + struct flags_cmd_context *ctx; + + ctx = doveadm_mail_cmd_alloc(struct flags_cmd_context); + ctx->modify_type = modify_type; + ctx->ctx.v.init = cmd_flags_init; + ctx->ctx.v.run = cmd_flags_run; + return &ctx->ctx; +} + +static struct doveadm_mail_cmd_context *cmd_flags_add_alloc(void) +{ + return cmd_flag_alloc(MODIFY_ADD); +} + +static struct doveadm_mail_cmd_context *cmd_flags_remove_alloc(void) +{ + return cmd_flag_alloc(MODIFY_REMOVE); +} + +static struct doveadm_mail_cmd_context *cmd_flags_replace_alloc(void) +{ + return cmd_flag_alloc(MODIFY_REPLACE); +} + +struct doveadm_cmd_ver2 doveadm_cmd_flags_add_ver2 = { + .name = "flags add", + .mail_cmd = cmd_flags_add_alloc, + .usage = DOVEADM_CMD_MAIL_USAGE_PREFIX "<flags> <search query>", +DOVEADM_CMD_PARAMS_START +DOVEADM_CMD_MAIL_COMMON +DOVEADM_CMD_PARAM('\0', "flag", CMD_PARAM_ARRAY, 0) +DOVEADM_CMD_PARAM('\0', "flagstr", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL|CMD_PARAM_FLAG_DO_NOT_EXPOSE) +DOVEADM_CMD_PARAM('\0', "query", CMD_PARAM_ARRAY, CMD_PARAM_FLAG_POSITIONAL) +DOVEADM_CMD_PARAMS_END +}; + +struct doveadm_cmd_ver2 doveadm_cmd_flags_remove_ver2 = { + .name = "flags remove", + .mail_cmd = cmd_flags_remove_alloc, + .usage = DOVEADM_CMD_MAIL_USAGE_PREFIX "<flags> <search query>", +DOVEADM_CMD_PARAMS_START +DOVEADM_CMD_MAIL_COMMON +DOVEADM_CMD_PARAM('\0', "flag", CMD_PARAM_ARRAY, 0) +DOVEADM_CMD_PARAM('\0', "flagstr", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL|CMD_PARAM_FLAG_DO_NOT_EXPOSE) +DOVEADM_CMD_PARAM('\0', "query", CMD_PARAM_ARRAY, CMD_PARAM_FLAG_POSITIONAL) +DOVEADM_CMD_PARAMS_END +}; + +struct doveadm_cmd_ver2 doveadm_cmd_flags_replace_ver2 = { + .name = "flags replace", + .mail_cmd = cmd_flags_replace_alloc, + .usage = DOVEADM_CMD_MAIL_USAGE_PREFIX "<flags> <search query>", +DOVEADM_CMD_PARAMS_START +DOVEADM_CMD_MAIL_COMMON +DOVEADM_CMD_PARAM('\0', "flag", CMD_PARAM_ARRAY, 0) +DOVEADM_CMD_PARAM('\0', "flagstr", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL|CMD_PARAM_FLAG_DO_NOT_EXPOSE) +DOVEADM_CMD_PARAM('\0', "query", CMD_PARAM_ARRAY, CMD_PARAM_FLAG_POSITIONAL) +DOVEADM_CMD_PARAMS_END +}; |