1 /* interp.c -- sieve script interpreter builder
2 * Larry Greenfield
3 *
4 * Copyright (c) 1994-2008 Carnegie Mellon University. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 *
18 * 3. The name "Carnegie Mellon University" must not be used to
19 * endorse or promote products derived from this software without
20 * prior written permission. For permission or any legal
21 * details, please contact
22 * Carnegie Mellon University
23 * Center for Technology Transfer and Enterprise Creation
24 * 4615 Forbes Avenue
25 * Suite 302
26 * Pittsburgh, PA 15213
27 * (412) 268-7393, fax: (412) 268-7395
28 * innovation@andrew.cmu.edu
29 *
30 * 4. Redistributions of any form whatsoever must retain the following
31 * acknowledgment:
32 * "This product includes software developed by Computing Services
33 * at Carnegie Mellon University (http://www.cmu.edu/computing/)."
34 *
35 * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
36 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
37 * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
38 * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
39 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
40 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
41 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
42 */
43
44 #ifdef HAVE_CONFIG_H
45 #include <config.h>
46 #endif
47
48 #include <stdlib.h>
49 #include <string.h>
50
51 #include "xmalloc.h"
52 #include "xstrlcat.h"
53
54 #include "sieve_interface.h"
55 #include "interp.h"
56 #include "libconfig.h"
57 #include "times.h"
58 #include "util.h"
59
60 #define EXT_LEN 4096
61
62 /* build a sieve interpreter */
sieve_interp_alloc(void * interp_context)63 EXPORTED sieve_interp_t *sieve_interp_alloc(void *interp_context)
64 {
65 sieve_interp_t *i;
66 static int initonce;
67
68 if (!initonce) {
69 initialize_siev_error_table();
70 initonce = 1;
71 }
72
73 i = (sieve_interp_t *) xmalloc(sizeof(sieve_interp_t));
74
75 i->redirect = i->discard = i->reject = i->fileinto = i->keep = NULL;
76 i->getsize = NULL;
77 i->getheader = NULL;
78 i->getenvelope = NULL;
79 i->getbody = NULL;
80 i->getinclude = NULL;
81 i->vacation = NULL;
82 i->notify = NULL;
83
84 i->markflags = NULL;
85
86 i->interp_context = interp_context;
87 i->err = NULL;
88 i->lastitem = NULL;
89 i->extensions[0] = '\0';
90
91 i->time = time(NULL);
92
93 return i;
94 }
95
sieve_listextensions(sieve_interp_t * i)96 EXPORTED const char *sieve_listextensions(sieve_interp_t *i)
97 {
98 if (i->extensions[0] == '\0') {
99 unsigned long config_sieve_extensions =
100 config_getbitfield(IMAPOPT_SIEVE_EXTENSIONS);
101
102 /* add comparators */
103 strlcat(i->extensions, "comparator-i;ascii-numeric", EXT_LEN);
104
105 /* add actions */
106 if (i->fileinto &&
107 (config_sieve_extensions & IMAP_ENUM_SIEVE_EXTENSIONS_FILEINTO))
108 strlcat(i->extensions, " fileinto", EXT_LEN);
109 if (i->reject &&
110 (config_sieve_extensions & IMAP_ENUM_SIEVE_EXTENSIONS_REJECT))
111 strlcat(i->extensions, " reject", EXT_LEN);
112 if (i->vacation &&
113 (config_sieve_extensions & IMAP_ENUM_SIEVE_EXTENSIONS_VACATION_SECONDS))
114 strlcat(i->extensions, " vacation vacation-seconds", EXT_LEN);
115 else if (i->vacation &&
116 (config_sieve_extensions & IMAP_ENUM_SIEVE_EXTENSIONS_VACATION))
117 strlcat(i->extensions, " vacation", EXT_LEN);
118 if (i->markflags &&
119 (config_sieve_extensions & IMAP_ENUM_SIEVE_EXTENSIONS_IMAPFLAGS))
120 strlcat(i->extensions, " imapflags", EXT_LEN);
121 if (i->notify &&
122 (config_sieve_extensions & IMAP_ENUM_SIEVE_EXTENSIONS_NOTIFY))
123 strlcat(i->extensions, " notify", EXT_LEN);
124 if (i->getinclude &&
125 (config_sieve_extensions & IMAP_ENUM_SIEVE_EXTENSIONS_INCLUDE))
126 strlcat(i->extensions, " include", EXT_LEN);
127
128 /* add tests */
129 if (i->getenvelope &&
130 (config_sieve_extensions & IMAP_ENUM_SIEVE_EXTENSIONS_ENVELOPE))
131 strlcat(i->extensions, " envelope", EXT_LEN);
132 if (i->getbody &&
133 (config_sieve_extensions & IMAP_ENUM_SIEVE_EXTENSIONS_BODY))
134 strlcat(i->extensions, " body", EXT_LEN);
135 if (config_sieve_extensions & IMAP_ENUM_SIEVE_EXTENSIONS_IMAP4FLAGS)
136 strlcat(i->extensions, " imap4flags", EXT_LEN);
137 if (config_sieve_extensions & IMAP_ENUM_SIEVE_EXTENSIONS_DATE)
138 strlcat(i->extensions, " date", EXT_LEN);
139 if (config_sieve_extensions & IMAP_ENUM_SIEVE_EXTENSIONS_MAILBOX)
140 strlcat(i->extensions, " mailbox", EXT_LEN);
141 if (config_sieve_extensions & IMAP_ENUM_SIEVE_EXTENSIONS_MBOXMETADATA)
142 strlcat(i->extensions, " mboxmetadata", EXT_LEN);
143 if (config_sieve_extensions & IMAP_ENUM_SIEVE_EXTENSIONS_SERVERMETADATA)
144 strlcat(i->extensions, " servermetadata", EXT_LEN);
145
146 /* add match-types */
147 if (config_sieve_extensions & IMAP_ENUM_SIEVE_EXTENSIONS_RELATIONAL)
148 strlcat(i->extensions, " relational", EXT_LEN);
149 #ifdef ENABLE_REGEX
150 if (config_sieve_extensions & IMAP_ENUM_SIEVE_EXTENSIONS_REGEX)
151 strlcat(i->extensions, " regex", EXT_LEN);
152 #endif
153
154 /* add misc extensions */
155 if (config_sieve_extensions & IMAP_ENUM_SIEVE_EXTENSIONS_SUBADDRESS)
156 strlcat(i->extensions, " subaddress", EXT_LEN);
157 if (config_sieve_extensions & IMAP_ENUM_SIEVE_EXTENSIONS_COPY)
158 strlcat(i->extensions, " copy", EXT_LEN);
159 if (config_sieve_extensions & IMAP_ENUM_SIEVE_EXTENSIONS_INDEX)
160 strlcat(i->extensions, " index", EXT_LEN);
161 if (config_sieve_extensions & IMAP_ENUM_SIEVE_EXTENSIONS_VARIABLES)
162 strlcat(i->extensions, " variables", EXT_LEN);
163 }
164
165 return i->extensions;
166 }
167
sieve_interp_free(sieve_interp_t ** interp)168 EXPORTED int sieve_interp_free(sieve_interp_t **interp)
169 {
170 if (*interp) {
171 free((*interp)->lastitem);
172 free(*interp);
173 *interp = NULL;
174 }
175
176 return SIEVE_OK;
177 }
178
179 /* add the callbacks */
sieve_register_redirect(sieve_interp_t * interp,sieve_callback * f)180 EXPORTED void sieve_register_redirect(sieve_interp_t *interp, sieve_callback *f)
181 {
182 interp->redirect = f;
183 }
184
sieve_register_discard(sieve_interp_t * interp,sieve_callback * f)185 EXPORTED void sieve_register_discard(sieve_interp_t *interp, sieve_callback *f)
186 {
187 interp->discard = f;
188 }
189
sieve_register_reject(sieve_interp_t * interp,sieve_callback * f)190 EXPORTED void sieve_register_reject(sieve_interp_t *interp, sieve_callback *f)
191 {
192 interp->reject = f;
193 }
194
sieve_register_fileinto(sieve_interp_t * interp,sieve_callback * f)195 EXPORTED void sieve_register_fileinto(sieve_interp_t *interp, sieve_callback *f)
196 {
197 interp->fileinto = f;
198 }
199
sieve_register_keep(sieve_interp_t * interp,sieve_callback * f)200 EXPORTED void sieve_register_keep(sieve_interp_t *interp, sieve_callback *f)
201 {
202 interp->keep = f;
203 }
204
sieve_register_imapflags(sieve_interp_t * interp,const strarray_t * mark)205 EXPORTED void sieve_register_imapflags(sieve_interp_t *interp, const strarray_t *mark)
206 {
207 static strarray_t default_mark = STRARRAY_INITIALIZER;
208
209 if (!default_mark.count)
210 strarray_append(&default_mark, "\\flagged");
211
212 interp->markflags =
213 (mark && mark->data && mark->count) ? mark : &default_mark;
214 }
215
sieve_register_notify(sieve_interp_t * interp,sieve_callback * f)216 EXPORTED void sieve_register_notify(sieve_interp_t *interp, sieve_callback *f)
217 {
218 interp->notify = f;
219 }
220
221 /* add the callbacks for messages. again, undefined if used after
222 sieve_script_parse */
sieve_register_size(sieve_interp_t * interp,sieve_get_size * f)223 EXPORTED void sieve_register_size(sieve_interp_t *interp, sieve_get_size *f)
224 {
225 interp->getsize = f;
226 }
227
sieve_register_mailboxexists(sieve_interp_t * interp,sieve_get_mailboxexists * f)228 EXPORTED void sieve_register_mailboxexists(sieve_interp_t *interp, sieve_get_mailboxexists *f)
229 {
230 interp->getmailboxexists = f;
231 }
232
sieve_register_metadata(sieve_interp_t * interp,sieve_get_metadata * f)233 EXPORTED void sieve_register_metadata(sieve_interp_t *interp, sieve_get_metadata *f)
234 {
235 interp->getmetadata = f;
236 }
237
sieve_register_header(sieve_interp_t * interp,sieve_get_header * f)238 EXPORTED void sieve_register_header(sieve_interp_t *interp, sieve_get_header *f)
239 {
240 interp->getheader = f;
241 }
242
sieve_register_fname(sieve_interp_t * interp,sieve_get_fname * f)243 EXPORTED void sieve_register_fname(sieve_interp_t *interp, sieve_get_fname *f)
244 {
245 interp->getfname = f;
246 }
247
sieve_register_envelope(sieve_interp_t * interp,sieve_get_envelope * f)248 EXPORTED void sieve_register_envelope(sieve_interp_t *interp, sieve_get_envelope *f)
249 {
250 interp->getenvelope = f;
251 }
252
sieve_register_include(sieve_interp_t * interp,sieve_get_include * f)253 EXPORTED void sieve_register_include(sieve_interp_t *interp, sieve_get_include *f)
254 {
255 interp->getinclude = f;
256 }
257
sieve_register_body(sieve_interp_t * interp,sieve_get_body * f)258 EXPORTED void sieve_register_body(sieve_interp_t *interp, sieve_get_body *f)
259 {
260 interp->getbody = f;
261 }
262
sieve_register_vacation(sieve_interp_t * interp,sieve_vacation_t * v)263 EXPORTED int sieve_register_vacation(sieve_interp_t *interp, sieve_vacation_t *v)
264 {
265 if (!interp->getenvelope) {
266 return SIEVE_NOT_FINALIZED; /* we need envelope for vacation! */
267 }
268
269 if (v->min_response == 0)
270 v->min_response = config_getint(IMAPOPT_SIEVE_VACATION_MIN_RESPONSE);
271 if (v->max_response == 0)
272 v->max_response = config_getint(IMAPOPT_SIEVE_VACATION_MAX_RESPONSE);
273 if (v->min_response < 0 || v->max_response < 7 * DAY2SEC || !v->autorespond
274 || !v->send_response) {
275 return SIEVE_FAIL;
276 }
277
278 interp->vacation = v;
279 return SIEVE_OK;
280 }
281
sieve_register_parse_error(sieve_interp_t * interp,sieve_parse_error * f)282 EXPORTED void sieve_register_parse_error(sieve_interp_t *interp, sieve_parse_error *f)
283 {
284 interp->err = f;
285 }
286
sieve_register_execute_error(sieve_interp_t * interp,sieve_execute_error * f)287 EXPORTED void sieve_register_execute_error(sieve_interp_t *interp, sieve_execute_error *f)
288 {
289 interp->execute_err = f;
290 }
291
interp_verify(sieve_interp_t * i)292 int interp_verify(sieve_interp_t *i)
293 {
294 if (i->redirect && i->keep && i->getsize && i->getheader) {
295 return SIEVE_OK;
296 } else {
297 return SIEVE_NOT_FINALIZED;
298 }
299 }
300