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

Contents of /imapfilter/request.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.4 - (show annotations)
Mon Oct 1 11:48:51 2001 UTC (22 years, 6 months ago) by lefcha
Branch: MAIN
Changes since 1.3: +9 -4 lines
File MIME type: text/plain
Added some log records.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26