1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
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
};
|