Andreas Krennmair:
[apps/madmutt.git] / sendlib.c
index 7a718a2..9ebab5e 100644 (file)
--- a/sendlib.c
+++ b/sendlib.c
 
 #define _SENDLIB_C 1
 
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
 #include "mutt.h"
 #include "mutt_curses.h"
 #include "rfc2047.h"
 #include <fcntl.h>
 #include <sys/utsname.h>
 
+#ifdef USE_LIBESMTP
+# include "mutt_libesmtp.h"
+#endif /* USE_LIBESMTP */
+
 #ifdef USE_NNTP
 #include <nntp.h>
 #endif
@@ -191,9 +199,6 @@ static void encode_quoted (FGETCONV * fc, FILE *fout, int istext)
       linelen = 3;
     }
 
-#ifdef USE_LIBESMTP
-# include "mutt_libesmtp.h"
-#endif /* USE_LIBESMTP */
 
     if (c == '\n' && istext)
     {
@@ -504,7 +509,7 @@ int mutt_write_mime_body (BODY *a, FILE *f)
   }
 
   if (a->type == TYPETEXT && (!a->noconv))
-    fc = fgetconv_open (fpin, Charset, 
+    fc = fgetconv_open (fpin, a->file_charset, 
                        mutt_get_body_charset (send_charset, sizeof (send_charset), a),
                        0);
   else
@@ -904,6 +909,7 @@ CONTENT *mutt_get_content_info (const char *fname, BODY *b)
   CONTENT *info;
   CONTENT_STATE state;
   FILE *fp = NULL;
+  char *fromcode;
   char *tocode;
   char buffer[100];
   char chsbuf[STRING];
@@ -938,15 +944,18 @@ CONTENT *mutt_get_content_info (const char *fname, BODY *b)
   if (b != NULL && b->type == TYPETEXT && (!b->noconv && !b->force_charset))
   {
     char *chs = mutt_get_parameter ("charset", b->parameter);
+    char *fchs = b->use_disp ? ((FileCharset && *FileCharset) ?
+                                FileCharset : Charset) : Charset;
     if (Charset && (chs || SendCharset) &&
-       convert_file_from_to (fp, Charset, chs ? chs : SendCharset,
-                             0, &tocode, info) != (size_t)(-1))
+        convert_file_from_to (fp, fchs, chs ? chs : SendCharset,
+                              &fromcode, &tocode, info) != (size_t)(-1))
     {
       if (!chs)
       {
        mutt_canonical_charset (chsbuf, sizeof (chsbuf), tocode);
        mutt_set_parameter ("charset", chsbuf, &b->parameter);
       }
+      b->file_charset = fromcode;
       FREE (&tocode);
       safe_fclose (&fp);
       return info;
@@ -1172,6 +1181,9 @@ static void transform_to_7bit (BODY *a, FILE *fpin)
     }
     else 
     {
+      a->noconv = 1;
+      a->force_charset = 1;
+      
       mutt_mktemp (buff);
       if ((s.fpout = safe_fopen (buff, "w")) == NULL) 
       {
@@ -1326,6 +1338,7 @@ BODY *mutt_make_message_attach (CONTEXT *ctx, HEADER *hdr, int attach_msg)
   body->unlink = 1;
   body->use_disp = 0;
   body->disposition = DISPINLINE;
+  body->noconv = 1;
 
   mutt_parse_mime_message (ctx, hdr);
 
@@ -1737,15 +1750,6 @@ int mutt_write_rfc822_header (FILE *fp, ENVELOPE *env, BODY *attach,
     }
   }
 
-  /* Add X-Face headers */
-  if (env->x_face)
-  {
-    LIST *face;
-
-    for (face = env->x_face; face; face = face->next)
-      fprintf (fp, "X-Face: %s\n", face->data);
-  }
-
   if (mode == 0 && !privacy && option (OPTXMAILER) && !has_agent)
   {
     struct utsname un;
@@ -1818,9 +1822,102 @@ const char *mutt_fqdn(short may_hide_host)
   return p;
 }
 
+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) */
+}
+
+static void mutt_gen_localpart(char * buf, unsigned int len, char * fmt) {
+  time_t now;
+  struct tm *tm;
+  char tmp[SHORT_STRING];
+
+  *buf = '\0';
+
+  now = time (NULL);
+  tm = gmtime (&now);
+
+  for (;*fmt;++fmt) {
+    if (*fmt == '%') {
+      switch (fmt[1]) {
+      case 0:
+        return;
+      case 'd':
+        snprintf(tmp,sizeof(tmp),"%02d",tm->tm_mday);
+        safe_strncat(buf,len,tmp,2);
+        break;
+      case 'h':
+        snprintf(tmp,sizeof(tmp),"%02d",tm->tm_hour);
+        safe_strncat(buf,len,tmp,2);
+        break;
+      case 'm':
+        snprintf(tmp,sizeof(tmp),"%02d",tm->tm_mon+1);
+        safe_strncat(buf,len,tmp,2);
+        break;
+      case 'M':
+        snprintf(tmp,sizeof(tmp),"%02d",tm->tm_min);
+        safe_strncat(buf,len,tmp,2);
+        break;
+      case 'O':
+        snprintf(tmp,sizeof(tmp),"%lo",(unsigned long)now);
+        safe_strncat(buf,len,tmp,strlen(tmp));
+        break;
+      case 'p':
+        snprintf(tmp,sizeof(tmp),"%u",(unsigned int)getpid());
+        safe_strncat(buf,len,tmp,strlen(tmp));
+        break;
+      case 'P':
+        snprintf(tmp,sizeof(tmp),"%c",MsgIdPfx);
+        MsgIdPfx = (MsgIdPfx == 'Z') ? 'A' : MsgIdPfx + 1;
+        safe_strncat(buf,len,tmp,1);
+        break;
+      case 'r':
+        snprintf(tmp,sizeof(tmp),"%u",(unsigned int)rand());
+        safe_strncat(buf,len,tmp,strlen(tmp));
+        break;
+      case 'R':
+        snprintf(tmp,sizeof(tmp),"%x",(unsigned int)rand());
+        safe_strncat(buf,len,tmp,strlen(tmp));
+        break;
+      case 's':
+        snprintf(tmp,sizeof(tmp),"%02d",tm->tm_sec);
+        safe_strncat(buf,len,tmp,2);
+        break;
+      case 'T':
+        snprintf(tmp,sizeof(tmp),"%u",(unsigned int)now);
+        safe_strncat(buf,len,tmp,strlen(tmp));
+        break;
+      case 'X':
+        snprintf(tmp,sizeof(tmp),"%x",(unsigned int)now);
+        safe_strncat(buf,len,tmp,strlen(tmp));
+        break;
+      case 'Y':
+        snprintf(tmp,sizeof(tmp),"%04d",tm->tm_year+1900); /* this will break in the year 10000 ;-) */
+        safe_strncat(buf,len,tmp,4);
+        break;
+      case '%':
+        safe_strncat(buf,len,"%",1);
+        break;
+      default:
+        safe_strncat(buf,len,".",1); /* invalid formats are replaced by '.' */
+      } /* switch */
+      ++fmt;
+    } else {
+      char c;
+      c = mutt_normalized_char(*fmt); /* @todo: filter out invalid characters */
+      safe_strncat(buf,len,&c,1);
+    }
+  }
+}
+
 char *mutt_gen_msgid (void)
 {
   char buf[SHORT_STRING];
+  char localpart[SHORT_STRING];
+  unsigned int localpart_length;
   time_t now;
   struct tm *tm;
   const char *fqdn;
@@ -1830,10 +1927,11 @@ char *mutt_gen_msgid (void)
   if(!(fqdn = mutt_fqdn(0)))
     fqdn = NONULL(Hostname);
 
-  snprintf (buf, sizeof (buf), "<%d%02d%02d%02d%02d%02d.G%c%d@%s>",
-           tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour,
-           tm->tm_min, tm->tm_sec, MsgIdPfx, getpid (), fqdn);
-  MsgIdPfx = (MsgIdPfx == 'Z') ? 'A' : MsgIdPfx + 1;
+  localpart_length = sizeof(buf) - 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 (safe_strdup (buf));
 }
 
@@ -2263,6 +2361,7 @@ void mutt_prepare_envelope (ENVELOPE *env, int final)
   /* Take care of 8-bit => 7-bit conversion. */
   rfc2047_encode_adrlist (env->to, "To");
   rfc2047_encode_adrlist (env->cc, "Cc");
+  rfc2047_encode_adrlist (env->bcc, "Bcc");
   rfc2047_encode_adrlist (env->from, "From");
   rfc2047_encode_adrlist (env->mail_followup_to, "Mail-Followup-To");
   rfc2047_encode_adrlist (env->reply_to, "Reply-To");
@@ -2289,6 +2388,7 @@ void mutt_unprepare_envelope (ENVELOPE *env)
   /* back conversions */
   rfc2047_decode_adrlist (env->to);
   rfc2047_decode_adrlist (env->cc);
+  rfc2047_decode_adrlist (env->bcc);
   rfc2047_decode_adrlist (env->from);
   rfc2047_decode_adrlist (env->reply_to);
   rfc2047_decode (&env->subject);
@@ -2384,40 +2484,42 @@ int mutt_bounce_message (FILE *fp, HEADER *h, ADDRESS *to)
 /* given a list of addresses, return a list of unique addresses */
 ADDRESS *mutt_remove_duplicates (ADDRESS *addr)
 {
-  ADDRESS *top = NULL;
+  ADDRESS *top = addr;
+  ADDRESS **last = &top;
   ADDRESS *tmp;
-  
-  if ((top = addr) == NULL)
-    return (NULL);
-  addr = addr->next;
-  top->next = NULL;
+  int dup;
+
   while (addr)
   {
-    tmp = top;
-    do {
-      if (addr->mailbox && tmp->mailbox &&
+    for (tmp = top, dup = 0; tmp && tmp != addr; tmp = tmp->next)
+    {
+      if (tmp->mailbox && addr->mailbox && 
          !ascii_strcasecmp (addr->mailbox, tmp->mailbox))
       {
-       /* duplicate address, just ignore it */
-       tmp = addr;
-       addr = addr->next;
-       tmp->next = NULL;
-       rfc822_free_address (&tmp);
-      }
-      else if (!tmp->next)
-      {
-       /* unique address.  add it to the list */
-       tmp->next = addr;
-       addr = addr->next;
-       tmp = tmp->next;
-       tmp->next = NULL;
-       tmp = NULL; /* so we exit the loop */
+       dup = 1;
+       break;
       }
-      else
-       tmp = tmp->next;
-    } while (tmp);
-  }
+    }
+    
+    if (dup)
+    {
+      dprint (2, (debugfile, "mutt_remove_duplicates: Removing %s\n",
+                 addr->mailbox));
+      
+      *last = addr->next;
 
+      addr->next = NULL;
+      rfc822_free_address(&addr);
+      
+      addr = *last;
+    }
+    else 
+    {
+      last = &addr->next;
+      addr = addr->next;
+    }
+  }
+  
   return (top);
 }
 
@@ -2512,6 +2614,8 @@ int mutt_write_fcc (const char *path, HEADER *hdr, const char *msgid, int post,
       if (PgpSignAs && *PgpSignAs)
         fprintf (msg->fp, "<%s>", PgpSignAs);
     }
+    if (hdr->security & INLINE)
+      fputc ('I', msg->fp);
     fputc ('\n', msg->fp);
   }
 
@@ -2530,6 +2634,8 @@ int mutt_write_fcc (const char *path, HEADER *hdr, const char *msgid, int post,
        if (SmimeDefaultKey && *SmimeDefaultKey)
            fprintf (msg->fp, "<%s>", SmimeDefaultKey);
     }
+    if (hdr->security & INLINE)
+      fputc ('I', msg->fp);
     fputc ('\n', msg->fp);
   }