]> diplodocus.org Git - nmh/blobdiff - uip/mhoutsbr.c
lock_file.c: close(2) file descriptor on failure, avoiding leak.
[nmh] / uip / mhoutsbr.c
index db64c4b87d1e2af79e4e448d4ed3a5bf86ea6b6a..4a3166f3f819b5c3401aa841768d1f8a28a359c8 100644 (file)
@@ -1,6 +1,4 @@
-
-/*
- * mhoutsbr.c -- routines to output MIME messages
+/* mhoutsbr.c -- routines to output MIME messages
  *            -- given a Content structure
  *
  * This code is Copyright (c) 2002, by the authors of nmh.  See the
  *            -- given a Content structure
  *
  * This code is Copyright (c) 2002, by the authors of nmh.  See the
 
 #include <h/mh.h>
 #include <fcntl.h>
 
 #include <h/mh.h>
 #include <fcntl.h>
-#include <h/signals.h>
+#include <h/utils.h>
 #include <h/md5.h>
 #include <h/md5.h>
-#include <errno.h>
-#include <signal.h>
 #include <h/mts.h>
 #include <h/tws.h>
 #include <h/mime.h>
 #include <h/mhparse.h>
 #include <h/mts.h>
 #include <h/tws.h>
 #include <h/mime.h>
 #include <h/mhparse.h>
+#include "mhoutsbr.h"
+#include "sbr/base64.h"
 
 
 
 
-/*
- * prototypes
- */
-int output_message (CT, char *);
-int output_message_fp (CT, FILE *, char *);
-
 /*
  * static prototypes
  */
 /*
  * static prototypes
  */
@@ -56,23 +48,6 @@ output_message_fp (CT ct, FILE *fp, char *file)
     return OK;
 }
 
     return OK;
 }
 
-int
-output_message (CT ct, char *file)
-{
-    FILE *fp;
-    int status;
-
-    if (! strcmp (file, "-")) {
-       fp = stdout;
-    } else if ((fp = fopen (file, "w")) == NULL) {
-       advise (file, "unable to open for writing");
-       return NOTOK;
-    }
-    status = output_message_fp(ct, fp, file);
-    if (strcmp (file, "-")) fclose(fp);
-    return status;
-}
-
 
 /*
  * Output a Content structure to a file.
 
 /*
  * Output a Content structure to a file.
@@ -83,14 +58,10 @@ output_content (CT ct, FILE *out)
 {
     int result = 0;
     CI ci = &ct->c_ctinfo;
 {
     int result = 0;
     CI ci = &ct->c_ctinfo;
-    char *boundary = ci->ci_values[0], **ap, **vp;
+    char *boundary = "", *cp;
 
 
-    for (ap = ci->ci_attrs, vp = ci->ci_values; *ap; ++ap, ++vp) {
-        if (! mh_strcasecmp ("boundary", *ap)) {
-            boundary = *vp;
-            break;
-        }
-    }
+    if ((cp = get_param(ci->ci_first_pm, "boundary", '-', 0)))
+       boundary = cp;
 
     /*
      * Output all header fields for this content
 
     /*
      * Output all header fields for this content
@@ -102,8 +73,11 @@ output_content (CT ct, FILE *out)
      * "message/external", then we are done with the
      * headers (since it has no body).
      */
      * "message/external", then we are done with the
      * headers (since it has no body).
      */
-    if (ct->c_ctexbody)
+    if (ct->c_ctexbody) {
+       if (*boundary != '\0')
+           free(boundary);
        return OK;
        return OK;
+    }
 
     /*
      * Now output the content bodies.
 
     /*
      * Now output the content bodies.
@@ -120,20 +94,23 @@ output_content (CT ct, FILE *out)
        m = (struct multipart *) ct->c_ctparams;
 
         if (m->mp_content_before) {
        m = (struct multipart *) ct->c_ctparams;
 
         if (m->mp_content_before) {
-           fprintf (out, "%s", m->mp_content_before);
+           fputs(m->mp_content_before, out);
         }
 
        for (part = m->mp_parts; part; part = part->mp_next) {
            CT p = part->mp_part;
 
            fprintf (out, "\n--%s\n", boundary);
         }
 
        for (part = m->mp_parts; part; part = part->mp_next) {
            CT p = part->mp_part;
 
            fprintf (out, "\n--%s\n", boundary);
-           if (output_content (p, out) == NOTOK)
-               return NOTOK;
+           if (output_content (p, out) == NOTOK) {
+               if (*boundary != '\0')
+                   free(boundary);
+                return NOTOK;
+           }
        }
        fprintf (out, "\n--%s--\n", boundary);
 
         if (m->mp_content_after) {
        }
        fprintf (out, "\n--%s--\n", boundary);
 
         if (m->mp_content_after) {
-           fprintf (out, "%s", m->mp_content_after);
+           fputs(m->mp_content_after, out);
         }
     }
     break;
         }
     }
     break;
@@ -165,7 +142,7 @@ output_content (CT ct, FILE *out)
               body, don't emit the newline that would appear between
               the headers and body.  In that case, the call to
               write8Bit() shouldn't be needed, but is harmless. */
               body, don't emit the newline that would appear between
               the headers and body.  In that case, the call to
               write8Bit() shouldn't be needed, but is harmless. */
-           if (ct->c_ctinfo.ci_attrs[0] != NULL  ||
+           if (ct->c_ctinfo.ci_first_pm != NULL  ||  ct->c_begin == 0  ||
                ct->c_begin != ct->c_end) {
                putc ('\n', out);
            }
                ct->c_begin != ct->c_end) {
                putc ('\n', out);
            }
@@ -188,18 +165,27 @@ output_content (CT ct, FILE *out)
            break;
 
        case CE_BINARY:
            break;
 
        case CE_BINARY:
-           advise (NULL, "can't handle binary transfer encoding in content");
-           result = NOTOK;
+           if (ct->c_type == CT_TEXT) {
+               /* So that mhfixmsg can decode to binary text. */
+               putc ('\n', out);
+               result = write8Bit (ct, out);
+           } else {
+               inform("can't handle binary transfer encoding in content");
+               result = NOTOK;
+           }
            break;
 
        default:
            break;
 
        default:
-           advise (NULL, "unknown transfer encoding in content");
+           inform("unknown transfer encoding in content");
            result = NOTOK;
            break;
        }
        break;
     }
 
            result = NOTOK;
            break;
        }
        break;
     }
 
+    if (*boundary != '\0')
+       free(boundary);
+
     return result;
 }
 
     return result;
 }
 
@@ -228,7 +214,7 @@ output_headers (CT ct, FILE *out)
 static int
 writeExternalBody (CT ct, FILE *out)
 {
 static int
 writeExternalBody (CT ct, FILE *out)
 {
-    char **ap, **ep, *cp;
+    char *cp, *dp;
     struct exbody *e = (struct exbody *) ct->c_ctparams;
                
     putc ('\n', out);
     struct exbody *e = (struct exbody *) ct->c_ctparams;
                
     putc ('\n', out);
@@ -240,7 +226,7 @@ writeExternalBody (CT ct, FILE *out)
            switch (*++cp) {
            case 'I':
                if (ct2->c_id) {
            switch (*++cp) {
            case 'I':
                if (ct2->c_id) {
-                   char *dp = trimcpy (ct2->c_id);
+                   dp = trimcpy (ct2->c_id);
 
                    fputs (dp, out);
                    free (dp);
 
                    fputs (dp, out);
                    free (dp);
@@ -248,17 +234,22 @@ writeExternalBody (CT ct, FILE *out)
                continue;
 
            case 'N':
                continue;
 
            case 'N':
-               for (ap = ci2->ci_attrs, ep = ci2->ci_values; *ap; ap++, ep++)
-                   if (!mh_strcasecmp (*ap, "name")) {
-                       fprintf (out, "%s", *ep);
-                       break;
-                   }
+               dp = get_param(ci2->ci_first_pm, "name", '_', 0);
+               if (dp) {
+                   fputs (dp, out);
+                   free (dp);
+               }
                continue;
 
            case 'T':
                fprintf (out, "%s/%s", ci2->ci_type, ci2->ci_subtype);
                continue;
 
            case 'T':
                fprintf (out, "%s/%s", ci2->ci_type, ci2->ci_subtype);
-               for (ap = ci2->ci_attrs, ep = ci2->ci_values; *ap; ap++, ep++)
-                   fprintf (out, "; %s=\"%s\"", *ap, *ep);
+               dp = output_params(strlen(ci2->ci_type) +
+                                  strlen(ci2->ci_subtype) + 1,
+                                  ci2->ci_first_pm, NULL, 0);
+               if (dp) {
+                   fputs (dp, out);
+                   free (dp);
+               }
                continue;
 
            case 'n':
                continue;
 
            case 'n':
@@ -300,7 +291,7 @@ write8Bit (CT ct, FILE *out)
     int fd;
     size_t inbytes;
     char c, *file, buffer[BUFSIZ];
     int fd;
     size_t inbytes;
     char c, *file, buffer[BUFSIZ];
-    CE ce = ct->c_cefile;
+    CE ce = &ct->c_cefile;
 
     file = NULL;
     if ((fd = (*ct->c_ceopenfnx) (ct, &file)) == NOTOK)
 
     file = NULL;
     if ((fd = (*ct->c_ceopenfnx) (ct, &file)) == NOTOK)
@@ -309,7 +300,9 @@ write8Bit (CT ct, FILE *out)
     c = '\n';
     while ((inbytes = fread (buffer, 1, sizeof buffer, ce->ce_fp)) > 0) {
         c = buffer[inbytes - 1];
     c = '\n';
     while ((inbytes = fread (buffer, 1, sizeof buffer, ce->ce_fp)) > 0) {
         c = buffer[inbytes - 1];
-        fwrite (buffer, 1, inbytes, out);
+        if (fwrite (buffer, 1, inbytes, out) < inbytes) {
+            advise ("write8Bit", "fwrite");
+        }
     }
     if (c != '\n')
        putc ('\n', out);
     }
     if (c != '\n')
        putc ('\n', out);
@@ -328,27 +321,35 @@ writeQuoted (CT ct, FILE *out)
 {
     int fd;
     char *cp, *file;
 {
     int fd;
     char *cp, *file;
-    char c, buffer[BUFSIZ];
-    CE ce = ct->c_cefile;
+    char c = '\0';
+    CE ce = &ct->c_cefile;
+    int n = 0;
+    char *bufp = NULL;
+    size_t buflen;
+    ssize_t gotlen;
 
     file = NULL;
     if ((fd = (*ct->c_ceopenfnx) (ct, &file)) == NOTOK)
        return NOTOK;
 
 
     file = NULL;
     if ((fd = (*ct->c_ceopenfnx) (ct, &file)) == NOTOK)
        return NOTOK;
 
-    while (fgets (buffer, sizeof(buffer) - 1, ce->ce_fp)) {
-       int n;
+    while ((gotlen = getline(&bufp, &buflen, ce->ce_fp)) != -1) {
 
 
-       cp = buffer + strlen (buffer) - 1;
+       cp = bufp + gotlen - 1;
        if ((c = *cp) == '\n')
        if ((c = *cp) == '\n')
-           *cp = '\0';
-
-       if (strncmp (cp = buffer, "From ", sizeof("From ") - 1) == 0) {
-           fprintf (out, "=%02X", *cp++ & 0xff);
-           n = 3;
-       } else {
-           n = 0;
+           gotlen--;
+
+       /*
+        * if the line starts with "From ", encode the 'F' so it
+        * doesn't falsely match an mbox delimiter.
+        */
+       cp = bufp;
+       if (gotlen >= 5 && has_prefix(cp, "From ")) {
+           fprintf (out, "=%02X", 'F');
+           cp++;
+           n += 3;
        }
        }
-       for (; *cp; cp++) {
+
+       for (; cp < bufp + gotlen; cp++) {
            if (n > CPERLIN - 3) {
                fputs ("=\n", out);
                n = 0;
            if (n > CPERLIN - 3) {
                fputs ("=\n", out);
                n = 0;
@@ -377,16 +378,19 @@ three_print:
        }
 
        if (c == '\n') {
        }
 
        if (c == '\n') {
-           if (cp > buffer && (*--cp == ' ' || *cp == '\t'))
+           if (cp > bufp && (*--cp == ' ' || *cp == '\t'))
                fputs ("=\n", out);
 
            putc ('\n', out);
                fputs ("=\n", out);
 
            putc ('\n', out);
-       } else {
-           fputs ("=\n", out);
+           n = 0;
        }
     }
 
        }
     }
 
+    if (c != '\n')
+       putc ('\n', out);
+
     (*ct->c_ceclosefnx) (ct);
     (*ct->c_ceclosefnx) (ct);
+    free (bufp);
     return OK;
 }
 
     return OK;
 }
 
@@ -400,13 +404,16 @@ writeBase64ct (CT ct, FILE *out)
 {
     int        fd, result;
     char *file;
 {
     int        fd, result;
     char *file;
-    CE ce = ct->c_cefile;
+    CE ce = &ct->c_cefile;
 
     file = NULL;
     if ((fd = (*ct->c_ceopenfnx) (ct, &file)) == NOTOK)
        return NOTOK;
 
 
     file = NULL;
     if ((fd = (*ct->c_ceopenfnx) (ct, &file)) == NOTOK)
        return NOTOK;
 
-    result = writeBase64aux (ce->ce_fp, out);
+    result = writeBase64aux (ce->ce_fp, out,
+                             ct->c_type == CT_TEXT  &&  ct->c_ctparams
+                             ?  ((struct text *) ct->c_ctparams)->lf_line_endings == 0
+                             :  0);
     (*ct->c_ceclosefnx) (ct);
     return result;
 }
     (*ct->c_ceclosefnx) (ct);
     return result;
 }