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

Diff of /imapfilter/request.c

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

revision 1.41 by lefcha, Mon Feb 3 20:22:01 2003 UTC revision 1.42 by lefcha, Sat Feb 22 16:06:41 2003 UTC
# Line 20  namesp_t nsppri, nspaux;       /* Primary and Line 20  namesp_t nsppri, nspaux;       /* Primary and
20  /*  /*
21   * Test/ping server.   * Test/ping server.
22   */   */
23  int test(int *sock)  int
24    test(int *sock)
25  {  {
26      return server_response(sock, imap_noop(sock));          return server_response(sock, imap_noop(sock));
27  }  }
28    
29  #endif  #endif
# Line 31  int test(int *sock) Line 32  int test(int *sock)
32  /*  /*
33   * Check server's capabilities.   * Check server's capabilities.
34   */   */
35  int check_capabilities(int *sock)  int
36    check_capabilities(int *sock)
37  {  {
38      capabilities = CAPABILITY_NONE;          capabilities = CAPABILITY_NONE;
39    
40      return capability_response(sock, imap_capability(sock));          return capability_response(sock, imap_capability(sock));
41  }  }
42    
43    
44  /*  /*
45   * Get namespace of mail server's mailboxes.   * Get namespace of mail server's mailboxes.
46   */   */
47  int check_namespace(int *sock, namesp_t * nsp)  int
48    check_namespace(int *sock, namesp_t * nsp)
49  {  {
50      nsp->prefix[0] = nsp->delim = 0;          nsp->prefix[0] = nsp->delim = '\0';
51    
52      if (!(options & OPTION_NAMESPACE) ||          if (!(options & OPTION_NAMESPACE) ||
53          !(capabilities & CAPABILITY_NAMESPACE))              !(capabilities & CAPABILITY_NAMESPACE))
54          return 0;                  return 0;
55      else          else
56          return namespace_response(sock, imap_namespace(sock), nsp);                  return namespace_response(sock, imap_namespace(sock), nsp);
57  }  }
58    
59    
60  /*  /*
61   * Login to server.   * Login to server.
62   */   */
63  int login(int *sock, char *user, char *pass)  int
64    login(int *sock, char *user, char *pass)
65  {  {
66      log_info(LOG_USERNAME, user);          return server_response(sock, imap_login(sock, user, pass));
   
     return server_response(sock, imap_login(sock, user, pass));  
67  }  }
68    
69    
# Line 69  int login(int *sock, char *user, char *p Line 71  int login(int *sock, char *user, char *p
71  /*  /*
72   * Check if a mailbox exists.   * Check if a mailbox exists.
73   */   */
74  int check_mailbox(int *sock, char *mbox, namesp_t * nsp)  int
75    check_mailbox(int *sock, char *mbox, namesp_t * nsp)
76  {  {
77      return server_response(sock, imap_examine(sock,          return server_response(sock, imap_examine(sock,
78                                                apply_namespace(mbox,                  apply_namespace(mbox, nsp->prefix, nsp->delim)));
                                                               nsp->prefix,  
                                                               nsp->delim)));  
79  }  }
80    
81    
82  /*  /*
83   * Open mailbox in read-write mode.   * Open mailbox in read-write mode.
84   */   */
85  int select_mailbox(int *sock, char *mbox, namesp_t * nsp)  int
86    select_mailbox(int *sock, char *mbox, namesp_t * nsp)
87  {  {
88      int r;          int r;
89    
90      if (mailbox_status(sock, mbox, nsp) == -2)          if (mailbox_status(sock, mbox, nsp) == -2)
91          return -2;              /* No messages exist. No filters need to be                  return -2;      /* No messages exist. No filters need to be
92                                     applied. */                                   * applied. */
93    
94      r = select_response(sock, imap_select(sock,          r = select_response(sock, imap_select(sock,
95                                            apply_namespace(mbox, nsp->prefix,                  apply_namespace(mbox, nsp->prefix,
96                                                            nsp->delim)));                      nsp->delim)));
97    
98      log_info(LOG_MAILBOX, mbox);          log_info(LOG_MAILBOX, mbox);
99    
100      return r;          return r;
101  }  }
102    
103    
104  /*  /*
105   * Get mailbox's status.   * Get mailbox's status.
106   */   */
107  int mailbox_status(int *sock, char *mbox, namesp_t * nsp)  int
108    mailbox_status(int *sock, char *mbox, namesp_t * nsp)
109  {  {
110      return status_response(sock, imap_status(sock,          return status_response(sock, imap_status(sock,
111                                            apply_namespace(mbox, nsp->prefix,                  apply_namespace(mbox, nsp->prefix, nsp->delim),
112                                                            nsp->delim),                  "MESSAGES RECENT UNSEEN"), mbox);
                                            "MESSAGES RECENT UNSEEN"), mbox);  
113  }  }
114    
115    
116  /*  /*
117   * Close examined/selected mailbox.   * Close examined/selected mailbox.
118   */   */
119  int close_mailbox(int *sock)  int
120    close_mailbox(int *sock)
121  {  {
122      return server_response(sock, imap_close(sock));          return server_response(sock, imap_close(sock));
123  }  }
124    
125    
126  /*  /*
127   * Logout from server.   * Logout from server.
128   */   */
129  int logout(int *sock)  int
130    logout(int *sock)
131  {  {
132      return logout_response(sock, imap_logout(sock));          return logout_response(sock, imap_logout(sock));
133  }  }
134    
135    
136  /*  /*
137   * Match and apply filters assigned to a mailbox.   * Match and apply filters assigned to a mailbox.
138   */   */
139  int apply_filters(filter_t ** filters)  int
140    apply_filters(filter_t ** filters)
141  {  {
142      int i;          int i;
143      char *mesgs;          char *mesgs;
144    
145      for (i = 0; filters[i]; i++) {          for (i = 0; filters[i] != NULL; i++) {
146          mesgs = NULL;                  mesgs = NULL;
147    
148          if (match_filter(filters[i], &mesgs))                  if (match_filter(filters[i], &mesgs))
149              continue;                          continue;
150    
151          log_info(LOG_FILTER, filters[i]->key);                  log_info(LOG_FILTER, filters[i]->key);
152    
153          apply_action(mesgs, &(filters[i]->action.type),                  apply_action(mesgs, &(filters[i]->action.type),
154                     filters[i]->action.raccount, filters[i]->action.destmbox,                      filters[i]->action.raccount, filters[i]->action.destmbox,
155                       &filters[i]->action.msgflags, filters[i]->action.args);                      &filters[i]->action.msgflags, filters[i]->action.args);
156    
157          xfree(mesgs);                  xfree(mesgs);
158      }          }
159    
160      return 0;          return 0;
161  }  }
162    
163    
# Line 160  int apply_filters(filter_t ** filters) Line 165  int apply_filters(filter_t ** filters)
165   * Generate the search request by the masks of the filter and try to   * Generate the search request by the masks of the filter and try to
166   * match the generated filter.   * match the generated filter.
167   */   */
168  int match_filter(filter_t * filter, char **mesgs)  int
169    match_filter(filter_t * filter, char **mesgs)
170  {  {
171      char *search;          char *search;
172    
173      if (filter->mode == FILTER_MODE_OR)          if (filter->mode == FILTER_MODE_OR)
174          search = generate_filter_or(filter->masks, filter->masknum,                  search = generate_filter_or(filter->masks, filter->masknum,
175                                      filter->masklen);                      filter->masklen);
176      else          else
177          search = generate_filter_and(filter->masks, filter->masknum,                  search = generate_filter_and(filter->masks, filter->masknum,
178                                       filter->masklen);                      filter->masklen);
179    
180      search_response(&sockpri, imap_search(&sockpri, charset, search), mesgs);          search_response(&sockpri, imap_search(&sockpri, charset, search),
181                mesgs);
182    
183      xfree(search);          xfree(search);
184    
185      if (!*mesgs)          if (*mesgs == '\0')
186          return 1;                  return 1;
187    
188      return 0;          return 0;
189  }  }
190    
191    
192  /*  /*
193   * Empty the FIFO inventory.   * Empty the FIFO inventory.
194   */   */
195  void empty_fifo(mask_t ** mfifo)  void
196    empty_fifo(mask_t ** mfifo)
197  {  {
198      mfifo[0] = NULL;          mfifo[0] = NULL;
199    
200      queue_fifo(NULL, NULL);          queue_fifo(NULL, NULL);
201      dequeue_fifo(NULL);          dequeue_fifo(NULL);
202  }  }
203    
204    
205  /*  /*
206   * Add item to FIFO inventory.   * Add item to FIFO inventory.
207   */   */
208  void queue_fifo(mask_t ** mfifo, mask_t * mask)  void
209    queue_fifo(mask_t ** mfifo, mask_t * mask)
210  {  {
211      static unsigned int i;          static unsigned int i;
212    
213      if (!mfifo) {          if (mfifo == NULL) {
214          i = 0;                  i = 0;
215          return;                  return;
216      }          }
217      mfifo[i++] = mask;          mfifo[i++] = mask;
218      mfifo[i] = NULL;          mfifo[i] = NULL;
219  }  }
220    
221    
222  /*  /*
223   * Get next item from FIFO inventory.   * Get next item from FIFO inventory.
224   */   */
225  mask_t *dequeue_fifo(mask_t ** mfifo)  mask_t *
226    dequeue_fifo(mask_t ** mfifo)
227  {  {
228      static unsigned int j;          static unsigned int j;
229    
230      if (!mfifo) {          if (mfifo == NULL) {
231          j = 0;                  j = 0;
232          return NULL;                  return NULL;
233      }          }
234      return mfifo[j++];          return mfifo[j++];
235  }  }
236    
237    
# Line 229  mask_t *dequeue_fifo(mask_t ** mfifo) Line 239  mask_t *dequeue_fifo(mask_t ** mfifo)
239   * Generate the filter search command from the masks, assuming that   * Generate the filter search command from the masks, assuming that
240   * masks are AND-ed.   * masks are AND-ed.
241   */   */
242  char *generate_filter_and(mask_t * mask, unsigned int masknum,  char *
243                             unsigned int masklen)  generate_filter_and(mask_t * mask, unsigned int masknum,
244  {      unsigned int masklen)
245      const unsigned int searchbuf = masklen + masknum * 6 + 8;  {
246      unsigned int len = 0;          const unsigned int searchbuf = masklen + masknum * 6 + 8;
247      char *search;          unsigned int len;
248      mask_t *tmp;          char *search;
249            mask_t *tmp;
250    
251      search = (char *)xmalloc(sizeof(char) * searchbuf);          len = 0;
252    
253      search[0] = 0;          search = (char *)xmalloc(sizeof(char) * searchbuf);
254            search[0] = '\0';
255    
256      tmp = mask;          tmp = mask;
257      if (!tmp) {          if (tmp == NULL) {
         strncat(search, "ALL ", searchbuf - len - 1);  
         len += 4;  
     } else  
         while ((tmp = tmp->next)) {  
             if (tmp->type != MASK_TYPE_OR) {  
258                  strncat(search, "ALL ", searchbuf - len - 1);                  strncat(search, "ALL ", searchbuf - len - 1);
259                  len += 4;                  len += 4;
260                  break;          } else
261              }                  while ((tmp = tmp->next) != NULL) {
262          }                          if (tmp->type != MASK_TYPE_OR) {
263                                    strncat(search, "ALL ", searchbuf - len - 1);
264      tmp = NULL;                                  len += 4;
265      while (mask) {                                  break;
266          tmp = mask;                          }
267          mask = mask->next;                  }
268    
269          if (mask && mask->type == MASK_TYPE_OR) {          tmp = NULL;
270              strncat(search, "OR (", searchbuf - len - 1);          while (mask != NULL) {
271              len += 4;                  tmp = mask;
   
             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 || 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;  
272                  mask = mask->next;                  mask = mask->next;
273              }  
274          } else {                  if (mask != NULL && mask->type == MASK_TYPE_OR) {
275              strncat(search, tmp->body, searchbuf - len - 1);                          strncat(search, "OR (", searchbuf - len - 1);
276              len = strlen(search);                          len += 4;
277              search[len] = ' ';  
278              search[++len] = 0;                          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          }          }
     }  
306    
307      search[len - 1] = 0;          search[len - 1] = '\0';
308    
309      return search;          return search;
310  }  }
311    
312    
# Line 300  char *generate_filter_and(mask_t * mask, Line 314  char *generate_filter_and(mask_t * mask,
314   * Generate the filter search command from the masks, assuming that   * Generate the filter search command from the masks, assuming that
315   * masks are OR-ed.   * masks are OR-ed.
316   */   */
317  char *generate_filter_or(mask_t * mask, unsigned int masknum,  char *
318                            unsigned int masklen)  generate_filter_or(mask_t * mask, unsigned int masknum,
319  {      unsigned int masklen)
320      const unsigned int searchbuf = masklen + masknum * 6 + 8;  {
321      unsigned int len = 0;          const unsigned int searchbuf = masklen + masknum * 6 + 8;
322      char *search;          unsigned int len;
323      mask_t **mfifo;             /* Mailbox FIFO queue. */          char *search;
324      mask_t *mf;                 /* Mask returned from FIFO. */          mask_t **mfifo;         /* Mailbox FIFO queue. */
325            mask_t *mf;             /* Mask returned from FIFO. */
     search = (char *)xmalloc(sizeof(char) * searchbuf);  
     mfifo = (mask_t **) xmalloc(sizeof(mask_t *) * (masknum + 1));  
   
     search[0] = 0;  
     empty_fifo(mfifo);  
326    
327      strncat(search, "ALL ", searchbuf - len - 1);          len = 0;
     len += 4;  
328    
329      while (mask) {          search = (char *)xmalloc(sizeof(char) * searchbuf);
330          queue_fifo(mfifo, mask);          mfifo = (mask_t **) xmalloc(sizeof(mask_t *) * (masknum + 1));
         mask = mask->next;  
331    
332          while (mask && mask->type == MASK_TYPE_AND) {          search[0] = '\0';
333              queue_fifo(mfifo, mask);          empty_fifo(mfifo);
             mask = mask->next;  
         }  
334    
335          if (mask) {          strncat(search, "ALL ", searchbuf - len - 1);
336              if (len == 4 && search[0] == 'A')          len += 4;
                 search[0] = len = 0;  
337    
338              strncat(search, "OR ", searchbuf - len - 1);          while (mask != NULL) {
339              len += 3;                  queue_fifo(mfifo, mask);
340          }                  mask = mask->next;
         if (search[0] != 'A') {  
             search[len] = '(';  
             search[++len] = 0;  
         }  
         while ((mf = dequeue_fifo(mfifo))) {  
             strncat(search, mf->body, searchbuf - len - 1);  
             len = strlen(search);  
             search[len] = ' ';  
             search[++len] = 0;  
         }  
341    
342          if (strchr(search, '(')) {                  while (mask != NULL && mask->type == MASK_TYPE_AND) {
343              search[len - 1] = ')';                          queue_fifo(mfifo, mask);
344              search[len] = ' ';                          mask = mask->next;
345              search[++len] = 0;                  }
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          }          }
         empty_fifo(mfifo);  
     }  
373    
374      search[len - 1] = 0;          search[len - 1] = '\0';
375    
376      xfree(mfifo);          xfree(mfifo);
377    
378      return search;          return search;
379  }  }
380    
381    
382  /*  /*
383   * Apply the appropriate action.   * Apply the appropriate action.
384   */   */
385  int apply_action(char *mesgs, unsigned int *type, account_t * raccount,  int
386                    char *destmbox, unsigned int *msgflags, char *args)  apply_action(char *mesgs, unsigned int *type, account_t * raccount,
387        char *destmbox, unsigned int *msgflags, char *args)
388  {  {
389      unsigned int cnt;          unsigned int cnt;
390    
391      if (!*mesgs)          if (*mesgs == '\0')
392          return 0;                  return 0;
393    
394      log_info(LOG_ACTION, type);          log_info(LOG_ACTION, type);
395      log_info(LOG_DESTINATION_MAILBOX, destmbox);          log_info(LOG_DESTINATION_ACCOUNT, raccount->key);
396            log_info(LOG_DESTINATION_MAILBOX, destmbox);
397    
398      cnt = count_messages(mesgs);          cnt = count_messages(mesgs);
399    
400      switch (*type) {          switch (*type) {
401      case FILTER_ACTION_DELETE:          case FILTER_ACTION_DELETE:
402          info("%d message%s deleted.\n", cnt, plural(cnt));                  info("%d message%s deleted.\n", cnt, plural(cnt));
403          action_delete(mesgs, args);                  action_delete(mesgs, args);
404          break;                  break;
405      case FILTER_ACTION_COPY:          case FILTER_ACTION_COPY:
406          info("%d message%s copied to mailbox \"%s\".\n", cnt, plural(cnt),                  info("%d message%s copied to mailbox \"%s\".\n", cnt,
407               destmbox);                      plural(cnt), destmbox);
408          action_copy(mesgs, apply_namespace(destmbox, nsppri.prefix,                  action_copy(mesgs, apply_namespace(destmbox, nsppri.prefix,
409                                             nsppri.delim), args);                          nsppri.delim), args);
410          break;                  break;
411      case FILTER_ACTION_MOVE:          case FILTER_ACTION_MOVE:
412          info("%d message%s moved to mailbox \"%s\".\n", cnt, plural(cnt),                  info("%d message%s moved to mailbox \"%s\".\n", cnt,
413               destmbox);                      plural(cnt), destmbox);
414          action_move(mesgs, apply_namespace(destmbox, nsppri.prefix,                  action_move(mesgs, apply_namespace(destmbox, nsppri.prefix,
415                                             nsppri.delim), args);                          nsppri.delim), args);
416          break;                  break;
417      case FILTER_ACTION_RCOPY:          case FILTER_ACTION_RCOPY:
418          info("%d message%s copied to mailbox \"%s\" at account %s.\n", cnt,                  info("%d message%s copied to mailbox \"%s\" at account %s.\n",
419               plural(cnt), destmbox, raccount->key);                      cnt, plural(cnt), destmbox, raccount->key);
420          action_rcopy(mesgs, raccount, destmbox, args);                  action_rcopy(mesgs, raccount, destmbox, args);
421          break;                  break;
422      case FILTER_ACTION_RMOVE:          case FILTER_ACTION_RMOVE:
423          info("%d message%s moved to mailbox \"%s\" at account %s.\n", cnt,                  info("%d message%s moved to mailbox \"%s\" at account %s.\n",
424               plural(cnt), destmbox, raccount->key);                      cnt, plural(cnt), destmbox, raccount->key);
425          action_rmove(mesgs, raccount, destmbox, args);                  action_rmove(mesgs, raccount, destmbox, args);
426          break;                  break;
427      case FILTER_ACTION_FLAG_REPLACE:          case FILTER_ACTION_FLAG_REPLACE:
428      case FILTER_ACTION_FLAG_ADD:          case FILTER_ACTION_FLAG_ADD:
429      case FILTER_ACTION_FLAG_REMOVE:          case FILTER_ACTION_FLAG_REMOVE:
430          info("%d message%s flagged.\n", cnt, plural(cnt));                  info("%d message%s flagged.\n", cnt, plural(cnt));
431          action_flag(mesgs, type, msgflags, args);                  action_flag(mesgs, type, msgflags, args);
432          break;                  break;
433      case FILTER_ACTION_LIST:          case FILTER_ACTION_LIST:
434          info("%d message%s listed.\n", cnt, plural(cnt));                  info("%d message%s listed.\n", cnt, plural(cnt));
435          action_list(mesgs, args);                  action_list(mesgs, args);
436          break;                  break;
437      }          }
438    
439      if (!*args)          if (*args == NULL)
440          log_info(LOG_WRITE, NULL);                  log_info(LOG_WRITE, NULL);
441    
442      return 0;          return 0;
443  }  }
444    
445    
446  /*  /*
447   * Delete messages and optionally list some of their headers.   * Delete messages and optionally list some of their headers.
448   */   */
449  int action_delete(char *mesgs, char *args)  int
450    action_delete(char *mesgs, char *args)
451  {  {
452      char *tok, *m, *mcp;          char *tok, *m, *mcp;
453    
454      action_list(mesgs, args);          action_list(mesgs, args);
455    
456      m = mcp = convert_messages(mesgs);          m = mcp = convert_messages(mesgs);
457    
458      tok = strtok_r(m, " ", &m);          tok = strtok_r(m, " ", &m);
459      while (tok) {          while (tok) {
460          server_response(&sockpri, imap_store(&sockpri, tok,                  server_response(&sockpri, imap_store(&sockpri, tok,
461                                               STORE_FLAG_ADD, "\\Deleted"));                          STORE_FLAG_ADD, "\\Deleted"));
462    
463          tok = strtok_r(NULL, " ", &m);                  tok = strtok_r(NULL, " ", &m);
464      }          }
465    
466      if (options & OPTION_EXPUNGE)          if (options & OPTION_EXPUNGE)
467          server_response(&sockpri, imap_expunge(&sockpri));                  server_response(&sockpri, imap_expunge(&sockpri));
468    
469      xfree(mcp);          xfree(mcp);
470    
471      return 0;          return 0;
472  }  }
473    
474    
475  /*  /*
476   * Copy messages to specified mailbox.   * Copy messages to specified mailbox.
477   */   */
478  int action_copy(char *mesgs, char *destmbox, char *args)  int
479    action_copy(char *mesgs, char *destmbox, char *args)
480  {  {
481      int r = 0;          int r;
482      char *tok = NULL, *mcp, *m;          char *tok, *mcp, *m;
483    
484      action_list(mesgs, args);          r = 0;
485            tok = NULL;
486    
487      m = mcp = convert_messages(mesgs);          action_list(mesgs, args);
488    
489      tok = strtok_r(m, " ", &m);          m = mcp = convert_messages(mesgs);
     while (tok) {  
         if ((r = copy_response(&sockpri,  
                                imap_copy(&sockpri, tok, destmbox))) ==  
             RESPONSE_TRYCREATE)  
             if (!server_response(&sockpri, imap_create(&sockpri, destmbox))) {  
                 if ((options & OPTION_SUBSCRIBE))  
                     server_response(&sockpri,  
                                     imap_subscribe(&sockpri, destmbox));  
                 r = copy_response(&sockpri,  
                                   imap_copy(&sockpri, tok, destmbox));  
             }  
         tok = strtok_r(NULL, " ", &m);  
     }  
490    
491      xfree(mcp);          tok = strtok_r(m, " ", &m);
492            while (tok != NULL) {
493                    if ((r = copy_response(&sockpri, imap_copy(&sockpri, tok,
494                                    destmbox))) == RESPONSE_TRYCREATE)
495                            if (!server_response(&sockpri, imap_create(&sockpri,
496                                        destmbox))) {
497                                    if ((options & OPTION_SUBSCRIBE))
498                                            server_response(&sockpri,
499                                                imap_subscribe(&sockpri, destmbox));
500                                    r = copy_response(&sockpri,
501                                        imap_copy(&sockpri, tok, destmbox));
502                            }
503                    tok = strtok_r(NULL, " ", &m);
504            }
505    
506            xfree(mcp);
507    
508      return r;          return r;
509  }  }
510    
511    
512  /*  /*
513   * Move messages to specified mailbox.   * Move messages to specified mailbox.
514   */   */
515  int action_move(char *mesgs, char *destmbox, char *args)  int
516    action_move(char *mesgs, char *destmbox, char *args)
517  {  {
518      if (!action_copy(mesgs, destmbox, args))          if (!action_copy(mesgs, destmbox, args))
519          action_delete(mesgs, "\0");                  action_delete(mesgs, "\0");
520    
521      return 0;          return 0;
522  }  }
523    
524    
525  /*  /*
526   * Copy messages to the specified mailbox of another mail server.   * Copy messages to the specified mailbox of another mail server.
527   */   */
528  int action_rcopy(char *mesgs, account_t * destacc, char *destmbox, char *args)  int
529    action_rcopy(char *mesgs, account_t * destacc, char *destmbox, char *args)
530  {  {
531      int r, ta, tf;          int r, ta, tf;
532      char *tok, *m, *mcp, *ndm;          char *tok, *m, *mcp, *ndm;
533      unsigned int n;          unsigned int n;
534      char buf[RESPONSE_BUF * 2];          char buf[RESPONSE_BUF * 2];
535    
536            if (init_connection(&sockaux, destacc->server, destacc->port,
537                    destacc->ssl))
538                    return ERROR_NETWORK;
539    
540      if (init_connection(&sockaux, destacc->server, destacc->port,          r = greeting_response(&sockaux);
                         destacc->ssl))  
         return ERROR_NETWORK;  
541    
542      r = greeting_response(&sockaux);          if (r == RESPONSE_BYE || check_capabilities(&sockaux))
543                    return ERROR_NETWORK;
     if (r == RESPONSE_BYE || check_capabilities(&sockaux))  
         return ERROR_NETWORK;  
544    
545  #ifdef DEBUG  #ifdef DEBUG
546      test(&sockaux);          test(&sockaux);
547  #endif  #endif
548    
549      if (r != RESPONSE_PREAUTH) {          if (r != RESPONSE_PREAUTH) {
550          if (destacc->passwdattr == PASSWORD_NONE) {                  if (destacc->passwdattr == PASSWORD_NONE) {
551              printf("Enter password for %s@%s: ", destacc->username,                          printf("Enter password for %s@%s: ", destacc->username,
552                     destacc->server);                              destacc->server);
553              get_password(destacc->password, PASSWORD_LEN);                          get_password(destacc->password, PASSWORD_LEN);
554              destacc->passwdattr = PASSWORD_PLAIN;                          destacc->passwdattr = PASSWORD_PLAIN;
555          }                  }
556          if (login(&sockaux, destacc->username,                  if (login(&sockaux, destacc->username,
557                    destacc->password) == RESPONSE_NO) {                          destacc->password) == RESPONSE_NO) {
558              error("imapfilter: username %s or password rejected at %s\n",                          error("username %s or password rejected at %s\n",
559                    destacc->username, destacc->server);                              destacc->username, destacc->server);
560              return ERROR_NETWORK;                          return ERROR_NETWORK;
561          }                  }
562      }          }
563      check_namespace(&sockaux, &nspaux);          check_namespace(&sockaux, &nspaux);
564    
565      /* apply_namespace() returns a pointer to a static buffer. */          /* apply_namespace() returns a pointer to a static buffer. */
566      ndm = apply_namespace(destmbox, nspaux.prefix, nspaux.delim);          ndm = apply_namespace(destmbox, nspaux.prefix, nspaux.delim);
567    
568      r = check_mailbox(&sockaux, destmbox, &nspaux);          r = check_mailbox(&sockaux, destmbox, &nspaux);
569    
570      if (r == RESPONSE_OK)          if (r == RESPONSE_OK)
571          close_mailbox(&sockaux);                  close_mailbox(&sockaux);
572      else if (r == RESPONSE_NO) {          else if (r == RESPONSE_NO) {
573          server_response(&sockaux, imap_create(&sockaux, ndm));                  server_response(&sockaux, imap_create(&sockaux, ndm));
574          if ((options & OPTION_SUBSCRIBE))                  if ((options & OPTION_SUBSCRIBE))
575              server_response(&sockaux, imap_subscribe(&sockaux, ndm));                          server_response(&sockaux, imap_subscribe(&sockaux,
576      }                                  ndm));
577      m = mcp = xstrdup(mesgs);          }
578            m = mcp = xstrdup(mesgs);
     tok = strtok_r(m, " ", &m);  
     while (tok) {  
         fetchsize_response(&sockpri, &n,  
                            imap_fetch(&sockpri, tok, "RFC822.SIZE"));  
579    
580          ta = imap_append(&sockaux, ndm, n);          tok = strtok_r(m, " ", &m);
581            while (tok != NULL) {
582                    fetchsize_response(&sockpri, &n,
583                        imap_fetch(&sockpri, tok, "RFC822.SIZE"));
584    
585          fetch_response(&sockpri, 0, 1, NULL);                  ta = imap_append(&sockaux, ndm, n);
         tf = imap_fetch(&sockpri, tok, "RFC822.HEADER");  
         do {  
             r = fetch_response(&sockpri, tf, 0, buf);  
             socket_write(&sockaux, buf);  
         } while (r == RESPONSE_NONE);  
586    
587          socket_write(&sockaux, "\r\n");                  fetch_response(&sockpri, 0, 1, NULL);
588                    tf = imap_fetch(&sockpri, tok, "RFC822.HEADER");
589                    do {
590                            r = fetch_response(&sockpri, tf, 0, buf);
591                            socket_write(&sockaux, buf);
592                    } while (r == RESPONSE_NONE);
593    
594          fetch_response(&sockpri, 0, 1, NULL);                  socket_write(&sockaux, "\r\n");
         tf = imap_fetch(&sockpri, tok, "BODY[TEXT]");  
         do {  
             r = fetch_response(&sockpri, tf, 0, buf);  
             if (r != RESPONSE_NULLBODY)  
                 socket_write(&sockaux, buf);  
         } while (r == RESPONSE_NONE);  
595    
596          if (r != RESPONSE_NULLBODY)                  fetch_response(&sockpri, 0, 1, NULL);
597              socket_write(&sockaux, "\r\n\r\n");                  tf = imap_fetch(&sockpri, tok, "BODY[TEXT]");
598          else                  do {
599              socket_write(&sockaux, "\r\n");                          r = fetch_response(&sockpri, tf, 0, buf);
600                            if (r != RESPONSE_NULLBODY)
601                                    socket_write(&sockaux, buf);
602                    } while (r == RESPONSE_NONE);
603    
604                    if (r != RESPONSE_NULLBODY)
605                            socket_write(&sockaux, "\r\n\r\n");
606                    else
607                            socket_write(&sockaux, "\r\n");
608    
609          append_response(&sockaux, ta);                  append_response(&sockaux, ta);
610    
611          tok = strtok_r(NULL, " ", &m);                  tok = strtok_r(NULL, " ", &m);
612      }          }
613    
614      logout(&sockaux);          logout(&sockaux);
615    
616      action_list(mesgs, args);          action_list(mesgs, args);
617    
618      xfree(mcp);          xfree(mcp);
619    
620      return 0;          return 0;
621  }  }
622    
623    
624  /*  /*
625   * Move messages to the specified mailbox of another mail server.   * Move messages to the specified mailbox of another mail server.
626   */   */
627  int action_rmove(char *mesgs, account_t * destacc, char *destmbox, char *args)  int
628    action_rmove(char *mesgs, account_t * destacc, char *destmbox, char *args)
629  {  {
630      if (!action_rcopy(mesgs, destacc, destmbox, args))          if (!action_rcopy(mesgs, destacc, destmbox, args))
631          action_delete(mesgs, "\0");                  action_delete(mesgs, "\0");
632    
633      return 0;          return 0;
634  }  }
635    
636    
637  /*  /*
638   * Flag messages by replacing, adding or removing specified flags.   * Flag messages by replacing, adding or removing specified flags.
639   */   */
640  int action_flag(char *mesgs, unsigned int *type, unsigned int *msgflags,  int
641                   char *args)  action_flag(char *mesgs, unsigned int *type, unsigned int *msgflags,
642  {      char *args)
643      unsigned int t;  {
644      char s[STORE_FLAGS_BUF];          unsigned int t;
645      char *tok, *m, *mcp;          char s[STORE_FLAGS_BUF];
646            char *tok, *m, *mcp;
647      *s = 0;  
648            *s = 0;
649      switch (*type) {  
650      case FILTER_ACTION_FLAG_ADD:          switch (*type) {
651          t = STORE_FLAG_ADD;          case FILTER_ACTION_FLAG_ADD:
652          break;                  t = STORE_FLAG_ADD;
653      case FILTER_ACTION_FLAG_REMOVE:                  break;
654          t = STORE_FLAG_REMOVE;          case FILTER_ACTION_FLAG_REMOVE:
655          break;                  t = STORE_FLAG_REMOVE;
656      default:                  break;
657          t = STORE_FLAG_REPLACE;          default:
658      }                  t = STORE_FLAG_REPLACE;
659            }
660      if ((*msgflags != MESSAGE_FLAG_NONE)) {  
661          if ((*msgflags & MESSAGE_FLAG_SEEN))          if ((*msgflags != MESSAGE_FLAG_NONE)) {
662              strncat(s, "\\Seen ", STORE_FLAGS_BUF - strlen(s) - 1);                  if ((*msgflags & MESSAGE_FLAG_SEEN))
663          if ((*msgflags & MESSAGE_FLAG_ANSWERED))                          strncat(s, "\\Seen ", STORE_FLAGS_BUF - strlen(s) - 1);
664              strncat(s, "\\Answered ", STORE_FLAGS_BUF - strlen(s) - 1);                  if ((*msgflags & MESSAGE_FLAG_ANSWERED))
665          if ((*msgflags & MESSAGE_FLAG_FLAGGED))                          strncat(s, "\\Answered ",
666              strncat(s, "\\Flagged ", STORE_FLAGS_BUF - strlen(s) - 1);                              STORE_FLAGS_BUF - strlen(s) - 1);
667          if ((*msgflags & MESSAGE_FLAG_DELETED))                  if ((*msgflags & MESSAGE_FLAG_FLAGGED))
668              strncat(s, "\\Deleted ", STORE_FLAGS_BUF - strlen(s) - 1);                          strncat(s, "\\Flagged ",
669          if ((*msgflags & MESSAGE_FLAG_DRAFT))                              STORE_FLAGS_BUF - strlen(s) - 1);
670              strncat(s, "\\Draft", STORE_FLAGS_BUF - strlen(s) - 1);                  if ((*msgflags & MESSAGE_FLAG_DELETED))
671          if ((s[strlen(s) - 1] == ' '))                          strncat(s, "\\Deleted ",
672              s[strlen(s) - 1] = 0;                              STORE_FLAGS_BUF - strlen(s) - 1);
673      }                  if ((*msgflags & MESSAGE_FLAG_DRAFT))
674      action_list(mesgs, args);                          strncat(s, "\\Draft", STORE_FLAGS_BUF - strlen(s) - 1);
675                    if ((s[strlen(s) - 1] == ' '))
676      m = mcp = convert_messages(mesgs);                          s[strlen(s) - 1] = 0;
677            }
678      tok = strtok_r(m, " ", &m);          action_list(mesgs, args);
679      while (tok) {  
680          server_response(&sockpri, imap_store(&sockpri, tok, t, s));          m = mcp = convert_messages(mesgs);
681    
682          tok = strtok_r(NULL, " ", &m);          tok = strtok_r(m, " ", &m);
683      }          while (tok != NULL) {
684                    server_response(&sockpri, imap_store(&sockpri, tok, t, s));
685    
686                    tok = strtok_r(NULL, " ", &m);
687            }
688    
689      if (options & OPTION_EXPUNGE)          if (options & OPTION_EXPUNGE)
690          server_response(&sockpri, imap_expunge(&sockpri));                  server_response(&sockpri, imap_expunge(&sockpri));
691    
692      xfree(mcp);          xfree(mcp);
693    
694      return 0;          return 0;
695  }  }
696    
697  /*  /*
698   * List user selected headers of messages.   * List user selected headers of messages.
699   */   */
700  int action_list(char *mesgs, char *args)  int
701    action_list(char *mesgs, char *args)
702  {  {
703      int r, t;          int r, t;
704      char *tok, *mcp, *m;          char *tok, *mcp, *m;
705      char s[ARGS_LEN + 27];          char s[ARGS_LEN + 27];
706      char hdrs[RESPONSE_BUF];          char hdrs[RESPONSE_BUF];
707    
708      if (!*args)          if (*args == '\0')
709          return 0;                  return 0;
710    
711      m = mcp = xstrdup(mesgs);          m = mcp = xstrdup(mesgs);
712    
713      snprintf(s, ARGS_LEN + 27 - 1, "BODY.PEEK[HEADER.FIELDS (%s)]", args);          snprintf(s, ARGS_LEN + 27 - 1, "BODY.PEEK[HEADER.FIELDS (%s)]", args);
714    
715            tok = strtok_r(m, " ", &m);
716            while (tok != NULL) {
717                    /* Reset internal fetch counter. */
718                    fetch_response(&sockpri, 0, 1, NULL);
719                    t = imap_fetch(&sockpri, tok, s);
720                    do {
721                            r = fetch_response(&sockpri, t, 0, hdrs);
722                    } while (r == RESPONSE_NONE);
723    
724                    if (*hdrs != '\0') {
725                            if (options & OPTION_HEADERS)
726                                    info("%s\n", hdrs);
727                            log_info(LOG_WRITE, hdrs);
728                    } else {
729                            log_info(LOG_WRITE, NULL);
730                    }
731    
732      tok = strtok_r(m, " ", &m);                  tok = strtok_r(NULL, " ", &m);
     while (tok) {  
         /* Reset internal fetch counter. */  
         fetch_response(&sockpri, 0, 1, NULL);  
         t = imap_fetch(&sockpri, tok, s);  
         do  
             r = fetch_response(&sockpri, t, 0, hdrs);  
         while (r == RESPONSE_NONE);  
   
         if (*hdrs) {  
             if (options & OPTION_HEADERS)  
                 info("%s\n", hdrs);  
             log_info(LOG_WRITE, hdrs);  
         } else {  
             log_info(LOG_WRITE, NULL);  
733          }          }
734    
735          tok = strtok_r(NULL, " ", &m);          xfree(mcp);
     }  
   
     xfree(mcp);  
736    
737      return 0;          return 0;
738  }  }
739    
740    
741  /*  /*
742   * Count how many messages matched the filter.   * Count how many messages matched the filter.
743   */   */
744  unsigned int count_messages(char *mesgs)  unsigned int
745    count_messages(char *mesgs)
746  {  {
747      unsigned int cnt = 0;          unsigned int cnt;
748      char *c = mesgs;          char *c;
749    
750      while ((c = strchr(c, ' '))) {          cnt = 0;
751          cnt++;          c = mesgs;
         c++;  
     }  
752    
753      return ++cnt;          while ((c = strchr(c, ' '))) {
754                    cnt++;
755                    c++;
756            }
757    
758            return ++cnt;
759  }  }
760    
761    
# Line 726  unsigned int count_messages(char *mesgs) Line 764  unsigned int count_messages(char *mesgs)
764   * number range, eg. 1 2 3 5 7 8 --> 1:3 5 7:8 and return a newly allocated   * number range, eg. 1 2 3 5 7 8 --> 1:3 5 7:8 and return a newly allocated
765   * buffer with the results.   * buffer with the results.
766   */   */
767  char *convert_messages(char *mesgs)  char *
768    convert_messages(char *mesgs)
769  {  {
770      int maxlen;          int maxlen;
771      unsigned int start, end, tmp;          unsigned int start, end, tmp;
772      char *c, *cp, *tail;          char *c, *cp, *tail;
773    
774      start = end = tmp = 0;          start = end = tmp = 0;
775      maxlen = strlen(mesgs) + 1;          maxlen = strlen(mesgs) + 1;
776      tail = NULL;          tail = NULL;
777    
778      c = cp = xstrdup(mesgs);          c = cp = xstrdup(mesgs);
779    
780      start = (unsigned int)strtoul(mesgs, &tail, 10);          start = (unsigned int)strtoul(mesgs, &tail, 10);
781      end = start;          end = start;
782    
783      do {          do {
784          if (tail) {                  if (tail != NULL) {
785              tmp = (unsigned int)strtoul(tail, &tail, 10);                          tmp = (unsigned int)strtoul(tail, &tail, 10);
786              if (!tmp)                          if (tmp == NULL)
787                  tail = NULL;                                  tail = NULL;
788          }                  }
789          if (tmp == end + 1)                  if (tmp == end + 1)
790              end++;                          end++;
791          else {                  else {
792              if (start == end) {                          if (start == end) {
793                  xstrncpy(c, ultostr(start, 10), maxlen);                                  xstrncpy(c, ultostr(start, 10), maxlen);
794                  c += strlen(c);                                  c += strlen(c);
795              } else {                          } else {
796                  xstrncpy(c, ultostr(start, 10), maxlen - 1);                                  xstrncpy(c, ultostr(start, 10), maxlen - 1);
797                  c += strlen(c);                                  c += strlen(c);
798                  *c = ':';                                  *c = ':';
799                  *++c = 0;                                  *++c = 0;
800                  xstrncpy(c, ultostr(end, 10), maxlen);                                  xstrncpy(c, ultostr(end, 10), maxlen);
801                  c += strlen(c);                                  c += strlen(c);
802              }                          }
803    
804              if (tail && c - cp < maxlen) {                          if (tail != NULL && c - cp < maxlen) {
805                  *c = ' ';                                  *c = ' ';
806                  *++c = 0;                                  *++c = 0;
807              }                          }
808              start = end = tmp;                          start = end = tmp;
809          }                  }
810      } while (tmp);          } while (tmp != NULL);
811    
812      return cp;          return cp;
813  }  }

Legend:
Removed from v.1.41  
changed lines
  Added in v.1.42

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26