]> diplodocus.org Git - nmh/blobdiff - uip/mhbuildsbr.c
Make sure to mark the sequence file as closed in the msgs struct.
[nmh] / uip / mhbuildsbr.c
index 5b7f074689e87b8e32512f2a648b4a67ee947c48..5d3679f66b7ee5f90eb04f9d0e52c184b3725924 100644 (file)
@@ -36,7 +36,6 @@
 extern int debugsw;
 extern int verbosw;
 
 extern int debugsw;
 extern int verbosw;
 
-extern int ebcdicsw;
 extern int listsw;
 extern int rfc934sw;
 extern int contentidsw;
 extern int listsw;
 extern int rfc934sw;
 extern int contentidsw;
@@ -55,6 +54,12 @@ pid_t xpid = 0;
 
 static char prefix[] = "----- =_aaaaaaaaaa";
 
 
 static char prefix[] = "----- =_aaaaaaaaaa";
 
+/*
+ * Maximum size of URL token in message/external-body
+ */
+
+#define MAXURLTOKEN 40
+
 
 /* mhmisc.c */
 void content_error (char *, CT, char *, ...);
 
 /* mhmisc.c */
 void content_error (char *, CT, char *, ...);
@@ -63,7 +68,6 @@ void content_error (char *, CT, char *, ...);
 int find_cache (CT, int, int *, char *, char *, int);
 
 /* mhfree.c */
 int find_cache (CT, int, int *, char *, char *, int);
 
 /* mhfree.c */
-void free_content (CT);
 void free_ctinfo (CT);
 void free_encoding (CT, int);
 
 void free_ctinfo (CT);
 void free_encoding (CT, int);
 
@@ -163,6 +167,7 @@ build_mime (char *infile, int directives)
      * draft into the linked list of header fields for
      * the new MIME message.
      */
      * draft into the linked list of header fields for
      * the new MIME message.
      */
+    m_getfld_track_filepos (&gstate, in);
     for (compnum = 1;;) {
        int bufsz = sizeof buf;
        switch (state = m_getfld (&gstate, name, buf, &bufsz, in)) {
     for (compnum = 1;;) {
        int bufsz = sizeof buf;
        switch (state = m_getfld (&gstate, name, buf, &bufsz, in)) {
@@ -342,12 +347,6 @@ finish_field:
 static int
 init_decoded_content (CT ct)
 {
 static int
 init_decoded_content (CT ct)
 {
-    CE ce;
-
-    if ((ce = (CE) calloc (1, sizeof(*ce))) == NULL)
-       adios (NULL, "out of memory");
-
-    ct->c_cefile     = ce;
     ct->c_ceopenfnx  = open7Bit;       /* since unencoded */
     ct->c_ceclosefnx = close_encoding;
     ct->c_cesizefnx  = NULL;           /* since unencoded */
     ct->c_ceopenfnx  = open7Bit;       /* since unencoded */
     ct->c_ceclosefnx = close_encoding;
     ct->c_cesizefnx  = NULL;           /* since unencoded */
@@ -403,8 +402,7 @@ static int
 user_content (FILE *in, char *file, char *buf, CT *ctp)
 {
     int        extrnal, vrsn;
 user_content (FILE *in, char *file, char *buf, CT *ctp)
 {
     int        extrnal, vrsn;
-    unsigned char *cp;
-    char **ap;
+    char *cp, **ap;
     char buffer[BUFSIZ];
     struct multipart *m;
     struct part **pp;
     char buffer[BUFSIZ];
     struct multipart *m;
     struct part **pp;
@@ -426,7 +424,7 @@ user_content (FILE *in, char *file, char *buf, CT *ctp)
 
     /* allocate basic structure for handling decoded content */
     init_decoded_content (ct);
 
     /* allocate basic structure for handling decoded content */
     init_decoded_content (ct);
-    ce = ct->c_cefile;
+    ce = &ct->c_cefile;
 
     ci = &ct->c_ctinfo;
     set_id (ct, 0);
 
     ci = &ct->c_ctinfo;
     set_id (ct, 0);
@@ -677,7 +675,7 @@ use_forw:
        if (ci->ci_magic) {
            /* check if specifies command to execute */
            if (*ci->ci_magic == '|' || *ci->ci_magic == '!') {
        if (ci->ci_magic) {
            /* check if specifies command to execute */
            if (*ci->ci_magic == '|' || *ci->ci_magic == '!') {
-               for (cp = ci->ci_magic + 1; isspace (*cp); cp++)
+               for (cp = ci->ci_magic + 1; isspace ((unsigned char) *cp); cp++)
                    continue;
                if (!*cp)
                    adios (NULL, "empty pipe command for #%s directive", ci->ci_type);
                    continue;
                if (!*cp)
                    adios (NULL, "empty pipe command for #%s directive", ci->ci_type);
@@ -749,7 +747,7 @@ use_forw:
        if (!folder)
            folder = add (getfolder (1), NULL);
 
        if (!folder)
            folder = add (getfolder (1), NULL);
 
-       if (!(mp = folder_read (folder)))
+       if (!(mp = folder_read (folder, 0)))
            adios (NULL, "unable to read folder %s", folder);
        for (ap = arguments; *ap; ap++) {
            cp = *ap;
            adios (NULL, "unable to read folder %s", folder);
        for (ap = arguments; *ap; ap++) {
            cp = *ap;
@@ -787,7 +785,7 @@ use_forw:
                    if ((p = (CT) calloc (1, sizeof(*p))) == NULL)
                        adios (NULL, "out of memory");
                    init_decoded_content (p);
                    if ((p = (CT) calloc (1, sizeof(*p))) == NULL)
                        adios (NULL, "out of memory");
                    init_decoded_content (p);
-                   pe = p->c_cefile;
+                   pe = &p->c_cefile;
                    if (get_ctinfo ("message/rfc822", p, 0) == NOTOK)
                        done (1);
                    p->c_type = CT_MESSAGE;
                    if (get_ctinfo ("message/rfc822", p, 0) == NOTOK)
                        done (1);
                    p->c_type = CT_MESSAGE;
@@ -913,42 +911,6 @@ set_id (CT ct, int top)
 }
 
 
 }
 
 
-static char ebcdicsafe[0x100] = {
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
-    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-    0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-    0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01,
-    0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-    0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-
 /*
  * Fill out, or expand the various contents in the composition
  * draft.  Read-in any necessary files.  Parse and execute any
 /*
  * Fill out, or expand the various contents in the composition
  * draft.  Read-in any necessary files.  Parse and execute any
@@ -958,7 +920,7 @@ static char ebcdicsafe[0x100] = {
 static int
 compose_content (CT ct)
 {
 static int
 compose_content (CT ct)
 {
-    CE ce = ct->c_cefile;
+    CE ce = &ct->c_cefile;
 
     switch (ct->c_type) {
     case CT_MULTIPART:
 
     switch (ct->c_type) {
     case CT_MULTIPART:
@@ -1132,7 +1094,7 @@ raw:
            if ((out = fopen (ce->ce_file, "w")) == NULL)
                adios (ce->ce_file, "unable to open for writing");
 
            if ((out = fopen (ce->ce_file, "w")) == NULL)
                adios (ce->ce_file, "unable to open for writing");
 
-           for (i = 0; (child_id = vfork()) == NOTOK && i > 5; i++)
+           for (i = 0; (child_id = fork()) == NOTOK && i > 5; i++)
                sleep (5);
            switch (child_id) {
            case NOTOK:
                sleep (5);
            switch (child_id) {
            case NOTOK:
@@ -1192,11 +1154,10 @@ scan_content (CT ct)
     int checklinelen = 0, linelen = 0;   /* check for long lines                       */
     int checkboundary = 0, boundaryclash = 0; /* check if clashes with multipart boundary   */
     int checklinespace = 0, linespace = 0;  /* check if any line ends with space          */
     int checklinelen = 0, linelen = 0;   /* check for long lines                       */
     int checkboundary = 0, boundaryclash = 0; /* check if clashes with multipart boundary   */
     int checklinespace = 0, linespace = 0;  /* check if any line ends with space          */
-    int checkebcdic = 0, ebcdicunsafe = 0;  /* check if contains ebcdic unsafe characters */
-    unsigned char *cp = NULL, buffer[BUFSIZ];
+    char *cp = NULL, buffer[BUFSIZ];
     struct text *t = NULL;
     FILE *in = NULL;
     struct text *t = NULL;
     FILE *in = NULL;
-    CE ce = ct->c_cefile;
+    CE ce = &ct->c_cefile;
 
     /*
      * handle multipart by scanning all subparts
 
     /*
      * handle multipart by scanning all subparts
@@ -1233,11 +1194,9 @@ scan_content (CT ct)
        check8bit = 1;
        checkboundary = 1;
        if (ct->c_subtype == TEXT_PLAIN) {
        check8bit = 1;
        checkboundary = 1;
        if (ct->c_subtype == TEXT_PLAIN) {
-           checkebcdic = 0;
            checklinelen = 0;
            checklinespace = 0;
        } else {
            checklinelen = 0;
            checklinespace = 0;
        } else {
-           checkebcdic = ebcdicsw;
            checklinelen = 1;
            checklinespace = 1;
        }
            checklinelen = 1;
            checklinespace = 1;
        }
@@ -1245,7 +1204,6 @@ scan_content (CT ct)
 
     case CT_APPLICATION:
        check8bit = 1;
 
     case CT_APPLICATION:
        check8bit = 1;
-       checkebcdic = ebcdicsw;
        checklinelen = 1;
        checklinespace = 1;
        checkboundary = 1;
        checklinelen = 1;
        checklinespace = 1;
        checkboundary = 1;
@@ -1253,7 +1211,6 @@ scan_content (CT ct)
 
     case CT_MESSAGE:
        check8bit = 0;
 
     case CT_MESSAGE:
        check8bit = 0;
-       checkebcdic = 0;
        checklinelen = 0;
        checklinespace = 0;
 
        checklinelen = 0;
        checklinespace = 0;
 
@@ -1272,7 +1229,6 @@ scan_content (CT ct)
         * since we are forcing use of base64.
         */
        check8bit = 0;
         * since we are forcing use of base64.
         */
        check8bit = 0;
-       checkebcdic = 0;
        checklinelen = 0;
        checklinespace = 0;
        checkboundary = 0;
        checklinelen = 0;
        checklinespace = 0;
        checkboundary = 0;
@@ -1293,18 +1249,10 @@ scan_content (CT ct)
             */
            if (check8bit) {
                for (cp = buffer; *cp; cp++) {
             */
            if (check8bit) {
                for (cp = buffer; *cp; cp++) {
-                   if (!isascii (*cp)) {
+                   if (!isascii ((unsigned char) *cp)) {
                        contains8bit = 1;
                        check8bit = 0;  /* no need to keep checking */
                    }
                        contains8bit = 1;
                        check8bit = 0;  /* no need to keep checking */
                    }
-                   /*
-                    * Check if character is ebcdic-safe.  We only check
-                    * this if also checking for 8bit data.
-                    */
-                   if (checkebcdic && !ebcdicsafe[*cp & 0xff]) {
-                       ebcdicunsafe = 1;
-                       checkebcdic = 0; /* no need to keep checking */
-                   }
                }
            }
 
                }
            }
 
@@ -1319,7 +1267,7 @@ scan_content (CT ct)
            /*
             * Check if line ends with a space.
             */
            /*
             * Check if line ends with a space.
             */
-           if (checklinespace && (cp = buffer + strlen (buffer) - 2) > buffer && isspace (*cp)) {
+           if (checklinespace && (cp = buffer + strlen (buffer) - 2) > buffer && isspace ((unsigned char) *cp)) {
                linespace = 1;
                checklinespace = 0;     /* no need to keep checking */
            }
                linespace = 1;
                checklinespace = 0;     /* no need to keep checking */
            }
@@ -1330,10 +1278,10 @@ scan_content (CT ct)
             */
            if (checkboundary && buffer[0] == '-' && buffer[1] == '-') {
                for (cp = buffer + strlen (buffer) - 1; cp >= buffer; cp--)
             */
            if (checkboundary && buffer[0] == '-' && buffer[1] == '-') {
                for (cp = buffer + strlen (buffer) - 1; cp >= buffer; cp--)
-                   if (!isspace (*cp))
+                   if (!isspace ((unsigned char) *cp))
                        break;
                *++cp = '\0';
                        break;
                *++cp = '\0';
-               if (!strncmp(buffer + 2, prefix, len) && isdigit(buffer[2 + len])) {
+               if (!strncmp(buffer + 2, prefix, len) && isdigit((unsigned char) buffer[2 + len])) {
                    boundaryclash = 1;
                    checkboundary = 0;  /* no need to keep checking */
                }
                    boundaryclash = 1;
                    checkboundary = 0;  /* no need to keep checking */
                }
@@ -1372,7 +1320,7 @@ scan_content (CT ct)
            *ep = cp;
        }
 
            *ep = cp;
        }
 
-       if (contains8bit || ebcdicunsafe || linelen || linespace || checksw)
+       if (contains8bit || linelen || linespace || checksw)
            ct->c_encoding = CE_QUOTED;
        else
            ct->c_encoding = CE_7BIT;
            ct->c_encoding = CE_QUOTED;
        else
            ct->c_encoding = CE_7BIT;
@@ -1380,7 +1328,7 @@ scan_content (CT ct)
 
     case CT_APPLICATION:
        /* For application type, use base64, except when postscript */
 
     case CT_APPLICATION:
        /* For application type, use base64, except when postscript */
-       if (contains8bit || ebcdicunsafe || linelen || linespace || checksw)
+       if (contains8bit || linelen || linespace || checksw)
            ct->c_encoding = (ct->c_subtype == APPLICATION_POSTSCRIPT)
                ? CE_QUOTED : CE_BASE64;
        else
            ct->c_encoding = (ct->c_subtype == APPLICATION_POSTSCRIPT)
                ? CE_QUOTED : CE_BASE64;
        else
@@ -1412,7 +1360,7 @@ scan_content (CT ct)
 static int
 build_headers (CT ct)
 {
 static int
 build_headers (CT ct)
 {
-    int        cc, mailbody, len;
+    int        cc, mailbody, extbody, len;
     char **ap, **ep;
     char *np, *vp, buffer[BUFSIZ];
     CI ci = &ct->c_ctinfo;
     char **ap, **ep;
     char *np, *vp, buffer[BUFSIZ];
     CI ci = &ct->c_ctinfo;
@@ -1454,9 +1402,8 @@ build_headers (CT ct)
     len = strlen (TYPE_FIELD) + strlen (ci->ci_type)
                + strlen (ci->ci_subtype) + 3;
 
     len = strlen (TYPE_FIELD) + strlen (ci->ci_type)
                + strlen (ci->ci_subtype) + 3;
 
-    mailbody = ct->c_type == CT_MESSAGE
-       && ct->c_subtype == MESSAGE_EXTERNAL
-       && ((struct exbody *) ct->c_ctparams)->eb_body;
+    extbody = ct->c_type == CT_MESSAGE && ct->c_subtype == MESSAGE_EXTERNAL;
+    mailbody = extbody && ((struct exbody *) ct->c_ctparams)->eb_body;
 
     /*
      * Append the attribute/value pairs to
 
     /*
      * Append the attribute/value pairs to
@@ -1469,6 +1416,42 @@ build_headers (CT ct)
        vp = add (";", vp);
        len++;
 
        vp = add (";", vp);
        len++;
 
+       /*
+        * According to RFC 2017, if we have a URL longer than 40 characters
+        * we have to break it across multiple lines
+        */
+
+       if (extbody && mh_strcasecmp (*ap, "url") == 0) {
+           char *value = *ep;
+
+           /* 7 here refers to " url=\"\"" */
+           if (len + 1 + (cc = (min(MAXURLTOKEN, strlen(value)) + 7)) >=
+                                                               CPERLIN) {
+               vp = add ("\n\t", vp);
+               len = 8;
+           } else {
+               vp = add (" ", vp);
+               len++;
+           }
+
+           vp = add ("url=\"", vp);
+           len += 5;
+
+           while (strlen(value) > MAXURLTOKEN) {
+               strncpy(buffer, value, MAXURLTOKEN);
+               buffer[MAXURLTOKEN] = '\0';
+               vp = add (buffer, vp);
+               vp = add ("\n\t", vp);
+               value += MAXURLTOKEN;
+               len = 8;
+           }
+
+           vp = add (value, vp);
+           vp = add ("\"", vp);
+           len += strlen(value) + 1;
+           continue;
+       }
+
        snprintf (buffer, sizeof(buffer), "%s=\"%s\"", *ap, *ep);
        if (len + 1 + (cc = strlen (buffer)) >= CPERLIN) {
            vp = add ("\n\t", vp);
        snprintf (buffer, sizeof(buffer), "%s=\"%s\"", *ap, *ep);
        if (len + 1 + (cc = strlen (buffer)) >= CPERLIN) {
            vp = add ("\n\t", vp);
@@ -1643,7 +1626,7 @@ calculate_digest (CT ct, int asciiP)
     unsigned char digest[16];
     unsigned char outbuf[25];
     MD5_CTX mdContext;
     unsigned char digest[16];
     unsigned char outbuf[25];
     MD5_CTX mdContext;
-    CE ce = ct->c_cefile;
+    CE ce = &ct->c_cefile;
     char *infilename = ce->ce_file ? ce->ce_file : ct->c_file;
     FILE *in;
 
     char *infilename = ce->ce_file ? ce->ce_file : ct->c_file;
     FILE *in;
 
@@ -1692,7 +1675,8 @@ calculate_digest (CT ct, int asciiP)
     }
 
     /* encode the digest using base64 */
     }
 
     /* encode the digest using base64 */
-    for (dp = digest, op = outbuf, cc = sizeof(digest) / sizeof(digest[0]);
+    for (dp = digest, op = (char *) outbuf,
+                               cc = sizeof(digest) / sizeof(digest[0]);
                cc > 0; cc -= 3, op += 4) {
        unsigned long bits;
        char *bp;
                cc > 0; cc -= 3, op += 4) {
        unsigned long bits;
        char *bp;