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

Annotation of /imapfilter/request.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.52 - (hide annotations)
Sun Jul 27 15:56:05 2003 UTC (20 years, 8 months ago) by lefcha
Branch: MAIN
Changes since 1.51: +0 -1 lines
File MIME type: text/plain
Removed unused variable.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26