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

Annotation of /imapfilter/request.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.9 - (hide annotations)
Sat Oct 6 12:31:39 2001 UTC (22 years, 6 months ago) by lefcha
Branch: MAIN
Changes since 1.8: +45 -42 lines
File MIME type: text/plain
Fixed a filter's logical operators bug.

1 lefcha 1.1 #include <stdio.h>
2     #include <stdlib.h>
3     #include <string.h>
4 lefcha 1.3 #include <errno.h>
5 lefcha 1.1
6     #include "config.h"
7     #include "imapfilter.h"
8     #include "data.h"
9    
10    
11     extern unsigned int options;
12    
13 lefcha 1.3
14 lefcha 1.2 #ifdef DEBUG
15 lefcha 1.1 /*
16     * Test/ping server.
17     */
18     int test(void)
19     {
20     imap_noop();
21 lefcha 1.3 return server_response("NOOP");
22 lefcha 1.1 }
23 lefcha 1.2 #endif
24 lefcha 1.1
25     /*
26     * Login to server.
27     */
28     int login(char *user, char *pass)
29     {
30     imap_login(user, pass);
31 lefcha 1.5
32 lefcha 1.4 log_info(LOG_USERNAME, user);
33 lefcha 1.5
34 lefcha 1.3 return server_response("LOGIN");
35 lefcha 1.1 }
36    
37    
38     /*
39 lefcha 1.8 * Open mailbox in read-only mode.
40     */
41     int examine_mailbox(char *mbox)
42     {
43     int r;
44    
45     imap_examine(mbox);
46     r = server_response("EXAMINE");
47    
48     if (!r)
49     mailbox_status(mbox);
50    
51     return r;
52     }
53    
54    
55     /*
56 lefcha 1.3 * Open mailbox in read-write mode.
57 lefcha 1.1 */
58 lefcha 1.3 int select_mailbox(char *mbox)
59 lefcha 1.1 {
60     int r;
61 lefcha 1.5
62 lefcha 1.3 imap_select(mbox);
63     r = server_response("SELECT");
64 lefcha 1.5
65 lefcha 1.3 if (!r)
66 lefcha 1.8 if (mailbox_status(mbox) == -2)
67     return -2; /* No messages exist. No filters need to
68     be applied. */
69 lefcha 1.5
70 lefcha 1.4 log_info(LOG_MAILBOX, mbox);
71 lefcha 1.5
72 lefcha 1.1 return r;
73     }
74    
75    
76     /*
77 lefcha 1.3 * Get mailbox's status.
78 lefcha 1.1 */
79 lefcha 1.3 int mailbox_status(char *mbox)
80 lefcha 1.1 {
81 lefcha 1.3 int r = 0;
82 lefcha 1.5
83 lefcha 1.3 if (!(options & OPTION_DETAILS_QUITE)) {
84     imap_status(mbox, "MESSAGES RECENT UNSEEN");
85     r = status_response();
86 lefcha 1.8 info("in mailbox %s.\n", mbox);
87 lefcha 1.3 }
88     return r;
89 lefcha 1.1 }
90 lefcha 1.9
91 lefcha 1.1 /*
92     * Close examined/selected mailbox.
93     */
94     int close_mailbox(void)
95     {
96     imap_close();
97 lefcha 1.3 return server_response("CLOSE");
98 lefcha 1.1 }
99    
100    
101     /*
102     * Logout from server.
103     */
104     int logout(void)
105     {
106     imap_logout();
107 lefcha 1.3 return server_response("LOGOUT");
108 lefcha 1.1 }
109    
110    
111     /*
112     * Match and apply filters assigned to a mailbox.
113     */
114     int apply_filters(filter_t ** filters, char *mbox)
115     {
116 lefcha 1.3 int i;
117 lefcha 1.1 char mesgs[SEARCH_MESSAGES_BUF];
118    
119     for (i = 0; filters[i]; i++) {
120    
121     mesgs[0] = 0;
122    
123     if (match_filter(filters[i], mesgs))
124     continue;
125 lefcha 1.5
126 lefcha 1.4 log_info(LOG_FILTER, filters[i]->key);
127 lefcha 1.1
128 lefcha 1.3 apply_action(mesgs, &(filters[i]->action.type),
129 lefcha 1.9 filters[i]->action.destmbox, filters[i]->action.args);
130 lefcha 1.1 }
131    
132     return 0;
133     }
134    
135    
136     /*
137     * Generate the search request by the masks of the filter and try to
138     * match the generated filter.
139     */
140     int match_filter(filter_t * filter, char *mesgs)
141     {
142 lefcha 1.3 char *search;
143 lefcha 1.5
144 lefcha 1.1 if (filter->mode == FILTER_MODE_OR)
145 lefcha 1.5 search = generate_filter_or(filter->masks, filter->masknum,
146     filter->masklen);
147 lefcha 1.1 else
148 lefcha 1.5 search = generate_filter_and(filter->masks, filter->masknum,
149     filter->masklen);
150 lefcha 1.1
151 lefcha 1.3 imap_search(search);
152     search_response(mesgs);
153 lefcha 1.5
154 lefcha 1.3 free(search);
155 lefcha 1.5
156 lefcha 1.3 if (!*mesgs)
157 lefcha 1.1 return 1;
158 lefcha 1.5
159 lefcha 1.1 return 0;
160     }
161    
162    
163     /*
164     * Empty the FIFO inventory.
165     */
166     void empty_fifo(mask_t ** mfifo)
167     {
168     mfifo[0] = NULL;
169    
170 lefcha 1.3 queue_fifo(NULL, NULL);
171     dequeue_fifo(NULL);
172 lefcha 1.1 }
173    
174    
175     /*
176     * Add item to FIFO inventory.
177     */
178 lefcha 1.3 void queue_fifo(mask_t ** mfifo, mask_t * mask)
179 lefcha 1.1 {
180     static int i;
181    
182     if (!mfifo) {
183     i = 0;
184     return;
185     }
186     mfifo[i++] = mask;
187     mfifo[i] = NULL;
188     }
189    
190    
191     /*
192     * Get next item from FIFO inventory.
193     */
194 lefcha 1.3 mask_t *dequeue_fifo(mask_t ** mfifo)
195 lefcha 1.1 {
196     static int j;
197    
198     if (!mfifo) {
199     j = 0;
200     return NULL;
201     }
202     return mfifo[j++];
203     }
204    
205    
206     /*
207     * Generate the filter search command from the masks, assuming that
208     * masks are AND-ed.
209     */
210 lefcha 1.9 char *generate_filter_and(mask_t * mask, unsigned int masknum,
211     unsigned int masklen)
212 lefcha 1.1 {
213 lefcha 1.3 const unsigned int searchbuf = masklen + masknum * 6 + 8;
214 lefcha 1.1 int len = 0;
215 lefcha 1.3 char *search;
216 lefcha 1.9 mask_t *tmp;
217 lefcha 1.5
218     search = (char *) xmalloc(sizeof(char) * searchbuf);
219    
220 lefcha 1.3 search[0] = 0;
221 lefcha 1.1
222 lefcha 1.9 tmp = mask;
223     while ((tmp = tmp->next)) {
224     if (tmp->type != MASK_TYPE_OR) {
225     strncat(search, "ALL ", searchbuf - len - 1);
226     len += 4;
227     break;
228     }
229     }
230 lefcha 1.1
231 lefcha 1.9 tmp = NULL;
232 lefcha 1.1 while (mask) {
233 lefcha 1.9 tmp = mask;
234     mask = mask->next;
235 lefcha 1.1
236 lefcha 1.9 if (mask && mask->type == MASK_TYPE_OR) {
237 lefcha 1.3 strncat(search, "OR (", searchbuf - len - 1);
238 lefcha 1.1 len += 4;
239    
240 lefcha 1.9 strncat(search, tmp->body, searchbuf - len - 1);
241     len = strlen(search);
242     search[len] = ' ';
243     search[++len] = 0;
244    
245     search[len - 1] = ')';
246     search[len] = ' ';
247     search[++len] = 0;
248    
249     if (!mask->next || mask->next->type != MASK_TYPE_OR) {
250     search[len] = '(';
251     search[++len] = 0;
252     strncat(search, mask->body, searchbuf - len - 1);
253 lefcha 1.1 len = strlen(search);
254 lefcha 1.9 search[len] = ')';
255     search[++len] = ' ';
256 lefcha 1.3 search[++len] = 0;
257 lefcha 1.9 mask = mask->next;
258 lefcha 1.1 }
259 lefcha 1.9 } else {
260     strncat(search, tmp->body, searchbuf - len - 1);
261     len = strlen(search);
262 lefcha 1.3 search[len] = ' ';
263     search[++len] = 0;
264 lefcha 1.1 }
265     }
266 lefcha 1.9
267     search[len - 1] = 0;
268 lefcha 1.5
269 lefcha 1.3 return search;
270 lefcha 1.1 }
271    
272    
273     /*
274     * Generate the filter search command from the masks, assuming that
275     * masks are OR-ed
276     */
277 lefcha 1.9 char *generate_filter_or(mask_t * mask, unsigned int masknum,
278     unsigned int masklen)
279 lefcha 1.1 {
280 lefcha 1.3 const unsigned int searchbuf = masklen + masknum * 6 + 8;
281 lefcha 1.1 int len = 0;
282 lefcha 1.3 char *search;
283     mask_t **mfifo; /* Mailbox FIFO queue. */
284 lefcha 1.1 mask_t *mf; /* Mask returned from FIFO. */
285 lefcha 1.5
286     search = (char *) xmalloc(sizeof(char) * searchbuf);
287     mfifo = (mask_t **) xmalloc(sizeof(mask_t *) * (masknum + 1));
288 lefcha 1.1
289 lefcha 1.3 search[0] = 0;
290 lefcha 1.1 empty_fifo(mfifo);
291    
292 lefcha 1.3 strncat(search, "ALL ", searchbuf - len - 1);
293 lefcha 1.1 len += 4;
294    
295     while (mask) {
296 lefcha 1.3 queue_fifo(mfifo, mask);
297 lefcha 1.1 mask = mask->next;
298    
299     while (mask && mask->type == MASK_TYPE_AND) {
300 lefcha 1.3 queue_fifo(mfifo, mask);
301 lefcha 1.1 mask = mask->next;
302     }
303    
304     if (mask) {
305 lefcha 1.3 if (len == 4 && search[0] == 'A')
306     search[0] = len = 0;
307 lefcha 1.5
308 lefcha 1.3 strncat(search, "OR ", searchbuf - len - 1);
309 lefcha 1.1 len += 3;
310     }
311 lefcha 1.3 if (search[0] != 'A') {
312     search[len] = '(';
313     search[++len] = 0;
314     }
315     while ((mf = dequeue_fifo(mfifo))) {
316     strncat(search, mf->body, searchbuf - len - 1);
317 lefcha 1.1 len = strlen(search);
318 lefcha 1.3 search[len] = ' ';
319     search[++len] = 0;
320 lefcha 1.1 }
321    
322 lefcha 1.3 if (strchr(search, '(')) {
323     search[len - 1] = ')';
324     search[len] = ' ';
325     search[++len] = 0;
326     }
327 lefcha 1.1 empty_fifo(mfifo);
328     }
329    
330     search[len - 1] = 0;
331 lefcha 1.9
332     free(mfifo);
333 lefcha 1.3
334     return search;
335 lefcha 1.1 }
336    
337    
338     /*
339     * Apply the appropriate action.
340     */
341 lefcha 1.9 int apply_action(char *mesgs, unsigned int *type, char *destmbox,
342     char *args)
343 lefcha 1.1 {
344 lefcha 1.3 unsigned int cnt;
345 lefcha 1.5
346 lefcha 1.3 if (!*mesgs)
347 lefcha 1.1 return 0;
348 lefcha 1.5
349 lefcha 1.4 log_info(LOG_ACTION, type);
350     log_info(LOG_DESTINATION_MAILBOX, destmbox);
351 lefcha 1.5
352 lefcha 1.3 cnt = convert_messages(mesgs);
353 lefcha 1.5
354 lefcha 1.3 switch (*type) {
355 lefcha 1.1 case FILTER_ACTION_DELETE:
356 lefcha 1.8 info("%d message%s deleted.\n", cnt, plural(cnt));
357 lefcha 1.1 action_delete(mesgs, args);
358     break;
359     case FILTER_ACTION_COPY:
360 lefcha 1.8 info("%d message%s copied to mailbox %s.\n", cnt, plural(cnt),
361     destmbox);
362 lefcha 1.3 action_copy(mesgs, destmbox, args);
363 lefcha 1.1 break;
364     case FILTER_ACTION_MOVE:
365 lefcha 1.8 info("%d message%s moved to mailbox %s.\n", cnt, plural(cnt),
366     destmbox);
367 lefcha 1.3 action_move(mesgs, destmbox, args);
368 lefcha 1.1 break;
369     case FILTER_ACTION_LIST:
370 lefcha 1.8 info("%d message%s listed.\n", cnt, plural(cnt));
371 lefcha 1.1 action_list(mesgs, args);
372     break;
373     }
374 lefcha 1.5
375     if (!*args)
376 lefcha 1.4 log_info(LOG_WRITE, NULL);
377 lefcha 1.5
378 lefcha 1.1 return 0;
379     }
380    
381    
382     /*
383     * Delete messages and optionally list some of their headers.
384     */
385     int action_delete(char *mesgs, char *args)
386     {
387     const char *delim = " ";
388 lefcha 1.7 char *tok, *mcp, *m, *acp = NULL, *occur;
389 lefcha 1.1
390 lefcha 1.5 m = mcp = xstrdup(mesgs);
391 lefcha 1.7
392 lefcha 1.6 if (*args) {
393     acp = xstrdup(args);
394     while ((occur = strchr(acp, ',')))
395     *occur = ' ';
396     }
397 lefcha 1.3 while ((tok = strsep(&m, delim))) {
398 lefcha 1.1 if (*args) {
399 lefcha 1.3 imap_fetch(0, tok, acp);
400     fetch_response();
401 lefcha 1.1 }
402     imap_store(tok, "\\Deleted");
403 lefcha 1.3 server_response("STORE");
404 lefcha 1.1 }
405 lefcha 1.5
406 lefcha 1.3 free(mcp);
407 lefcha 1.9
408 lefcha 1.6 if (*args)
409     free(acp);
410 lefcha 1.1
411     return 0;
412     }
413    
414    
415     /*
416     * Copy messages to specified mailbox.
417     */
418 lefcha 1.3 int action_copy(char *mesgs, char *destmbox, char *args)
419 lefcha 1.1 {
420     const char *delim = " ";
421 lefcha 1.7 char *tok, *mcp, *m, *acp = NULL, *occur;
422 lefcha 1.1
423 lefcha 1.5 m = mcp = xstrdup(mesgs);
424 lefcha 1.8
425 lefcha 1.6 if (*args) {
426     acp = xstrdup(args);
427 lefcha 1.8
428 lefcha 1.6 while ((occur = strchr(acp, ',')))
429     *occur = ' ';
430     }
431 lefcha 1.3 while ((tok = strsep(&m, delim))) {
432 lefcha 1.6 if (*args) {
433 lefcha 1.3 imap_fetch(1, tok, acp);
434     fetch_response();
435     }
436     imap_copy(tok, destmbox);
437 lefcha 1.1 if (copy_response() == 1) {
438 lefcha 1.3 imap_create(destmbox);
439     if (!server_response("CREATE")) {
440     imap_copy(tok, destmbox);
441 lefcha 1.1 copy_response();
442     }
443     }
444     }
445    
446 lefcha 1.3 free(mcp);
447 lefcha 1.8
448 lefcha 1.6 if (*args)
449     free(acp);
450 lefcha 1.1
451     return 0;
452     }
453    
454    
455     /*
456     * Move messages to specified mailbox.
457     */
458 lefcha 1.3 int action_move(char *mesgs, char *destmbox, char *args)
459 lefcha 1.1 {
460 lefcha 1.3 action_copy(mesgs, destmbox, args);
461 lefcha 1.1 action_delete(mesgs, "\0");
462     imap_expunge();
463 lefcha 1.3 server_response("EXPUNGE");
464 lefcha 1.1
465     return 0;
466     }
467    
468    
469     /*
470     * List user selected headers of messages.
471     */
472     int action_list(char *mesgs, char *args)
473     {
474     const char *delim = " ";
475 lefcha 1.5 char *tok, *mcp, *m, *acp, *occur;
476    
477 lefcha 1.2 if (!*args)
478     return 0;
479 lefcha 1.1
480 lefcha 1.5 m = mcp = xstrdup(mesgs);
481     acp = xstrdup(args);
482 lefcha 1.6
483 lefcha 1.5 while ((occur = strchr(acp, ',')))
484 lefcha 1.1 *occur = ' ';
485    
486 lefcha 1.3 while ((tok = strsep(&m, delim))) {
487 lefcha 1.5 imap_fetch(1, tok, acp);
488 lefcha 1.3 fetch_response();
489 lefcha 1.1 }
490    
491 lefcha 1.3 free(mcp);
492 lefcha 1.5 free(acp);
493 lefcha 1.1
494     return 0;
495     }
496    
497    
498     /*
499     * Convert messages with contiguous sequense number to the corresponding
500 lefcha 1.5 * number range, eg. 1 2 3 5 7 8 --> 1:3 5 7:8
501 lefcha 1.1 */
502     unsigned int convert_messages(char *mesgs)
503     {
504 lefcha 1.3 unsigned int cnt, len;
505 lefcha 1.1 unsigned int start, end, tmp;
506     char *cp, *tail = NULL;
507 lefcha 1.5
508 lefcha 1.3 cnt = len = start = end = tmp = 0;
509 lefcha 1.1
510 lefcha 1.5 cp = xstrdup(mesgs);
511 lefcha 1.1
512     start = (unsigned int) strtoul(cp, &tail, 0);
513 lefcha 1.3 cnt++;
514 lefcha 1.1 end = start;
515    
516     do {
517     if (tail) {
518     tmp = (unsigned int) strtoul(tail, &tail, 0);
519     if (tmp)
520 lefcha 1.3 cnt++;
521 lefcha 1.1 }
522     if (tmp == end + 1)
523     end++;
524     else {
525     if (start == end)
526     snprintf(mesgs + len, SEARCH_MESSAGES_BUF - len - 1, "%d ",
527     start);
528     else
529     snprintf(mesgs + len, SEARCH_MESSAGES_BUF - len - 1,
530     "%d:%d ", start, end);
531    
532     len = strlen(mesgs);
533     start = end = tmp;
534     }
535     } while (tmp);
536    
537     mesgs[len - 1] = 0;
538    
539     free(cp);
540 lefcha 1.5
541 lefcha 1.3 return cnt;
542 lefcha 1.1 }

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26