mutt_*mktemp--
[apps/madmutt.git] / pattern.c
index a02e96e..1eee48c 100644 (file)
--- a/pattern.c
+++ b/pattern.c
@@ -7,40 +7,22 @@
  * please see the file GPL in the top level source directory.
  */
 
-#if HAVE_CONFIG_H
-# include "config.h"
-#endif
+#include <lib-lib/lib-lib.h>
 
-#include <lib-lib/mem.h>
-#include <lib-lib/ascii.h>
-#include <lib-lib/str.h>
-#include <lib-lib/macros.h>
-#include <lib-lib/file.h>
-#include <lib-lib/buffer.h>
+#include <lib-mime/mime.h>
+#include <lib-ui/enter.h>
+#include <lib-ui/curses.h>
+#include <lib-mx/mx.h>
 
 #include "mutt.h"
+#include "alias.h"
 #include "handler.h"
-#include "enter.h"
-#include "mx.h"
-#include "mapping.h"
 #include "keymap.h"
 #include "copy.h"
-#include "mime.h"
-
-
-#ifdef USE_IMAP
-#include "mx.h"
-#include "imap/imap.h"
-#endif
 
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <stdarg.h>
+#include <imap/imap.h>
 
-#include "mutt_crypt.h"
+#include <lib-crypt/crypt.h>
 
 static int eat_regexp (pattern_t * pat, BUFFER *, BUFFER *);
 static int eat_date (pattern_t * pat, BUFFER *, BUFFER *);
@@ -51,59 +33,56 @@ struct pattern_flags {
   int tag;                      /* character used to represent this op */
   int op;                       /* operation to perform */
   int class;
-  int (*eat_arg) (pattern_t *, BUFFER *, BUFFER *);
+  int (*eat_arg)(pattern_t *, BUFFER *, BUFFER *);
 } Flags[] = {
-  {
-  'A', M_ALL, 0, NULL}, {
-  'b', M_BODY, M_FULL_MSG, eat_regexp}, {
-  'B', M_WHOLE_MSG, M_FULL_MSG, eat_regexp}, {
-  'c', M_CC, 0, eat_regexp}, {
-  'C', M_RECIPIENT, 0, eat_regexp}, {
-  'd', M_DATE, 0, eat_date}, {
-  'D', M_DELETED, 0, NULL}, {
-  'e', M_SENDER, 0, eat_regexp}, {
-  'E', M_EXPIRED, 0, NULL}, {
-  'f', M_FROM, 0, eat_regexp}, {
-  'F', M_FLAG, 0, NULL}, {
-  'g', M_CRYPT_SIGN, 0, NULL}, {
-  'G', M_CRYPT_ENCRYPT, 0, NULL}, {
-  'h', M_HEADER, M_FULL_MSG, eat_regexp}, {
-  'H', M_HORMEL, 0, eat_regexp}, {
-  'i', M_ID, 0, eat_regexp}, {
-  'k', M_PGP_KEY, 0, NULL}, {
-  'L', M_ADDRESS, 0, eat_regexp}, {
-  'l', M_LIST, 0, NULL}, {
-  'm', M_MESSAGE, 0, eat_range}, {
-  'M', M_MULTIPART, 0, NULL}, {
-  'n', M_SCORE, 0, eat_range}, {
-  'N', M_NEW, 0, NULL}, {
-  'O', M_OLD, 0, NULL}, {
-  'p', M_PERSONAL_RECIP, 0, NULL}, {
-  'P', M_PERSONAL_FROM, 0, NULL}, {
-  'Q', M_REPLIED, 0, NULL}, {
-  'R', M_READ, 0, NULL}, {
-  'r', M_DATE_RECEIVED, 0, eat_date}, {
-  's', M_SUBJECT, 0, eat_regexp}, {
-  'S', M_SUPERSEDED, 0, NULL}, {
-  'T', M_TAG, 0, NULL}, {
-  't', M_TO, 0, eat_regexp}, {
-  'U', M_UNREAD, 0, NULL}, {
-  'u', M_SUBSCRIBED_LIST, 0, NULL}, {
-  'v', M_COLLAPSED, 0, NULL}, {
-  'V', M_CRYPT_VERIFIED, 0, NULL},
+  {'A', M_ALL, 0, NULL},
+  {'b', M_BODY, M_FULL_MSG, eat_regexp},
+  {'B', M_WHOLE_MSG, M_FULL_MSG, eat_regexp},
+  {'c', M_CC, 0, eat_regexp},
+  {'C', M_RECIPIENT, 0, eat_regexp},
+  {'d', M_DATE, 0, eat_date},
+  {'D', M_DELETED, 0, NULL},
+  {'e', M_SENDER, 0, eat_regexp},
+  {'E', M_EXPIRED, 0, NULL},
+  {'f', M_FROM, 0, eat_regexp},
+  {'F', M_FLAG, 0, NULL},
+  {'g', M_CRYPT_SIGN, 0, NULL},
+  {'G', M_CRYPT_ENCRYPT, 0, NULL},
+  {'h', M_HEADER, M_FULL_MSG, eat_regexp},
+  {'H', M_HORMEL, 0, eat_regexp},
+  {'i', M_ID, 0, eat_regexp},
+  {'k', M_PGP_KEY, 0, NULL},
+  {'L', M_ADDRESS, 0, eat_regexp},
+  {'l', M_LIST, 0, NULL},
+  {'m', M_MESSAGE, 0, eat_range},
+  {'M', M_MULTIPART, 0, NULL},
+  {'n', M_SCORE, 0, eat_range},
+  {'N', M_NEW, 0, NULL},
+  {'O', M_OLD, 0, NULL},
+  {'p', M_PERSONAL_RECIP, 0, NULL},
+  {'P', M_PERSONAL_FROM, 0, NULL},
+  {'Q', M_REPLIED, 0, NULL},
+  {'R', M_READ, 0, NULL},
+  {'r', M_DATE_RECEIVED, 0, eat_date},
+  {'s', M_SUBJECT, 0, eat_regexp},
+  {'S', M_SUPERSEDED, 0, NULL},
+  {'T', M_TAG, 0, NULL},
+  {'t', M_TO, 0, eat_regexp},
+  {'U', M_UNREAD, 0, NULL},
+  {'u', M_SUBSCRIBED_LIST, 0, NULL},
+  {'v', M_COLLAPSED, 0, NULL},
+  {'V', M_CRYPT_VERIFIED, 0, NULL},
 #ifdef USE_NNTP
-  {
-  'w', M_NEWSGROUPS, 0, eat_regexp},
+  {'w', M_NEWSGROUPS, 0, eat_regexp},
 #endif
-  {
-  'x', M_REFERENCE, 0, eat_regexp}, {
-  'X', M_MIMEATTACH, 0, eat_range}, {
-  'y', M_XLABEL, 0, eat_regexp}, {
-  'z', M_SIZE, 0, eat_range}, {
-  '=', M_DUPLICATED, 0, NULL}, {
-  '$', M_UNREFERENCED, 0, NULL}, {
-  '*', M_REALNAME, 0, NULL}, {
-  0, 0, 0, NULL}
+  {'x', M_REFERENCE, 0, eat_regexp},
+  {'X', M_MIMEATTACH, 0, eat_range},
+  {'y', M_XLABEL, 0, eat_regexp},
+  {'z', M_SIZE, 0, eat_range},
+  {'=', M_DUPLICATED, 0, NULL},
+  {'$', M_UNREFERENCED, 0, NULL},
+  {'*', M_REALNAME, 0, NULL},
+  {0, 0, 0, NULL}
 };
 
 static pattern_t *SearchPattern = NULL; /* current search pattern */
@@ -123,19 +102,6 @@ static char LastSearchExpn[LONG_STRING] = { 0 };        /* expanded version of
 #define M_PDR_ERROR    0x0100
 #define M_PDR_ERRORDONE        (M_PDR_ERROR | M_PDR_DONE)
 
-
-int mutt_getvaluebychar (char ch, struct mapping_t *table)
-{
-  int i;
-
-  for (i = 0; table[i].name; i++) {
-    if (ch == table[i].name[0])
-      return table[i].value;
-  }
-
-  return (-1);
-}
-
 /* if no uppercase letters are given, do a case-insensitive search */
 int mutt_which_case (const char *s)
 {
@@ -159,7 +125,7 @@ msg_search (CONTEXT *ctx, pattern_t* pat, int msgno)
   int match = 0;
   HEADER *h = ctx->hdrs[msgno];
   char* buf;
-  size_t blen;
+  ssize_t blen;
 
   if ((msg = mx_open_message (ctx, msgno)) != NULL) {
     if (option (OPTTHOROUGHSRC)) {
@@ -167,9 +133,9 @@ msg_search (CONTEXT *ctx, pattern_t* pat, int msgno)
       p_clear(&s, 1);
       s.fpin = msg->fp;
       s.flags = M_CHARCONV;
-      mutt_mktemp (tempfile);
-      if ((s.fpout = safe_fopen (tempfile, "w+")) == NULL) {
-        mutt_perror (tempfile);
+      s.fpout = m_tempfile(tempfile, sizeof(tempfile), NONULL(Tempdir), NULL);
+      if (!s.fpout) {
+        mutt_error(_("Could not create temporary file"));
         return (0);
       }
 
@@ -179,11 +145,11 @@ msg_search (CONTEXT *ctx, pattern_t* pat, int msgno)
       if (pat->op != M_HEADER) {
         mutt_parse_mime_message (ctx, h);
 
-        if (WithCrypto && (h->security & ENCRYPT)
-            && !crypt_valid_passphrase (h->security)) {
+        if ((h->security & ENCRYPT) && !crypt_valid_passphrase (h->security))
+        {
           mx_close_message (&msg);
           if (fp) {
-            fclose (fp);
+            m_fclose(&fp);
             unlink (tempfile);
           }
           return (0);
@@ -218,7 +184,7 @@ msg_search (CONTEXT *ctx, pattern_t* pat, int msgno)
     /* search the file "fp" */
     while (lng > 0) {
       if (pat->op == M_HEADER) {
-        if (*(buf = mutt_read_rfc822_line (fp, buf, &blen)) == '\0')
+        if (!mutt_read_rfc822_line(fp, &buf, &blen))
           break;
       } else if (fgets (buf, blen - 1, fp) == NULL)
         break;                  /* don't loop forever */
@@ -234,7 +200,7 @@ msg_search (CONTEXT *ctx, pattern_t* pat, int msgno)
     mx_close_message (&msg);
 
     if (option (OPTTHOROUGHSRC)) {
-      fclose (fp);
+      m_fclose(&fp);
       unlink (tempfile);
     }
   }
@@ -290,7 +256,7 @@ static int patmatch (const pattern_t* pat, const char* buf) {
     return regexec (pat->rx, buf, 0, NULL, 0);
 }
 
-int eat_range (pattern_t * pat, BUFFER * s, BUFFER * err)
+int eat_range (pattern_t * pat, BUFFER * s, BUFFER * err __attribute__ ((unused)))
 {
   char *tmp;
   int do_exclusive = 0;
@@ -359,8 +325,7 @@ int eat_range (pattern_t * pat, BUFFER * s, BUFFER * err)
   if (skip_quote && *tmp == '"')
     tmp++;
 
-  SKIPWS (tmp);
-  s->dptr = tmp;
+  s->dptr = vskipspaces(tmp);
   return 0;
 }
 
@@ -468,7 +433,7 @@ static const char *parse_date_range (const char *pc, struct tm *min,
     const char *pt;
     char ch = *pc++;
 
-    SKIPWS (pc);
+    pc = vskipspaces(pc);
     switch (ch) {
     case '-':
       {
@@ -524,7 +489,7 @@ static const char *parse_date_range (const char *pc, struct tm *min,
     default:
       flag |= M_PDR_ERRORDONE;
     }
-    SKIPWS (pc);
+    pc = vskipspaces(pc);
   }
   if ((flag & M_PDR_ERROR) && !(flag & M_PDR_ABSOLUTE)) {       /* getDate has its own error message, don't overwrite it here */
     snprintf (err->data, err->dsize, _("Invalid relative date: %s"), pc - 1);
@@ -608,11 +573,11 @@ static int eat_date (pattern_t * pat, BUFFER * s, BUFFER * err)
         return (-1);
       }
       haveMin = TRUE;
-      SKIPWS (pc);
+      pc = vskipspaces(pc);
       if (*pc == '-') {
-        const char *pt = pc + 1;
+        const char *pt;
 
-        SKIPWS (pt);
+        pt = skipspaces(pc + 1);
         untilNow = (*pt == '\0');
       }
     }
@@ -718,7 +683,7 @@ pattern_t *mutt_pattern_comp ( /* const */ char *s, int flags, BUFFER * err)
   ps.dsize = m_strlen(s);
 
   while (*ps.dptr) {
-    SKIPWS (ps.dptr);
+    ps.dptr = vskipspaces(ps.dptr);
     switch (*ps.dptr) {
     case '^':
       ps.dptr++;
@@ -792,8 +757,7 @@ pattern_t *mutt_pattern_comp ( /* const */ char *s, int flags, BUFFER * err)
       }
       tmp->op = entry->op;
 
-      ps.dptr++;                /* eat the operator and any optional whitespace */
-      SKIPWS (ps.dptr);
+      ps.dptr = vskipspaces(ps.dptr + 1);
 
       if (entry->eat_arg) {
         if (!*ps.dptr) {
@@ -817,7 +781,7 @@ pattern_t *mutt_pattern_comp ( /* const */ char *s, int flags, BUFFER * err)
         return NULL;
       }
       /* compile the sub-expression */
-      buf = str_substrdup (ps.dptr + 1, p);
+      buf = p_dupstr(ps.dptr + 1, p - ps.dptr - 1);
       if ((tmp = mutt_pattern_comp (buf, flags, err)) == NULL) {
         p_delete(&buf);
         mutt_pattern_free (&curlist);
@@ -874,15 +838,15 @@ perform_or (struct pattern_t *pat, pattern_exec_flag flags, CONTEXT * ctx,
   return 0;
 }
 
-static int match_adrlist (pattern_t* pat, int match_personal, int alladdr,
+static int match_adrlist (pattern_t* pat, int match_personal, int alladdr __attribute__ ((unused)),
                           int n, ...)
 {
   va_list ap;
-  ADDRESS *a;
+  address_t *a;
 
   va_start (ap, n);
   for (; n; n--) {
-    for (a = va_arg (ap, ADDRESS *); a; a = a->next) {
+    for (a = va_arg (ap, address_t *); a; a = a->next) {
       if (pat->alladdr ^
           ((a->mailbox && patmatch (pat, a->mailbox) == 0) ||
            (match_personal && a->personal &&
@@ -896,7 +860,7 @@ static int match_adrlist (pattern_t* pat, int match_personal, int alladdr,
   return pat->alladdr;               /* No matches, or all matches if alladdr */
 }
 
-static int match_reference (pattern_t* pat, LIST * refs)
+static int match_reference (pattern_t* pat, string_list_t * refs)
 {
   for (; refs; refs = refs->next)
     if (patmatch (pat, refs->data) == 0)
@@ -904,7 +868,7 @@ static int match_reference (pattern_t* pat, LIST * refs)
   return 0;
 }
 
-int mutt_is_list_recipient (int alladdr, ADDRESS * a1, ADDRESS * a2)
+int mutt_is_list_recipient (int alladdr, address_t * a1, address_t * a2)
 {
   for (; a1; a1 = a1->next)
     if (alladdr ^ mutt_is_subscribed_list (a1))
@@ -915,7 +879,7 @@ int mutt_is_list_recipient (int alladdr, ADDRESS * a1, ADDRESS * a2)
   return alladdr;
 }
 
-int mutt_is_list_cc (int alladdr, ADDRESS * a1, ADDRESS * a2)
+int mutt_is_list_cc (int alladdr, address_t * a1, address_t * a2)
 {
   for (; a1; a1 = a1->next)
     if (alladdr ^ mutt_is_mail_list (a1))
@@ -926,7 +890,7 @@ int mutt_is_list_cc (int alladdr, ADDRESS * a1, ADDRESS * a2)
   return alladdr;
 }
 
-static int match_user (int alladdr, ADDRESS * a1, ADDRESS * a2)
+static int match_user (int alladdr, address_t * a1, address_t * a2)
 {
   for (; a1; a1 = a1->next)
     if (alladdr ^ mutt_addr_is_user (a1))
@@ -1001,11 +965,9 @@ mutt_pattern_exec (struct pattern_t *pat, pattern_exec_flag flags,
   case M_BODY:
   case M_HEADER:
   case M_WHOLE_MSG:
-#ifdef USE_IMAP
     /* IMAP search sets h->matched at search compile time */
     if (ctx->magic == M_IMAP && pat->stringmatch)
       return (h->matched);
-#endif
     return (pat->not ^ msg_search (ctx, pat, h->msgno));
   case M_SENDER:
     return (pat->not ^ match_adrlist (pat, flags & M_MATCH_FULL_ADDRESS,
@@ -1070,20 +1032,12 @@ mutt_pattern_exec (struct pattern_t *pat, pattern_exec_flag flags,
   case M_COLLAPSED:
     return (pat->not ^ (h->collapsed && h->num_hidden > 1));
   case M_CRYPT_SIGN:
-    if (!WithCrypto)
-      break;
     return (pat->not ^ ((h->security & SIGN) ? 1 : 0));
   case M_CRYPT_VERIFIED:
-    if (!WithCrypto)
-      break;
     return (pat->not ^ ((h->security & GOODSIGN) ? 1 : 0));
   case M_CRYPT_ENCRYPT:
-    if (!WithCrypto)
-      break;
     return (pat->not ^ ((h->security & ENCRYPT) ? 1 : 0));
   case M_PGP_KEY:
-    if (!(WithCrypto & APPLICATION_PGP))
-      break;
     return (pat->not ^ ((h->security & APPLICATION_PGP)
                         && (h->security & PGPKEY)));
   case M_XLABEL:
@@ -1106,7 +1060,7 @@ mutt_pattern_exec (struct pattern_t *pat, pattern_exec_flag flags,
       else {
         mutt_parse_mime_message(ctx, h);
         count = mutt_count_body_parts(h, 0);
-        mutt_free_body(&h->content->parts);
+        body_list_wipe(&h->content->parts);
       }
       
       return (pat->not ^ (count >= pat->min && (pat->max == M_MAXRANGE ||
@@ -1124,17 +1078,13 @@ mutt_pattern_exec (struct pattern_t *pat, pattern_exec_flag flags,
      * - or we have an alias for current address
      * - or From: contains valid email address _and_ name has >= 2 fields
      */
-    return (pat->
-            not ^ (h->env && h->env->from && (mutt_addr_is_user (h->env->from)
-                                              ||
-                                              (alias_reverse_lookup
-                                               (h->env->from) != NULL)
-                                              || (h->env->from->personal
-                                                  && valid_realname (h->env->
-                                                                     from->
-                                                                     personal)
-                                                  && h->env->from->mailbox)
-                   )));
+    return (h->env && h->env->from
+        && (mutt_addr_is_user(h->env->from)
+            || alias_reverse_lookup(h->env->from)
+            || (h->env->from->personal
+                && valid_realname(h->env-> from->personal)
+                && h->env->from->mailbox)
+           )) ^ pat->not;
 #ifdef USE_NNTP
   case M_NEWSGROUPS:
     return (pat->
@@ -1146,9 +1096,9 @@ mutt_pattern_exec (struct pattern_t *pat, pattern_exec_flag flags,
   return (-1);
 }
 
-static void quote_simple (char *tmp, size_t len, const char *p)
+static void quote_simple (char *tmp, ssize_t len, const char *p)
 {
-  int i = 0;
+  ssize_t i = 0;
 
   tmp[i++] = '"';
   while (*p && i < len - 3) {
@@ -1161,7 +1111,7 @@ static void quote_simple (char *tmp, size_t len, const char *p)
 }
 
 /* convert a simple search into a real request */
-void mutt_check_simple (char *s, size_t len, const char *simple)
+void mutt_check_simple (char *s, ssize_t len, const char *simple)
 {
   char tmp[LONG_STRING];
 
@@ -1191,7 +1141,7 @@ void mutt_check_simple (char *s, size_t len, const char *simple)
       m_strcpy(s, len, "~U");
     else {
       quote_simple (tmp, sizeof (tmp), s);
-      mutt_expand_fmt (s, len, simple, tmp);
+      m_file_fmt(s, len, simple, tmp);
     }
   }
 }
@@ -1221,10 +1171,8 @@ int mutt_pattern_func (int op, char *prompt)
     return (-1);
   }
 
-#ifdef USE_IMAP
   if (Context->magic == M_IMAP && imap_search (Context, pat) < 0)
     return -1;
-#endif
 
   mutt_message _("Executing command on matching messages...");
 
@@ -1352,10 +1300,8 @@ int mutt_search_command (int cur, int op)
   if (option (OPTSEARCHINVALID)) {
     for (i = 0; i < Context->msgcount; i++)
       Context->hdrs[i]->searched = 0;
-#ifdef USE_IMAP
     if (Context->magic == M_IMAP && imap_search (Context, SearchPattern) < 0)
       return -1;
-#endif
     unset_option (OPTSEARCHINVALID);
   }