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