11
11
#include "sieve-extensions.h"
12
12
#include "sieve-commands.h"
13
13
#include "sieve-result.h"
14
#include "sieve-validator.h"
14
#include "sieve-validator.h"
15
15
#include "sieve-generator.h"
16
16
#include "sieve-interpreter.h"
17
17
#include "sieve-actions.h"
25
25
* Flags tagged argument
28
28
static bool tag_flags_validate
29
(struct sieve_validator *valdtr, struct sieve_ast_argument **arg,
29
(struct sieve_validator *valdtr, struct sieve_ast_argument **arg,
30
30
struct sieve_command *cmd);
31
31
static bool tag_flags_validate_persistent
32
32
(struct sieve_validator *valdtr, struct sieve_command *cmd,
35
35
(const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg,
36
36
struct sieve_command *cmd);
38
const struct sieve_argument_def tag_flags = {
38
const struct sieve_argument_def tag_flags = {
46
const struct sieve_argument_def tag_flags_implicit = {
49
tag_flags_validate_persistent,
46
const struct sieve_argument_def tag_flags_implicit = {
49
tag_flags_validate_persistent,
57
57
static bool seff_flags_dump_context
58
58
(const struct sieve_side_effect *seffect,
59
59
const struct sieve_dumptime_env *denv, sieve_size_t *address);
60
60
static int seff_flags_read_context
61
(const struct sieve_side_effect *seffect,
61
(const struct sieve_side_effect *seffect,
62
62
const struct sieve_runtime_env *renv, sieve_size_t *address,
65
65
static int seff_flags_merge
66
(const struct sieve_runtime_env *renv, const struct sieve_action *action,
67
const struct sieve_side_effect *old_seffect,
66
(const struct sieve_runtime_env *renv, const struct sieve_action *action,
67
const struct sieve_side_effect *old_seffect,
68
68
const struct sieve_side_effect *new_seffect, void **old_context);
70
70
static void seff_flags_print
71
71
(const struct sieve_side_effect *seffect, const struct sieve_action *action,
72
72
const struct sieve_result_print_env *rpenv, bool *keep);
73
static bool seff_flags_pre_execute
74
(const struct sieve_side_effect *seffect, const struct sieve_action *action,
73
static int seff_flags_pre_execute
74
(const struct sieve_side_effect *seffect, const struct sieve_action *action,
75
75
const struct sieve_action_exec_env *aenv, void **context, void *tr_context);
77
77
const struct sieve_side_effect_def flags_side_effect = {
93
93
static const struct sieve_extension_objects ext_side_effects =
94
94
SIEVE_EXT_DEFINE_SIDE_EFFECT(flags_side_effect);
96
const struct sieve_operand_def flags_side_effect_operand = {
96
const struct sieve_operand_def flags_side_effect_operand = {
98
98
&imap4flags_extension,
100
100
&sieve_side_effect_operand_class,
101
101
&ext_side_effects
108
108
static bool tag_flags_validate_persistent
112
112
if ( sieve_command_find_argument(cmd, &tag_flags) == NULL ) {
113
113
sieve_command_add_dynamic_tag(cmd, ext, &tag_flags_implicit, -1);
119
119
static bool tag_flags_validate
120
(struct sieve_validator *valdtr, struct sieve_ast_argument **arg,
120
(struct sieve_validator *valdtr, struct sieve_ast_argument **arg,
121
121
struct sieve_command *cmd)
123
123
struct sieve_ast_argument *tag = *arg;
125
125
/* Detach the tag itself */
126
126
*arg = sieve_ast_argument_next(*arg);
129
129
* :flags <list-of-flags: string-list>
132
132
(valdtr, cmd, tag, *arg, NULL, 0, SAAT_STRING_LIST, FALSE) ) {
136
136
tag->parameters = *arg;
138
138
/* Detach parameter */
139
139
*arg = sieve_ast_arguments_detach(*arg,1);
148
148
static bool tag_flags_generate
162
162
/* Explicit :flags tag */
163
163
param = arg->parameters;
165
/* Call the generation function for the argument */
166
if ( param->argument != NULL && param->argument->def != NULL &&
167
param->argument->def->generate != NULL &&
168
!param->argument->def->generate(cgenv, param, cmd) )
165
/* Call the generation function for the argument */
166
if ( param->argument != NULL && param->argument->def != NULL &&
167
param->argument->def->generate != NULL &&
168
!param->argument->def->generate(cgenv, param, cmd) )
171
171
} else if ( sieve_argument_is(arg, tag_flags_implicit) ) {
172
172
/* Implicit flags */
173
173
sieve_opr_omitted_emit(cgenv->sblock);
176
176
/* Something else?! */
184
184
* Side effect implementation
187
187
/* Context data */
189
189
struct seff_flags_context {
190
ARRAY_DEFINE(keywords, const char *);
190
ARRAY(const char *) keywords;
191
191
enum mail_flags flags;
194
194
/* Context coding */
196
196
static bool seff_flags_dump_context
197
(const struct sieve_side_effect *seffect ATTR_UNUSED,
197
(const struct sieve_side_effect *seffect ATTR_UNUSED,
198
198
const struct sieve_dumptime_env *denv, sieve_size_t *address)
200
200
return sieve_opr_stringlist_dump_ex(denv, address, "flags", "INTERNAL");
207
207
struct seff_flags_context *ctx;
208
208
const char *flag;
209
209
struct ext_imap4flags_iter flit;
211
211
ctx = p_new(pool, struct seff_flags_context, 1);
212
212
p_array_init(&ctx->keywords, pool, 2);
217
217
ext_imap4flags_get_implicit_flags_init(&flit, this_ext, result);
218
while ( (flag=ext_imap4flags_iter_get_flag(&flit)) != NULL ) {
218
while ( (flag=ext_imap4flags_iter_get_flag(&flit)) != NULL ) {
219
219
if (flag != NULL && *flag != '\\') {
221
221
const char *keyword = p_strdup(pool, flag);
243
243
static int seff_flags_do_read_context
244
(const struct sieve_side_effect *seffect,
244
(const struct sieve_side_effect *seffect,
245
245
const struct sieve_runtime_env *renv, sieve_size_t *address,
246
246
void **se_context)
249
249
struct seff_flags_context *ctx;
250
250
string_t *flags_item;
251
251
struct sieve_stringlist *flag_list = NULL;
254
254
if ( (ret=sieve_opr_stringlist_read_ex
255
255
(renv, address, "flags", TRUE, &flag_list)) <= 0 )
258
258
if ( flag_list == NULL ) {
259
/* Flag list is omitted, use current value of internal
259
/* Flag list is omitted, use current value of internal
260
260
* variable to construct side effect context.
262
262
*se_context = seff_flags_get_implicit_context
263
263
(SIEVE_OBJECT_EXTENSION(seffect), renv->result);
264
264
return SIEVE_EXEC_OK;
267
267
ctx = p_new(pool, struct seff_flags_context, 1);
268
268
p_array_init(&ctx->keywords, pool, 2);
274
274
struct ext_imap4flags_iter flit;
276
276
ext_imap4flags_iter_init(&flit, flags_item);
278
while ( (flag=ext_imap4flags_iter_get_flag(&flit)) != NULL ) {
278
while ( (flag=ext_imap4flags_iter_get_flag(&flit)) != NULL ) {
279
279
if (flag != NULL && *flag != '\\') {
281
281
const char *keyword = p_strdup(pool, flag);
303
303
return flag_list->exec_status;
305
305
*se_context = (void *) ctx;
307
307
return SIEVE_EXEC_OK;
310
310
static int seff_flags_read_context
311
(const struct sieve_side_effect *seffect,
311
(const struct sieve_side_effect *seffect,
312
312
const struct sieve_runtime_env *renv, sieve_size_t *address,
313
313
void **se_context)
324
324
/* Result verification */
326
326
static int seff_flags_merge
327
(const struct sieve_runtime_env *renv ATTR_UNUSED,
328
const struct sieve_action *action ATTR_UNUSED,
329
const struct sieve_side_effect *old_seffect ATTR_UNUSED,
330
const struct sieve_side_effect *new_seffect,
327
(const struct sieve_runtime_env *renv ATTR_UNUSED,
328
const struct sieve_action *action ATTR_UNUSED,
329
const struct sieve_side_effect *old_seffect ATTR_UNUSED,
330
const struct sieve_side_effect *new_seffect,
331
331
void **old_context)
333
333
if ( new_seffect != NULL )
334
334
*old_context = new_seffect->context;
339
339
/* Result printing */
341
341
static void seff_flags_print
342
(const struct sieve_side_effect *seffect,
343
const struct sieve_action *action ATTR_UNUSED,
342
(const struct sieve_side_effect *seffect,
343
const struct sieve_action *action ATTR_UNUSED,
344
344
const struct sieve_result_print_env *rpenv,bool *keep ATTR_UNUSED)
346
346
struct sieve_result *result = rpenv->result;
347
struct seff_flags_context *ctx =
347
struct seff_flags_context *ctx =
348
348
(struct seff_flags_context *) seffect->context;
351
351
if ( ctx == NULL )
352
352
ctx = seff_flags_get_implicit_context
353
353
(SIEVE_OBJECT_EXTENSION(seffect), result);
355
355
if ( ctx->flags != 0 || array_count(&ctx->keywords) > 0 ) {
357
357
string_t *flags = t_str_new(128);
359
359
if ( (ctx->flags & MAIL_FLAGGED) > 0 )
360
360
str_printfa(flags, " \\flagged");
362
362
if ( (ctx->flags & MAIL_ANSWERED) > 0 )
363
363
str_printfa(flags, " \\answered");
365
365
if ( (ctx->flags & MAIL_DELETED) > 0 )
366
366
str_printfa(flags, " \\deleted");
368
368
if ( (ctx->flags & MAIL_SEEN) > 0 )
369
369
str_printfa(flags, " \\seen");
371
371
if ( (ctx->flags & MAIL_DRAFT) > 0 )
372
372
str_printfa(flags, " \\draft");
384
384
/* Result execution */
386
static bool seff_flags_pre_execute
387
(const struct sieve_side_effect *seffect,
386
static int seff_flags_pre_execute
387
(const struct sieve_side_effect *seffect,
388
388
const struct sieve_action *action ATTR_UNUSED,
389
389
const struct sieve_action_exec_env *aenv, void **context, void *tr_context)
391
391
struct seff_flags_context *ctx = (struct seff_flags_context *) *context;
392
392
const char *const *keywords;
394
394
if ( ctx == NULL ) {
395
395
ctx = seff_flags_get_implicit_context
396
396
(SIEVE_OBJECT_EXTENSION(seffect), aenv->result);
397
397
*context = (void *) ctx;
400
400
(void)array_append_space(&ctx->keywords);
401
401
keywords = array_idx(&ctx->keywords, 0);
403
403
sieve_act_store_add_flags(aenv, tr_context, keywords, ctx->flags);
405
return SIEVE_EXEC_OK;