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

Contents of /imapfilter/request.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.13 - (show annotations)
Thu Nov 8 17:53:53 2001 UTC (22 years, 5 months ago) by lefcha
Branch: MAIN
Changes since 1.12: +22 -12 lines
File MIME type: text/plain
Changed to support dynamically allocated messages buffer.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26