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

Annotation of /imapfilter/request.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.14 - (hide annotations)
Thu Nov 8 17:57:41 2001 UTC (22 years, 4 months ago) by lefcha
Branch: MAIN
Changes since 1.13: +0 -2 lines
File MIME type: text/plain
Small changes.

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