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

Contents of /imapfilter/request.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.3 - (show 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 #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 imap_noop();
21 return server_response("NOOP");
22 }
23 #endif
24
25 /*
26 * Login to server.
27 */
28 int login(char *user, char *pass)
29 {
30 imap_login(user, pass);
31 return server_response("LOGIN");
32 }
33
34
35 /*
36 * Open mailbox in read-write mode.
37 */
38 int select_mailbox(char *mbox)
39 {
40 int r;
41
42 imap_select(mbox);
43 r = server_response("SELECT");
44
45 if (!r)
46 mailbox_status(mbox);
47
48 log_info(2, mbox);
49
50 return r;
51 }
52
53
54 /*
55 * Get mailbox's status.
56 */
57 int mailbox_status(char *mbox)
58 {
59 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 }
69 /*
70 * Close examined/selected mailbox.
71 */
72 int close_mailbox(void)
73 {
74 imap_close();
75 return server_response("CLOSE");
76 }
77
78
79 /*
80 * Logout from server.
81 */
82 int logout(void)
83 {
84 imap_logout();
85 return server_response("LOGOUT");
86 }
87
88
89 /*
90 * Match and apply filters assigned to a mailbox.
91 */
92 int apply_filters(filter_t ** filters, char *mbox)
93 {
94 int i;
95 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 apply_action(mesgs, &(filters[i]->action.type),
105 filters[i]->action.destmbox, filters[i]->action.args);
106 }
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 char *search;
119
120 if (filter->mode == FILTER_MODE_OR)
121 search = generate_filter_or(filter->masks, filter->masknum, filter->masklen);
122 else
123 search = generate_filter_and(filter->masks, filter->masknum, filter->masklen);
124
125 imap_search(search);
126 search_response(mesgs);
127
128 free(search);
129
130 if (!*mesgs)
131 return 1;
132
133 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 queue_fifo(NULL, NULL);
145 dequeue_fifo(NULL);
146 }
147
148
149 /*
150 * Add item to FIFO inventory.
151 */
152 void queue_fifo(mask_t ** mfifo, mask_t * mask)
153 {
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 mask_t *dequeue_fifo(mask_t ** mfifo)
170 {
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 char *generate_filter_and(mask_t * mask, unsigned int masknum, unsigned int masklen)
187 {
188 const unsigned int searchbuf = masklen + masknum * 6 + 8;
189 int len = 0;
190 char *search;
191 mask_t **mfifo; /* Mailbox FIFO queue. */
192 mask_t *mf; /* Mask returned from FIFO. */
193
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 empty_fifo(mfifo);
203
204 strncat(search, "ALL ", searchbuf - len - 1);
205 len += 4;
206
207 while (mask) {
208 if (mask->type == MASK_TYPE_OR) {
209
210 if (len == 4 && search[0] == 'A')
211 search[0] = len = 0;
212
213 strncat(search, "OR (", searchbuf - len - 1);
214 len += 4;
215
216 while ((mf = dequeue_fifo(mfifo))) {
217 strncat(search, mf->body, searchbuf - len - 1);
218 len = strlen(search);
219 search[len] = ' ';
220 search[++len] = 0;
221 }
222
223 empty_fifo(mfifo);
224
225 search[len - 1] = ')';
226 search[len] = ' ';
227 search[++len] = 0;
228 }
229
230 queue_fifo(mfifo, mask);
231
232 mask = mask->next;
233 }
234
235 if (search[0] != 'A') {
236 search[len] = '(';
237 search[++len] = 0;
238 }
239
240 while ((mf = dequeue_fifo(mfifo))) {
241 strncat(search, mf->body, searchbuf - len - 1);
242 len = strlen(search);
243 search[len] = ' ';
244 search[++len] = 0;
245 }
246
247 if (strchr(search, '(')) {
248 search[len - 1] = ')';
249 search[len] = 0;
250 }
251
252 if (search[len - 1] == ' ')
253 search[len - 1] = 0;
254
255 return search;
256 }
257
258
259 /*
260 * Generate the filter search command from the masks, assuming that
261 * masks are OR-ed
262 */
263 char *generate_filter_or(mask_t * mask, unsigned int masknum, unsigned int masklen)
264 {
265 const unsigned int searchbuf = masklen + masknum * 6 + 8;
266 int len = 0;
267 char *search;
268 mask_t **mfifo; /* Mailbox FIFO queue. */
269 mask_t *mf; /* Mask returned from FIFO. */
270
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
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
301 if (search[0] != 'A') {
302 search[len] = '(';
303 search[++len] = 0;
304 }
305
306 while ((mf = dequeue_fifo(mfifo))) {
307 strncat(search, mf->body, searchbuf - len - 1);
308 len = strlen(search);
309 search[len] = ' ';
310 search[++len] = 0;
311 }
312
313 if (strchr(search, '(')) {
314 search[len - 1] = ')';
315 search[len] = ' ';
316 search[++len] = 0;
317 }
318
319 empty_fifo(mfifo);
320 }
321
322 search[len - 1] = 0;
323
324 return search;
325 }
326
327
328 /*
329 * Apply the appropriate action.
330 */
331 int apply_action(char *mesgs, unsigned int *type, char *destmbox, char *args)
332 {
333 unsigned int cnt;
334
335 if (!*mesgs)
336 return 0;
337
338 log_info(3, type);
339 log_info(4, destmbox);
340
341 cnt = convert_messages(mesgs);
342
343 switch (*type) {
344 case FILTER_ACTION_DELETE:
345 info("%d messages deleted.\n", cnt);
346 action_delete(mesgs, args);
347 break;
348 case FILTER_ACTION_COPY:
349 info("%d messages copied to mailbox %s.\n", cnt, destmbox);
350 action_copy(mesgs, destmbox, args);
351 break;
352 case FILTER_ACTION_MOVE:
353 info("%d messages moved to mailbox %s.\n", cnt, destmbox);
354 action_move(mesgs, destmbox, args);
355 break;
356 case FILTER_ACTION_LIST:
357 info("%d messages listed.\n", cnt);
358 action_list(mesgs, args);
359 break;
360 }
361
362 if(!*args)
363 log_info(0, NULL);
364
365 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 char *tok, *mcp, *m, *acp, *occur;
376
377 m = mcp = strdup(mesgs);
378 acp = strdup(args);
379
380 while((occur = strchr(acp, ',')))
381 *occur = ' ';
382
383 while ((tok = strsep(&m, delim))) {
384 if (*args) {
385 imap_fetch(0, tok, acp);
386 fetch_response();
387 }
388 imap_store(tok, "\\Deleted");
389 server_response("STORE");
390 }
391
392 free(mcp);
393
394 return 0;
395 }
396
397
398 /*
399 * Copy messages to specified mailbox.
400 */
401 int action_copy(char *mesgs, char *destmbox, char *args)
402 {
403 const char *delim = " ";
404 char *tok, *mcp, *m, *acp, *occur;
405
406 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
418 imap_copy(tok, destmbox);
419 if (copy_response() == 1) {
420 imap_create(destmbox);
421 if (!server_response("CREATE")) {
422 imap_copy(tok, destmbox);
423 copy_response();
424 }
425 }
426 }
427
428 free(mcp);
429 free(acp);
430
431 return 0;
432 }
433
434
435 /*
436 * Move messages to specified mailbox.
437 */
438 int action_move(char *mesgs, char *destmbox, char *args)
439 {
440 action_copy(mesgs, destmbox, args);
441 action_delete(mesgs, "\0");
442 imap_expunge();
443 server_response("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, *occur;
456
457 if (!*args)
458 return 0;
459
460 while ((occur = strchr(args, ',')))
461 *occur = ' ';
462
463 m = mcp = strdup(mesgs);
464
465 while ((tok = strsep(&m, delim))) {
466 imap_fetch(1, tok, args);
467 fetch_response();
468 }
469
470 free(mcp);
471
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 unsigned int cnt, len;
483 unsigned int start, end, tmp;
484 char *cp, *tail = NULL;
485
486 cnt = len = start = end = tmp = 0;
487
488 cp = strdup(mesgs);
489
490 start = (unsigned int) strtoul(cp, &tail, 0);
491 cnt++;
492 end = start;
493
494 do {
495 if (tail) {
496 tmp = (unsigned int) strtoul(tail, &tail, 0);
497 if (tmp)
498 cnt++;
499 }
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 return cnt;
521 }

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26