1 #ifndef SIEVE_ACTIONS_H
2 #define SIEVE_ACTIONS_H
3
4 #include "lib.h"
5 #include "mail-types.h"
6 #include "mail-error.h"
7
8 #include "sieve-common.h"
9 #include "sieve-objects.h"
10 #include "sieve-extensions.h"
11 #include "sieve-execute.h"
12
13 /*
14 * Action execution environment
15 */
16
17 struct sieve_action_exec_env {
18 const struct sieve_execute_env *exec_env;
19 struct sieve_result_execution *rexec;
20 const struct sieve_action *action;
21 struct event *event;
22
23 struct sieve_result *result;
24 struct sieve_error_handler *ehandler;
25
26 struct sieve_message_context *msgctx;
27 };
28
29 struct event_passthrough *
30 sieve_action_create_finish_event(const struct sieve_action_exec_env *aenv);
31
32 /*
33 * Action flags
34 */
35
36 enum sieve_action_flags {
37 SIEVE_ACTFLAG_TRIES_DELIVER = (1 << 0),
38 SIEVE_ACTFLAG_SENDS_RESPONSE = (1 << 1),
39 SIEVE_ACTFLAG_MAIL_STORAGE = (1 << 2)
40 };
41
42 /*
43 * Action definition
44 */
45
46 struct sieve_action_def {
47 const char *name;
48 unsigned int flags;
49
50 bool (*equals)(const struct sieve_script_env *senv,
51 const struct sieve_action *act1,
52 const struct sieve_action *act2);
53
54 /* Result verification */
55 int (*check_duplicate)(const struct sieve_runtime_env *renv,
56 const struct sieve_action *act,
57 const struct sieve_action *act_other);
58 int (*check_conflict)(const struct sieve_runtime_env *renv,
59 const struct sieve_action *act,
60 const struct sieve_action *act_other);
61
62 /* Result printing */
63 void (*print)(const struct sieve_action *action,
64 const struct sieve_result_print_env *penv, bool *keep);
65
66 /* Result execution */
67 int (*start)(const struct sieve_action_exec_env *aenv,
68 void **tr_context);
69 int (*execute)(const struct sieve_action_exec_env *aenv,
70 void *tr_context, bool *keep);
71 int (*commit)(const struct sieve_action_exec_env *aenv,
72 void *tr_context);
73 void (*rollback)(const struct sieve_action_exec_env *aenv,
74 void *tr_context, bool success);
75 void (*finish)(const struct sieve_action_exec_env *aenv,
76 void *tr_context, int status);
77 };
78
79 /*
80 * Action instance
81 */
82
83 struct sieve_action {
84 const struct sieve_action_def *def;
85 const struct sieve_extension *ext;
86 struct event *event;
87
88 const char *name;
89 const char *location;
90 unsigned int exec_seq;
91 void *context;
92 struct mail *mail;
93
94 bool keep:1;
95 };
96
97 #define sieve_action_is(act, definition) ((act)->def == &(definition))
98 #define sieve_action_name(act) ((act)->name)
99
100 bool sieve_action_is_executed(const struct sieve_action *act,
101 struct sieve_result *result);
102
103 /*
104 * Action side effects
105 */
106
107 /* Side effect object */
108
109 struct sieve_side_effect_def {
110 struct sieve_object_def obj_def;
111
112 /* Precedence (side effects with higher value are executed first) */
113
114 unsigned int precedence;
115
116 /* The action it is supposed to link to */
117 const struct sieve_action_def *to_action;
118
119 /* Context coding */
120 bool (*dump_context)(const struct sieve_side_effect *seffect,
121 const struct sieve_dumptime_env *renv,
122 sieve_size_t *address);
123 int (*read_context)(const struct sieve_side_effect *seffect,
124 const struct sieve_runtime_env *renv,
125 sieve_size_t *address, void **se_context);
126
127 /* Result verification */
128 int (*merge)(const struct sieve_runtime_env *renv,
129 const struct sieve_action *action,
130 const struct sieve_side_effect *old_seffect,
131 const struct sieve_side_effect *new_seffect,
132 void **old_context);
133
134 /* Result printing */
135 void (*print)(const struct sieve_side_effect *seffect,
136 const struct sieve_action *action,
137 const struct sieve_result_print_env *penv, bool *keep);
138
139 /* Result execution */
140
141 int (*pre_execute)(const struct sieve_side_effect *seffect,
142 const struct sieve_action_exec_env *aenv,
143 void *tr_context, void **se_tr_context);
144 int (*post_execute)(const struct sieve_side_effect *seffect,
145 const struct sieve_action_exec_env *aenv,
146 void *tr_context, void *se_tr_context, bool *keep);
147 void (*post_commit)(const struct sieve_side_effect *seffect,
148 const struct sieve_action_exec_env *aenv,
149 void *tr_context, void *se_tr_context,
150 int commit_status);
151 void (*rollback)(const struct sieve_side_effect *seffect,
152 const struct sieve_action_exec_env *aenv,
153 void *tr_context, void *se_tr_context, bool success);
154 };
155
156 struct sieve_side_effect {
157 struct sieve_object object;
158
159 const struct sieve_side_effect_def *def;
160
161 void *context;
162 };
163
164 /*
165 * Side effect operand
166 */
167
168 #define SIEVE_EXT_DEFINE_SIDE_EFFECT(SEF) SIEVE_EXT_DEFINE_OBJECT(SEF)
169 #define SIEVE_EXT_DEFINE_SIDE_EFFECTS(SEFS) SIEVE_EXT_DEFINE_OBJECTS(SEFS)
170
171 #define SIEVE_OPT_SIDE_EFFECT (-1)
172
173 extern const struct sieve_operand_class sieve_side_effect_operand_class;
174
175 static inline void
sieve_opr_side_effect_emit(struct sieve_binary_block * sblock,const struct sieve_extension * ext,const struct sieve_side_effect_def * seff)176 sieve_opr_side_effect_emit(struct sieve_binary_block *sblock,
177 const struct sieve_extension *ext,
178 const struct sieve_side_effect_def *seff)
179 {
180 sieve_opr_object_emit(sblock, ext, &seff->obj_def);
181 }
182
183 bool sieve_opr_side_effect_dump(const struct sieve_dumptime_env *denv,
184 sieve_size_t *address);
185 int sieve_opr_side_effect_read(const struct sieve_runtime_env *renv,
186 sieve_size_t *address,
187 struct sieve_side_effect *seffect);
188
189 /*
190 * Optional operands
191 */
192
193 int sieve_action_opr_optional_dump(const struct sieve_dumptime_env *denv,
194 sieve_size_t *address, signed int *opt_code);
195
196 int sieve_action_opr_optional_read(const struct sieve_runtime_env *renv,
197 sieve_size_t *address, signed int *opt_code,
198 int *exec_status,
199 struct sieve_side_effects_list **list);
200
201 /*
202 * Core actions
203 */
204
205 extern const struct sieve_action_def act_redirect;
206 extern const struct sieve_action_def act_store;
207 extern const struct sieve_action_def act_discard;
208
209 /*
210 * Store action
211 */
212
213 struct act_store_context {
214 /* Folder name represented in utf-8 */
215 const char *mailbox;
216 };
217
218 struct act_store_transaction {
219 struct act_store_context *context;
220 struct mailbox *box;
221 struct mailbox_transaction_context *mail_trans;
222
223 const char *mailbox_name;
224 const char *mailbox_identifier;
225
226 const char *error;
227 enum mail_error error_code;
228
229 enum mail_flags flags;
230 ARRAY_TYPE(const_string) keywords;
231
232 bool flags_altered:1;
233 bool disabled:1;
234 bool redundant:1;
235 };
236
237 int sieve_act_store_add_to_result(const struct sieve_runtime_env *renv,
238 const char *name,
239 struct sieve_side_effects_list *seffects,
240 const char *folder);
241
242 void sieve_act_store_add_flags(const struct sieve_action_exec_env *aenv,
243 void *tr_context, const char *const *keywords,
244 enum mail_flags flags);
245
246 void sieve_act_store_get_storage_error(const struct sieve_action_exec_env *aenv,
247 struct act_store_transaction *trans);
248
249 /*
250 * Redirect action
251 */
252
253 struct act_redirect_context {
254 const struct smtp_address *to_address;
255 };
256
257 int sieve_act_redirect_add_to_result(const struct sieve_runtime_env *renv,
258 const char *name,
259 struct sieve_side_effects_list *seffects,
260 const struct smtp_address *to_address);
261
262 /*
263 * Checking for duplicates
264 */
265
266 static inline bool
sieve_action_duplicate_check_available(const struct sieve_action_exec_env * aenv)267 sieve_action_duplicate_check_available(const struct sieve_action_exec_env *aenv)
268 {
269 const struct sieve_execute_env *eenv = aenv->exec_env;
270
271 return sieve_execute_duplicate_check_available(eenv);
272 }
273
274 static inline int
sieve_action_duplicate_check(const struct sieve_action_exec_env * aenv,const void * id,size_t id_size,bool * duplicate_r)275 sieve_action_duplicate_check(const struct sieve_action_exec_env *aenv,
276 const void *id, size_t id_size,
277 bool *duplicate_r)
278 {
279 const struct sieve_execute_env *eenv = aenv->exec_env;
280
281 return sieve_execute_duplicate_check(eenv, id, id_size,
282 duplicate_r);
283 }
284
285 static inline void
sieve_action_duplicate_mark(const struct sieve_action_exec_env * aenv,const void * id,size_t id_size,time_t time)286 sieve_action_duplicate_mark(const struct sieve_action_exec_env *aenv,
287 const void *id, size_t id_size, time_t time)
288 {
289 const struct sieve_execute_env *eenv = aenv->exec_env;
290
291 return sieve_execute_duplicate_mark(eenv, id, id_size, time);
292 }
293
294 /*
295 * Action utility functions
296 */
297
298 /* Rejecting mail */
299
300 int sieve_action_reject_mail(const struct sieve_action_exec_env *aenv,
301 const struct smtp_address *recipient,
302 const char *reason);
303
304 /*
305 * Mailbox
306 */
307
308 // FIXME: move this to a more appropriate location
309 bool sieve_mailbox_check_name(const char *mailbox, const char **error_r);
310
311 #endif
312