1 /* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file
2 */
3
4 /* Extension imapflags
5 * --------------------
6 *
7 * Authors: Stephan Bosch
8 * Specification: draft-melnikov-sieve-imapflags-03.txt
9 * Implementation: full, but deprecated; provided for backwards compatibility
10 * Status: testing
11 *
12 */
13
14 #include "lib.h"
15 #include "mempool.h"
16 #include "str.h"
17
18 #include "sieve-common.h"
19
20 #include "sieve-ast.h"
21 #include "sieve-code.h"
22 #include "sieve-extensions.h"
23 #include "sieve-actions.h"
24 #include "sieve-commands.h"
25 #include "sieve-validator.h"
26 #include "sieve-generator.h"
27 #include "sieve-interpreter.h"
28
29 #include "ext-imap4flags-common.h"
30
31 /*
32 * Commands
33 */
34
35 static bool cmd_mark_validate
36 (struct sieve_validator *valdtr, struct sieve_command *cmd);
37
38 /* Mark command
39 *
40 * Syntax:
41 * mark
42 */
43
44 static const struct sieve_command_def cmd_mark = {
45 .identifier = "mark",
46 .type = SCT_COMMAND,
47 .positional_args = 0,
48 .subtests = 0,
49 .block_allowed = FALSE,
50 .block_required = FALSE,
51 .validate = cmd_mark_validate
52 };
53
54 /* Unmark command
55 *
56 * Syntax:
57 * unmark
58 */
59 static const struct sieve_command_def cmd_unmark = {
60 .identifier = "unmark",
61 .type = SCT_COMMAND,
62 .positional_args = 0,
63 .subtests = 0,
64 .block_allowed = FALSE,
65 .block_required = FALSE,
66 .validate = cmd_mark_validate
67 };
68
69 /*
70 * Extension
71 */
72
73 static bool ext_imapflags_load
74 (const struct sieve_extension *ext, void **context);
75 static bool ext_imapflags_validator_load
76 (const struct sieve_extension *ext, struct sieve_validator *valdtr);
77 static bool ext_imapflags_interpreter_load
78 (const struct sieve_extension *ext, const struct sieve_runtime_env *renv,
79 sieve_size_t *address);
80
81 const struct sieve_extension_def imapflags_extension = {
82 .name = "imapflags",
83 .load = ext_imapflags_load,
84 .validator_load = ext_imapflags_validator_load,
85 .interpreter_load = ext_imapflags_interpreter_load
86 };
87
ext_imapflags_load(const struct sieve_extension * ext,void ** context)88 static bool ext_imapflags_load
89 (const struct sieve_extension *ext, void **context)
90 {
91 if ( *context == NULL ) {
92 /* Make sure real extension is registered, it is needed by the binary */
93 *context = (void *)
94 sieve_extension_require(ext->svinst, &imap4flags_extension, FALSE);
95 }
96
97 return TRUE;
98 }
99
100 /*
101 * Validator
102 */
103
104 static bool ext_imapflags_validator_check_conflict
105 (const struct sieve_extension *ext,
106 struct sieve_validator *valdtr, void *context,
107 struct sieve_ast_argument *require_arg,
108 const struct sieve_extension *other_ext,
109 bool required);
110 static bool ext_imapflags_validator_validate
111 (const struct sieve_extension *ext,
112 struct sieve_validator *valdtr, void *context,
113 struct sieve_ast_argument *require_arg,
114 bool required);
115
116 const struct sieve_validator_extension
117 imapflags_validator_extension = {
118 .ext = &imapflags_extension,
119 .check_conflict = ext_imapflags_validator_check_conflict,
120 .validate = ext_imapflags_validator_validate
121 };
122
ext_imapflags_validator_load(const struct sieve_extension * ext,struct sieve_validator * valdtr)123 static bool ext_imapflags_validator_load
124 (const struct sieve_extension *ext, struct sieve_validator *valdtr)
125 {
126 sieve_validator_extension_register
127 (valdtr, ext, &imapflags_validator_extension, NULL);
128
129 return TRUE;
130 }
131
ext_imapflags_validator_check_conflict(const struct sieve_extension * ext,struct sieve_validator * valdtr,void * context ATTR_UNUSED,struct sieve_ast_argument * require_arg,const struct sieve_extension * ext_other,bool required ATTR_UNUSED)132 static bool ext_imapflags_validator_check_conflict
133 (const struct sieve_extension *ext,
134 struct sieve_validator *valdtr, void *context ATTR_UNUSED,
135 struct sieve_ast_argument *require_arg,
136 const struct sieve_extension *ext_other,
137 bool required ATTR_UNUSED)
138 {
139 const struct sieve_extension *master_ext =
140 (const struct sieve_extension *) ext->context;
141
142 if ( ext_other == master_ext ) {
143 sieve_argument_validate_error(valdtr, require_arg,
144 "the (deprecated) imapflags extension cannot be used "
145 "together with the imap4flags extension");
146 return FALSE;
147 }
148
149 return TRUE;
150 }
151
ext_imapflags_validator_validate(const struct sieve_extension * ext,struct sieve_validator * valdtr,void * context ATTR_UNUSED,struct sieve_ast_argument * require_arg ATTR_UNUSED,bool required ATTR_UNUSED)152 static bool ext_imapflags_validator_validate
153 (const struct sieve_extension *ext,
154 struct sieve_validator *valdtr, void *context ATTR_UNUSED,
155 struct sieve_ast_argument *require_arg ATTR_UNUSED,
156 bool required ATTR_UNUSED)
157 {
158 const struct sieve_extension *master_ext =
159 (const struct sieve_extension *) ext->context;
160
161 /* No conflicts */
162
163 /* Register commands */
164 sieve_validator_register_command(valdtr, master_ext, &cmd_setflag);
165 sieve_validator_register_command(valdtr, master_ext, &cmd_addflag);
166 sieve_validator_register_command(valdtr, master_ext, &cmd_removeflag);
167
168 sieve_validator_register_command(valdtr, master_ext, &cmd_mark);
169 sieve_validator_register_command(valdtr, master_ext, &cmd_unmark);
170
171 /* Attach flags side-effect to keep and fileinto actions */
172 sieve_ext_imap4flags_register_side_effect(valdtr, master_ext, "keep");
173 sieve_ext_imap4flags_register_side_effect(valdtr, master_ext, "fileinto");
174
175 return TRUE;
176 }
177
178 /*
179 * Interpreter
180 */
181
ext_imapflags_interpreter_load(const struct sieve_extension * ext,const struct sieve_runtime_env * renv,sieve_size_t * address ATTR_UNUSED)182 static bool ext_imapflags_interpreter_load
183 (const struct sieve_extension *ext, const struct sieve_runtime_env *renv,
184 sieve_size_t *address ATTR_UNUSED)
185 {
186 const struct sieve_extension *master_ext =
187 (const struct sieve_extension *) ext->context;
188
189 sieve_ext_imap4flags_interpreter_load(master_ext, renv);
190 return TRUE;
191 }
192
193 /*
194 * Command validation
195 */
196
cmd_mark_validate(struct sieve_validator * valdtr,struct sieve_command * cmd)197 static bool cmd_mark_validate
198 (struct sieve_validator *valdtr, struct sieve_command *cmd)
199 {
200 if ( sieve_command_is(cmd, cmd_mark) )
201 cmd->def = &cmd_addflag;
202 else
203 cmd->def = &cmd_removeflag;
204
205 cmd->first_positional = sieve_ast_argument_cstring_create
206 (cmd->ast_node, "\\flagged", cmd->ast_node->source_line);
207
208 if ( !sieve_validator_argument_activate
209 (valdtr, cmd, cmd->first_positional, FALSE) )
210 return FALSE;
211
212 return TRUE;
213 }
214