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