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

Diff of /imapfilter/request.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.53 by lefcha, Sun Jul 27 17:39:45 2003 UTC revision 1.54 by lefcha, Thu Jul 31 15:53:19 2003 UTC
# Line 1  Line 1 
1  #include <stdio.h>  #include <stdio.h>
 #include <stdlib.h>  
 #include <string.h>  
 #include <errno.h>  
 #include <time.h>  
2    
3  #include "config.h"  #include "config.h"
4  #include "imapfilter.h"  #include "imapfilter.h"
 #include "data.h"  
5    
6    
7  extern conn_t connpri, connaux;  extern conn_t connpri, connaux;
8  extern unsigned int options;  extern unsigned int options;
 extern char charset[CHARSET_LEN];  
9    
10    
11  #ifdef DEBUG  #ifdef DEBUG
# Line 23  test(conn_t * conn) Line 17  test(conn_t * conn)
17  {  {
18          return server_response(conn, imap_noop(conn));          return server_response(conn, imap_noop(conn));
19  }  }
   
20  #endif  #endif
21    
22    
# Line 60  check_namespace(conn_t * conn) Line 53  check_namespace(conn_t * conn)
53   * Begin TLS negotiation (STARTTLS).   * Begin TLS negotiation (STARTTLS).
54   */   */
55  int  int
56  imf_starttls(conn_t * conn)  negotiate_tls(conn_t * conn)
57  {  {
58          int r;          int r;
59    
60          r = server_response(conn, imap_starttls(conn));          r = server_response(conn, imap_starttls(conn));
61          imf_ssl_init(conn, SSL_TLS_V1);          init_secure_connection(conn, SSL_TLS_V1);
62    
63          return r;          return r;
64  }  }
   
65  #endif  #endif
66    
67    
# Line 145  logout(conn_t * conn) Line 137  logout(conn_t * conn)
137  {  {
138          return logout_response(conn, imap_logout(conn));          return logout_response(conn, imap_logout(conn));
139  }  }
   
   
 /*  
  * Match and apply filters assigned to a mailbox.  
  */  
 int  
 apply_filters(char *mbox, filter_t ** filters)  
 {  
         int i;  
         char *mesgs;  
   
         for (i = 0; filters[i] != NULL; i++) {  
                 mesgs = NULL;  
   
                 if (match_filter(filters[i], &mesgs))  
                         continue;  
   
                 log_info(LOG_FILTER, filters[i]->key);  
   
                 apply_action(mbox, mesgs, &(filters[i]->action.type),  
                     filters[i]->action.raccount, filters[i]->action.destmbox,  
                     &filters[i]->action.msgflags, filters[i]->action.args);  
   
                 xfree(mesgs);  
         }  
   
         return 0;  
 }  
   
   
 /*  
  * Generate the search request by the masks of the filter and try to  
  * match the generated filter.  
  */  
 int  
 match_filter(filter_t * filter, char **mesgs)  
 {  
         char *search;  
   
         if (filter->mode == FILTER_MODE_OR)  
                 search = generate_filter_or(filter->masks, filter->masknum,  
                     filter->masklen);  
         else  
                 search = generate_filter_and(filter->masks, filter->masknum,  
                     filter->masklen);  
   
         search_response(&connpri, imap_search(&connpri, charset, search),  
             mesgs);  
   
         xfree(search);  
   
         if (*mesgs == '\0')  
                 return 1;  
   
         return 0;  
 }  
   
   
 /*  
  * Empty the FIFO inventory.  
  */  
 void  
 empty_fifo(mask_t ** mfifo)  
 {  
         mfifo[0] = NULL;  
   
         queue_fifo(NULL, NULL);  
         dequeue_fifo(NULL);  
 }  
   
   
 /*  
  * Add item to FIFO inventory.  
  */  
 void  
 queue_fifo(mask_t ** mfifo, mask_t * mask)  
 {  
         static unsigned int i;  
   
         if (mfifo == NULL) {  
                 i = 0;  
                 return;  
         }  
         mfifo[i++] = mask;  
         mfifo[i] = NULL;  
 }  
   
   
 /*  
  * Get next item from FIFO inventory.  
  */  
 mask_t *  
 dequeue_fifo(mask_t ** mfifo)  
 {  
         static unsigned int j;  
   
         if (mfifo == NULL) {  
                 j = 0;  
                 return NULL;  
         }  
         return mfifo[j++];  
 }  
   
   
 /*  
  * Generate the filter search command from the masks, assuming that  
  * masks are AND-ed.  
  */  
 char *  
 generate_filter_and(mask_t * mask, unsigned int masknum,  
     unsigned int masklen)  
 {  
         const unsigned int searchbuf = masklen + masknum * 6 + 8;  
         unsigned int len;  
         char *search;  
         mask_t *tmp;  
   
         len = 0;  
   
         search = (char *)xmalloc(sizeof(char) * searchbuf);  
         search[0] = '\0';  
   
         tmp = mask;  
         if (tmp == NULL) {  
                 strncat(search, "ALL ", searchbuf - len - 1);  
                 len += 4;  
         } else  
                 while ((tmp = tmp->next) != NULL) {  
                         if (tmp->type != MASK_TYPE_OR) {  
                                 strncat(search, "ALL ", searchbuf - len - 1);  
                                 len += 4;  
                                 break;  
                         }  
                 }  
   
         tmp = NULL;  
         while (mask != NULL) {  
                 tmp = mask;  
                 mask = mask->next;  
   
                 if (mask != NULL && mask->type == MASK_TYPE_OR) {  
                         strncat(search, "OR (", searchbuf - len - 1);  
                         len += 4;  
   
                         strncat(search, tmp->body, searchbuf - len - 1);  
                         len = strlen(search);  
                         search[len] = ' ';  
                         search[++len] = '\0';  
   
                         search[len - 1] = ')';  
                         search[len] = ' ';  
                         search[++len] = '\0';  
   
                         if (mask->next == NULL ||  
                             mask->next->type != MASK_TYPE_OR) {  
                                 search[len] = '(';  
                                 search[++len] = '\0';  
                                 strncat(search, mask->body,  
                                     searchbuf - len - 1);  
                                 len = strlen(search);  
                                 search[len] = ')';  
                                 search[++len] = ' ';  
                                 search[++len] = '\0';  
                                 mask = mask->next;  
                         }  
                 } else {  
                         strncat(search, tmp->body, searchbuf - len - 1);  
                         len = strlen(search);  
                         search[len] = ' ';  
                         search[++len] = '\0';  
                 }  
         }  
   
         search[len - 1] = '\0';  
   
         return search;  
 }  
   
   
 /*  
  * Generate the filter search command from the masks, assuming that  
  * masks are OR-ed.  
  */  
 char *  
 generate_filter_or(mask_t * mask, unsigned int masknum,  
     unsigned int masklen)  
 {  
         const unsigned int searchbuf = masklen + masknum * 6 + 8;  
         unsigned int len;  
         char *search;  
         mask_t **mfifo;         /* Mailbox FIFO queue. */  
         mask_t *mf;             /* Mask returned from FIFO. */  
   
         len = 0;  
   
         search = (char *)xmalloc(sizeof(char) * searchbuf);  
         mfifo = (mask_t **) xmalloc(sizeof(mask_t *) * (masknum + 1));  
   
         search[0] = '\0';  
         empty_fifo(mfifo);  
   
         strncat(search, "ALL ", searchbuf - len - 1);  
         len += 4;  
   
         while (mask != NULL) {  
                 queue_fifo(mfifo, mask);  
                 mask = mask->next;  
   
                 while (mask != NULL && mask->type == MASK_TYPE_AND) {  
                         queue_fifo(mfifo, mask);  
                         mask = mask->next;  
                 }  
   
                 if (mask != NULL) {  
                         if (len == 4 && search[0] == 'A') {  
                                 search[0] = '\0';  
                                 len = 0;  
                         }  
                         strncat(search, "OR ", searchbuf - len - 1);  
                         len += 3;  
                 }  
                 if (search[0] != 'A') {  
                         search[len] = '(';  
                         search[++len] = '\0';  
                 }  
                 while ((mf = dequeue_fifo(mfifo)) != NULL) {  
                         strncat(search, mf->body, searchbuf - len - 1);  
                         len = strlen(search);  
                         search[len] = ' ';  
                         search[++len] = '\0';  
                 }  
   
                 if (strchr(search, '(')) {  
                         search[len - 1] = ')';  
                         search[len] = ' ';  
                         search[++len] = '\0';  
                 }  
                 empty_fifo(mfifo);  
         }  
   
         search[len - 1] = '\0';  
   
         xfree(mfifo);  
   
         return search;  
 }  
   
   
 /*  
  * Apply the appropriate action.  
  */  
 int  
 apply_action(char *mbox, char *mesgs, unsigned int *type, account_t * raccount,  
     char *destmbox, unsigned int *msgflags, char *args)  
 {  
         unsigned int cnt;  
   
         if (*mesgs == '\0')  
                 return 0;  
   
         log_info(LOG_ACTION, type);  
         log_info(LOG_DESTINATION_ACCOUNT, raccount->key);  
         log_info(LOG_DESTINATION_MAILBOX, destmbox);  
   
         cnt = count_messages(mesgs);  
   
         switch (*type) {  
         case FILTER_ACTION_DELETE:  
                 info("%d message%s deleted.\n", cnt, plural(cnt));  
                 action_delete(mesgs, args);  
                 break;  
         case FILTER_ACTION_COPY:  
                 info("%d message%s copied from \"%s\" to mailbox \"%s\".\n",  
                     cnt, plural(cnt), mbox, destmbox);  
                 action_copy(mbox, mesgs, apply_namespace(destmbox,  
                         connpri.nsp.prefix, connpri.nsp.delim), args);  
                 break;  
         case FILTER_ACTION_MOVE:  
                 info("%d message%s moved from \"%s\" to mailbox \"%s\".\n",  
                     cnt, plural(cnt), mbox, destmbox);  
                 action_move(mbox, mesgs, apply_namespace(destmbox,  
                         connpri.nsp.prefix, connpri.nsp.delim), args);  
                 break;  
         case FILTER_ACTION_RCOPY:  
                 info("%d message%s copied from \"%s\" to mailbox "  
                     "\"%s\" at account %s.\n", cnt, plural(cnt),  
                     mbox, destmbox, raccount->key);  
                 action_rcopy(mbox, mesgs, raccount, destmbox, args);  
                 break;  
         case FILTER_ACTION_RMOVE:  
                 info("%d message%s moved from \"%s\" to mailbox "  
                     "\"%s\" at account %s.\n", cnt, plural(cnt),  
                     mbox, destmbox, raccount->key);  
                 action_rmove(mbox, mesgs, raccount, destmbox, args);  
                 break;  
         case FILTER_ACTION_FLAG_REPLACE:  
         case FILTER_ACTION_FLAG_ADD:  
         case FILTER_ACTION_FLAG_REMOVE:  
                 info("%d message%s flagged.\n", cnt, plural(cnt));  
                 action_flag(mesgs, type, msgflags, args);  
                 break;  
         case FILTER_ACTION_LIST:  
                 info("%d message%s listed.\n", cnt, plural(cnt));  
                 action_list(mesgs, args);  
                 break;  
         }  
   
         if (*args == '\0')  
                 log_info(LOG_PREAMBLE, NULL);  
   
         return 0;  
 }  
   
   
 /*  
  * Delete messages and optionally list some of their headers.  
  */  
 int  
 action_delete(char *mesgs, char *args)  
 {  
         char *tok, *m, *mcp;  
   
         action_list(mesgs, args);  
   
         m = mcp = convert_messages(mesgs);  
   
         tok = strtok_r(m, " ", &m);  
         while (tok) {  
                 server_response(&connpri, imap_store(&connpri, tok,  
                         STORE_FLAG_ADD, "\\Deleted"));  
   
                 tok = strtok_r(NULL, " ", &m);  
         }  
   
         if (options & OPTION_EXPUNGE)  
                 server_response(&connpri, imap_expunge(&connpri));  
   
         xfree(mcp);  
   
         return 0;  
 }  
   
   
 /*  
  * Copy messages to specified mailbox.  
  */  
 int  
 action_copy(char *mbox, char *mesgs, char *destmbox, char *args)  
 {  
         int r;  
         char *tok, *mcp, *m;  
         char dm[2][MBOX_NAME_LEN];  
   
         r = 0;  
         tok = NULL;  
   
         action_list(mesgs, args);  
   
         if (strchr(destmbox, '@'))  
                 m = mcp = xstrdup(mesgs);  
         else  
                 m = mcp = convert_messages(mesgs);  
   
         xstrncpy(dm[0], destmbox, MBOX_NAME_LEN - 1);  
         default_variables(mbox, dm[0]);  
         current_date(dm[0]);  
         tok = strtok_r(m, " ", &m);  
         while (tok != NULL) {  
                 xstrncpy(dm[1], dm[0], MBOX_NAME_LEN - 1);  
                 message_date(tok, dm[1]);  
   
                 if ((r = copy_response(&connpri, imap_copy(&connpri, tok,  
                                 dm[1]))) == RESPONSE_TRYCREATE)  
                         if (!server_response(&connpri, imap_create(&connpri,  
                                     dm[1]))) {  
                                 if ((options & OPTION_SUBSCRIBE))  
                                         server_response(&connpri,  
                                             imap_subscribe(&connpri, dm[1]));  
                                 r = copy_response(&connpri,  
                                     imap_copy(&connpri, tok, dm[1]));  
                         }  
                 tok = strtok_r(NULL, " ", &m);  
         }  
   
         xfree(mcp);  
   
         return r;  
 }  
   
   
 /*  
  * Move messages to specified mailbox.  
  */  
 int  
 action_move(char *mbox, char *mesgs, char *destmbox, char *args)  
 {  
         if (!action_copy(mbox, mesgs, destmbox, args))  
                 action_delete(mesgs, "\0");  
   
         return 0;  
 }  
   
   
 /*  
  * Copy messages to the specified mailbox of another mail server.  
  */  
 int  
 action_rcopy(char *mbox, char *mesgs, account_t * destacc, char *destmbox,  
     char *args)  
 {  
         int r, ta, tf;  
         char *tok, *m, *mcp, *ndm;  
         unsigned int n;  
         char buf[RESPONSE_BUF * 2 + 1];  
         char dm[3][MBOX_NAME_LEN];  
   
         *dm[0] = *dm[1] = *dm[2] = '\0';  
   
         if (init_connection(&connaux, destacc->server, destacc->port,  
                 destacc->ssl))  
                 return ERROR_NETWORK;  
   
         r = greeting_response(&connaux);  
   
 #ifdef DEBUG  
         test(&connaux);  
 #endif  
   
         if (r == RESPONSE_BYE || check_capabilities(&connaux))  
                 return ERROR_NETWORK;  
   
 #ifdef SSL_TLS  
         if (destacc->ssl == SSL_DISABLED && connaux.caps & CAPABILITY_STARTTLS)  
                 if (imf_starttls(&connaux) == RESPONSE_OK)  
                         check_capabilities(&connaux);  
 #endif  
   
         if (r != RESPONSE_PREAUTH) {  
                 if (destacc->passwdattr == PASSWORD_NONE) {  
                         printf("Enter password for %s@%s: ", destacc->username,  
                             destacc->server);  
                         get_password(destacc->password, PASSWORD_LEN);  
                         destacc->passwdattr = PASSWORD_PLAIN;  
                 }  
 #ifdef CRAM_MD5  
                 if (connaux.caps & CAPABILITY_AUTH_CRAM_MD5)  
                         r = imf_cram_md5(&connaux, destacc->username,  
                             destacc->password);  
                 else  
 #endif  
                         r = login(&connaux, destacc->username,  
                             destacc->password);  
   
                 if (r == RESPONSE_NO) {  
                         error("username %s or password rejected at %s\n",  
                             destacc->username, destacc->server);  
                         return ERROR_NETWORK;  
                 }  
         }  
         check_namespace(&connaux);  
   
         m = mcp = xstrdup(mesgs);  
   
         xstrncpy(dm[1], destmbox, MBOX_NAME_LEN - 1);  
         current_date(dm[1]);  
   
         tok = strtok_r(m, " ", &m);  
         while (tok != NULL) {  
                 xstrncpy(dm[2], dm[1], MBOX_NAME_LEN - 1);  
                 message_date(tok, dm[2]);  
   
                 /* apply_namespace() returns a pointer to a static buffer. */  
                 ndm = apply_namespace(dm[2], connaux.nsp.prefix,  
                     connaux.nsp.delim);  
   
                 /* Check only if mailbox name is different from last one. */  
                 if (strncmp(dm[0], dm[2], strlen(dm[2]))) {  
                         r = check_mailbox(&connaux, ndm);  
                         if (r == RESPONSE_NO) {  
                                 server_response(&connaux,  
                                     imap_create(&connaux, ndm));  
                                 if ((options & OPTION_SUBSCRIBE))  
                                         server_response(&connaux,  
                                             imap_subscribe(&connaux, ndm));  
                         }  
                 }  
                 xstrncpy(dm[0], dm[2], MBOX_NAME_LEN - 1);  
   
                 fetchsize_response(&connpri, &n,  
                     imap_fetch(&connpri, tok, "RFC822.SIZE"));  
   
                 ta = imap_append(&connaux, ndm, n);  
   
                 fetch_response(&connpri, 0, 1, NULL);  
                 tf = imap_fetch(&connpri, tok, "RFC822.HEADER");  
                 do {  
                         r = fetch_response(&connpri, tf, 0, buf);  
                         socket_write(&connaux, buf);  
                 } while (r == RESPONSE_NONE);  
   
                 socket_write(&connaux, "\r\n");  
   
                 fetch_response(&connpri, 0, 1, NULL);  
                 tf = imap_fetch(&connpri, tok, "BODY[TEXT]");  
                 do {  
                         r = fetch_response(&connpri, tf, 0, buf);  
                         if (r != RESPONSE_NULLBODY)  
                                 socket_write(&connaux, buf);  
                 } while (r == RESPONSE_NONE);  
   
                 if (r != RESPONSE_NULLBODY)  
                         socket_write(&connaux, "\r\n\r\n");  
                 else  
                         socket_write(&connaux, "\r\n");  
   
                 append_response(&connaux, ta);  
   
                 tok = strtok_r(NULL, " ", &m);  
         }  
   
         logout(&connaux);  
   
         action_list(mesgs, args);  
   
         xfree(mcp);  
   
         return 0;  
 }  
   
   
 /*  
  * Move messages to the specified mailbox of another mail server.  
  */  
 int  
 action_rmove(char *mbox, char *mesgs, account_t * destacc, char *destmbox,  
     char *args)  
 {  
         if (!action_rcopy(mbox, mesgs, destacc, destmbox, args))  
                 action_delete(mesgs, "\0");  
   
         return 0;  
 }  
   
   
 /*  
  * Flag messages by replacing, adding or removing specified flags.  
  */  
 int  
 action_flag(char *mesgs, unsigned int *type, unsigned int *msgflags,  
     char *args)  
 {  
         unsigned int t;  
         char s[STORE_FLAGS_BUF];  
         char *tok, *m, *mcp;  
   
         *s = 0;  
   
         switch (*type) {  
         case FILTER_ACTION_FLAG_ADD:  
                 t = STORE_FLAG_ADD;  
                 break;  
         case FILTER_ACTION_FLAG_REMOVE:  
                 t = STORE_FLAG_REMOVE;  
                 break;  
         default:  
                 t = STORE_FLAG_REPLACE;  
         }  
   
         if ((*msgflags != MESSAGE_FLAG_NONE)) {  
                 if ((*msgflags & MESSAGE_FLAG_SEEN))  
                         strncat(s, "\\Seen ", STORE_FLAGS_BUF - strlen(s) - 1);  
                 if ((*msgflags & MESSAGE_FLAG_ANSWERED))  
                         strncat(s, "\\Answered ",  
                             STORE_FLAGS_BUF - strlen(s) - 1);  
                 if ((*msgflags & MESSAGE_FLAG_FLAGGED))  
                         strncat(s, "\\Flagged ",  
                             STORE_FLAGS_BUF - strlen(s) - 1);  
                 if ((*msgflags & MESSAGE_FLAG_DELETED))  
                         strncat(s, "\\Deleted ",  
                             STORE_FLAGS_BUF - strlen(s) - 1);  
                 if ((*msgflags & MESSAGE_FLAG_DRAFT))  
                         strncat(s, "\\Draft", STORE_FLAGS_BUF - strlen(s) - 1);  
                 if ((s[strlen(s) - 1] == ' '))  
                         s[strlen(s) - 1] = 0;  
         }  
         action_list(mesgs, args);  
   
         m = mcp = convert_messages(mesgs);  
   
         tok = strtok_r(m, " ", &m);  
         while (tok != NULL) {  
                 server_response(&connpri, imap_store(&connpri, tok, t, s));  
   
                 tok = strtok_r(NULL, " ", &m);  
         }  
   
         if (options & OPTION_EXPUNGE)  
                 server_response(&connpri, imap_expunge(&connpri));  
   
         xfree(mcp);  
   
         return 0;  
 }  
   
 /*  
  * List user selected headers of messages.  
  */  
 int  
 action_list(char *mesgs, char *args)  
 {  
         int r, t;  
         char *tok, *mcp, *m;  
         char s[ARGS_LEN + 27];  
         char hdrs[RESPONSE_BUF * 2 + 1];  
   
         if (*args == '\0')  
                 return 0;  
   
         m = mcp = xstrdup(mesgs);  
   
         snprintf(s, ARGS_LEN + 27 - 1, "BODY.PEEK[HEADER.FIELDS (%s)]", args);  
   
         tok = strtok_r(m, " ", &m);  
         while (tok != NULL) {  
                 /* Reset internal fetch counter. */  
                 fetch_response(&connpri, 0, 1, NULL);  
                 t = imap_fetch(&connpri, tok, s);  
   
                 log_info(LOG_PREAMBLE, NULL);  
                 do {  
                         r = fetch_response(&connpri, t, 0, hdrs);  
   
                         if (*hdrs != '\0') {  
                                 if (options & OPTION_HEADERS)  
                                         info("%s\n", hdrs);  
                                 log_info(LOG_HEADER, hdrs);  
                         }  
                 } while (r == RESPONSE_NONE);  
   
                 tok = strtok_r(NULL, " ", &m);  
         }  
   
         xfree(mcp);  
   
         return 0;  
 }  
   
   
 /*  
  * Count how many messages matched the filter.  
  */  
 unsigned int  
 count_messages(char *mesgs)  
 {  
         unsigned int cnt;  
         char *c;  
   
         cnt = 0;  
         c = mesgs;  
   
         while ((c = strchr(c, ' '))) {  
                 cnt++;  
                 c++;  
         }  
   
         return ++cnt;  
 }  
   
   
 /*  
  * Convert messages with contiguous sequence number to the corresponding  
  * number range, eg. 1 2 3 5 7 8 --> 1:3 5 7:8 and return a newly allocated  
  * buffer with the results.  
  */  
 char *  
 convert_messages(char *mesgs)  
 {  
         int maxlen;  
         unsigned int start, end, tmp;  
         char *c, *cp, *tail;  
   
         start = end = tmp = 0;  
         maxlen = strlen(mesgs) + 1;  
         tail = NULL;  
   
         c = cp = xstrdup(mesgs);  
   
         start = (unsigned int)strtoul(mesgs, &tail, 10);  
         end = start;  
   
         do {  
                 if (tail != NULL) {  
                         tmp = (unsigned int)strtoul(tail, &tail, 10);  
                         if (tmp == 0)  
                                 tail = NULL;  
                 }  
                 if (tmp == end + 1)  
                         end++;  
                 else {  
                         if (start == end) {  
                                 xstrncpy(c, ultostr(start, 10), maxlen);  
                                 c += strlen(c);  
                         } else {  
                                 xstrncpy(c, ultostr(start, 10), maxlen - 1);  
                                 c += strlen(c);  
                                 *c = ':';  
                                 *++c = 0;  
                                 xstrncpy(c, ultostr(end, 10), maxlen);  
                                 c += strlen(c);  
                         }  
   
                         if (tail != NULL && c - cp < maxlen) {  
                                 *c = ' ';  
                                 *++c = 0;  
                         }  
                         start = end = tmp;  
                 }  
         } while (tmp != 0);  
   
         return cp;  
 }  
   
   
 /*  
  * Substitute all occurences of the '@' character with the '%' character,  
  * and any double '@' characters with a signle '@' character, returning the  
  * number of replacements.  
  */  
 int  
 substitute_date(char *str)  
 {  
         int n;  
         char *r, *w, *s;  
   
         n = 0;  
   
         s = xstrdup(str);  
   
         for (r = s, w = str; *r != '\0'; r++, w++) {  
                 if (*r == '%') {  
                         *w++ = '%';  
                         *w = '%';  
                 } else if (*r == '@') {  
                         if (*(r + 1) == '@') {  
                                 *w = *r++;  
                         } else {  
                                 *w = '%';  
                                 n++;  
                         }  
                 } else {  
                         *w = *r;  
                 }  
         }  
         *w = '\0';  
   
         xfree(s);  
   
         return n;  
 }  
   
   
 /*  
  * Format the destination mailbox according to the current date conversion  
  * specifiers.  
  */  
 void  
 current_date(char *destmbox)  
 {  
         char s[MBOX_NAME_LEN];  
         time_t te;  
         struct tm *tl;  
   
         if (!strchr(destmbox, '%'))  
                 return;  
   
         te = time(NULL);  
         tl = localtime(&te);  
   
         if (strftime(s, MBOX_NAME_LEN - 1, destmbox, tl))  
                 xstrncpy(destmbox, s, MBOX_NAME_LEN - 1);  
 }  
   
   
 /*  
  * Format the destination mailbox according to the message date conversion  
  * specifiers.  
  */  
 void  
 message_date(char *mesg, char *destmbox)  
 {  
         unsigned int t;  
         char s[MBOX_NAME_LEN];  
         struct tm tl;  
         char dbuf[RESPONSE_BUF + 1];  
   
         if (!strchr(destmbox, '@'))  
                 return;  
   
         substitute_date(destmbox);  
   
         fetch_response(&connpri, 0, 1, NULL);  
         t = imap_fetch(&connpri, mesg, "BODY.PEEK[HEADER.FIELDS (DATE)]");  
   
         while (fetch_response(&connpri, t, 0, dbuf) == RESPONSE_NONE);  
   
         if (strptime(dbuf, "Date: %a, %d %b %Y %H:%M:%S", &tl) &&  
             strftime(s, MBOX_NAME_LEN - 1, destmbox, &tl))  
                 xstrncpy(destmbox, s, MBOX_NAME_LEN - 1);  
 }  
   
   
 /*  
  * Format the destination mailbox according to "default variables" specifiers.  
  */  
 void  
 default_variables(char *mbox, char *destmbox)  
 {  
         char *m, *r, *w, *s;  
   
         if (!strchr(destmbox, '$'))  
                 return;  
   
         s = xstrdup(destmbox);  
   
         for (r = s, w = destmbox; *r != '\0';) {  
                 if (w - destmbox >= MBOX_NAME_LEN - 1)  
                         break;  
                 if (*r == '$') {  
                         switch (*(r + 1)) {  
                         case '_':  
                                 if (w + strlen(mbox) - destmbox >  
                                     MBOX_NAME_LEN - 1) {  
                                         r += 2;  
                                         break;  
                                 }  
                                 for (m = mbox; *m != '\0'; m++, w++)  
                                         *w = *m;  
                                 r += 2;  
                                 break;  
                         case '$':  
                                 *w++ = '$';  
                                 r += 2;  
                                 break;  
                         default:  
                                 *w++ = *r++;  
                                 break;  
                         }  
                 } else {  
                         *w++ = *r++;  
                 }  
         }  
         *w = '\0';  
   
         xfree(s);  
 }  

Legend:
Removed from v.1.53  
changed lines
  Added in v.1.54

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26