1 /* tree.c -- abstract syntax tree handling
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 "xmalloc.h"
50 
51 #include "tree.h"
52 #include "sieve/sieve_interface.h"
53 #include "sieve/sieve.h"
54 
new_tag(int type,char * s)55 tag_t *new_tag(int type, char *s)
56 {
57     tag_t *p = (tag_t *) xzmalloc(sizeof(tag_t));
58     p->type = type;
59     p->arg = s;
60     return p;
61 }
62 
new_taglist(tag_t * t,taglist_t * n)63 taglist_t *new_taglist(tag_t *t, taglist_t *n)
64 {
65     taglist_t *p = (taglist_t *) xzmalloc(sizeof(taglist_t));
66     p->t = t;
67     p->next = n;
68     return p;
69 }
70 
new_test(int type)71 test_t *new_test(int type)
72 {
73     test_t *p = (test_t *) xzmalloc(sizeof(test_t));
74     p->type = type;
75     return p;
76 }
77 
new_testlist(test_t * t,testlist_t * n)78 testlist_t *new_testlist(test_t *t, testlist_t *n)
79 {
80     testlist_t *p = (testlist_t *) xmalloc(sizeof(testlist_t));
81     p->t = t;
82     p->next = n;
83     return p;
84 }
85 
new_command(int type)86 commandlist_t *new_command(int type)
87 {
88     commandlist_t *p = (commandlist_t *) xzmalloc(sizeof(commandlist_t));
89     p->type = type;
90     p->next = NULL;
91     return p;
92 }
93 
new_if(test_t * t,commandlist_t * y,commandlist_t * n)94 commandlist_t *new_if(test_t *t, commandlist_t *y, commandlist_t *n)
95 {
96     commandlist_t *p = (commandlist_t *) xzmalloc(sizeof(commandlist_t));
97     p->type = IF;
98     p->u.i.t = t;
99     p->u.i.do_then = y;
100     p->u.i.do_else = n;
101     p->next = NULL;
102     return p;
103 }
104 
105 void free_test(test_t *t);
106 
free_tl(testlist_t * tl)107 static void free_tl(testlist_t *tl)
108 {
109     testlist_t *tl2;
110 
111     while (tl) {
112         tl2 = tl->next;
113 
114         if (tl->t) free_test(tl->t);
115 
116         free(tl);
117         tl = tl2;
118     }
119 }
120 
free_test(test_t * t)121 void free_test(test_t *t)
122 {
123     if (t == NULL) return;
124 
125     switch (t->type) {
126     case ANYOF:
127     case ALLOF:
128         free_tl(t->u.tl);
129         break;
130 
131     case EXISTS:
132         strarray_free(t->u.sl);
133         break;
134 
135     case SIZE:
136     case SFALSE:
137     case STRUE:
138         break;
139 
140     case HASFLAG:
141     case HEADER:
142         free(t->u.h.comparator);
143         strarray_free(t->u.h.sl);
144         strarray_free(t->u.h.pl);
145         break;
146 
147     case ADDRESS:
148     case ENVELOPE:
149         free(t->u.ae.comparator);
150         strarray_free(t->u.ae.sl);
151         strarray_free(t->u.ae.pl);
152         break;
153 
154     case BODY:
155         free(t->u.b.comparator);
156         strarray_free(t->u.b.content_types);
157         strarray_free(t->u.b.pl);
158         break;
159 
160     case NOT:
161         free_test(t->u.t);
162         break;
163 
164     case DATE:
165         free(t->u.dt.header_name);
166         /* fall-through */
167     case CURRENTDATE:
168         free(t->u.dt.comparator);
169         free(t->u.dt.zone);
170         strarray_free(t->u.dt.kl);
171         break;
172 
173     case MAILBOXEXISTS:
174     case METADATA:
175     case METADATAEXISTS:
176     case SERVERMETADATA:
177     case SERVERMETADATAEXISTS:
178         free(t->u.mbx.extname);
179         free(t->u.mbx.keyname);
180         strarray_free(t->u.mbx.keylist);
181         free(t->u.mbx.comparator);
182         break;
183     }
184 
185     free(t);
186 }
187 
free_tree(commandlist_t * cl)188 void free_tree(commandlist_t *cl)
189 {
190     commandlist_t *cl2;
191 
192     while (cl != NULL) {
193         cl2 = cl->next;
194         switch (cl->type) {
195         case IF:
196             free_test(cl->u.i.t);
197             free_tree(cl->u.i.do_then);
198             free_tree(cl->u.i.do_else);
199             break;
200 
201         case INCLUDE:
202             free(cl->u.inc.script);
203             break;
204 
205         case SETFLAG:
206         case ADDFLAG:
207         case REMOVEFLAG:
208             free(cl->u.fl.variable);
209             strarray_free(cl->u.fl.flags);
210             break;
211 
212         case FILEINTO:
213             free(cl->u.f.folder);
214             strarray_free(cl->u.f.flags);
215             break;
216 
217         case REDIRECT:
218             free(cl->u.r.address);
219             break;
220 
221         case REJCT:
222             free(cl->u.reject);
223             break;
224 
225         case VACATION:
226             free(cl->u.v.subject);
227             strarray_free(cl->u.v.addresses);
228             free(cl->u.v.message);
229             break;
230 
231         case KEEP:
232             strarray_free(cl->u.k.flags);
233             break;
234 
235         case STOP:
236         case DISCARD:
237         case RETURN:
238             break;
239 
240         case NOTIFY:
241             if (cl->u.n.method) free(cl->u.n.method);
242             if (cl->u.n.id) free(cl->u.n.id);
243             if (cl->u.n.options) strarray_free(cl->u.n.options);
244             if (cl->u.n.message) free(cl->u.n.message);
245             break;
246 
247         case DENOTIFY:
248             if (cl->u.d.pattern) {
249 #ifdef ENABLE_REGEX
250                 if (cl->u.d.comptag == REGEX) {
251                     regfree((regex_t *) cl->u.d.pattern);
252                 }
253 #endif
254                 free(cl->u.d.pattern);
255             }
256             break;
257         }
258 
259         free(cl);
260         cl = cl2;
261     }
262 }
263