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

Annotation of /imapfilter/request.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.12 - (hide annotations)
Tue Nov 6 17:41:27 2001 UTC (22 years, 4 months ago) by lefcha
Branch: MAIN
Changes since 1.11: +14 -13 lines
File MIME type: text/plain
Dynamically allocate response buffer.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26