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

Diff of /imapfilter/request.c

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

revision 1.20 by lefcha, Fri Jan 25 17:10:17 2002 UTC revision 1.21 by lefcha, Tue Jun 18 21:21:47 2002 UTC
# Line 8  Line 8 
8  #include "data.h"  #include "data.h"
9    
10    
11    extern int sockpri, sockaux;
12  extern unsigned int options;  extern unsigned int options;
13  extern unsigned int capabilities;  extern unsigned int capabilities;
14    
15  static struct {  namesp_t nsppri, nspaux;        /* Primary and auxiliary namespace. */
     char prefix[NAMESPACE_PREFIX_LEN];  
     char delim;  
 } namesp;  
16    
17    
18  #ifdef DEBUG  #ifdef DEBUG
19  /*  /*
20   * Test/ping server.   * Test/ping server.
21   */   */
22  int test(void)  int test(int *sock)
23  {  {
24      return server_response(imap_noop());      return server_response(sock, imap_noop(sock));
25  }  }
26  #endif  #endif
27    
# Line 31  int test(void) Line 29  int test(void)
29  /*  /*
30   * Check server's capabilities.   * Check server's capabilities.
31   */   */
32  int check_capabilities(void)  int check_capabilities(int *sock)
33  {  {
34      capabilities = CAPABILITY_NONE;      capabilities = CAPABILITY_NONE;
35    
36      return capability_response(imap_capability());      return capability_response(sock, imap_capability(sock));
37  }  }
38    
39    
40  /*  /*
41   * Get namespace of mail server's mailboxes.   * Get namespace of mail server's mailboxes.
42   */   */
43  int check_namespace(void)  int check_namespace(int *sock, namesp_t *nsp)
44  {  {
45      namesp.prefix[0] = namesp.delim = 0;      nsp->prefix[0] = nsp->delim = 0;
46    
47      if (!(options & OPTION_NAMESPACE) ||      if (!(options & OPTION_NAMESPACE) ||
48          !(capabilities & CAPABILITY_NAMESPACE))          !(capabilities & CAPABILITY_NAMESPACE))
49          return 0;          return 0;
50      else      else
51          return namespace_response(imap_namespace(),          return namespace_response(sock, imap_namespace(sock), nsp);
                                   namesp.prefix, namesp.delim);  
52  }  }
53    
54    
55  /*  /*
56   * Login to server.   * Login to server.
57   */   */
58  int login(char *user, char *pass)  int login(int *sock, char *user, char *pass)
59  {  {
60      log_info(LOG_USERNAME, user);      log_info(LOG_USERNAME, user);
61    
62      return server_response(imap_login(user, pass));      return server_response(sock, imap_login(sock, user, pass));
63    }
64    
65    
66    
67    /*
68     * Check if a mailbox exists.
69     */
70    int check_mailbox(int *sock, char *mbox, namesp_t *nsp)
71    {
72        return server_response(sock, imap_examine(sock,
73                                                  apply_namespace(mbox,
74                                                                  nsp->prefix,
75                                                                  nsp->delim)));
76  }  }
77    
78    
79  /*  /*
80   * Open mailbox in read-write mode.   * Open mailbox in read-write mode.
81   */   */
82  int select_mailbox(char *mbox)  int select_mailbox(int *sock, char *mbox, namesp_t *nsp)
83  {  {
84      int r;      int r;
85    
86      if (mailbox_status(mbox) == -2)      if (mailbox_status(sock, mbox, nsp) == -2)
87          return -2;              /* No messages exist. No filters need to          return -2;              /* No messages exist. No filters need to
88                                     be applied. */                                     be applied. */
89    
90      r = select_response(imap_select(apply_namespace(mbox, namesp.prefix,      r = select_response(sock, imap_select(sock,
91                                                      namesp.delim)));                                            apply_namespace(mbox, nsp->prefix,
92                                                              nsp->delim)));
93    
94      log_info(LOG_MAILBOX, mbox);      log_info(LOG_MAILBOX, mbox);
95    
# Line 89  int select_mailbox(char *mbox) Line 100  int select_mailbox(char *mbox)
100  /*  /*
101   * Get mailbox's status.   * Get mailbox's status.
102   */   */
103  int mailbox_status(char *mbox)  int mailbox_status(int *sock, char *mbox, namesp_t *nsp)
104  {  {
105      return status_response(imap_status(apply_namespace(mbox, namesp.prefix,      return status_response(sock, imap_status(sock,
106                                                         namesp.delim),                                               apply_namespace(mbox, nsp->prefix,
107                                         "MESSAGES RECENT UNSEEN"), mbox);                                                               nsp->delim),
108                                                 "MESSAGES RECENT UNSEEN"), mbox);
109  }  }
110    
111    
112  /*  /*
113   * Close examined/selected mailbox.   * Close examined/selected mailbox.
114   */   */
115  int close_mailbox(void)  int close_mailbox(int *sock)
116  {  {
117      return server_response(imap_close());      return server_response(sock, imap_close(sock));
118  }  }
119    
120    
121  /*  /*
122   * Logout from server.   * Logout from server.
123   */   */
124  int logout(void)  int logout(int *sock)
125  {  {
126      return server_response(imap_logout());      return server_response(sock, imap_logout(sock));
127  }  }
128    
129    
# Line 132  int apply_filters(filter_t ** filters) Line 144  int apply_filters(filter_t ** filters)
144          log_info(LOG_FILTER, filters[i]->key);          log_info(LOG_FILTER, filters[i]->key);
145    
146          apply_action(mesgs, &(filters[i]->action.type),          apply_action(mesgs, &(filters[i]->action.type),
147                     filters[i]->action.destmbox, filters[i]->action.args);                       filters[i]->action.raccount, filters[i]->action.destmbox,
148                         filters[i]->action.args);
149    
150          xfree(mesgs);          xfree(mesgs);
151      }      }
# Line 156  int match_filter(filter_t * filter, char Line 169  int match_filter(filter_t * filter, char
169          search = generate_filter_and(filter->masks, filter->masknum,          search = generate_filter_and(filter->masks, filter->masknum,
170                                       filter->masklen);                                       filter->masklen);
171    
172      search_response(imap_search(search), mesgs);      search_response(&sockpri, imap_search(&sockpri, search), mesgs);
173    
174      xfree(search);      xfree(search);
175    
# Line 349  char *generate_filter_or(mask_t * mask, Line 362  char *generate_filter_or(mask_t * mask,
362  /*  /*
363   * Apply the appropriate action.   * Apply the appropriate action.
364   */   */
365  int apply_action(char *mesgs, unsigned int *type, char *destmbox,  int apply_action(char *mesgs, unsigned int *type, account_t *raccount,
366                    char *args)                   char *destmbox, char *args)
367  {  {
368      unsigned int cnt;      unsigned int cnt;
369    
370      if (!*mesgs)      if (!*mesgs)
371          return 0;          return 0;
372        
373      log_info(LOG_ACTION, type);      log_info(LOG_ACTION, type);
374      log_info(LOG_DESTINATION_MAILBOX, destmbox);      log_info(LOG_DESTINATION_MAILBOX, destmbox);
375        
376      cnt = convert_messages(mesgs);      cnt = count_messages(mesgs);
377        
378      switch (*type) {      switch (*type) {
379      case FILTER_ACTION_DELETE:      case FILTER_ACTION_DELETE:
380          info("%d message%s deleted.\n", cnt, plural(cnt));          info("%d message%s deleted.\n", cnt, plural(cnt));
# Line 370  int apply_action(char *mesgs, unsigned i Line 383  int apply_action(char *mesgs, unsigned i
383      case FILTER_ACTION_COPY:      case FILTER_ACTION_COPY:
384          info("%d message%s copied to mailbox \"%s\".\n", cnt, plural(cnt),          info("%d message%s copied to mailbox \"%s\".\n", cnt, plural(cnt),
385               destmbox);               destmbox);
386          action_copy(mesgs, apply_namespace(destmbox, namesp.prefix,          action_copy(mesgs, apply_namespace(destmbox, nsppri.prefix,
387                                             namesp.delim), args);                                             nsppri.delim), args);
388          break;          break;
389      case FILTER_ACTION_MOVE:      case FILTER_ACTION_MOVE:
390          info("%d message%s moved to mailbox \"%s\".\n", cnt, plural(cnt),          info("%d message%s moved to mailbox \"%s\".\n", cnt, plural(cnt),
391               destmbox);               destmbox);
392          action_move(mesgs, apply_namespace(destmbox, namesp.prefix,          action_move(mesgs, apply_namespace(destmbox, nsppri.prefix,
393                                             namesp.delim), args);                                             nsppri.delim), args);
394            break;
395        case FILTER_ACTION_RCOPY:
396            info("%d message%s copied to mailbox \"%s\" at account %s\n", cnt,
397                 plural(cnt), destmbox, raccount->key);
398            action_rcopy(mesgs, raccount, destmbox, args);
399            break;
400        case FILTER_ACTION_RMOVE:
401            info("%d messages%s moved to mailbox \"%s\" at account %s\n", cnt,
402                 plural(cnt), destmbox, raccount->key);
403            action_rmove(mesgs, raccount, destmbox, args);
404          break;          break;
405      case FILTER_ACTION_LIST:      case FILTER_ACTION_LIST:
406          info("%d message%s listed.\n", cnt, plural(cnt));          info("%d message%s listed.\n", cnt, plural(cnt));
# Line 397  int apply_action(char *mesgs, unsigned i Line 420  int apply_action(char *mesgs, unsigned i
420   */   */
421  int action_delete(char *mesgs, char *args)  int action_delete(char *mesgs, char *args)
422  {  {
423      const char *delim = " ";      char *tok, *mcp, *m;
424      char *tok, *mcp, *m, *acp = NULL, *occur;      
425        action_list(mesgs, args);
426    
427        convert_messages(mesgs);
428          
429      m = mcp = xstrdup(mesgs);      m = mcp = xstrdup(mesgs);
430        
431      if (*args) {      while ((tok = strsep(&m, " ")))
432          acp = xstrdup(args);          server_response(&sockpri, imap_store(&sockpri, tok, "\\Deleted"));
         while ((occur = strchr(acp, ',')))  
             *occur = ' ';  
     }  
     while ((tok = strsep(&m, delim))) {  
         if (*args)  
             fetch_response(imap_fetch(tok, acp, 0));  
   
         server_response(imap_store(tok, "\\Deleted"));  
     }  
433    
434      xfree(mcp);      xfree(mcp);
435    
     if (*args)  
         xfree(acp);  
   
436      return 0;      return 0;
437  }  }
438    
# Line 429  int action_delete(char *mesgs, char *arg Line 443  int action_delete(char *mesgs, char *arg
443  int action_copy(char *mesgs, char *destmbox, char *args)  int action_copy(char *mesgs, char *destmbox, char *args)
444  {  {
445      int r = 0;      int r = 0;
446      const char *delim = " ";      char *tok = NULL, *mcp, *m;
447      char *tok, *mcp, *m, *acp = NULL, *occur;      
448        action_list(mesgs, args);
449        
450        convert_messages(mesgs);
451        
452      m = mcp = xstrdup(mesgs);      m = mcp = xstrdup(mesgs);
453        
454      if (*args) {      if ((r = copy_response(&sockpri, imap_copy(&sockpri, tok, destmbox))) ==
455          acp = xstrdup(args);          RESPONSE_TRYCREATE)
456            if (!server_response(&sockpri, imap_create(&sockpri, destmbox))) {
457          while ((occur = strchr(acp, ',')))              server_response(&sockpri, imap_subscribe(&sockpri, destmbox));
458              *occur = ' ';              r = copy_response(&sockpri, imap_copy(&sockpri, tok, destmbox));
459      }          }
460      while ((tok = strsep(&m, delim))) {      
         if (*args)  
             fetch_response(imap_fetch(tok, acp, 0));  
   
         if ((r = copy_response(imap_copy(tok, destmbox))) == RESPONSE_TRYCREATE)  
             if (!server_response(imap_create(destmbox)))  
                 r = copy_response(imap_copy(tok, destmbox));  
     }  
   
461      xfree(mcp);      xfree(mcp);
462    
     if (*args)  
         xfree(acp);  
   
463      return r;      return r;
464  }  }
465    
# Line 474  int action_move(char *mesgs, char *destm Line 480  int action_move(char *mesgs, char *destm
480    
481    
482  /*  /*
483     * Copy messages to the specified mailbox of another mail server.
484     */
485    int action_rcopy(char *mesgs, account_t *destacc, char *destmbox, char *args)
486    {
487        int r;
488        char *tok, *m, *mcp, *ndm;
489        unsigned int n, t = 0;
490        char buf[RESPONSE_BUF];
491        
492        if (init_connection(&sockaux, destacc->server, destacc->port,
493                            destacc->ssl))
494            return ERROR_NETWORK;
495        
496        r = greeting_response(&sockaux);
497        
498        if (r == RESPONSE_BYE || check_capabilities(&sockaux))
499            return ERROR_NETWORK;
500        
501    #ifdef DEBUG
502        test(&sockaux);
503    #endif
504        
505        if (r != RESPONSE_PREAUTH) {
506            if (destacc->passwdattr == PASSWORD_NONE) {
507                printf("Enter password for %s@%s: ", destacc->username,
508                       destacc->server);
509                get_password(destacc->password, PASSWORD_LEN);
510                destacc->passwdattr = PASSWORD_PLAIN;
511            }
512            if (login(&sockaux, destacc->username,
513                      destacc->password) == RESPONSE_NO) {
514                error("imapfilter: username %s or password rejected at %s\n",
515                      destacc->username, destacc->server);
516                return ERROR_NETWORK;
517            }
518        }
519        check_namespace(&sockaux, &nspaux);
520    
521        /* apply_namespace() returns a pointer to a static buffer. */
522        ndm = apply_namespace(destmbox, nspaux.prefix, nspaux.delim);
523        
524        r = check_mailbox(&sockaux, ndm, &nspaux);
525    
526        if (r == RESPONSE_OK)
527            close_mailbox(&sockaux);
528        else if (r == RESPONSE_NO) {
529            server_response(&sockaux, imap_create(&sockaux, ndm));
530            server_response(&sockaux, imap_subscribe(&sockaux, ndm));
531        }
532    
533        m = mcp = xstrdup(mesgs);
534    
535        while ((tok = strsep(&m, " "))) {
536            fetchsize_response(&sockpri, &n,
537                                   imap_fetch(&sockpri, tok, "RFC822.SIZE"));
538            
539            t = imap_append(&sockaux, ndm, n);
540    
541            do {
542                r = fetch_response(&sockpri, 0, buf, imap_fetch(&sockpri, tok,
543                                                                "RFC822.HEADER"));
544    
545                socket_write(&sockaux, buf);
546            } while (r == RESPONSE_NONE);
547            
548            socket_write(&sockaux, "\r\n");
549    
550            fetch_response(&sockpri, 1, NULL, 0);
551            do {
552                r = fetch_response(&sockpri, 0, buf, imap_fetch(&sockpri, tok,
553                                                                "BODY[TEXT]"));
554                
555                socket_write(&sockaux, buf);
556            } while (r == RESPONSE_NONE);
557        }
558    
559        socket_write(&sockaux, "\r\n\r\n");
560    
561        append_response(&sockaux, t);
562    
563        logout(&sockaux);
564        
565        action_list(mesgs, args);
566        
567        xfree(mcp);
568    
569        return 0;
570    }
571    
572    
573    /*
574     * Move messages to the specified mailbox of another mail server.
575     */
576    int action_rmove(char *mesgs, account_t *destacc, char *destmbox, char *args)
577    {
578        if (!action_rcopy(mesgs, destacc, destmbox, args))
579            action_delete(mesgs, "\0");
580          
581        return 0;
582    }
583    
584    
585    /*
586   * List user selected headers of messages.   * List user selected headers of messages.
587   */   */
588  int action_list(char *mesgs, char *args)  int action_list(char *mesgs, char *args)
589  {  {
590      const char *delim = " ";      int r;
591      char *tok, *mcp, *m, *acp, *occur;      char *tok, *mcp, *m;
592        char s[ARGS_LEN + 27];
593        char hdrs[RESPONSE_BUF];
594    
595      if (!*args)      if (!*args)
596          return 0;          return 0;
597    
598      m = mcp = xstrdup(mesgs);      m = mcp = xstrdup(mesgs);
     acp = xstrdup(args);  
599    
600      while ((occur = strchr(acp, ',')))      snprintf(s, ARGS_LEN + 27 - 1, "BODY.PEEK[HEADER.FIELDS (%s)]", args);
         *occur = ' ';  
601    
602      while ((tok = strsep(&m, delim)))      while ((tok = strsep(&m, " "))) {
603          fetch_response(imap_fetch(tok, acp, 1));          /* Reset internal fetch counter. */
604            fetch_response(&sockpri, 1, NULL, 0);
605    
606            do {
607                r = fetch_response(&sockpri, 0, hdrs, imap_fetch(&sockpri, tok, s));
608                
609                if (*hdrs) {
610                    if (options & OPTION_HEADERS)
611                        info("%s\n", hdrs);
612                    log_info(LOG_WRITE, hdrs);
613                } else {
614                    log_info(LOG_WRITE, NULL);
615                }
616            } while (r == RESPONSE_NONE);
617        }
618    
619      xfree(mcp);      xfree(mcp);
     xfree(acp);  
620    
621      return 0;      return 0;
622  }  }
623    
624    
625  /*  /*
626     * Count how many messages matched the filter.
627     */
628    unsigned int count_messages(char *mesgs)
629    {
630        unsigned int cnt = 0;
631        char *c = mesgs;
632        
633        while ((c = strchr(c, ' '))) {
634            cnt++;
635            c++;
636        }
637    
638        return ++cnt;
639    }
640    
641    
642    /*
643   * Convert messages with contiguous sequence number to the corresponding   * Convert messages with contiguous sequence number to the corresponding
644   * number range, eg. 1 2 3 5 7 8 --> 1:3 5 7:8   * number range, eg. 1 2 3 5 7 8 --> 1:3 5 7:8
645   */   */
646  unsigned int convert_messages(char *mesgs)  void convert_messages(char *mesgs)
647  {  {
648      unsigned int cnt, maxlen;      unsigned int maxlen;
649      unsigned int start, end, tmp;      unsigned int start, end, tmp;
650      char *cp, *tail, *m;      char *cp, *tail, *m;
651        
652      cnt = start = end = tmp = 0;      start = end = tmp = 0;
653      maxlen = strlen(mesgs) + 1;      maxlen = strlen(mesgs) + 1;
654      tail = NULL;      tail = NULL;
655    
# Line 518  unsigned int convert_messages(char *mesg Line 657  unsigned int convert_messages(char *mesg
657      m = mesgs;      m = mesgs;
658    
659      start = (unsigned int) strtoul(cp, &tail, 10);      start = (unsigned int) strtoul(cp, &tail, 10);
     cnt++;  
660      end = start;      end = start;
661    
662      do {      do {
663          if (tail) {          if (tail) {
664              tmp = (unsigned int) strtoul(tail, &tail, 10);              tmp = (unsigned int) strtoul(tail, &tail, 10);
665              if (tmp)              if (!tmp)
                 cnt++;  
             else  
666                  tail = NULL;                  tail = NULL;
667          }          }
668          if (tmp == end + 1)          if (tmp == end + 1)
# Line 553  unsigned int convert_messages(char *mesg Line 689  unsigned int convert_messages(char *mesg
689      } while (tmp);      } while (tmp);
690    
691      xfree(cp);      xfree(cp);
   
     return cnt;  
692  }  }

Legend:
Removed from v.1.20  
changed lines
  Added in v.1.21

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26