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

Annotation of /imapfilter/request.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.8 - (hide annotations)
Thu Oct 4 15:47:49 2001 UTC (22 years, 5 months ago) by lefcha
Branch: MAIN
Changes since 1.7: +30 -11 lines
File MIME type: text/plain
Use imap_examine() if no filters  to apply.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26