+ /* record boundary separators */
+ m->mp_start = concat(bp, "\n", NULL);
+ m->mp_stop = concat(bp, "--\n", NULL);
+
+ if (!ct->c_fp && (ct->c_fp = fopen(ct->c_file, "r")) == NULL) {
+ advise(ct->c_file, "unable to open for reading");
+ return NOTOK;
+ }
+
+ fseek(fp = ct->c_fp, pos = ct->c_begin, SEEK_SET);
+ last = ct->c_end;
+ next = &m->mp_parts;
+ part = NULL;
+ inout = 1;
+
+ while (fgets(buffer, sizeof(buffer) - 1, fp)) {
+ if (pos > last)
+ break;
+
+ pos += strlen(buffer);
+ if (buffer[0] != '-' || buffer[1] != '-')
+ continue;
+ if (inout) {
+ if (strcmp(buffer + 2, m->mp_start)!=0)
+ continue;
+next_part:
+ if ((part = (struct part *) calloc(1, sizeof(*part)))
+ == NULL)
+ adios(NULL, "out of memory");
+ *next = part;
+ next = &part->mp_next;
+
+ if (!(p = get_content(fp, ct->c_file,
+ ct->c_subtype == MULTI_DIGEST ? -1 : 0))) {
+ ct->c_fp = NULL;
+ return NOTOK;
+ }
+ p->c_fp = NULL;
+ part->mp_part = p;
+ pos = p->c_begin;
+ fseek(fp, pos, SEEK_SET);
+ inout = 0;
+ } else {
+ if (strcmp(buffer + 2, m->mp_start) == 0) {
+ inout = 1;
+end_part:
+ p = part->mp_part;
+ p->c_end = ftell(fp) - (strlen(buffer) + 1);
+ if (p->c_end < p->c_begin)
+ p->c_begin = p->c_end;
+ if (inout)
+ goto next_part;
+ goto last_part;
+ } else {
+ if (strcmp(buffer + 2, m->mp_stop) == 0)
+ goto end_part;
+ }
+ }
+ }
+
+ advise(NULL, "bogus multipart content in message %s", ct->c_file);
+ if (!inout && part) {
+ p = part->mp_part;
+ p->c_end = ct->c_end;
+
+ if (p->c_begin >= p->c_end) {
+ for (next = &m->mp_parts; *next != part;
+ next = &((*next)->mp_next))
+ continue;
+ *next = NULL;
+ free_content(p);
+ free((char *) part);
+ }
+ }
+
+last_part:
+ /* reverse the order of the parts for multipart/alternative */
+ if (ct->c_subtype == MULTI_ALTERNATE)
+ reverse_parts(ct);
+
+ /*
+ ** label all subparts with part number, and
+ ** then initialize the content of the subpart.
+ */
+ {
+ int partnum;
+ char *pp;
+ char partnam[BUFSIZ];
+
+ if (ct->c_partno) {
+ snprintf(partnam, sizeof(partnam), "%s.",
+ ct->c_partno);
+ pp = partnam + strlen(partnam);
+ } else {
+ pp = partnam;
+ }
+
+ for (part = m->mp_parts, partnum = 1; part;
+ part = part->mp_next, partnum++) {
+ p = part->mp_part;
+
+ sprintf(pp, "%d", partnum);
+ p->c_partno = getcpy(partnam);
+
+ /* initialize the content of the subparts */
+ if (p->c_ctinitfnx && (*p->c_ctinitfnx) (p) == NOTOK) {
+ fclose(ct->c_fp);
+ ct->c_fp = NULL;
+ return NOTOK;
+ }
+ }
+ }
+
+ fclose(ct->c_fp);
+ ct->c_fp = NULL;
+ return OK;
+}
+
+
+/*
+** reverse the order of the parts of a multipart
+*/
+
+static void
+reverse_parts(CT ct)
+{
+ int i;
+ struct multipart *m;
+ struct part **base, **bmp, **next, *part;
+
+ m = (struct multipart *) ct->c_ctparams;
+
+ /* if only one part, just return */
+ if (!m->mp_parts || !m->mp_parts->mp_next)
+ return;
+
+ /* count number of parts */
+ i = 0;
+ for (part = m->mp_parts; part; part = part->mp_next)
+ i++;
+
+ /* allocate array of pointers to the parts */
+ if (!(base = (struct part **) calloc((size_t) (i + 1), sizeof(*base))))
+ adios(NULL, "out of memory");
+ bmp = base;
+
+ /* point at all the parts */
+ for (part = m->mp_parts; part; part = part->mp_next)
+ *bmp++ = part;
+ *bmp = NULL;
+
+ /* reverse the order of the parts */
+ next = &m->mp_parts;
+ for (bmp--; bmp >= base; bmp--) {
+ part = *bmp;
+ *next = part;
+ next = &part->mp_next;
+ }
+ *next = NULL;
+
+ /* free array of pointers */
+ free((char *) base);
+}
+
+
+/*
+** MESSAGE
+*/
+
+static int
+InitMessage(CT ct)
+{
+ struct k2v *kv;
+ CI ci = &ct->c_ctinfo;
+
+ if ((ct->c_encoding != CE_7BIT) && (ct->c_encoding != CE_8BIT)) {
+ admonish(NULL, "\"%s/%s\" type in message %s should be encoded in 7bit or 8bit", ci->ci_type, ci->ci_subtype, ct->c_file);
+ return NOTOK;
+ }
+
+ /* check for missing subtype */
+ if (!*ci->ci_subtype)
+ ci->ci_subtype = add("rfc822", ci->ci_subtype);
+
+ /* match subtype */
+ for (kv = SubMessage; kv->kv_key; kv++)
+ if (!mh_strcasecmp(ci->ci_subtype, kv->kv_key))
+ break;
+ ct->c_subtype = kv->kv_value;
+
+ switch (ct->c_subtype) {
+ case MESSAGE_RFC822:
+ break;
+
+ case MESSAGE_PARTIAL:
+ {