]> diplodocus.org Git - nmh/commitdiff
Multipart parts might have content before the first subpart
authorDavid Levine <levinedl@acm.org>
Mon, 11 Feb 2013 02:55:54 +0000 (20:55 -0600)
committerDavid Levine <levinedl@acm.org>
Mon, 11 Feb 2013 02:55:54 +0000 (20:55 -0600)
and/or after the last subpart that hasn't been stored anywhere
else, so do that at the end of InitMultiPart(), and output it
in output_content().

h/mhparse.h
uip/mhfree.c
uip/mhoutsbr.c
uip/mhparse.c

index 8a40af5..b11f706 100644 (file)
@@ -191,6 +191,8 @@ struct part {
 struct multipart {
     char *mp_start;            /* boundary string separating parts   */
     char *mp_stop;             /* terminating boundary string        */
+    char *mp_content_before;   /* any content before the first subpart */
+    char *mp_content_after;    /* any content after the last subpart */
     struct part *mp_parts;     /* pointer to first subpart structure */
 };
 
index a0b09a0..83ed536 100644 (file)
@@ -204,6 +204,8 @@ free_multi (CT ct)
        free (m->mp_start);
     if (m->mp_stop)
        free (m->mp_stop);
+    free (m->mp_content_before);
+    free (m->mp_content_after);
        
     for (part = m->mp_parts; part; part = next) {
        next = part->mp_next;
index d3a0a85..aac061d 100644 (file)
@@ -118,6 +118,11 @@ output_content (CT ct, FILE *out)
            putc ('\n', out);
 
        m = (struct multipart *) ct->c_ctparams;
+
+        if (m->mp_content_before) {
+           fprintf (out, "%s", m->mp_content_before);
+        }
+
        for (part = m->mp_parts; part; part = part->mp_next) {
            CT p = part->mp_part;
 
@@ -126,6 +131,10 @@ output_content (CT ct, FILE *out)
                return NOTOK;
        }
        fprintf (out, "\n--%s--\n", boundary);
+
+        if (m->mp_content_after) {
+           fprintf (out, "%s", m->mp_content_after);
+        }
     }
     break;
 
index 87e8592..a80cc74 100644 (file)
@@ -123,6 +123,7 @@ static int openFTP (CT, char **);
 static int InitMail (CT);
 static int openMail (CT, char **);
 static int readDigest (CT, char *);
+static int get_leftover_mp_content (CT, int);
 
 struct str2init str2cts[] = {
     { "application", CT_APPLICATION, InitApplication },
@@ -1294,6 +1295,9 @@ last_part:
        }
     }
 
+    get_leftover_mp_content (ct, 1);
+    get_leftover_mp_content (ct, 0);
+
     fclose (ct->c_fp);
     ct->c_fp = NULL;
     return OK;
@@ -2886,3 +2890,109 @@ invalid_digest:
 
     return OK;
 }
+
+
+/* Multipart parts might have content before the first subpart and/or
+   after the last subpart that hasn't been stored anywhere else, so do
+   that. */
+int
+get_leftover_mp_content (CT ct, int before /* or after */) {
+    struct multipart *m = (struct multipart *) ct->c_ctparams;
+    char *boundary;
+    int found_boundary = 0;
+    char buffer[BUFSIZ];
+    int max = BUFSIZ;
+    int read = 0;
+    char *content = NULL;
+
+    if (! m) return NOTOK;
+
+    if (before) {
+        if (! m->mp_parts  ||  ! m->mp_parts->mp_part) return NOTOK;
+
+        /* Isolate the beginning of this part to the beginning of the
+           first subpart and save any content between them. */
+        fseeko (ct->c_fp, ct->c_begin, SEEK_SET);
+        max = m->mp_parts->mp_part->c_begin - ct->c_begin;
+        boundary = concat ("--", m->mp_start, NULL);
+    } else {
+        struct part *last_subpart = NULL;
+        struct part *subpart;
+
+        /* Go to the last subpart to get its end position. */
+        for (subpart = m->mp_parts; subpart; subpart = subpart->mp_next) {
+            last_subpart = subpart;
+        }
+
+        if (last_subpart == NULL) return NOTOK;
+
+        /* Isolate the end of the last subpart to the end of this part
+           and save any content between them. */
+        fseeko (ct->c_fp, last_subpart->mp_part->c_end, SEEK_SET);
+        max = ct->c_end - last_subpart->mp_part->c_end;
+        boundary = concat ("--", m->mp_stop, NULL);
+    }
+
+    /* Back up by 1 to pick up the newline. */
+    while (fgets (buffer, sizeof(buffer) - 1, ct->c_fp)) {
+        read += strlen (buffer);
+        /* Don't look beyond beginning of first subpart (before) or
+           next part (after). */
+        if (read > max) buffer[read-max] = '\0';
+
+        if (before) {
+            if (! strcmp (buffer, boundary)) {
+                found_boundary = 1;
+            }
+        } else {
+            if (! found_boundary  &&  ! strcmp (buffer, boundary)) {
+                found_boundary = 1;
+                continue;
+            }
+        }
+
+        if ((before && ! found_boundary)  ||  (! before && found_boundary)) {
+            if (content) {
+                char *old_content = content;
+                content = concat (content, buffer, NULL);
+                free (old_content);
+            } else {
+                content = before
+                    ?  concat ("\n", buffer, NULL)
+                    :  concat (buffer, NULL);
+            }
+        }
+
+        if (before) {
+            if (found_boundary  ||  read > max) break;
+        } else {
+            if (read > max) break;
+        }
+    }
+
+    /* Skip the newline if that's all there is. */
+    if (content) {
+        char *cp;
+
+        /* Remove trailing newline, except at EOF. */
+        if ((before || ! feof (ct->c_fp)) &&
+            (cp = content + strlen (content)) > content  &&
+            *--cp == '\n') {
+            *cp = '\0';
+        }
+
+        if (strlen (content) > 1) {
+            if (before) {
+                m->mp_content_before = content;
+            } else {
+                m->mp_content_after = content;
+            }
+        } else {
+            free (content);
+        }
+    }
+
+    free (boundary);
+
+    return OK;
+}