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

Annotation of /imapfilter/request.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.17 - (hide annotations)
Sat Nov 10 15:34:48 2001 UTC (22 years, 4 months ago) by lefcha
Branch: MAIN
CVS Tags: release-0_7
Branch point for: release-0_7-patches
Changes since 1.16: +1 -1 lines
File MIME type: text/plain
Typo fix.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26