/[imapfilter]/imapfilter/match.c
ViewVC logotype

Annotation of /imapfilter/match.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.7 - (hide annotations)
Fri Feb 13 12:17:16 2004 UTC (20 years, 1 month ago) by lefcha
Branch: MAIN
Changes since 1.6: +3 -3 lines
File MIME type: text/plain
Stylistic changes.

1 lefcha 1.1 #include <stdio.h>
2     #include <string.h>
3    
4     #include "config.h"
5     #include "imapfilter.h"
6     #include "account.h"
7     #include "filter.h"
8    
9    
10 lefcha 1.7 extern options_t opts;
11     extern connection_t connpri, connaux;
12 lefcha 1.1
13    
14     int match_filter(filter_t * filter, char **mesgs);
15    
16 lefcha 1.6 char *generate_filter_and(mask_t * mask, unsigned int masknum, unsigned int masklen);
17     char *generate_filter_or(mask_t * mask, unsigned int masknum, unsigned int masklen);
18 lefcha 1.2 char *normalize_mask(char *body);
19     void convert_date(char *body);
20 lefcha 1.1
21     void empty_fifo(mask_t ** mfifo);
22     void queue_fifo(mask_t ** mfifo, mask_t * mask);
23     mask_t *dequeue_fifo(mask_t ** mfifo);
24    
25    
26     /*
27     * Match and apply filters assigned to a mailbox.
28     */
29     int
30     apply_filters(char *mbox, filter_t ** filters)
31     {
32     int i;
33     char *mesgs;
34    
35     for (i = 0; filters[i] != NULL; i++) {
36     mesgs = NULL;
37    
38     if (match_filter(filters[i], &mesgs))
39     continue;
40    
41     log_info(LOG_FILTER, filters[i]->key);
42    
43     apply_action(mbox, mesgs, &(filters[i]->action.type),
44     filters[i]->action.raccount, filters[i]->action.destmbox,
45     &filters[i]->action.msgflags, filters[i]->action.args);
46    
47     xfree(mesgs);
48     }
49    
50     return 0;
51     }
52    
53    
54     /*
55     * Generate the search request by the masks of the filter and try to
56     * match the generated filter.
57     */
58     int
59     match_filter(filter_t * filter, char **mesgs)
60     {
61     char *search;
62    
63     if (filter->mode == FILTER_MODE_OR)
64     search = generate_filter_or(filter->masks, filter->masknum,
65     filter->masklen);
66     else
67     search = generate_filter_and(filter->masks, filter->masknum,
68     filter->masklen);
69    
70 lefcha 1.7 response_search(&connpri, imap_search(&connpri, opts.charset, search),
71 lefcha 1.1 mesgs);
72    
73     xfree(search);
74    
75     if (*mesgs == '\0')
76     return 1;
77    
78     return 0;
79     }
80    
81    
82     /*
83     * Generate the filter search command from the masks, assuming that
84     * masks are AND-ed.
85     */
86     char *
87     generate_filter_and(mask_t * mask, unsigned int masknum,
88     unsigned int masklen)
89     {
90     const unsigned int searchbuf = masklen + masknum * 6 + 8;
91     unsigned int len;
92     char *search;
93     mask_t *tmp;
94    
95     len = 0;
96    
97     search = (char *)xmalloc(sizeof(char) * searchbuf);
98     search[0] = '\0';
99    
100     tmp = mask;
101     if (tmp == NULL) {
102     strncat(search, "ALL ", searchbuf - len - 1);
103     len += 4;
104     } else
105     while ((tmp = tmp->next) != NULL) {
106     if (tmp->type != MASK_TYPE_OR) {
107     strncat(search, "ALL ", searchbuf - len - 1);
108     len += 4;
109     break;
110     }
111     }
112    
113     tmp = NULL;
114     while (mask != NULL) {
115     tmp = mask;
116     mask = mask->next;
117    
118     if (mask != NULL && mask->type == MASK_TYPE_OR) {
119     strncat(search, "OR (", searchbuf - len - 1);
120     len += 4;
121    
122 lefcha 1.2 strncat(search, normalize_mask(tmp->body),
123     searchbuf - len - 1);
124 lefcha 1.1 len = strlen(search);
125     search[len] = ' ';
126     search[++len] = '\0';
127    
128     search[len - 1] = ')';
129     search[len] = ' ';
130     search[++len] = '\0';
131    
132     if (mask->next == NULL ||
133     mask->next->type != MASK_TYPE_OR) {
134     search[len] = '(';
135     search[++len] = '\0';
136 lefcha 1.2 strncat(search, normalize_mask(mask->body),
137 lefcha 1.1 searchbuf - len - 1);
138     len = strlen(search);
139     search[len] = ')';
140     search[++len] = ' ';
141     search[++len] = '\0';
142     mask = mask->next;
143     }
144     } else {
145 lefcha 1.2 strncat(search, normalize_mask(tmp->body),
146     searchbuf - len - 1);
147 lefcha 1.1 len = strlen(search);
148     search[len] = ' ';
149     search[++len] = '\0';
150     }
151     }
152    
153     search[len - 1] = '\0';
154    
155     return search;
156     }
157    
158    
159     /*
160     * Generate the filter search command from the masks, assuming that
161     * masks are OR-ed.
162     */
163     char *
164     generate_filter_or(mask_t * mask, unsigned int masknum,
165     unsigned int masklen)
166     {
167     const unsigned int searchbuf = masklen + masknum * 6 + 8;
168     unsigned int len;
169     char *search;
170     mask_t **mfifo; /* Mailbox FIFO queue. */
171     mask_t *mf; /* Mask returned from FIFO. */
172    
173     len = 0;
174    
175     search = (char *)xmalloc(sizeof(char) * searchbuf);
176     mfifo = (mask_t **) xmalloc(sizeof(mask_t *) * (masknum + 1));
177    
178     search[0] = '\0';
179     empty_fifo(mfifo);
180    
181     strncat(search, "ALL ", searchbuf - len - 1);
182     len += 4;
183    
184     while (mask != NULL) {
185     queue_fifo(mfifo, mask);
186     mask = mask->next;
187    
188     while (mask != NULL && mask->type == MASK_TYPE_AND) {
189     queue_fifo(mfifo, mask);
190     mask = mask->next;
191     }
192    
193     if (mask != NULL) {
194     if (len == 4 && search[0] == 'A') {
195     search[0] = '\0';
196     len = 0;
197     }
198     strncat(search, "OR ", searchbuf - len - 1);
199     len += 3;
200     }
201     if (search[0] != 'A') {
202     search[len] = '(';
203     search[++len] = '\0';
204     }
205     while ((mf = dequeue_fifo(mfifo)) != NULL) {
206 lefcha 1.2 strncat(search, normalize_mask(mf->body), searchbuf - len - 1);
207 lefcha 1.1 len = strlen(search);
208     search[len] = ' ';
209     search[++len] = '\0';
210     }
211    
212     if (strchr(search, '(')) {
213     search[len - 1] = ')';
214     search[len] = ' ';
215     search[++len] = '\0';
216     }
217     empty_fifo(mfifo);
218     }
219    
220     search[len - 1] = '\0';
221    
222     xfree(mfifo);
223    
224     return search;
225     }
226    
227    
228     /*
229 lefcha 1.2 * Make any necessary conversions to the mask body before sending it to server.
230     */
231     char *
232     normalize_mask(char *body)
233     {
234     static char nb[MASK_BODY_LEN];
235    
236    
237     if (strstr(body, "OLDER") ||
238     strstr(body, "NEWER")) {
239     xstrncpy(nb, body, MASK_BODY_LEN - 1);
240     convert_date(nb);
241    
242     return nb;
243     }
244     return body;
245     }
246    
247    
248     /*
249     * Converts masks related to date filtering, because IMAP servers do not
250     * understand for example "OLDER 3", but "BEFORE 18-Oct-2001" (if
251     * hypothetically current date was 21-Oct-2001).
252     */
253     void
254     convert_date(char *body)
255     {
256     char *cp, *c;
257     char s[16];
258     time_t te;
259     struct tm *tl;
260    
261     cp = xstrdup(body);
262     body[0] = '\0';
263    
264     if (strstr(cp, "NOT"))
265     strncat(body, "NOT ", 4);
266    
267     if ((c = strstr(cp, "OLDER")))
268     strncat(body, "BEFORE ", 7);
269     else if ((c = strstr(cp, "NEWER")))
270     strncat(body, "SINCE ", 6);
271    
272     c += 6;
273    
274     te = time(NULL) - (time_t) (strtoul(c, NULL, 10) * 24 * 60 * 60);
275     tl = localtime(&te);
276    
277     if (strftime(s, 15, "%d-%b-%Y", tl))
278     strncat(body, s, 15);
279    
280     xfree(cp);
281     }
282    
283    
284     /*
285 lefcha 1.1 * Empty the FIFO inventory.
286     */
287     void
288     empty_fifo(mask_t ** mfifo)
289     {
290     mfifo[0] = NULL;
291    
292     queue_fifo(NULL, NULL);
293     dequeue_fifo(NULL);
294     }
295    
296    
297     /*
298     * Add item to FIFO inventory.
299     */
300     void
301     queue_fifo(mask_t ** mfifo, mask_t * mask)
302     {
303     static unsigned int i;
304    
305     if (mfifo == NULL) {
306     i = 0;
307     return;
308     }
309     mfifo[i++] = mask;
310     mfifo[i] = NULL;
311     }
312    
313    
314     /*
315     * Get next item from FIFO inventory.
316     */
317     mask_t *
318     dequeue_fifo(mask_t ** mfifo)
319     {
320     static unsigned int j;
321    
322     if (mfifo == NULL) {
323     j = 0;
324     return NULL;
325     }
326     return mfifo[j++];
327     }

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26