From d0bd14488c8392bcbbaa444759bae9c735178475 Mon Sep 17 00:00:00 2001 From: David Levine Date: Sun, 10 Feb 2013 20:55:54 -0600 Subject: [PATCH] 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 at the end of InitMultiPart(), and output it in output_content(). --- h/mhparse.h | 2 + uip/mhfree.c | 2 + uip/mhoutsbr.c | 9 ++++ uip/mhparse.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 123 insertions(+) diff --git a/h/mhparse.h b/h/mhparse.h index 8a40af5d..b11f706d 100644 --- a/h/mhparse.h +++ b/h/mhparse.h @@ -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 */ }; diff --git a/uip/mhfree.c b/uip/mhfree.c index a0b09a06..83ed5366 100644 --- a/uip/mhfree.c +++ b/uip/mhfree.c @@ -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; diff --git a/uip/mhoutsbr.c b/uip/mhoutsbr.c index d3a0a85b..aac061dd 100644 --- a/uip/mhoutsbr.c +++ b/uip/mhoutsbr.c @@ -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; diff --git a/uip/mhparse.c b/uip/mhparse.c index 87e85925..a80cc746 100644 --- a/uip/mhparse.c +++ b/uip/mhparse.c @@ -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; +} -- 2.56.0