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

Annotation of /imapfilter/match.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.4 - (hide annotations)
Mon Feb 9 20:49:01 2004 UTC (20 years, 1 month ago) by lefcha
Branch: MAIN
Changes since 1.3: +4 -2 lines
File MIME type: text/plain
Wrap some long >80 lines.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26