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

Annotation of /imapfilter/request.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.3 - (hide annotations)
Sun Sep 30 20:23:37 2001 UTC (22 years, 6 months ago) by lefcha
Branch: MAIN
Changes since 1.2: +185 -134 lines
File MIME type: text/plain
Bug fixes, error codes.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26