bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen#include "lib.h"
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen#include "imap-util.h"
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen#include "mail-storage.h"
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen#include "doveadm-mailbox-list-iter.h"
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen#include "doveadm-mail-iter.h"
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen#include "doveadm-mail.h"
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen#include <stdio.h>
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainenstruct flags_cmd_context {
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen struct doveadm_mail_cmd_context ctx;
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen enum modify_type modify_type;
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen enum mail_flags flags;
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen const char *const *keywords;
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen};
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainenstatic int
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainencmd_flags_run_box(struct flags_cmd_context *ctx,
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen const struct mailbox_info *info)
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen{
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen struct doveadm_mail_iter *iter;
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen struct mailbox *box;
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen struct mail *mail;
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen struct mail_keywords *kw = NULL;
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen
2dbb7b30d9bf6d6b0cd104c6931c4b44a77c2383Aki Tuomi if (doveadm_mail_iter_init(&ctx->ctx, info, ctx->ctx.search_args,
2dbb7b30d9bf6d6b0cd104c6931c4b44a77c2383Aki Tuomi 0, NULL, FALSE, &iter) < 0)
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen return -1;
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen box = doveadm_mail_iter_get_mailbox(iter);
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen if (ctx->keywords != NULL) {
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen if (mailbox_keywords_create(box, ctx->keywords, &kw) < 0) {
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen i_error("Invalid keywords: %s",
bf7dc750b95039981c0e9d728f313d50cf38a156Martti Rannanjärvi mailbox_get_last_internal_error(box, NULL));
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen (void)doveadm_mail_iter_deinit(&iter);
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen ctx->ctx.exit_code = DOVEADM_EX_NOTPOSSIBLE;
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen return -1;
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen }
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen }
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen while (doveadm_mail_iter_next(iter, &mail)) {
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen mail_update_flags(mail, ctx->modify_type, ctx->flags);
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen if (kw != NULL)
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen mail_update_keywords(mail, ctx->modify_type, kw);
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen }
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen if (kw != NULL)
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen mailbox_keywords_unref(&kw);
af2cc755b98e6e61e3167b0d5e69b7c88d8e6aa5Timo Sirainen return doveadm_mail_iter_deinit_sync(&iter);
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen}
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainenstatic int
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainencmd_flags_run(struct doveadm_mail_cmd_context *_ctx, struct mail_user *user)
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen{
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen struct flags_cmd_context *ctx = (struct flags_cmd_context *)_ctx;
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen const enum mailbox_list_iter_flags iter_flags =
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen MAILBOX_LIST_ITER_NO_AUTO_BOXES |
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen MAILBOX_LIST_ITER_RETURN_NO_FLAGS;
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen struct doveadm_mailbox_list_iter *iter;
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen const struct mailbox_info *info;
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen int ret = 0;
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen iter = doveadm_mailbox_list_iter_init(_ctx, user, _ctx->search_args,
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen iter_flags);
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen while ((info = doveadm_mailbox_list_iter_next(iter)) != NULL) T_BEGIN {
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen if (cmd_flags_run_box(ctx, info) < 0)
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen ret = -1;
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen } T_END;
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen if (doveadm_mailbox_list_iter_deinit(&iter) < 0)
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen ret = -1;
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen return ret;
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen}
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainenstatic void cmd_flags_init(struct doveadm_mail_cmd_context *_ctx,
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen const char *const args[])
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen{
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen struct flags_cmd_context *ctx = (struct flags_cmd_context *)_ctx;
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen const char *const *tmp;
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen enum mail_flags flag;
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen ARRAY_TYPE(const_string) keywords;
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen
209335fbc1a5fe68e662242ea91e236fdb2ba29dTimo Sirainen if (args[0] == NULL || args[1] == NULL) {
209335fbc1a5fe68e662242ea91e236fdb2ba29dTimo Sirainen switch (ctx->modify_type) {
209335fbc1a5fe68e662242ea91e236fdb2ba29dTimo Sirainen case MODIFY_ADD:
209335fbc1a5fe68e662242ea91e236fdb2ba29dTimo Sirainen doveadm_mail_help_name("flags add");
209335fbc1a5fe68e662242ea91e236fdb2ba29dTimo Sirainen case MODIFY_REMOVE:
209335fbc1a5fe68e662242ea91e236fdb2ba29dTimo Sirainen doveadm_mail_help_name("flags remove");
209335fbc1a5fe68e662242ea91e236fdb2ba29dTimo Sirainen case MODIFY_REPLACE:
209335fbc1a5fe68e662242ea91e236fdb2ba29dTimo Sirainen doveadm_mail_help_name("flags replace");
209335fbc1a5fe68e662242ea91e236fdb2ba29dTimo Sirainen }
209335fbc1a5fe68e662242ea91e236fdb2ba29dTimo Sirainen i_unreached();
209335fbc1a5fe68e662242ea91e236fdb2ba29dTimo Sirainen }
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen p_array_init(&keywords, _ctx->pool, 8);
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen for (tmp = t_strsplit(args[0], " "); *tmp != NULL; tmp++) {
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen const char *str = *tmp;
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen if (str[0] == '\\') {
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen flag = imap_parse_system_flag(str);
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen if (flag == 0)
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen i_fatal("Invalid system flag: %s", str);
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen ctx->flags |= flag;
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen } else {
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen str = p_strdup(_ctx->pool, str);
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen array_append(&keywords, &str, 1);
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen }
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen }
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen if (array_count(&keywords) > 0 || ctx->modify_type == MODIFY_REPLACE) {
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen array_append_zero(&keywords);
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen ctx->keywords = array_idx(&keywords, 0);
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen }
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen _ctx->search_args = doveadm_mail_build_search_args(args+1);
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen}
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainenstatic struct doveadm_mail_cmd_context *
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainencmd_flag_alloc(enum modify_type modify_type)
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen{
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen struct flags_cmd_context *ctx;
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen ctx = doveadm_mail_cmd_alloc(struct flags_cmd_context);
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen ctx->modify_type = modify_type;
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen ctx->ctx.v.init = cmd_flags_init;
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen ctx->ctx.v.run = cmd_flags_run;
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen return &ctx->ctx;
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen}
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainenstatic struct doveadm_mail_cmd_context *cmd_flags_add_alloc(void)
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen{
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen return cmd_flag_alloc(MODIFY_ADD);
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen}
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainenstatic struct doveadm_mail_cmd_context *cmd_flags_remove_alloc(void)
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen{
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen return cmd_flag_alloc(MODIFY_REMOVE);
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen}
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainenstatic struct doveadm_mail_cmd_context *cmd_flags_replace_alloc(void)
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen{
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen return cmd_flag_alloc(MODIFY_REPLACE);
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen}
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen
a893aaa999856b1ba6e4541890016767aaa283c7Aki Tuomistruct doveadm_cmd_ver2 doveadm_cmd_flags_add_ver2 = {
a893aaa999856b1ba6e4541890016767aaa283c7Aki Tuomi .name = "flags add",
a893aaa999856b1ba6e4541890016767aaa283c7Aki Tuomi .mail_cmd = cmd_flags_add_alloc,
a893aaa999856b1ba6e4541890016767aaa283c7Aki Tuomi .usage = DOVEADM_CMD_MAIL_USAGE_PREFIX "<flags> <search query>",
a893aaa999856b1ba6e4541890016767aaa283c7Aki TuomiDOVEADM_CMD_PARAMS_START
a893aaa999856b1ba6e4541890016767aaa283c7Aki TuomiDOVEADM_CMD_MAIL_COMMON
2d83aa5eebd1bb710ca2fc21316b89442f027f3dAki TuomiDOVEADM_CMD_PARAM('\0', "flag", CMD_PARAM_ARRAY, 0)
2d83aa5eebd1bb710ca2fc21316b89442f027f3dAki TuomiDOVEADM_CMD_PARAM('\0', "flagstr", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL|CMD_PARAM_FLAG_DO_NOT_EXPOSE)
a893aaa999856b1ba6e4541890016767aaa283c7Aki TuomiDOVEADM_CMD_PARAM('\0', "query", CMD_PARAM_ARRAY, CMD_PARAM_FLAG_POSITIONAL)
a893aaa999856b1ba6e4541890016767aaa283c7Aki TuomiDOVEADM_CMD_PARAMS_END
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen};
a893aaa999856b1ba6e4541890016767aaa283c7Aki Tuomi
a893aaa999856b1ba6e4541890016767aaa283c7Aki Tuomistruct doveadm_cmd_ver2 doveadm_cmd_flags_remove_ver2 = {
a893aaa999856b1ba6e4541890016767aaa283c7Aki Tuomi .name = "flags remove",
a893aaa999856b1ba6e4541890016767aaa283c7Aki Tuomi .mail_cmd = cmd_flags_remove_alloc,
a893aaa999856b1ba6e4541890016767aaa283c7Aki Tuomi .usage = DOVEADM_CMD_MAIL_USAGE_PREFIX "<flags> <search query>",
a893aaa999856b1ba6e4541890016767aaa283c7Aki TuomiDOVEADM_CMD_PARAMS_START
a893aaa999856b1ba6e4541890016767aaa283c7Aki TuomiDOVEADM_CMD_MAIL_COMMON
2d83aa5eebd1bb710ca2fc21316b89442f027f3dAki TuomiDOVEADM_CMD_PARAM('\0', "flag", CMD_PARAM_ARRAY, 0)
2d83aa5eebd1bb710ca2fc21316b89442f027f3dAki TuomiDOVEADM_CMD_PARAM('\0', "flagstr", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL|CMD_PARAM_FLAG_DO_NOT_EXPOSE)
a893aaa999856b1ba6e4541890016767aaa283c7Aki TuomiDOVEADM_CMD_PARAM('\0', "query", CMD_PARAM_ARRAY, CMD_PARAM_FLAG_POSITIONAL)
a893aaa999856b1ba6e4541890016767aaa283c7Aki TuomiDOVEADM_CMD_PARAMS_END
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen};
a893aaa999856b1ba6e4541890016767aaa283c7Aki Tuomi
a893aaa999856b1ba6e4541890016767aaa283c7Aki Tuomistruct doveadm_cmd_ver2 doveadm_cmd_flags_replace_ver2 = {
a893aaa999856b1ba6e4541890016767aaa283c7Aki Tuomi .name = "flags replace",
a893aaa999856b1ba6e4541890016767aaa283c7Aki Tuomi .mail_cmd = cmd_flags_replace_alloc,
a893aaa999856b1ba6e4541890016767aaa283c7Aki Tuomi .usage = DOVEADM_CMD_MAIL_USAGE_PREFIX "<flags> <search query>",
a893aaa999856b1ba6e4541890016767aaa283c7Aki TuomiDOVEADM_CMD_PARAMS_START
a893aaa999856b1ba6e4541890016767aaa283c7Aki TuomiDOVEADM_CMD_MAIL_COMMON
2d83aa5eebd1bb710ca2fc21316b89442f027f3dAki TuomiDOVEADM_CMD_PARAM('\0', "flag", CMD_PARAM_ARRAY, 0)
2d83aa5eebd1bb710ca2fc21316b89442f027f3dAki TuomiDOVEADM_CMD_PARAM('\0', "flagstr", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL|CMD_PARAM_FLAG_DO_NOT_EXPOSE)
a893aaa999856b1ba6e4541890016767aaa283c7Aki TuomiDOVEADM_CMD_PARAM('\0', "query", CMD_PARAM_ARRAY, CMD_PARAM_FLAG_POSITIONAL)
a893aaa999856b1ba6e4541890016767aaa283c7Aki TuomiDOVEADM_CMD_PARAMS_END
6eb7938cd366fc087b39fc9a901e7de426131384Timo Sirainen};