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

Annotation of /imapfilter/request.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.48 - (hide annotations)
Fri Mar 28 17:02:25 2003 UTC (21 years ago) by lefcha
Branch: MAIN
Changes since 1.47: +15 -15 lines
File MIME type: text/plain
Corrected bug with long headers and action list.

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.45 #include <time.h>
6 lefcha 1.1
7     #include "config.h"
8     #include "imapfilter.h"
9     #include "data.h"
10    
11    
12 lefcha 1.21 extern int sockpri, sockaux;
13 lefcha 1.1 extern unsigned int options;
14 lefcha 1.41 extern char charset[CHARSET_LEN];
15 lefcha 1.18 extern unsigned int capabilities;
16    
17 lefcha 1.21 namesp_t nsppri, nspaux; /* Primary and auxiliary namespace. */
18 lefcha 1.1
19 lefcha 1.3
20 lefcha 1.2 #ifdef DEBUG
21 lefcha 1.1 /*
22     * Test/ping server.
23     */
24 lefcha 1.42 int
25     test(int *sock)
26 lefcha 1.1 {
27 lefcha 1.42 return server_response(sock, imap_noop(sock));
28 lefcha 1.1 }
29 lefcha 1.25
30 lefcha 1.2 #endif
31 lefcha 1.1
32 lefcha 1.10
33 lefcha 1.1 /*
34 lefcha 1.10 * Check server's capabilities.
35 lefcha 1.1 */
36 lefcha 1.42 int
37     check_capabilities(int *sock)
38 lefcha 1.1 {
39 lefcha 1.42 capabilities = CAPABILITY_NONE;
40 lefcha 1.18
41 lefcha 1.42 return capability_response(sock, imap_capability(sock));
42 lefcha 1.1 }
43    
44    
45     /*
46 lefcha 1.18 * Get namespace of mail server's mailboxes.
47     */
48 lefcha 1.42 int
49     check_namespace(int *sock, namesp_t * nsp)
50 lefcha 1.18 {
51 lefcha 1.42 nsp->prefix[0] = nsp->delim = '\0';
52 lefcha 1.18
53 lefcha 1.42 if (!(options & OPTION_NAMESPACE) ||
54     !(capabilities & CAPABILITY_NAMESPACE))
55     return 0;
56     else
57     return namespace_response(sock, imap_namespace(sock), nsp);
58 lefcha 1.18 }
59    
60    
61     /*
62 lefcha 1.10 * Login to server.
63 lefcha 1.8 */
64 lefcha 1.42 int
65     login(int *sock, char *user, char *pass)
66 lefcha 1.8 {
67 lefcha 1.42 return server_response(sock, imap_login(sock, user, pass));
68 lefcha 1.21 }
69    
70    
71    
72     /*
73     * Check if a mailbox exists.
74     */
75 lefcha 1.42 int
76 lefcha 1.45 check_mailbox(int *sock, char *mbox)
77 lefcha 1.21 {
78 lefcha 1.45 return server_response(sock, imap_status(sock, mbox, "MESSAGES"));
79 lefcha 1.8 }
80    
81 lefcha 1.18
82 lefcha 1.8 /*
83 lefcha 1.3 * Open mailbox in read-write mode.
84 lefcha 1.1 */
85 lefcha 1.42 int
86     select_mailbox(int *sock, char *mbox, namesp_t * nsp)
87 lefcha 1.1 {
88 lefcha 1.42 int r;
89 lefcha 1.5
90 lefcha 1.42 if (mailbox_status(sock, mbox, nsp) == -2)
91     return -2; /* No messages exist. No filters need to be
92     * applied. */
93 lefcha 1.5
94 lefcha 1.42 r = select_response(sock, imap_select(sock,
95     apply_namespace(mbox, nsp->prefix,
96     nsp->delim)));
97 lefcha 1.5
98 lefcha 1.42 log_info(LOG_MAILBOX, mbox);
99 lefcha 1.5
100 lefcha 1.42 return r;
101 lefcha 1.1 }
102    
103    
104     /*
105 lefcha 1.3 * Get mailbox's status.
106 lefcha 1.1 */
107 lefcha 1.42 int
108     mailbox_status(int *sock, char *mbox, namesp_t * nsp)
109 lefcha 1.1 {
110 lefcha 1.42 return status_response(sock, imap_status(sock,
111     apply_namespace(mbox, nsp->prefix, nsp->delim),
112     "MESSAGES RECENT UNSEEN"), mbox);
113 lefcha 1.16 }
114 lefcha 1.5
115 lefcha 1.9
116 lefcha 1.1 /*
117     * Close examined/selected mailbox.
118     */
119 lefcha 1.42 int
120     close_mailbox(int *sock)
121 lefcha 1.1 {
122 lefcha 1.42 return server_response(sock, imap_close(sock));
123 lefcha 1.1 }
124    
125    
126     /*
127     * Logout from server.
128     */
129 lefcha 1.42 int
130     logout(int *sock)
131 lefcha 1.1 {
132 lefcha 1.42 return logout_response(sock, imap_logout(sock));
133 lefcha 1.1 }
134    
135    
136     /*
137     * Match and apply filters assigned to a mailbox.
138     */
139 lefcha 1.42 int
140 lefcha 1.47 apply_filters(char *mbox, filter_t ** filters)
141 lefcha 1.1 {
142 lefcha 1.42 int i;
143     char *mesgs;
144 lefcha 1.1
145 lefcha 1.42 for (i = 0; filters[i] != NULL; i++) {
146     mesgs = NULL;
147 lefcha 1.1
148 lefcha 1.42 if (match_filter(filters[i], &mesgs))
149     continue;
150 lefcha 1.5
151 lefcha 1.42 log_info(LOG_FILTER, filters[i]->key);
152 lefcha 1.1
153 lefcha 1.47 apply_action(mbox, mesgs, &(filters[i]->action.type),
154 lefcha 1.42 filters[i]->action.raccount, filters[i]->action.destmbox,
155     &filters[i]->action.msgflags, filters[i]->action.args);
156 lefcha 1.12
157 lefcha 1.42 xfree(mesgs);
158     }
159 lefcha 1.1
160 lefcha 1.42 return 0;
161 lefcha 1.1 }
162    
163    
164     /*
165     * Generate the search request by the masks of the filter and try to
166     * match the generated filter.
167     */
168 lefcha 1.42 int
169     match_filter(filter_t * filter, char **mesgs)
170 lefcha 1.1 {
171 lefcha 1.42 char *search;
172 lefcha 1.5
173 lefcha 1.42 if (filter->mode == FILTER_MODE_OR)
174     search = generate_filter_or(filter->masks, filter->masknum,
175     filter->masklen);
176     else
177     search = generate_filter_and(filter->masks, filter->masknum,
178     filter->masklen);
179 lefcha 1.1
180 lefcha 1.42 search_response(&sockpri, imap_search(&sockpri, charset, search),
181     mesgs);
182 lefcha 1.5
183 lefcha 1.42 xfree(search);
184 lefcha 1.5
185 lefcha 1.42 if (*mesgs == '\0')
186     return 1;
187 lefcha 1.5
188 lefcha 1.42 return 0;
189 lefcha 1.1 }
190    
191    
192     /*
193     * Empty the FIFO inventory.
194     */
195 lefcha 1.42 void
196     empty_fifo(mask_t ** mfifo)
197 lefcha 1.1 {
198 lefcha 1.42 mfifo[0] = NULL;
199 lefcha 1.1
200 lefcha 1.42 queue_fifo(NULL, NULL);
201     dequeue_fifo(NULL);
202 lefcha 1.1 }
203    
204    
205     /*
206     * Add item to FIFO inventory.
207     */
208 lefcha 1.42 void
209     queue_fifo(mask_t ** mfifo, mask_t * mask)
210 lefcha 1.1 {
211 lefcha 1.42 static unsigned int i;
212 lefcha 1.1
213 lefcha 1.42 if (mfifo == NULL) {
214     i = 0;
215     return;
216     }
217     mfifo[i++] = mask;
218     mfifo[i] = NULL;
219 lefcha 1.1 }
220    
221    
222     /*
223     * Get next item from FIFO inventory.
224     */
225 lefcha 1.42 mask_t *
226     dequeue_fifo(mask_t ** mfifo)
227 lefcha 1.1 {
228 lefcha 1.42 static unsigned int j;
229 lefcha 1.1
230 lefcha 1.42 if (mfifo == NULL) {
231     j = 0;
232     return NULL;
233     }
234     return mfifo[j++];
235 lefcha 1.1 }
236    
237    
238     /*
239     * Generate the filter search command from the masks, assuming that
240     * masks are AND-ed.
241     */
242 lefcha 1.42 char *
243     generate_filter_and(mask_t * mask, unsigned int masknum,
244     unsigned int masklen)
245     {
246     const unsigned int searchbuf = masklen + masknum * 6 + 8;
247     unsigned int len;
248     char *search;
249     mask_t *tmp;
250 lefcha 1.5
251 lefcha 1.42 len = 0;
252 lefcha 1.5
253 lefcha 1.42 search = (char *)xmalloc(sizeof(char) * searchbuf);
254     search[0] = '\0';
255 lefcha 1.1
256 lefcha 1.42 tmp = mask;
257     if (tmp == NULL) {
258 lefcha 1.12 strncat(search, "ALL ", searchbuf - len - 1);
259     len += 4;
260 lefcha 1.42 } else
261     while ((tmp = tmp->next) != NULL) {
262     if (tmp->type != MASK_TYPE_OR) {
263     strncat(search, "ALL ", searchbuf - len - 1);
264     len += 4;
265     break;
266     }
267     }
268    
269     tmp = NULL;
270     while (mask != NULL) {
271     tmp = mask;
272     mask = mask->next;
273 lefcha 1.1
274 lefcha 1.42 if (mask != NULL && mask->type == MASK_TYPE_OR) {
275     strncat(search, "OR (", searchbuf - len - 1);
276     len += 4;
277    
278     strncat(search, tmp->body, searchbuf - len - 1);
279     len = strlen(search);
280     search[len] = ' ';
281     search[++len] = '\0';
282    
283     search[len - 1] = ')';
284     search[len] = ' ';
285     search[++len] = '\0';
286    
287     if (mask->next == NULL ||
288     mask->next->type != MASK_TYPE_OR) {
289     search[len] = '(';
290     search[++len] = '\0';
291     strncat(search, mask->body,
292     searchbuf - len - 1);
293     len = strlen(search);
294     search[len] = ')';
295     search[++len] = ' ';
296     search[++len] = '\0';
297     mask = mask->next;
298     }
299     } else {
300     strncat(search, tmp->body, searchbuf - len - 1);
301     len = strlen(search);
302     search[len] = ' ';
303     search[++len] = '\0';
304     }
305 lefcha 1.1 }
306 lefcha 1.10
307 lefcha 1.42 search[len - 1] = '\0';
308 lefcha 1.5
309 lefcha 1.42 return search;
310 lefcha 1.1 }
311    
312    
313     /*
314     * Generate the filter search command from the masks, assuming that
315 lefcha 1.22 * masks are OR-ed.
316 lefcha 1.1 */
317 lefcha 1.42 char *
318     generate_filter_or(mask_t * mask, unsigned int masknum,
319     unsigned int masklen)
320     {
321     const unsigned int searchbuf = masklen + masknum * 6 + 8;
322     unsigned int len;
323     char *search;
324     mask_t **mfifo; /* Mailbox FIFO queue. */
325     mask_t *mf; /* Mask returned from FIFO. */
326 lefcha 1.5
327 lefcha 1.42 len = 0;
328 lefcha 1.1
329 lefcha 1.42 search = (char *)xmalloc(sizeof(char) * searchbuf);
330     mfifo = (mask_t **) xmalloc(sizeof(mask_t *) * (masknum + 1));
331 lefcha 1.1
332 lefcha 1.42 search[0] = '\0';
333     empty_fifo(mfifo);
334 lefcha 1.1
335 lefcha 1.42 strncat(search, "ALL ", searchbuf - len - 1);
336     len += 4;
337 lefcha 1.1
338 lefcha 1.42 while (mask != NULL) {
339     queue_fifo(mfifo, mask);
340     mask = mask->next;
341 lefcha 1.1
342 lefcha 1.42 while (mask != NULL && mask->type == MASK_TYPE_AND) {
343     queue_fifo(mfifo, mask);
344     mask = mask->next;
345     }
346    
347     if (mask != NULL) {
348     if (len == 4 && search[0] == 'A') {
349     search[0] = '\0';
350     len = 0;
351     }
352     strncat(search, "OR ", searchbuf - len - 1);
353     len += 3;
354     }
355     if (search[0] != 'A') {
356     search[len] = '(';
357     search[++len] = '\0';
358     }
359     while ((mf = dequeue_fifo(mfifo)) != NULL) {
360     strncat(search, mf->body, searchbuf - len - 1);
361     len = strlen(search);
362     search[len] = ' ';
363     search[++len] = '\0';
364     }
365    
366     if (strchr(search, '(')) {
367     search[len - 1] = ')';
368     search[len] = ' ';
369     search[++len] = '\0';
370     }
371     empty_fifo(mfifo);
372 lefcha 1.1 }
373    
374 lefcha 1.42 search[len - 1] = '\0';
375 lefcha 1.10
376 lefcha 1.42 xfree(mfifo);
377 lefcha 1.3
378 lefcha 1.42 return search;
379 lefcha 1.1 }
380    
381    
382     /*
383     * Apply the appropriate action.
384     */
385 lefcha 1.42 int
386 lefcha 1.47 apply_action(char *mbox, char *mesgs, unsigned int *type, account_t * raccount,
387 lefcha 1.42 char *destmbox, unsigned int *msgflags, char *args)
388 lefcha 1.1 {
389 lefcha 1.42 unsigned int cnt;
390 lefcha 1.5
391 lefcha 1.42 if (*mesgs == '\0')
392     return 0;
393 lefcha 1.25
394 lefcha 1.42 log_info(LOG_ACTION, type);
395     log_info(LOG_DESTINATION_ACCOUNT, raccount->key);
396     log_info(LOG_DESTINATION_MAILBOX, destmbox);
397 lefcha 1.25
398 lefcha 1.42 cnt = count_messages(mesgs);
399 lefcha 1.25
400 lefcha 1.42 switch (*type) {
401     case FILTER_ACTION_DELETE:
402     info("%d message%s deleted.\n", cnt, plural(cnt));
403     action_delete(mesgs, args);
404     break;
405     case FILTER_ACTION_COPY:
406     info("%d message%s copied to mailbox \"%s\".\n", cnt,
407     plural(cnt), destmbox);
408 lefcha 1.47 action_copy(mbox, mesgs, apply_namespace(destmbox,
409     nsppri.prefix, nsppri.delim), args);
410 lefcha 1.42 break;
411     case FILTER_ACTION_MOVE:
412     info("%d message%s moved to mailbox \"%s\".\n", cnt,
413     plural(cnt), destmbox);
414 lefcha 1.47 action_move(mbox, mesgs, apply_namespace(destmbox,
415     nsppri.prefix, nsppri.delim), args);
416 lefcha 1.42 break;
417     case FILTER_ACTION_RCOPY:
418     info("%d message%s copied to mailbox \"%s\" at account %s.\n",
419     cnt, plural(cnt), destmbox, raccount->key);
420 lefcha 1.47 action_rcopy(mbox, mesgs, raccount, destmbox, args);
421 lefcha 1.42 break;
422     case FILTER_ACTION_RMOVE:
423     info("%d message%s moved to mailbox \"%s\" at account %s.\n",
424     cnt, plural(cnt), destmbox, raccount->key);
425 lefcha 1.47 action_rmove(mbox, mesgs, raccount, destmbox, args);
426 lefcha 1.42 break;
427     case FILTER_ACTION_FLAG_REPLACE:
428     case FILTER_ACTION_FLAG_ADD:
429     case FILTER_ACTION_FLAG_REMOVE:
430     info("%d message%s flagged.\n", cnt, plural(cnt));
431     action_flag(mesgs, type, msgflags, args);
432     break;
433     case FILTER_ACTION_LIST:
434     info("%d message%s listed.\n", cnt, plural(cnt));
435     action_list(mesgs, args);
436     break;
437     }
438 lefcha 1.5
439 lefcha 1.43 if (*args == '\0')
440 lefcha 1.48 log_info(LOG_PREAMBLE, NULL);
441 lefcha 1.5
442 lefcha 1.42 return 0;
443 lefcha 1.1 }
444    
445    
446     /*
447     * Delete messages and optionally list some of their headers.
448     */
449 lefcha 1.42 int
450     action_delete(char *mesgs, char *args)
451 lefcha 1.1 {
452 lefcha 1.42 char *tok, *m, *mcp;
453 lefcha 1.23
454 lefcha 1.42 action_list(mesgs, args);
455 lefcha 1.25
456 lefcha 1.42 m = mcp = convert_messages(mesgs);
457 lefcha 1.25
458 lefcha 1.42 tok = strtok_r(m, " ", &m);
459     while (tok) {
460     server_response(&sockpri, imap_store(&sockpri, tok,
461     STORE_FLAG_ADD, "\\Deleted"));
462 lefcha 1.5
463 lefcha 1.42 tok = strtok_r(NULL, " ", &m);
464     }
465 lefcha 1.34
466 lefcha 1.42 if (options & OPTION_EXPUNGE)
467     server_response(&sockpri, imap_expunge(&sockpri));
468 lefcha 1.25
469 lefcha 1.42 xfree(mcp);
470 lefcha 1.10
471 lefcha 1.42 return 0;
472 lefcha 1.1 }
473    
474    
475     /*
476     * Copy messages to specified mailbox.
477     */
478 lefcha 1.42 int
479 lefcha 1.47 action_copy(char *mbox, char *mesgs, char *destmbox, char *args)
480 lefcha 1.1 {
481 lefcha 1.42 int r;
482     char *tok, *mcp, *m;
483 lefcha 1.45 char dm[2][MBOX_NAME_LEN];
484 lefcha 1.42
485     r = 0;
486     tok = NULL;
487 lefcha 1.25
488 lefcha 1.42 action_list(mesgs, args);
489 lefcha 1.25
490 lefcha 1.44 if (strchr(destmbox, '@'))
491     m = mcp = xstrdup(mesgs);
492     else
493     m = mcp = convert_messages(mesgs);
494 lefcha 1.23
495 lefcha 1.45 xstrncpy(dm[0], destmbox, MBOX_NAME_LEN - 1);
496 lefcha 1.47 default_variables(mbox, dm[0]);
497 lefcha 1.45 current_date(dm[0]);
498 lefcha 1.42 tok = strtok_r(m, " ", &m);
499     while (tok != NULL) {
500 lefcha 1.45 xstrncpy(dm[1], dm[0], MBOX_NAME_LEN - 1);
501     message_date(tok, dm[1]);
502 lefcha 1.44
503 lefcha 1.42 if ((r = copy_response(&sockpri, imap_copy(&sockpri, tok,
504 lefcha 1.45 dm[1]))) == RESPONSE_TRYCREATE)
505 lefcha 1.42 if (!server_response(&sockpri, imap_create(&sockpri,
506 lefcha 1.45 dm[1]))) {
507 lefcha 1.42 if ((options & OPTION_SUBSCRIBE))
508     server_response(&sockpri,
509 lefcha 1.45 imap_subscribe(&sockpri, dm[1]));
510 lefcha 1.42 r = copy_response(&sockpri,
511 lefcha 1.45 imap_copy(&sockpri, tok, dm[1]));
512 lefcha 1.42 }
513     tok = strtok_r(NULL, " ", &m);
514     }
515 lefcha 1.23
516 lefcha 1.42 xfree(mcp);
517 lefcha 1.8
518 lefcha 1.42 return r;
519 lefcha 1.1 }
520    
521    
522     /*
523     * Move messages to specified mailbox.
524     */
525 lefcha 1.42 int
526 lefcha 1.47 action_move(char *mbox, char *mesgs, char *destmbox, char *args)
527 lefcha 1.1 {
528 lefcha 1.47 if (!action_copy(mbox, mesgs, destmbox, args))
529 lefcha 1.42 action_delete(mesgs, "\0");
530 lefcha 1.16
531 lefcha 1.42 return 0;
532 lefcha 1.1 }
533    
534    
535     /*
536 lefcha 1.21 * Copy messages to the specified mailbox of another mail server.
537     */
538 lefcha 1.42 int
539 lefcha 1.47 action_rcopy(char *mbox, char *mesgs, account_t * destacc, char *destmbox,
540     char *args)
541 lefcha 1.21 {
542 lefcha 1.42 int r, ta, tf;
543     char *tok, *m, *mcp, *ndm;
544     unsigned int n;
545 lefcha 1.48 char buf[RESPONSE_BUF * 2 + 1];
546 lefcha 1.45 char dm[3][MBOX_NAME_LEN];
547    
548     *dm[0] = *dm[1] = *dm[2] = '\0';
549 lefcha 1.42
550     if (init_connection(&sockaux, destacc->server, destacc->port,
551     destacc->ssl))
552     return ERROR_NETWORK;
553 lefcha 1.25
554 lefcha 1.42 r = greeting_response(&sockaux);
555 lefcha 1.25
556 lefcha 1.21 #ifdef DEBUG
557 lefcha 1.42 test(&sockaux);
558 lefcha 1.21 #endif
559 lefcha 1.25
560 lefcha 1.48 if (r == RESPONSE_BYE || check_capabilities(&sockaux))
561     return ERROR_NETWORK;
562    
563 lefcha 1.42 if (r != RESPONSE_PREAUTH) {
564     if (destacc->passwdattr == PASSWORD_NONE) {
565     printf("Enter password for %s@%s: ", destacc->username,
566     destacc->server);
567     get_password(destacc->password, PASSWORD_LEN);
568     destacc->passwdattr = PASSWORD_PLAIN;
569     }
570     if (login(&sockaux, destacc->username,
571     destacc->password) == RESPONSE_NO) {
572     error("username %s or password rejected at %s\n",
573     destacc->username, destacc->server);
574     return ERROR_NETWORK;
575     }
576     }
577     check_namespace(&sockaux, &nspaux);
578    
579 lefcha 1.45 m = mcp = xstrdup(mesgs);
580 lefcha 1.42
581 lefcha 1.45 xstrncpy(dm[1], destmbox, MBOX_NAME_LEN - 1);
582     current_date(dm[1]);
583 lefcha 1.25
584 lefcha 1.42 tok = strtok_r(m, " ", &m);
585     while (tok != NULL) {
586 lefcha 1.45 xstrncpy(dm[2], dm[1], MBOX_NAME_LEN - 1);
587     message_date(tok, dm[2]);
588    
589     /* apply_namespace() returns a pointer to a static buffer. */
590     ndm = apply_namespace(dm[2], nspaux.prefix, nspaux.delim);
591    
592     /* Check only if mailbox name is different from last one. */
593     if (strncmp(dm[0], dm[2], strlen(dm[2]))) {
594     r = check_mailbox(&sockaux, ndm);
595     if (r == RESPONSE_NO) {
596     server_response(&sockaux,
597     imap_create(&sockaux, ndm));
598     if ((options & OPTION_SUBSCRIBE))
599     server_response(&sockaux,
600     imap_subscribe(&sockaux, ndm));
601     }
602     }
603     xstrncpy(dm[0], dm[2], MBOX_NAME_LEN - 1);
604    
605 lefcha 1.42 fetchsize_response(&sockpri, &n,
606     imap_fetch(&sockpri, tok, "RFC822.SIZE"));
607 lefcha 1.21
608 lefcha 1.42 ta = imap_append(&sockaux, ndm, n);
609    
610     fetch_response(&sockpri, 0, 1, NULL);
611     tf = imap_fetch(&sockpri, tok, "RFC822.HEADER");
612     do {
613     r = fetch_response(&sockpri, tf, 0, buf);
614     socket_write(&sockaux, buf);
615     } while (r == RESPONSE_NONE);
616 lefcha 1.25
617 lefcha 1.42 socket_write(&sockaux, "\r\n");
618 lefcha 1.21
619 lefcha 1.42 fetch_response(&sockpri, 0, 1, NULL);
620     tf = imap_fetch(&sockpri, tok, "BODY[TEXT]");
621     do {
622     r = fetch_response(&sockpri, tf, 0, buf);
623     if (r != RESPONSE_NULLBODY)
624     socket_write(&sockaux, buf);
625     } while (r == RESPONSE_NONE);
626 lefcha 1.25
627 lefcha 1.42 if (r != RESPONSE_NULLBODY)
628     socket_write(&sockaux, "\r\n\r\n");
629     else
630     socket_write(&sockaux, "\r\n");
631 lefcha 1.25
632 lefcha 1.42 append_response(&sockaux, ta);
633 lefcha 1.34
634 lefcha 1.42 tok = strtok_r(NULL, " ", &m);
635     }
636 lefcha 1.21
637 lefcha 1.42 logout(&sockaux);
638 lefcha 1.25
639 lefcha 1.42 action_list(mesgs, args);
640 lefcha 1.25
641 lefcha 1.42 xfree(mcp);
642 lefcha 1.21
643 lefcha 1.42 return 0;
644 lefcha 1.21 }
645    
646    
647     /*
648     * Move messages to the specified mailbox of another mail server.
649     */
650 lefcha 1.42 int
651 lefcha 1.47 action_rmove(char *mbox, char *mesgs, account_t * destacc, char *destmbox,
652     char *args)
653 lefcha 1.21 {
654 lefcha 1.47 if (!action_rcopy(mbox, mesgs, destacc, destmbox, args))
655 lefcha 1.42 action_delete(mesgs, "\0");
656 lefcha 1.25
657 lefcha 1.42 return 0;
658 lefcha 1.21 }
659    
660 lefcha 1.26
661     /*
662 lefcha 1.27 * Flag messages by replacing, adding or removing specified flags.
663 lefcha 1.26 */
664 lefcha 1.42 int
665     action_flag(char *mesgs, unsigned int *type, unsigned int *msgflags,
666     char *args)
667     {
668     unsigned int t;
669     char s[STORE_FLAGS_BUF];
670     char *tok, *m, *mcp;
671    
672     *s = 0;
673    
674     switch (*type) {
675     case FILTER_ACTION_FLAG_ADD:
676     t = STORE_FLAG_ADD;
677     break;
678     case FILTER_ACTION_FLAG_REMOVE:
679     t = STORE_FLAG_REMOVE;
680     break;
681     default:
682     t = STORE_FLAG_REPLACE;
683     }
684    
685     if ((*msgflags != MESSAGE_FLAG_NONE)) {
686     if ((*msgflags & MESSAGE_FLAG_SEEN))
687     strncat(s, "\\Seen ", STORE_FLAGS_BUF - strlen(s) - 1);
688     if ((*msgflags & MESSAGE_FLAG_ANSWERED))
689     strncat(s, "\\Answered ",
690     STORE_FLAGS_BUF - strlen(s) - 1);
691     if ((*msgflags & MESSAGE_FLAG_FLAGGED))
692     strncat(s, "\\Flagged ",
693     STORE_FLAGS_BUF - strlen(s) - 1);
694     if ((*msgflags & MESSAGE_FLAG_DELETED))
695     strncat(s, "\\Deleted ",
696     STORE_FLAGS_BUF - strlen(s) - 1);
697     if ((*msgflags & MESSAGE_FLAG_DRAFT))
698     strncat(s, "\\Draft", STORE_FLAGS_BUF - strlen(s) - 1);
699     if ((s[strlen(s) - 1] == ' '))
700     s[strlen(s) - 1] = 0;
701     }
702     action_list(mesgs, args);
703    
704     m = mcp = convert_messages(mesgs);
705    
706     tok = strtok_r(m, " ", &m);
707     while (tok != NULL) {
708     server_response(&sockpri, imap_store(&sockpri, tok, t, s));
709    
710     tok = strtok_r(NULL, " ", &m);
711     }
712 lefcha 1.34
713 lefcha 1.42 if (options & OPTION_EXPUNGE)
714     server_response(&sockpri, imap_expunge(&sockpri));
715 lefcha 1.26
716 lefcha 1.42 xfree(mcp);
717 lefcha 1.26
718 lefcha 1.42 return 0;
719 lefcha 1.26 }
720 lefcha 1.21
721     /*
722 lefcha 1.1 * List user selected headers of messages.
723     */
724 lefcha 1.42 int
725     action_list(char *mesgs, char *args)
726 lefcha 1.1 {
727 lefcha 1.42 int r, t;
728     char *tok, *mcp, *m;
729     char s[ARGS_LEN + 27];
730 lefcha 1.48 char hdrs[RESPONSE_BUF * 2 + 1];
731 lefcha 1.42
732     if (*args == '\0')
733     return 0;
734    
735     m = mcp = xstrdup(mesgs);
736    
737     snprintf(s, ARGS_LEN + 27 - 1, "BODY.PEEK[HEADER.FIELDS (%s)]", args);
738    
739     tok = strtok_r(m, " ", &m);
740     while (tok != NULL) {
741     /* Reset internal fetch counter. */
742     fetch_response(&sockpri, 0, 1, NULL);
743     t = imap_fetch(&sockpri, tok, s);
744 lefcha 1.48
745     log_info(LOG_PREAMBLE, NULL);
746 lefcha 1.42 do {
747     r = fetch_response(&sockpri, t, 0, hdrs);
748 lefcha 1.48
749     if (*hdrs != '\0') {
750     if (options & OPTION_HEADERS)
751     info("%s\n", hdrs);
752     log_info(LOG_HEADER, hdrs);
753     }
754 lefcha 1.42 } while (r == RESPONSE_NONE);
755    
756     tok = strtok_r(NULL, " ", &m);
757 lefcha 1.33 }
758 lefcha 1.34
759 lefcha 1.42 xfree(mcp);
760 lefcha 1.1
761 lefcha 1.42 return 0;
762 lefcha 1.1 }
763    
764    
765     /*
766 lefcha 1.21 * Count how many messages matched the filter.
767     */
768 lefcha 1.42 unsigned int
769     count_messages(char *mesgs)
770 lefcha 1.21 {
771 lefcha 1.42 unsigned int cnt;
772     char *c;
773 lefcha 1.25
774 lefcha 1.42 cnt = 0;
775     c = mesgs;
776 lefcha 1.21
777 lefcha 1.42 while ((c = strchr(c, ' '))) {
778     cnt++;
779     c++;
780     }
781    
782     return ++cnt;
783 lefcha 1.21 }
784    
785    
786     /*
787 lefcha 1.11 * Convert messages with contiguous sequence number to the corresponding
788 lefcha 1.27 * number range, eg. 1 2 3 5 7 8 --> 1:3 5 7:8 and return a newly allocated
789     * buffer with the results.
790 lefcha 1.1 */
791 lefcha 1.42 char *
792     convert_messages(char *mesgs)
793 lefcha 1.1 {
794 lefcha 1.42 int maxlen;
795     unsigned int start, end, tmp;
796     char *c, *cp, *tail;
797    
798     start = end = tmp = 0;
799     maxlen = strlen(mesgs) + 1;
800     tail = NULL;
801    
802     c = cp = xstrdup(mesgs);
803    
804     start = (unsigned int)strtoul(mesgs, &tail, 10);
805     end = start;
806    
807     do {
808     if (tail != NULL) {
809     tmp = (unsigned int)strtoul(tail, &tail, 10);
810 lefcha 1.43 if (tmp == 0)
811 lefcha 1.42 tail = NULL;
812     }
813     if (tmp == end + 1)
814     end++;
815     else {
816     if (start == end) {
817     xstrncpy(c, ultostr(start, 10), maxlen);
818     c += strlen(c);
819     } else {
820     xstrncpy(c, ultostr(start, 10), maxlen - 1);
821     c += strlen(c);
822     *c = ':';
823     *++c = 0;
824     xstrncpy(c, ultostr(end, 10), maxlen);
825     c += strlen(c);
826     }
827    
828     if (tail != NULL && c - cp < maxlen) {
829     *c = ' ';
830     *++c = 0;
831     }
832     start = end = tmp;
833     }
834 lefcha 1.43 } while (tmp != 0);
835 lefcha 1.1
836 lefcha 1.42 return cp;
837 lefcha 1.44 }
838    
839    
840     /*
841     * Substitute all occurences of the '@' character with the '%' character,
842     * and any double '@' characters with a signle '@' character, returning the
843     * number of replacements.
844     */
845     int
846     substitute_date(char *str)
847     {
848     int n;
849     char *r, *w, *s;
850    
851     n = 0;
852    
853     s = xstrdup(str);
854    
855     for (r = s, w = str; *r != '\0'; r++, w++) {
856     if (*r == '%') {
857     *w++ = '%';
858     *w = '%';
859     } else if (*r == '@') {
860     if (*(r + 1) == '@') {
861     *w = *r++;
862     } else {
863     *w = '%';
864     n++;
865     }
866     } else {
867     *w = *r;
868     }
869     }
870     *w = '\0';
871    
872 lefcha 1.47 xfree(s);
873 lefcha 1.44
874     return n;
875     }
876    
877    
878     /*
879     * Format the destination mailbox according to the current date conversion
880     * specifiers.
881     */
882     void
883     current_date(char *destmbox)
884     {
885     char s[MBOX_NAME_LEN];
886     time_t te;
887     struct tm *tl;
888    
889     if (!strchr(destmbox, '%'))
890     return;
891    
892     te = time(NULL);
893     tl = localtime(&te);
894    
895     if (strftime(s, MBOX_NAME_LEN - 1, destmbox, tl))
896     xstrncpy(destmbox, s, MBOX_NAME_LEN - 1);
897     }
898    
899    
900     /*
901     * Format the destination mailbox according to the message date conversion
902     * specifiers.
903     */
904     void
905     message_date(char *mesg, char *destmbox)
906     {
907     unsigned int t;
908     char s[MBOX_NAME_LEN];
909     struct tm tl;
910 lefcha 1.48 char dbuf[RESPONSE_BUF + 1];
911 lefcha 1.44
912     if (!strchr(destmbox, '@'))
913     return;
914    
915     substitute_date(destmbox);
916    
917     fetch_response(&sockpri, 0, 1, NULL);
918     t = imap_fetch(&sockpri, mesg, "BODY.PEEK[HEADER.FIELDS (DATE)]");
919    
920     while (fetch_response(&sockpri, t, 0, dbuf) == RESPONSE_NONE);
921    
922 lefcha 1.46 if (strptime(dbuf, "Date: %a, %d %b %Y %H:%M:%S", &tl) &&
923 lefcha 1.44 strftime(s, MBOX_NAME_LEN - 1, destmbox, &tl))
924     xstrncpy(destmbox, s, MBOX_NAME_LEN - 1);
925 lefcha 1.47 }
926    
927    
928     /*
929     * Format the destination mailbox according to "default variables" specifiers.
930     */
931     void
932     default_variables(char *mbox, char *destmbox)
933     {
934     char *m, *r, *w, *s;
935    
936     if (!strchr(destmbox, '$'))
937     return;
938    
939     s = xstrdup(destmbox);
940    
941     for (r = s, w = destmbox; *r != '\0';) {
942     if (w - destmbox >= MBOX_NAME_LEN - 1)
943     break;
944     if (*r == '$') {
945     switch (*(r + 1)) {
946     case '_':
947     if (w + strlen(mbox) - destmbox >
948     MBOX_NAME_LEN - 1) {
949     r += 2;
950     break;
951     }
952     for (m = mbox; *m != '\0'; m++, w++)
953     *w = *m;
954     r += 2;
955     break;
956     case '$':
957     *w++ = '$';
958     r += 2;
959     break;
960     default:
961     *w++ = *r++;
962     break;
963     }
964     } else {
965     *w++ = *r++;
966     }
967     }
968     *w = '\0';
969    
970     xfree(s);
971 lefcha 1.1 }

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26