make m_dupstr return NULL if the string was empty.
[apps/madmutt.git] / sendlib.c
index 48f95b1..a461354 100644 (file)
--- a/sendlib.c
+++ b/sendlib.c
 #endif
 
 #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 "mutt.h"
-#include "ascii.h"
 #include "handler.h"
 #include "recvattach.h"
 #include "mutt_curses.h"
@@ -31,7 +33,6 @@
 #include "mutt_crypt.h"
 #include "mutt_idna.h"
 
-#include "lib/str.h"
 #include "lib/debug.h"
 
 #include <string.h>
@@ -295,7 +296,7 @@ int mutt_write_mime_header (BODY * a, FILE * f)
   fprintf (f, "Content-Type: %s/%s", TYPE (a), a->subtype);
 
   if (a->parameter) {
-    len = 25 + str_len (a->subtype);        /* approximate len. of content-type */
+    len = 25 + m_strlen(a->subtype);        /* approximate len. of content-type */
 
     for (p = a->parameter; p; p = p->next) {
       char *tmp;
@@ -306,7 +307,7 @@ int mutt_write_mime_header (BODY * a, FILE * f)
       fputc (';', f);
 
       buffer[0] = 0;
-      tmp = str_dup (p->value);
+      tmp = m_strdup(p->value);
       encode = rfc2231_encode_string (&tmp);
       rfc822_cat (buffer, sizeof (buffer), tmp, MimeSpecials);
 
@@ -321,7 +322,7 @@ int mutt_write_mime_header (BODY * a, FILE * f)
 
       p_delete(&tmp);
 
-      tmplen = str_len (buffer) + str_len (p->attribute) + 1;
+      tmplen = m_strlen(buffer) + m_strlen(p->attribute) + 1;
 
       if (len + tmplen + 2 > 76) {
         fputs ("\n\t", f);
@@ -358,7 +359,7 @@ int mutt_write_mime_header (BODY * a, FILE * f)
         t = fn;
 
       buffer[0] = 0;
-      tmp = str_dup (t);
+      tmp = m_strdup(t);
       encode = rfc2231_encode_string (&tmp);
       rfc822_cat (buffer, sizeof (buffer), tmp, MimeSpecials);
       p_delete(&tmp);
@@ -412,7 +413,7 @@ int mutt_write_mime_body (BODY * a, FILE * f)
   /* This is pretty gross, but it's the best solution for now... */
   if ((WithCrypto & APPLICATION_PGP)
       && a->type == TYPEAPPLICATION
-      && str_cmp (a->subtype, "pgp-encrypted") == 0) {
+      && m_strcmp(a->subtype, "pgp-encrypted") == 0) {
     fputs ("Version: 1\n", f);
     return 0;
   }
@@ -807,7 +808,7 @@ CONTENT *mutt_get_content_info (const char *fname, BODY * b)
   CONTENT_STATE state;
   FILE *fp = NULL;
   char *fromcode = NULL;
-  char *tocode;
+  char *tocode = NULL;
   char buffer[100];
   char chsbuf[STRING];
   size_t r;
@@ -833,7 +834,7 @@ CONTENT *mutt_get_content_info (const char *fname, BODY * b)
   }
 
   info = p_new(CONTENT, 1);
-  memset (&state, 0, sizeof (state));
+  p_clear(&state, 1);
 
   if (b != NULL && b->type == TYPETEXT && (!b->noconv && !b->force_charset)) {
     char *chs = mutt_get_parameter ("charset", b->parameter);
@@ -891,7 +892,7 @@ int mutt_lookup_mime_type (BODY * att, const char *path)
   type = TYPEOTHER;
   cur_sze = 0;
 
-  szf = str_len (path);
+  szf = m_strlen(path);
 
   for (count = 0; count < 4; count++) {
     /*
@@ -934,7 +935,7 @@ int mutt_lookup_mime_type (BODY * att, const char *path)
 
         /* cycle through the file extensions */
         while ((p = strtok (p, " \t\n"))) {
-          sze = str_len (p);
+          sze = m_strlen(p);
           if ((sze > cur_sze) && (szf >= sze) &&
               (str_casecmp (path + szf - sze, p) == 0
                || ascii_strcasecmp (path + szf - sze, p) == 0) && (szf == sze
@@ -1035,7 +1036,7 @@ cleanup:
   a->d_filename = a->filename;
   if (a->filename && a->unlink)
     unlink (a->filename);
-  a->filename = str_dup (temp);
+  a->filename = m_strdup(temp);
   a->unlink = 1;
   if (stat (a->filename, &sb) == -1) {
     mutt_perror ("stat");
@@ -1052,7 +1053,7 @@ static void transform_to_7bit (BODY * a, FILE * fpin)
   STATE s;
   struct stat sb;
 
-  memset (&s, 0, sizeof (s));
+  p_clear(&s, 1);
   for (; a; a = a->next) {
     if (a->type == TYPEMULTIPART) {
       if (a->encoding != ENC7BIT)
@@ -1076,7 +1077,7 @@ static void transform_to_7bit (BODY * a, FILE * fpin)
       mutt_decode_attachment (a, &s);
       fclose (s.fpout);
       a->d_filename = a->filename;
-      a->filename = str_dup (buff);
+      a->filename = m_strdup(buff);
       a->unlink = 1;
       if (stat (a->filename, &sb) == -1) {
         mutt_perror ("stat");
@@ -1213,8 +1214,8 @@ BODY *mutt_make_message_attach (CONTEXT * ctx, HEADER * hdr, int attach_msg)
 
   body = mutt_new_body ();
   body->type = TYPEMESSAGE;
-  body->subtype = str_dup ("rfc822");
-  body->filename = str_dup (buffer);
+  body->subtype = m_strdup("rfc822");
+  body->filename = m_strdup(buffer);
   body->unlink = 1;
   body->use_disp = 0;
   body->disposition = DISPINLINE;
@@ -1280,7 +1281,7 @@ BODY *mutt_make_file_attach (const char *path)
   CONTENT *info;
 
   att = mutt_new_body ();
-  att->filename = str_dup (path);
+  att->filename = m_strdup(path);
 
   /* Attempt to determine the appropriate content-type based on the filename
    * suffix.
@@ -1292,8 +1293,8 @@ BODY *mutt_make_file_attach (const char *path)
        mutt_lookup_mime_type (buf, sizeof (buf), xbuf, sizeof (xbuf),
                               path)) != TYPEOTHER || *xbuf != '\0') {
     att->type = n;
-    att->subtype = str_dup (buf);
-    att->xtype = str_dup (xbuf);
+    att->subtype = m_strdup(buf);
+    att->xtype = m_strdup(xbuf);
   }
 
 #else
@@ -1315,11 +1316,11 @@ BODY *mutt_make_file_attach (const char *path)
        * chars if this is really a binary file...
        */
       att->type = TYPETEXT;
-      att->subtype = str_dup ("plain");
+      att->subtype = m_strdup("plain");
     }
     else {
       att->type = TYPEAPPLICATION;
-      att->subtype = str_dup ("octet-stream");
+      att->subtype = m_strdup("octet-stream");
     }
   }
 
@@ -1347,7 +1348,7 @@ BODY *mutt_make_multipart (BODY * b)
 
   new = mutt_new_body ();
   new->type = TYPEMULTIPART;
-  new->subtype = str_dup ("mixed");
+  new->subtype = m_strdup("mixed");
   new->encoding = get_toplevel_encoding (b);
   mutt_generate_boundary (&new->parameter);
   new->use_disp = 0;
@@ -1401,7 +1402,7 @@ void mutt_write_address_list (ADDRESS * adr, FILE * fp, int linelen,
     adr->next = NULL;
     buf[0] = 0;
     rfc822_write_address (buf, sizeof (buf), adr, display);
-    len = str_len (buf);
+    len = m_strlen(buf);
     if (count && linelen + len > 74) {
       fputs ("\n\t", fp);
       linelen = len + 8;        /* tab is usually about 8 spaces... */
@@ -1643,13 +1644,13 @@ static void encode_headers (LIST * h)
     i = p - h->data;
     ++p;
     SKIPWS (p);
-    tmp = str_dup (p);
+    tmp = m_strdup(p);
 
     if (!tmp)
       continue;
 
     rfc2047_encode_string (&tmp);
-    p_realloc(&h->data, str_len(h->data) + 2 + str_len(tmp) + 1);
+    p_realloc(&h->data, m_strlen(h->data) + 2 + m_strlen(tmp) + 1);
 
     sprintf (h->data + i, ": %s", NONULL (tmp));        /* __SPRINTF_CHECKED__ */
 
@@ -1680,99 +1681,98 @@ const char *mutt_fqdn (short may_hide_host)
   return p;
 }
 
-static char mutt_normalized_char (char c)
+/* normalized character (we're stricter than RFC2822, 3.6.4) */
+static char mutt_normalized_char(char c)
 {
-  if (isalnum (c))
-    return c;
-  if (strchr (".!#$%&'*+-/=?^_`{|}~", c))
-    return c;
-  return '.';                   /* normalized character (we're stricter than RFC2822, 3.6.4) */
+    return (isalnum(c) || strchr(".!#$%&'*+-/=?^_`{|}~", c)) ? c : '.';
 }
 
-static void mutt_gen_localpart (char *buf, unsigned int len, char *fmt)
+static void mutt_gen_localpart(char *buf, unsigned int len, const char *fmt)
 {
-  time_t now;
-  struct tm *tm;
-  char tmp[SHORT_STRING];
+#define APPEND_FMT(fmt, arg) \
+        if (len > 1) {                                  \
+            int snlen = snprintf(buf, len, fmt, arg);   \
+            buf += snlen;                               \
+            len -= snlen;                               \
+        }
 
-  *buf = '\0';
+#define APPEND_BYTE(c) \
+        if (len > 1) {                                  \
+            *buf++ = c;                                 \
+            *buf   = '\0';                              \
+            len--;                                      \
+        }
 
-  now = time (NULL);
-  tm = gmtime (&now);
+    time_t now;
+    struct tm *tm;
 
-  for (; *fmt; ++fmt) {
-    if (*fmt == '%') {
-      switch (fmt[1]) {
-      case 0:
-        return;
-      case 'd':
-        snprintf (tmp, sizeof (tmp), "%02d", tm->tm_mday);
-        str_ncat (buf, len, tmp, 2);
-        break;
-      case 'h':
-        snprintf (tmp, sizeof (tmp), "%02d", tm->tm_hour);
-        str_ncat (buf, len, tmp, 2);
-        break;
-      case 'm':
-        snprintf (tmp, sizeof (tmp), "%02d", tm->tm_mon + 1);
-        str_ncat (buf, len, tmp, 2);
-        break;
-      case 'M':
-        snprintf (tmp, sizeof (tmp), "%02d", tm->tm_min);
-        str_ncat (buf, len, tmp, 2);
-        break;
-      case 'O':
-        snprintf (tmp, sizeof (tmp), "%lo", (unsigned long) now);
-        str_ncat (buf, len, tmp, str_len (tmp));
-        break;
-      case 'p':
-        snprintf (tmp, sizeof (tmp), "%u", (unsigned int) getpid ());
-        str_ncat (buf, len, tmp, str_len (tmp));
-        break;
-      case 'P':
-        snprintf (tmp, sizeof (tmp), "%c", MsgIdPfx);
-        MsgIdPfx = (MsgIdPfx == 'Z') ? 'A' : MsgIdPfx + 1;
-        str_ncat (buf, len, tmp, 1);
-        break;
-      case 'r':
-        snprintf (tmp, sizeof (tmp), "%u", (unsigned int) rand ());
-        str_ncat (buf, len, tmp, str_len (tmp));
-        break;
-      case 'R':
-        snprintf (tmp, sizeof (tmp), "%x", (unsigned int) rand ());
-        str_ncat (buf, len, tmp, str_len (tmp));
-        break;
-      case 's':
-        snprintf (tmp, sizeof (tmp), "%02d", tm->tm_sec);
-        str_ncat (buf, len, tmp, 2);
-        break;
-      case 'T':
-        snprintf (tmp, sizeof (tmp), "%u", (unsigned int) now);
-        str_ncat (buf, len, tmp, str_len (tmp));
-        break;
-      case 'X':
-        snprintf (tmp, sizeof (tmp), "%x", (unsigned int) now);
-        str_ncat (buf, len, tmp, str_len (tmp));
-        break;
-      case 'Y':
-        snprintf (tmp, sizeof (tmp), "%04d", tm->tm_year + 1900);       /* this will break in the year 10000 ;-) */
-        str_ncat (buf, len, tmp, 4);
-        break;
-      case '%':
-        str_ncat (buf, len, "%", 1);
-        break;
-      default:
-        str_ncat (buf, len, ".", 1);        /* invalid formats are replaced by '.' */
-      }                         /* switch */
-      ++fmt;
-    }
-    else {
-      char c;
+    now = time (NULL);
+    tm = gmtime (&now);
+
+    while (*fmt) {
+        int c = *fmt++;
 
-      c = mutt_normalized_char (*fmt);  /* @todo: filter out invalid characters */
-      str_ncat (buf, len, &c, 1);
+        if (c != '%') {
+            APPEND_BYTE(mutt_normalized_char(c));
+            continue;
+        }
+
+        switch (*fmt++) {
+          case 0:
+            return;
+          case 'd':
+            APPEND_FMT("%02d", tm->tm_mday);
+            break;
+          case 'h':
+            APPEND_FMT("%02d", tm->tm_hour);
+            break;
+          case 'm':
+            APPEND_FMT("%02d", tm->tm_mon + 1);
+            break;
+          case 'M':
+            APPEND_FMT("%02d", tm->tm_min);
+            break;
+          case 'O':
+            APPEND_FMT("%lo", (unsigned long)now);
+            break;
+          case 'p':
+            APPEND_FMT("%u", (unsigned int)getpid());
+            break;
+          case 'P':
+            APPEND_FMT("%c", MsgIdPfx);
+            MsgIdPfx = (MsgIdPfx == 'Z') ? 'A' : MsgIdPfx + 1;
+            break;
+          case 'r':
+            APPEND_FMT("%u", (unsigned int)rand());
+            break;
+          case 'R':
+            APPEND_FMT("%x", (unsigned int)rand());
+            break;
+          case 's':
+            APPEND_FMT("%02d", tm->tm_sec);
+            break;
+          case 'T':
+            APPEND_FMT("%u", (unsigned int) now);
+            break;
+          case 'X':
+            APPEND_FMT("%x", (unsigned int) now);
+            break;
+          case 'Y':       /* this will break in the year 10000 ;-) */
+            APPEND_FMT("%04d", tm->tm_year + 1900);
+            break;
+          case '%':
+            APPEND_BYTE('%');
+            break;
+          default:       /* invalid formats are replaced by '.' */
+            APPEND_BYTE('.');
+            m_strncat(buf, len, ".", 1); 
+        }
     }
-  }
+
+    *buf = '\0';
+
+#undef APPEND_BYTE
+#undef APPEND_FMT
 }
 
 char *mutt_gen_msgid (void)
@@ -1785,12 +1785,12 @@ char *mutt_gen_msgid (void)
   if (!(fqdn = mutt_fqdn (0)))
     fqdn = NONULL (Hostname);
 
-  localpart_length = sizeof (buf) - str_len (fqdn) - 4;  /* the 4 characters are '<', '@', '>' and '\0' */
+  localpart_length = sizeof (buf) - m_strlen(fqdn) - 4;  /* the 4 characters are '<', '@', '>' and '\0' */
 
   mutt_gen_localpart (localpart, localpart_length, MsgIdFormat);
 
   snprintf (buf, sizeof (buf), "<%s@%s>", localpart, fqdn);
-  return (str_dup (buf));
+  return (m_strdup(buf));
 }
 
 static RETSIGTYPE alarm_handler (int sig)
@@ -1823,7 +1823,7 @@ send_msg(const char *path, const char **args, const char *msg, char **tempfile)
     char tmp[_POSIX_PATH_MAX];
 
     mutt_mktemp (tmp);
-    *tempfile = str_dup (tmp);
+    *tempfile = m_strdup(tmp);
   }
 
   if ((pid = fork ()) == 0) {
@@ -1990,11 +1990,11 @@ static int mutt_invoke_sendmail (ADDRESS * from,        /* the sender */
       return i;
     }
 
-    s = str_dup (cmd);
+    s = m_strdup(cmd);
   }
   else
 #endif
-    s = str_dup (Sendmail);
+    s = m_strdup(Sendmail);
 
   ps = s;
   i = 0;
@@ -2005,7 +2005,7 @@ static int mutt_invoke_sendmail (ADDRESS * from,        /* the sender */
     if (i)
       args[argslen++] = ps;
     else {
-      path = str_dup (ps);
+      path = m_strdup(ps);
       ps = strrchr (ps, '/');
       if (ps)
         ps++;
@@ -2108,9 +2108,9 @@ int mutt_invoke_mta (ADDRESS * from,    /* the sender */
    string. */
 char *mutt_append_string (char *a, const char *b)
 {
-  size_t la = str_len (a);
+  size_t la = m_strlen(a);
 
-  p_realloc(&a, la + str_len(b) + 1);
+  p_realloc(&a, la + m_strlen(b) + 1);
   strcpy (a + la, b);           /* __STRCPY_CHECKED__ */
   return (a);
 }
@@ -2138,7 +2138,7 @@ char *mutt_quote_string (const char *s)
   char *r, *pr;
   size_t rlen;
 
-  rlen = str_len (s) + 3;
+  rlen = m_strlen(s) + 3;
   pr = r = p_new(char, rlen);
   *pr++ = '"';
   while (*s) {
@@ -2175,7 +2175,7 @@ void mutt_prepare_envelope (ENVELOPE * env, int final)
       rfc822_cat (buffer, sizeof (buffer), "undisclosed-recipients",
                   RFC822Specials);
 
-      env->to->mailbox = str_dup (buffer);
+      env->to->mailbox = m_strdup(buffer);
     }
 
     mutt_set_followup_to (env);