doveadm-mail-flags.c revision 2d83aa5eebd1bb710ca2fc21316b89442f027f3d
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Copyright (c) 2013-2016 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen#include "imap-util.h"
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen#include "mail-storage.h"
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen#include "doveadm-mailbox-list-iter.h"
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen#include "doveadm-mail-iter.h"
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen#include "doveadm-mail.h"
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen#include <stdio.h>
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainenstruct flags_cmd_context {
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen struct doveadm_mail_cmd_context ctx;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen enum modify_type modify_type;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen enum mail_flags flags;
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen const char *const *keywords;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen};
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainenstatic int
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainencmd_flags_run_box(struct flags_cmd_context *ctx,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct mailbox_info *info)
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen{
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen struct doveadm_mail_iter *iter;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen struct mailbox *box;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen struct mail *mail;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen struct mail_keywords *kw = NULL;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen if (doveadm_mail_iter_init(&ctx->ctx, info, ctx->ctx.search_args,
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen 0, NULL, &iter) < 0)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen return -1;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen box = doveadm_mail_iter_get_mailbox(iter);
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (ctx->keywords != NULL) {
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (mailbox_keywords_create(box, ctx->keywords, &kw) < 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_error("Invalid keywords: %s",
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen mailbox_get_last_error(box, NULL));
7c95b03620a03a43dd72d39608cea5fc77393ad6Timo Sirainen (void)doveadm_mail_iter_deinit(&iter);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen ctx->ctx.exit_code = DOVEADM_EX_NOTPOSSIBLE;
73e7998716853b5b7621c06aea0022dccda70ad1Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen while (doveadm_mail_iter_next(iter, &mail)) {
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen mail_update_flags(mail, ctx->modify_type, ctx->flags);
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen if (kw != NULL)
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen mail_update_keywords(mail, ctx->modify_type, kw);
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen }
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (kw != NULL)
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen mailbox_keywords_unref(&kw);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen return doveadm_mail_iter_deinit(&iter);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
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_append(&keywords, &str, 1);
}
}
if (array_count(&keywords) > 0 || ctx->modify_type == MODIFY_REPLACE) {
array_append_zero(&keywords);
ctx->keywords = array_idx(&keywords, 0);
}
_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
};