X-Git-Url: http://git.marmaro.de/?p=mmh;a=blobdiff_plain;f=uip%2Fmhbuildsbr.c;h=1ca8091013ea46d581d4d6de138de799b9aee80c;hp=f01abd5360af28c384c1e8261a0e13f393b18af0;hb=a485ed478abbd599d8c9aab48934e7a26733ecb1;hpb=f480c03187724e54e5391ee61b810827da319a6c diff --git a/uip/mhbuildsbr.c b/uip/mhbuildsbr.c index f01abd5..1ca8091 100644 --- a/uip/mhbuildsbr.c +++ b/uip/mhbuildsbr.c @@ -1,4 +1,3 @@ - /* * mhbuildsbr.c -- routines to expand/translate MIME composition files * @@ -51,11 +50,11 @@ extern int listsw; extern int rfc934sw; extern int contentidsw; -extern int endian; /* mhmisc.c */ +extern int endian; /* mhmisc.c */ /* cache policies */ -extern int rcachesw; /* mhcachesbr.c */ -extern int wcachesw; /* mhcachesbr.c */ +extern int rcachesw; /* mhcachesbr.c */ +extern int wcachesw; /* mhcachesbr.c */ /* * Directory to place tmp files. This must @@ -113,205 +112,205 @@ static char *calculate_digest (CT, int); CT build_mime (char *infile) { - int compnum, state; - char buf[BUFSIZ], name[NAMESZ]; - char *cp, *np, *vp; - struct multipart *m; - struct part **pp; - CT ct; - FILE *in; - - umask (~m_gmprot ()); - - /* open the composition draft */ - if ((in = fopen (infile, "r")) == NULL) - adios (infile, "unable to open for reading"); - - /* - * Allocate space for primary (outside) content - */ - if ((ct = (CT) calloc (1, sizeof(*ct))) == NULL) - adios (NULL, "out of memory"); - - /* - * Allocate structure for handling decoded content - * for this part. We don't really need this, but - * allocate it to remain consistent. - */ - init_decoded_content (ct); - - /* - * Parse some of the header fields in the composition - * draft into the linked list of header fields for - * the new MIME message. - */ - for (compnum = 1, state = FLD;;) { - switch (state = m_getfld (state, name, buf, sizeof(buf), in)) { - case FLD: - case FLDPLUS: - case FLDEOF: - compnum++; - - /* abort if draft has Mime-Version header field */ - if (!mh_strcasecmp (name, VRSN_FIELD)) - adios (NULL, "draft shouldn't contain %s: field", VRSN_FIELD); - - /* abort if draft has Content-Transfer-Encoding header field */ - if (!mh_strcasecmp (name, ENCODING_FIELD)) - adios (NULL, "draft shouldn't contain %s: field", ENCODING_FIELD); - - /* ignore any Content-Type fields in the header */ - if (!mh_strcasecmp (name, TYPE_FIELD)) { - while (state == FLDPLUS) - state = m_getfld (state, name, buf, sizeof(buf), in); - goto finish_field; - } - - /* get copies of the buffers */ - np = add (name, NULL); - vp = add (buf, NULL); - - /* if necessary, get rest of field */ - while (state == FLDPLUS) { - state = m_getfld (state, name, buf, sizeof(buf), in); - vp = add (buf, vp); /* add to previous value */ - } - - /* Now add the header data to the list */ - add_header (ct, np, vp); + int compnum, state; + char buf[BUFSIZ], name[NAMESZ]; + char *cp, *np, *vp; + struct multipart *m; + struct part **pp; + CT ct; + FILE *in; + + umask (~m_gmprot ()); + + /* open the composition draft */ + if ((in = fopen (infile, "r")) == NULL) + adios (infile, "unable to open for reading"); + + /* + * Allocate space for primary (outside) content + */ + if ((ct = (CT) calloc (1, sizeof(*ct))) == NULL) + adios (NULL, "out of memory"); + + /* + * Allocate structure for handling decoded content + * for this part. We don't really need this, but + * allocate it to remain consistent. + */ + init_decoded_content (ct); + + /* + * Parse some of the header fields in the composition + * draft into the linked list of header fields for + * the new MIME message. + */ + for (compnum = 1, state = FLD;;) { + switch (state = m_getfld (state, name, buf, sizeof(buf), in)) { + case FLD: + case FLDPLUS: + case FLDEOF: + compnum++; + + /* abort if draft has Mime-Version header field */ + if (!mh_strcasecmp (name, VRSN_FIELD)) + adios (NULL, "draft shouldn't contain %s: field", VRSN_FIELD); + + /* abort if draft has Content-Transfer-Encoding header field */ + if (!mh_strcasecmp (name, ENCODING_FIELD)) + adios (NULL, "draft shouldn't contain %s: field", ENCODING_FIELD); + + /* ignore any Content-Type fields in the header */ + if (!mh_strcasecmp (name, TYPE_FIELD)) { + while (state == FLDPLUS) + state = m_getfld (state, name, buf, sizeof(buf), in); + goto finish_field; + } + + /* get copies of the buffers */ + np = add (name, NULL); + vp = add (buf, NULL); + + /* if necessary, get rest of field */ + while (state == FLDPLUS) { + state = m_getfld (state, name, buf, sizeof(buf), in); + vp = add (buf, vp); /* add to previous value */ + } + + /* Now add the header data to the list */ + add_header (ct, np, vp); finish_field: - /* if this wasn't the last header field, then continue */ - if (state != FLDEOF) - continue; - /* else fall... */ + /* if this wasn't the last header field, then continue */ + if (state != FLDEOF) + continue; + /* else fall... */ + + case FILEEOF: + adios (NULL, "draft has empty body -- no directives!"); + /* NOTREACHED */ + + case BODY: + case BODYEOF: + fseek (in, (long) (-strlen (buf)), SEEK_CUR); + break; - case FILEEOF: - adios (NULL, "draft has empty body -- no directives!"); - /* NOTREACHED */ + case LENERR: + case FMTERR: + adios (NULL, "message format error in component #%d", compnum); - case BODY: - case BODYEOF: - fseek (in, (long) (-strlen (buf)), SEEK_CUR); - break; + default: + adios (NULL, "getfld() returned %d", state); + } + break; + } - case LENERR: - case FMTERR: - adios (NULL, "message format error in component #%d", compnum); + /* + * Now add the MIME-Version header field + * to the list of header fields. + */ + np = add (VRSN_FIELD, NULL); + vp = concat (" ", VRSN_VALUE, "\n", NULL); + add_header (ct, np, vp); - default: - adios (NULL, "getfld() returned %d", state); + /* + * We initally assume we will find multiple contents in the + * draft. So create a multipart/mixed content to hold everything. + * We can remove this later, if it is not needed. + */ + if (get_ctinfo ("multipart/mixed", ct, 0) == NOTOK) + done (1); + ct->c_type = CT_MULTIPART; + ct->c_subtype = MULTI_MIXED; + ct->c_file = add (infile, NULL); + + if ((m = (struct multipart *) calloc (1, sizeof(*m))) == NULL) + adios (NULL, "out of memory"); + ct->c_ctparams = (void *) m; + pp = &m->mp_parts; + + /* + * read and parse the composition file + * and the directives it contains. + */ + while (fgetstr (buf, sizeof(buf) - 1, in)) { + struct part *part; + CT p; + + if (user_content (in, infile, buf, &p) == DONE) { + admonish (NULL, "ignoring spurious #end"); + continue; + } + if (!p) + continue; + + if ((part = (struct part *) calloc (1, sizeof(*part))) == NULL) + adios (NULL, "out of memory"); + *pp = part; + pp = &part->mp_next; + part->mp_part = p; } - break; - } - - /* - * Now add the MIME-Version header field - * to the list of header fields. - */ - np = add (VRSN_FIELD, NULL); - vp = concat (" ", VRSN_VALUE, "\n", NULL); - add_header (ct, np, vp); - - /* - * We initally assume we will find multiple contents in the - * draft. So create a multipart/mixed content to hold everything. - * We can remove this later, if it is not needed. - */ - if (get_ctinfo ("multipart/mixed", ct, 0) == NOTOK) - done (1); - ct->c_type = CT_MULTIPART; - ct->c_subtype = MULTI_MIXED; - ct->c_file = add (infile, NULL); - - if ((m = (struct multipart *) calloc (1, sizeof(*m))) == NULL) - adios (NULL, "out of memory"); - ct->c_ctparams = (void *) m; - pp = &m->mp_parts; - - /* - * read and parse the composition file - * and the directives it contains. - */ - while (fgetstr (buf, sizeof(buf) - 1, in)) { - struct part *part; - CT p; - - if (user_content (in, infile, buf, &p) == DONE) { - admonish (NULL, "ignoring spurious #end"); - continue; + + /* + * close the composition draft since + * it's not needed any longer. + */ + fclose (in); + + /* check if any contents were found */ + if (!m->mp_parts) + adios (NULL, "no content directives found"); + + /* + * If only one content was found, then remove and + * free the outer multipart content. + */ + if (!m->mp_parts->mp_next) { + CT p; + + p = m->mp_parts->mp_part; + m->mp_parts->mp_part = NULL; + + /* move header fields */ + p->c_first_hf = ct->c_first_hf; + p->c_last_hf = ct->c_last_hf; + ct->c_first_hf = NULL; + ct->c_last_hf = NULL; + + free_content (ct); + ct = p; + } else { + set_id (ct, 1); } - if (!p) - continue; - - if ((part = (struct part *) calloc (1, sizeof(*part))) == NULL) - adios (NULL, "out of memory"); - *pp = part; - pp = &part->mp_next; - part->mp_part = p; - } - - /* - * close the composition draft since - * it's not needed any longer. - */ - fclose (in); - - /* check if any contents were found */ - if (!m->mp_parts) - adios (NULL, "no content directives found"); - - /* - * If only one content was found, then remove and - * free the outer multipart content. - */ - if (!m->mp_parts->mp_next) { - CT p; - - p = m->mp_parts->mp_part; - m->mp_parts->mp_part = NULL; - - /* move header fields */ - p->c_first_hf = ct->c_first_hf; - p->c_last_hf = ct->c_last_hf; - ct->c_first_hf = NULL; - ct->c_last_hf = NULL; - - free_content (ct); - ct = p; - } else { - set_id (ct, 1); - } - - /* - * Fill out, or expand directives. Parse and execute - * commands specified by profile composition strings. - */ - compose_content (ct); - - if ((cp = strchr(prefix, 'a')) == NULL) - adios (NULL, "internal error(4)"); - - /* - * Scan the contents. Choose a transfer encoding, and - * check if prefix for multipart boundary clashes with - * any of the contents. - */ - while (scan_content (ct) == NOTOK) { - if (*cp < 'z') { - (*cp)++; - } else { - if (*++cp == 0) - adios (NULL, "giving up trying to find a unique delimiter string"); - else - (*cp)++; + + /* + * Fill out, or expand directives. Parse and execute + * commands specified by profile composition strings. + */ + compose_content (ct); + + if ((cp = strchr(prefix, 'a')) == NULL) + adios (NULL, "internal error(4)"); + + /* + * Scan the contents. Choose a transfer encoding, and + * check if prefix for multipart boundary clashes with + * any of the contents. + */ + while (scan_content (ct) == NOTOK) { + if (*cp < 'z') { + (*cp)++; + } else { + if (*++cp == 0) + adios (NULL, "giving up trying to find a unique delimiter string"); + else + (*cp)++; + } } - } - /* Build the rest of the header field structures */ - build_headers (ct); + /* Build the rest of the header field structures */ + build_headers (ct); - return ct; + return ct; } @@ -323,41 +322,41 @@ finish_field: static int init_decoded_content (CT ct) { - CE ce; + CE ce; - if ((ce = (CE) calloc (1, sizeof(*ce))) == NULL) - adios (NULL, "out of memory"); + 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_cefile = ce; + ct->c_ceopenfnx = open7Bit; /* since unencoded */ + ct->c_ceclosefnx = close_encoding; + ct->c_cesizefnx = NULL; /* since unencoded */ - return OK; + return OK; } static char * fgetstr (char *s, int n, FILE *stream) { - char *cp, *ep; + char *cp, *ep; - for (ep = (cp = s) + n; cp < ep; ) { - int i; + for (ep = (cp = s) + n; cp < ep; ) { + int i; - if (!fgets (cp, n, stream)) - return (cp != s ? s : NULL); - if (cp == s && *cp != '#') - return s; + if (!fgets (cp, n, stream)) + return (cp != s ? s : NULL); + if (cp == s && *cp != '#') + return s; - cp += (i = strlen (cp)) - 1; - if (i <= 1 || *cp-- != '\n' || *cp != '\\') - break; - *cp = '\0'; - n -= (i - 2); - } + cp += (i = strlen (cp)) - 1; + if (i <= 1 || *cp-- != '\n' || *cp != '\\') + break; + *cp = '\0'; + n -= (i - 2); + } - return s; + return s; } @@ -369,551 +368,551 @@ fgetstr (char *s, int n, FILE *stream) static int user_content (FILE *in, char *file, char *buf, CT *ctp) { - int extrnal, vrsn; - unsigned char *cp; - char **ap; - char buffer[BUFSIZ]; - struct multipart *m; - struct part **pp; - struct stat st; - struct str2init *s2i; - CI ci; - CT ct; - CE ce; - - if (buf[0] == '\n' || strcmp (buf, "#\n") == 0) { - *ctp = NULL; - return OK; - } - - /* allocate basic Content structure */ - if ((ct = (CT) calloc (1, sizeof(*ct))) == NULL) - adios (NULL, "out of memory"); - *ctp = ct; - - /* allocate basic structure for handling decoded content */ - init_decoded_content (ct); - ce = ct->c_cefile; - - ci = &ct->c_ctinfo; - set_id (ct, 0); - - /* - * Handle inline text. Check if line - * is one of the following forms: - * - * 1) doesn't begin with '#' (implicit directive) - * 2) begins with "##" (implicit directive) - * 3) begins with "#<" - */ - if (buf[0] != '#' || buf[1] == '#' || buf[1] == '<') { - int headers; - int inlineD; - long pos; - char content[BUFSIZ]; - FILE *out; - char *cp; - - cp = m_mktemp2(NULL, invo_name, NULL, &out); - if (cp == NULL) adios("mhbuildsbr", "unable to create temporary file"); - - /* use a temp file to collect the plain text lines */ - ce->ce_file = add (cp, NULL); - ce->ce_unlink = 1; - - if (buf[0] == '#' && buf[1] == '<') { - strncpy (content, buf + 2, sizeof(content)); - inlineD = 1; - goto rock_and_roll; - } else { - inlineD = 0; + int extrnal, vrsn; + unsigned char *cp; + char **ap; + char buffer[BUFSIZ]; + struct multipart *m; + struct part **pp; + struct stat st; + struct str2init *s2i; + CI ci; + CT ct; + CE ce; + + if (buf[0] == '\n' || strcmp (buf, "#\n") == 0) { + *ctp = NULL; + return OK; } - /* the directive is implicit */ - strncpy (content, "text/plain", sizeof(content)); - headers = 0; - strncpy (buffer, buf[0] != '#' ? buf : buf + 1, sizeof(buffer)); - for (;;) { - int i; + /* allocate basic Content structure */ + if ((ct = (CT) calloc (1, sizeof(*ct))) == NULL) + adios (NULL, "out of memory"); + *ctp = ct; - if (headers >= 0 && uprf (buffer, DESCR_FIELD) - && buffer[i = strlen (DESCR_FIELD)] == ':') { - headers = 1; + /* allocate basic structure for handling decoded content */ + init_decoded_content (ct); + ce = ct->c_cefile; -again_descr: - ct->c_descr = add (buffer + i + 1, ct->c_descr); - if (!fgetstr (buffer, sizeof(buffer) - 1, in)) - adios (NULL, "end-of-file after %s: field in plaintext", DESCR_FIELD); - switch (buffer[0]) { - case ' ': - case '\t': - i = -1; - goto again_descr; - - case '#': - adios (NULL, "#-directive after %s: field in plaintext", DESCR_FIELD); - /* NOTREACHED */ + ci = &ct->c_ctinfo; + set_id (ct, 0); - default: - break; + /* + * Handle inline text. Check if line + * is one of the following forms: + * + * 1) doesn't begin with '#' (implicit directive) + * 2) begins with "##" (implicit directive) + * 3) begins with "#<" + */ + if (buf[0] != '#' || buf[1] == '#' || buf[1] == '<') { + int headers; + int inlineD; + long pos; + char content[BUFSIZ]; + FILE *out; + char *cp; + + cp = m_mktemp2(NULL, invo_name, NULL, &out); + if (cp == NULL) adios("mhbuildsbr", "unable to create temporary file"); + + /* use a temp file to collect the plain text lines */ + ce->ce_file = add (cp, NULL); + ce->ce_unlink = 1; + + if (buf[0] == '#' && buf[1] == '<') { + strncpy (content, buf + 2, sizeof(content)); + inlineD = 1; + goto rock_and_roll; + } else { + inlineD = 0; } - } - if (headers >= 0 && uprf (buffer, DISPO_FIELD) - && buffer[i = strlen (DISPO_FIELD)] == ':') { - headers = 1; + /* the directive is implicit */ + strncpy (content, "text/plain", sizeof(content)); + headers = 0; + strncpy (buffer, buf[0] != '#' ? buf : buf + 1, sizeof(buffer)); + for (;;) { + int i; -again_dispo: - ct->c_dispo = add (buffer + i + 1, ct->c_dispo); - if (!fgetstr (buffer, sizeof(buffer) - 1, in)) - adios (NULL, "end-of-file after %s: field in plaintext", DISPO_FIELD); - switch (buffer[0]) { - case ' ': - case '\t': - i = -1; - goto again_dispo; - - case '#': - adios (NULL, "#-directive after %s: field in plaintext", DISPO_FIELD); - /* NOTREACHED */ + if (headers >= 0 && uprf (buffer, DESCR_FIELD) + && buffer[i = strlen (DESCR_FIELD)] == ':') { + headers = 1; - default: - break; - } - } +again_descr: + ct->c_descr = add (buffer + i + 1, ct->c_descr); + if (!fgetstr (buffer, sizeof(buffer) - 1, in)) + adios (NULL, "end-of-file after %s: field in plaintext", DESCR_FIELD); + switch (buffer[0]) { + case ' ': + case '\t': + i = -1; + goto again_descr; + + case '#': + adios (NULL, "#-directive after %s: field in plaintext", DESCR_FIELD); + /* NOTREACHED */ + + default: + break; + } + } - if (headers != 1 || buffer[0] != '\n') - fputs (buffer, out); + if (headers >= 0 && uprf (buffer, DISPO_FIELD) + && buffer[i = strlen (DISPO_FIELD)] == ':') { + headers = 1; -rock_and_roll: - headers = -1; - pos = ftell (in); - if ((cp = fgetstr (buffer, sizeof(buffer) - 1, in)) == NULL) - break; - if (buffer[0] == '#') { - char *bp; +again_dispo: + ct->c_dispo = add (buffer + i + 1, ct->c_dispo); + if (!fgetstr (buffer, sizeof(buffer) - 1, in)) + adios (NULL, "end-of-file after %s: field in plaintext", DISPO_FIELD); + switch (buffer[0]) { + case ' ': + case '\t': + i = -1; + goto again_dispo; + + case '#': + adios (NULL, "#-directive after %s: field in plaintext", DISPO_FIELD); + /* NOTREACHED */ + + default: + break; + } + } - if (buffer[1] != '#') - break; - for (cp = (bp = buffer) + 1; *cp; cp++) - *bp++ = *cp; - *bp = '\0'; - } - } + if (headers != 1 || buffer[0] != '\n') + fputs (buffer, out); - if (listsw) - ct->c_end = ftell (out); - fclose (out); +rock_and_roll: + headers = -1; + pos = ftell (in); + if ((cp = fgetstr (buffer, sizeof(buffer) - 1, in)) == NULL) + break; + if (buffer[0] == '#') { + char *bp; + + if (buffer[1] != '#') + break; + for (cp = (bp = buffer) + 1; *cp; cp++) + *bp++ = *cp; + *bp = '\0'; + } + } - /* parse content type */ - if (get_ctinfo (content, ct, inlineD) == NOTOK) - done (1); + if (listsw) + ct->c_end = ftell (out); + fclose (out); - for (s2i = str2cts; s2i->si_key; s2i++) - if (!mh_strcasecmp (ci->ci_type, s2i->si_key)) - break; - if (!s2i->si_key && !uprf (ci->ci_type, "X-")) - s2i++; + /* parse content type */ + if (get_ctinfo (content, ct, inlineD) == NOTOK) + done (1); - /* - * check type specified (possibly implicitly) - */ - switch (ct->c_type = s2i->si_val) { - case CT_MESSAGE: - if (!mh_strcasecmp (ci->ci_subtype, "rfc822")) { - ct->c_encoding = CE_7BIT; - goto call_init; - } - /* else fall... */ - case CT_MULTIPART: - adios (NULL, "it doesn't make sense to define an in-line %s content", - ct->c_type == CT_MESSAGE ? "message" : "multipart"); - /* NOTREACHED */ + for (s2i = str2cts; s2i->si_key; s2i++) + if (!mh_strcasecmp (ci->ci_type, s2i->si_key)) + break; + if (!s2i->si_key && !uprf (ci->ci_type, "X-")) + s2i++; + + /* + * check type specified (possibly implicitly) + */ + switch (ct->c_type = s2i->si_val) { + case CT_MESSAGE: + if (!mh_strcasecmp (ci->ci_subtype, "rfc822")) { + ct->c_encoding = CE_7BIT; + goto call_init; + } + /* else fall... */ + case CT_MULTIPART: + adios (NULL, "it doesn't make sense to define an in-line %s content", + ct->c_type == CT_MESSAGE ? "message" : "multipart"); + /* NOTREACHED */ - default: + default: call_init: - if ((ct->c_ctinitfnx = s2i->si_init)) - (*ct->c_ctinitfnx) (ct); - break; + if ((ct->c_ctinitfnx = s2i->si_init)) + (*ct->c_ctinitfnx) (ct); + break; + } + + if (cp) + fseek (in, pos, SEEK_SET); + return OK; } - if (cp) - fseek (in, pos, SEEK_SET); - return OK; - } - - /* - * If we've reached this point, the next line - * must be some type of explicit directive. - */ - - /* check if directive is external-type */ - extrnal = (buf[1] == '@'); - - /* parse directive */ - if (get_ctinfo (buf + (extrnal ? 2 : 1), ct, 1) == NOTOK) - done (1); - - /* check directive against the list of MIME types */ - for (s2i = str2cts; s2i->si_key; s2i++) - if (!mh_strcasecmp (ci->ci_type, s2i->si_key)) - break; - - /* - * Check if the directive specified a valid type. - * This will happen if it was one of the following forms: - * - * #type/subtype (or) - * #@type/subtype - */ - if (s2i->si_key) { - if (!ci->ci_subtype) - adios (NULL, "missing subtype in \"#%s\"", ci->ci_type); - - switch (ct->c_type = s2i->si_val) { - case CT_MULTIPART: - adios (NULL, "use \"#begin ... #end\" instead of \"#%s/%s\"", - ci->ci_type, ci->ci_subtype); - /* NOTREACHED */ + /* + * If we've reached this point, the next line + * must be some type of explicit directive. + */ - case CT_MESSAGE: - if (!mh_strcasecmp (ci->ci_subtype, "partial")) - adios (NULL, "sorry, \"#%s/%s\" isn't supported", - ci->ci_type, ci->ci_subtype); - if (!mh_strcasecmp (ci->ci_subtype, "external-body")) - adios (NULL, "use \"#@type/subtype ... [] ...\" instead of \"#%s/%s\"", - ci->ci_type, ci->ci_subtype); -use_forw: - adios (NULL, - "use \"#forw [+folder] [msgs]\" instead of \"#%s/%s\"", - ci->ci_type, ci->ci_subtype); - /* NOTREACHED */ + /* check if directive is external-type */ + extrnal = (buf[1] == '@'); - default: - if ((ct->c_ctinitfnx = s2i->si_init)) - (*ct->c_ctinitfnx) (ct); - break; - } + /* parse directive */ + if (get_ctinfo (buf + (extrnal ? 2 : 1), ct, 1) == NOTOK) + done (1); + + /* check directive against the list of MIME types */ + for (s2i = str2cts; s2i->si_key; s2i++) + if (!mh_strcasecmp (ci->ci_type, s2i->si_key)) + break; /* - * #@type/subtype (external types directive) + * Check if the directive specified a valid type. + * This will happen if it was one of the following forms: + * + * #type/subtype (or) + * #@type/subtype */ - if (extrnal) { - struct exbody *e; - CT p; - - if (!ci->ci_magic) - adios (NULL, "need external information for \"#@%s/%s\"", - ci->ci_type, ci->ci_subtype); - p = ct; - - snprintf (buffer, sizeof(buffer), "message/external-body; %s", ci->ci_magic); - free (ci->ci_magic); - ci->ci_magic = NULL; - - /* - * Since we are using the current Content structure to - * hold information about the type of the external - * reference, we need to create another Content structure - * for the message/external-body to wrap it in. - */ - if ((ct = (CT) calloc (1, sizeof(*ct))) == NULL) - adios (NULL, "out of memory"); - *ctp = ct; - ci = &ct->c_ctinfo; - if (get_ctinfo (buffer, ct, 0) == NOTOK) - done (1); - ct->c_type = CT_MESSAGE; - ct->c_subtype = MESSAGE_EXTERNAL; + if (s2i->si_key) { + if (!ci->ci_subtype) + adios (NULL, "missing subtype in \"#%s\"", ci->ci_type); + + switch (ct->c_type = s2i->si_val) { + case CT_MULTIPART: + adios (NULL, "use \"#begin ... #end\" instead of \"#%s/%s\"", + ci->ci_type, ci->ci_subtype); + /* NOTREACHED */ + + case CT_MESSAGE: + if (!mh_strcasecmp (ci->ci_subtype, "partial")) + adios (NULL, "sorry, \"#%s/%s\" isn't supported", + ci->ci_type, ci->ci_subtype); + if (!mh_strcasecmp (ci->ci_subtype, "external-body")) + adios (NULL, "use \"#@type/subtype ... [] ...\" instead of \"#%s/%s\"", + ci->ci_type, ci->ci_subtype); +use_forw: + adios (NULL, + "use \"#forw [+folder] [msgs]\" instead of \"#%s/%s\"", + ci->ci_type, ci->ci_subtype); + /* NOTREACHED */ - if ((e = (struct exbody *) calloc (1, sizeof(*e))) == NULL) - adios (NULL, "out of memory"); - ct->c_ctparams = (void *) e; + default: + if ((ct->c_ctinitfnx = s2i->si_init)) + (*ct->c_ctinitfnx) (ct); + break; + } - e->eb_parent = ct; - e->eb_content = p; - p->c_ctexbody = e; + /* + * #@type/subtype (external types directive) + */ + if (extrnal) { + struct exbody *e; + CT p; - if (params_external (ct, 1) == NOTOK) - done (1); + if (!ci->ci_magic) + adios (NULL, "need external information for \"#@%s/%s\"", + ci->ci_type, ci->ci_subtype); + p = ct; - return OK; - } + snprintf (buffer, sizeof(buffer), "message/external-body; %s", ci->ci_magic); + free (ci->ci_magic); + ci->ci_magic = NULL; - /* Handle [file] argument */ - 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++) - continue; - if (!*cp) - adios (NULL, "empty pipe command for #%s directive", ci->ci_type); - cp = add (cp, NULL); - free (ci->ci_magic); - ci->ci_magic = cp; - } else { - /* record filename of decoded contents */ - ce->ce_file = ci->ci_magic; - if (access (ce->ce_file, R_OK) == NOTOK) - adios ("reading", "unable to access %s for", ce->ce_file); - if (listsw && stat (ce->ce_file, &st) != NOTOK) - ct->c_end = (long) st.st_size; - ci->ci_magic = NULL; - } - return OK; + /* + * Since we are using the current Content structure to + * hold information about the type of the external + * reference, we need to create another Content structure + * for the message/external-body to wrap it in. + */ + if ((ct = (CT) calloc (1, sizeof(*ct))) == NULL) + adios (NULL, "out of memory"); + *ctp = ct; + ci = &ct->c_ctinfo; + if (get_ctinfo (buffer, ct, 0) == NOTOK) + done (1); + ct->c_type = CT_MESSAGE; + ct->c_subtype = MESSAGE_EXTERNAL; + + if ((e = (struct exbody *) calloc (1, sizeof(*e))) == NULL) + adios (NULL, "out of memory"); + ct->c_ctparams = (void *) e; + + e->eb_parent = ct; + e->eb_content = p; + p->c_ctexbody = e; + + if (params_external (ct, 1) == NOTOK) + done (1); + + return OK; + } + + /* Handle [file] argument */ + 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++) + continue; + if (!*cp) + adios (NULL, "empty pipe command for #%s directive", ci->ci_type); + cp = add (cp, NULL); + free (ci->ci_magic); + ci->ci_magic = cp; + } else { + /* record filename of decoded contents */ + ce->ce_file = ci->ci_magic; + if (access (ce->ce_file, R_OK) == NOTOK) + adios ("reading", "unable to access %s for", ce->ce_file); + if (listsw && stat (ce->ce_file, &st) != NOTOK) + ct->c_end = (long) st.st_size; + ci->ci_magic = NULL; + } + return OK; + } + + /* + * No [file] argument, so check profile for + * method to compose content. + */ + snprintf (buffer, sizeof(buffer), "%s-compose-%s/%s", + invo_name, ci->ci_type, ci->ci_subtype); + if ((cp = context_find (buffer)) == NULL || *cp == '\0') { + snprintf (buffer, sizeof(buffer), "%s-compose-%s", invo_name, ci->ci_type); + if ((cp = context_find (buffer)) == NULL || *cp == '\0') { + content_error (NULL, ct, "don't know how to compose content"); + done (1); + } + } + ci->ci_magic = add (cp, NULL); + return OK; } + if (extrnal) + adios (NULL, "external definition not allowed for \"#%s\"", ci->ci_type); + /* - * No [file] argument, so check profile for - * method to compose content. + * Message directive + * #forw [+folder] [msgs] */ - snprintf (buffer, sizeof(buffer), "%s-compose-%s/%s", - invo_name, ci->ci_type, ci->ci_subtype); - if ((cp = context_find (buffer)) == NULL || *cp == '\0') { - snprintf (buffer, sizeof(buffer), "%s-compose-%s", invo_name, ci->ci_type); - if ((cp = context_find (buffer)) == NULL || *cp == '\0') { - content_error (NULL, ct, "don't know how to compose content"); - done (1); - } - } - ci->ci_magic = add (cp, NULL); - return OK; - } - - if (extrnal) - adios (NULL, "external definition not allowed for \"#%s\"", ci->ci_type); - - /* - * Message directive - * #forw [+folder] [msgs] - */ - if (!mh_strcasecmp (ci->ci_type, "forw")) { - int msgnum; - char *folder, *arguments[MAXARGS]; - struct msgs *mp; - - if (ci->ci_magic) { - ap = brkstring (ci->ci_magic, " ", "\n"); - copyip (ap, arguments, MAXARGS); - } else { - arguments[0] = "cur"; - arguments[1] = NULL; - } - folder = NULL; - - /* search the arguments for a folder name */ - for (ap = arguments; *ap; ap++) { - cp = *ap; - if (*cp == '+' || *cp == '@') { - if (folder) - adios (NULL, "only one folder per #forw directive"); - else - folder = pluspath (cp); - } - } + if (!mh_strcasecmp (ci->ci_type, "forw")) { + int msgnum; + char *folder, *arguments[MAXARGS]; + struct msgs *mp; + + if (ci->ci_magic) { + ap = brkstring (ci->ci_magic, " ", "\n"); + copyip (ap, arguments, MAXARGS); + } else { + arguments[0] = "cur"; + arguments[1] = NULL; + } + folder = NULL; + + /* search the arguments for a folder name */ + for (ap = arguments; *ap; ap++) { + cp = *ap; + if (*cp == '+' || *cp == '@') { + if (folder) + adios (NULL, "only one folder per #forw directive"); + else + folder = pluspath (cp); + } + } - /* else, use the current folder */ - if (!folder) - folder = add (getfolder (1), NULL); - - if (!(mp = folder_read (folder))) - adios (NULL, "unable to read folder %s", folder); - for (ap = arguments; *ap; ap++) { - cp = *ap; - if (*cp != '+' && *cp != '@') - if (!m_convert (mp, cp)) - done (1); + /* else, use the current folder */ + if (!folder) + folder = add (getfolder (1), NULL); + + if (!(mp = folder_read (folder))) + adios (NULL, "unable to read folder %s", folder); + for (ap = arguments; *ap; ap++) { + cp = *ap; + if (*cp != '+' && *cp != '@') + if (!m_convert (mp, cp)) + done (1); + } + free (folder); + free_ctinfo (ct); + + /* + * If there is more than one message to include, make this + * a content of type "multipart/digest" and insert each message + * as a subpart. If there is only one message, then make this + * a content of type "message/rfc822". + */ + if (mp->numsel > 1) { + /* we are forwarding multiple messages */ + if (get_ctinfo ("multipart/digest", ct, 0) == NOTOK) + done (1); + ct->c_type = CT_MULTIPART; + ct->c_subtype = MULTI_DIGEST; + + if ((m = (struct multipart *) calloc (1, sizeof(*m))) == NULL) + adios (NULL, "out of memory"); + ct->c_ctparams = (void *) m; + pp = &m->mp_parts; + + for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) { + if (is_selected(mp, msgnum)) { + struct part *part; + CT p; + CE pe; + + if ((p = (CT) calloc (1, sizeof(*p))) == NULL) + adios (NULL, "out of memory"); + init_decoded_content (p); + pe = p->c_cefile; + if (get_ctinfo ("message/rfc822", p, 0) == NOTOK) + done (1); + p->c_type = CT_MESSAGE; + p->c_subtype = MESSAGE_RFC822; + + snprintf (buffer, sizeof(buffer), "%s/%d", mp->foldpath, msgnum); + pe->ce_file = add (buffer, NULL); + if (listsw && stat (pe->ce_file, &st) != NOTOK) + p->c_end = (long) st.st_size; + + if ((part = (struct part *) calloc (1, sizeof(*part))) == NULL) + adios (NULL, "out of memory"); + *pp = part; + pp = &part->mp_next; + part->mp_part = p; + } + } + } else { + /* we are forwarding one message */ + if (get_ctinfo ("message/rfc822", ct, 0) == NOTOK) + done (1); + ct->c_type = CT_MESSAGE; + ct->c_subtype = MESSAGE_RFC822; + + msgnum = mp->lowsel; + snprintf (buffer, sizeof(buffer), "%s/%d", mp->foldpath, msgnum); + ce->ce_file = add (buffer, NULL); + if (listsw && stat (ce->ce_file, &st) != NOTOK) + ct->c_end = (long) st.st_size; + } + + folder_free (mp); /* free folder/message structure */ + return OK; } - free (folder); - free_ctinfo (ct); /* - * If there is more than one message to include, make this - * a content of type "multipart/digest" and insert each message - * as a subpart. If there is only one message, then make this - * a content of type "message/rfc822". + * #end */ - if (mp->numsel > 1) { - /* we are forwarding multiple messages */ - if (get_ctinfo ("multipart/digest", ct, 0) == NOTOK) - done (1); - ct->c_type = CT_MULTIPART; - ct->c_subtype = MULTI_DIGEST; - - if ((m = (struct multipart *) calloc (1, sizeof(*m))) == NULL) - adios (NULL, "out of memory"); - ct->c_ctparams = (void *) m; - pp = &m->mp_parts; + if (!mh_strcasecmp (ci->ci_type, "end")) { + free_content (ct); + *ctp = NULL; + return DONE; + } - for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) { - if (is_selected(mp, msgnum)) { - struct part *part; - CT p; - CE pe; + /* + * #begin [ alternative | parallel ] + */ + if (!mh_strcasecmp (ci->ci_type, "begin")) { + if (!ci->ci_magic) { + vrsn = MULTI_MIXED; + cp = SubMultiPart[vrsn - 1].kv_key; + } else if (!mh_strcasecmp (ci->ci_magic, "alternative")) { + vrsn = MULTI_ALTERNATE; + cp = SubMultiPart[vrsn - 1].kv_key; + } else if (!mh_strcasecmp (ci->ci_magic, "parallel")) { + vrsn = MULTI_PARALLEL; + cp = SubMultiPart[vrsn - 1].kv_key; + } else if (uprf (ci->ci_magic, "digest")) { + goto use_forw; + } else { + vrsn = MULTI_UNKNOWN; + cp = ci->ci_magic; + } - if ((p = (CT) calloc (1, sizeof(*p))) == NULL) - adios (NULL, "out of memory"); - init_decoded_content (p); - pe = p->c_cefile; - if (get_ctinfo ("message/rfc822", p, 0) == NOTOK) + free_ctinfo (ct); + snprintf (buffer, sizeof(buffer), "multipart/%s", cp); + if (get_ctinfo (buffer, ct, 0) == NOTOK) done (1); - p->c_type = CT_MESSAGE; - p->c_subtype = MESSAGE_RFC822; + ct->c_type = CT_MULTIPART; + ct->c_subtype = vrsn; - snprintf (buffer, sizeof(buffer), "%s/%d", mp->foldpath, msgnum); - pe->ce_file = add (buffer, NULL); - if (listsw && stat (pe->ce_file, &st) != NOTOK) - p->c_end = (long) st.st_size; - - if ((part = (struct part *) calloc (1, sizeof(*part))) == NULL) + if ((m = (struct multipart *) calloc (1, sizeof(*m))) == NULL) adios (NULL, "out of memory"); - *pp = part; - pp = &part->mp_next; - part->mp_part = p; - } - } - } else { - /* we are forwarding one message */ - if (get_ctinfo ("message/rfc822", ct, 0) == NOTOK) - done (1); - ct->c_type = CT_MESSAGE; - ct->c_subtype = MESSAGE_RFC822; - - msgnum = mp->lowsel; - snprintf (buffer, sizeof(buffer), "%s/%d", mp->foldpath, msgnum); - ce->ce_file = add (buffer, NULL); - if (listsw && stat (ce->ce_file, &st) != NOTOK) - ct->c_end = (long) st.st_size; - } - - folder_free (mp); /* free folder/message structure */ - return OK; - } - - /* - * #end - */ - if (!mh_strcasecmp (ci->ci_type, "end")) { - free_content (ct); - *ctp = NULL; - return DONE; - } - - /* - * #begin [ alternative | parallel ] - */ - if (!mh_strcasecmp (ci->ci_type, "begin")) { - if (!ci->ci_magic) { - vrsn = MULTI_MIXED; - cp = SubMultiPart[vrsn - 1].kv_key; - } else if (!mh_strcasecmp (ci->ci_magic, "alternative")) { - vrsn = MULTI_ALTERNATE; - cp = SubMultiPart[vrsn - 1].kv_key; - } else if (!mh_strcasecmp (ci->ci_magic, "parallel")) { - vrsn = MULTI_PARALLEL; - cp = SubMultiPart[vrsn - 1].kv_key; - } else if (uprf (ci->ci_magic, "digest")) { - goto use_forw; - } else { - vrsn = MULTI_UNKNOWN; - cp = ci->ci_magic; - } + ct->c_ctparams = (void *) m; - free_ctinfo (ct); - snprintf (buffer, sizeof(buffer), "multipart/%s", cp); - if (get_ctinfo (buffer, ct, 0) == NOTOK) - done (1); - ct->c_type = CT_MULTIPART; - ct->c_subtype = vrsn; - - if ((m = (struct multipart *) calloc (1, sizeof(*m))) == NULL) - adios (NULL, "out of memory"); - ct->c_ctparams = (void *) m; + pp = &m->mp_parts; + while (fgetstr (buffer, sizeof(buffer) - 1, in)) { + struct part *part; + CT p; - pp = &m->mp_parts; - while (fgetstr (buffer, sizeof(buffer) - 1, in)) { - struct part *part; - CT p; - - if (user_content (in, file, buffer, &p) == DONE) { - if (!m->mp_parts) - adios (NULL, "empty \"#begin ... #end\" sequence"); + if (user_content (in, file, buffer, &p) == DONE) { + if (!m->mp_parts) + adios (NULL, "empty \"#begin ... #end\" sequence"); + return OK; + } + if (!p) + continue; + + if ((part = (struct part *) calloc (1, sizeof(*part))) == NULL) + adios (NULL, "out of memory"); + *pp = part; + pp = &part->mp_next; + part->mp_part = p; + } + admonish (NULL, "premature end-of-file, missing #end"); return OK; - } - if (!p) - continue; - - if ((part = (struct part *) calloc (1, sizeof(*part))) == NULL) - adios (NULL, "out of memory"); - *pp = part; - pp = &part->mp_next; - part->mp_part = p; } - admonish (NULL, "premature end-of-file, missing #end"); - return OK; - } - /* - * Unknown directive - */ - adios (NULL, "unknown directive \"#%s\"", ci->ci_type); - return NOTOK; /* NOT REACHED */ + /* + * Unknown directive + */ + adios (NULL, "unknown directive \"#%s\"", ci->ci_type); + return NOTOK; /* NOT REACHED */ } static void set_id (CT ct, int top) { - char msgid[BUFSIZ]; - static int partno; - static time_t clock = 0; - static char *msgfmt; - - if (clock == 0) { - time (&clock); - snprintf (msgid, sizeof(msgid), "<%d.%ld.%%d@%s>\n", - (int) getpid(), (long) clock, LocalName()); - partno = 0; - msgfmt = getcpy(msgid); - } - snprintf (msgid, sizeof(msgid), msgfmt, top ? 0 : ++partno); - ct->c_id = getcpy (msgid); + char msgid[BUFSIZ]; + static int partno; + static time_t clock = 0; + static char *msgfmt; + + if (clock == 0) { + time (&clock); + snprintf (msgid, sizeof(msgid), "<%d.%ld.%%d@%s>\n", + (int) getpid(), (long) clock, LocalName()); + partno = 0; + msgfmt = getcpy(msgid); + } + snprintf (msgid, sizeof(msgid), msgfmt, top ? 0 : ++partno); + ct->c_id = getcpy (msgid); } 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 + 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 }; @@ -926,216 +925,216 @@ static char ebcdicsafe[0x100] = { static int compose_content (CT ct) { - CE ce = ct->c_cefile; - - switch (ct->c_type) { - case CT_MULTIPART: - { - int partnum; - char *pp; - char partnam[BUFSIZ]; - struct multipart *m = (struct multipart *) ct->c_ctparams; - struct part *part; - - if (ct->c_partno) { - snprintf (partnam, sizeof(partnam), "%s.", ct->c_partno); - pp = partnam + strlen (partnam); - } else { - pp = partnam; - } + CE ce = ct->c_cefile; - /* first, we call compose_content on all the subparts */ - for (part = m->mp_parts, partnum = 1; part; part = part->mp_next, partnum++) { - CT p = part->mp_part; + switch (ct->c_type) { + case CT_MULTIPART: + { + int partnum; + char *pp; + char partnam[BUFSIZ]; + struct multipart *m = (struct multipart *) ct->c_ctparams; + struct part *part; + + if (ct->c_partno) { + snprintf (partnam, sizeof(partnam), "%s.", ct->c_partno); + pp = partnam + strlen (partnam); + } else { + pp = partnam; + } - sprintf (pp, "%d", partnum); - p->c_partno = add (partnam, NULL); - if (compose_content (p) == NOTOK) - return NOTOK; - } + /* first, we call compose_content on all the subparts */ + for (part = m->mp_parts, partnum = 1; part; part = part->mp_next, partnum++) { + CT p = part->mp_part; - /* - * If the -rfc934mode switch is given, then check all - * the subparts of a multipart/digest. If they are all - * message/rfc822, then mark this content and all - * subparts with the rfc934 compatibility mode flag. - */ - if (rfc934sw && ct->c_subtype == MULTI_DIGEST) { - int is934 = 1; + sprintf (pp, "%d", partnum); + p->c_partno = add (partnam, NULL); + if (compose_content (p) == NOTOK) + return NOTOK; + } - for (part = m->mp_parts; part; part = part->mp_next) { - CT p = part->mp_part; + /* + * If the -rfc934mode switch is given, then check all + * the subparts of a multipart/digest. If they are all + * message/rfc822, then mark this content and all + * subparts with the rfc934 compatibility mode flag. + */ + if (rfc934sw && ct->c_subtype == MULTI_DIGEST) { + int is934 = 1; + + for (part = m->mp_parts; part; part = part->mp_next) { + CT p = part->mp_part; + + if (p->c_subtype != MESSAGE_RFC822) { + is934 = 0; + break; + } + } + ct->c_rfc934 = is934; + for (part = m->mp_parts; part; part = part->mp_next) { + CT p = part->mp_part; - if (p->c_subtype != MESSAGE_RFC822) { - is934 = 0; - break; + if ((p->c_rfc934 = is934)) + p->c_end++; + } } - } - ct->c_rfc934 = is934; - for (part = m->mp_parts; part; part = part->mp_next) { - CT p = part->mp_part; - - if ((p->c_rfc934 = is934)) - p->c_end++; - } - } - if (listsw) { - ct->c_end = (partnum = strlen (prefix) + 2) + 2; - if (ct->c_rfc934) - ct->c_end += 1; + if (listsw) { + ct->c_end = (partnum = strlen (prefix) + 2) + 2; + if (ct->c_rfc934) + ct->c_end += 1; - for (part = m->mp_parts; part; part = part->mp_next) - ct->c_end += part->mp_part->c_end + partnum; + for (part = m->mp_parts; part; part = part->mp_next) + ct->c_end += part->mp_part->c_end + partnum; + } } - } - break; - - case CT_MESSAGE: - /* Nothing to do for type message */ break; - /* - * Discrete types (text/application/audio/image/video) - */ - default: - if (!ce->ce_file) { - pid_t child_id; - int i, xstdout, len, buflen; - char *bp, **ap, *cp; - char *vec[4], buffer[BUFSIZ]; - FILE *out; - CI ci = &ct->c_ctinfo; - char *tfile = NULL; - - if (!(cp = ci->ci_magic)) - adios (NULL, "internal error(5)"); - - tfile = m_mktemp2(NULL, invo_name, NULL, NULL); - if (tfile == NULL) { - adios("mhbuildsbr", "unable to create temporary file"); - } - ce->ce_file = add (tfile, NULL); - ce->ce_unlink = 1; - - xstdout = 0; - - /* Get buffer ready to go */ - bp = buffer; - bp[0] = '\0'; - buflen = sizeof(buffer); - - /* - * Parse composition string into buffer - */ - for ( ; *cp; cp++) { - if (*cp == '%') { - switch (*++cp) { - case 'a': - { - /* insert parameters from directive */ - char **ep; - char *s = ""; - - for (ap = ci->ci_attrs, ep = ci->ci_values; *ap; ap++, ep++) { - snprintf (bp, buflen, "%s%s=\"%s\"", s, *ap, *ep); - len = strlen (bp); - bp += len; - buflen -= len; - s = " "; + case CT_MESSAGE: + /* Nothing to do for type message */ + break; + + /* + * Discrete types (text/application/audio/image/video) + */ + default: + if (!ce->ce_file) { + pid_t child_id; + int i, xstdout, len, buflen; + char *bp, **ap, *cp; + char *vec[4], buffer[BUFSIZ]; + FILE *out; + CI ci = &ct->c_ctinfo; + char *tfile = NULL; + + if (!(cp = ci->ci_magic)) + adios (NULL, "internal error(5)"); + + tfile = m_mktemp2(NULL, invo_name, NULL, NULL); + if (tfile == NULL) { + adios("mhbuildsbr", "unable to create temporary file"); } - } - break; + ce->ce_file = add (tfile, NULL); + ce->ce_unlink = 1; + + xstdout = 0; - case 'F': - /* %f, and stdout is not-redirected */ - xstdout = 1; - /* and fall... */ + /* Get buffer ready to go */ + bp = buffer; + bp[0] = '\0'; + buflen = sizeof(buffer); - case 'f': /* - * insert temporary filename where - * content should be written + * Parse composition string into buffer */ - snprintf (bp, buflen, "%s", ce->ce_file); - break; + for ( ; *cp; cp++) { + if (*cp == '%') { + switch (*++cp) { + case 'a': + { + /* insert parameters from directive */ + char **ep; + char *s = ""; + + for (ap = ci->ci_attrs, ep = ci->ci_values; *ap; ap++, ep++) { + snprintf (bp, buflen, "%s%s=\"%s\"", s, *ap, *ep); + len = strlen (bp); + bp += len; + buflen -= len; + s = " "; + } + } + break; + + case 'F': + /* %f, and stdout is not-redirected */ + xstdout = 1; + /* and fall... */ + + case 'f': + /* + * insert temporary filename where + * content should be written + */ + snprintf (bp, buflen, "%s", ce->ce_file); + break; + + case 's': + /* insert content subtype */ + strncpy (bp, ci->ci_subtype, buflen); + break; + + case '%': + /* insert character % */ + goto raw; + + default: + *bp++ = *--cp; + *bp = '\0'; + buflen--; + continue; + } + len = strlen (bp); + bp += len; + buflen -= len; + } else { +raw: + *bp++ = *cp; + *bp = '\0'; + buflen--; + } + } - case 's': - /* insert content subtype */ - strncpy (bp, ci->ci_subtype, buflen); - break; + if (verbosw) + printf ("composing content %s/%s from command\n\t%s\n", + ci->ci_type, ci->ci_subtype, buffer); + + fflush (stdout); /* not sure if need for -noverbose */ + + vec[0] = "/bin/sh"; + vec[1] = "-c"; + vec[2] = buffer; + vec[3] = NULL; + + 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++) + sleep (5); + switch (child_id) { + case NOTOK: + adios ("fork", "unable to fork"); + /* NOTREACHED */ + + case OK: + if (!xstdout) + dup2 (fileno (out), 1); + close (fileno (out)); + execvp ("/bin/sh", vec); + fprintf (stderr, "unable to exec "); + perror ("/bin/sh"); + _exit (-1); + /* NOTREACHED */ + + default: + fclose (out); + if (pidXwait(child_id, NULL)) + done (1); + break; + } + } - case '%': - /* insert character % */ - goto raw; + /* Check size of file */ + if (listsw && ct->c_end == 0L) { + struct stat st; - default: - *bp++ = *--cp; - *bp = '\0'; - buflen--; - continue; - } - len = strlen (bp); - bp += len; - buflen -= len; - } else { -raw: - *bp++ = *cp; - *bp = '\0'; - buflen--; + if (stat (ce->ce_file, &st) != NOTOK) + ct->c_end = (long) st.st_size; } - } - - if (verbosw) - printf ("composing content %s/%s from command\n\t%s\n", - ci->ci_type, ci->ci_subtype, buffer); - - fflush (stdout); /* not sure if need for -noverbose */ - - vec[0] = "/bin/sh"; - vec[1] = "-c"; - vec[2] = buffer; - vec[3] = NULL; - - 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++) - sleep (5); - switch (child_id) { - case NOTOK: - adios ("fork", "unable to fork"); - /* NOTREACHED */ - - case OK: - if (!xstdout) - dup2 (fileno (out), 1); - close (fileno (out)); - execvp ("/bin/sh", vec); - fprintf (stderr, "unable to exec "); - perror ("/bin/sh"); - _exit (-1); - /* NOTREACHED */ - - default: - fclose (out); - if (pidXwait(child_id, NULL)) - done (1); break; - } } - /* Check size of file */ - if (listsw && ct->c_end == 0L) { - struct stat st; - - if (stat (ce->ce_file, &st) != NOTOK) - ct->c_end = (long) st.st_size; - } - break; - } - - return OK; + return OK; } @@ -1155,220 +1154,220 @@ raw: static int scan_content (CT ct) { - int len; - int check8bit = 0, contains8bit = 0; /* check if contains 8bit data */ - 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]; - struct text *t = NULL; - FILE *in = NULL; - CE ce = ct->c_cefile; - - /* - * handle multipart by scanning all subparts - * and then checking their encoding. - */ - if (ct->c_type == CT_MULTIPART) { - struct multipart *m = (struct multipart *) ct->c_ctparams; - struct part *part; - - /* initially mark the domain of enclosing multipart as 7bit */ - ct->c_encoding = CE_7BIT; - - for (part = m->mp_parts; part; part = part->mp_next) { - CT p = part->mp_part; - - if (scan_content (p) == NOTOK) /* choose encoding for subpart */ - return NOTOK; - - /* if necessary, enlarge encoding for enclosing multipart */ - if (p->c_encoding == CE_BINARY) - ct->c_encoding = CE_BINARY; - if (p->c_encoding == CE_8BIT && ct->c_encoding != CE_BINARY) - ct->c_encoding = CE_8BIT; - } + int len; + int check8bit = 0, contains8bit = 0; /* check if contains 8bit data */ + 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]; + struct text *t = NULL; + FILE *in = NULL; + CE ce = ct->c_cefile; - return OK; - } - - /* - * Decide what to check while scanning this content. - */ - switch (ct->c_type) { - case CT_TEXT: - check8bit = 1; - checkboundary = 1; - if (ct->c_subtype == TEXT_PLAIN) { - checkebcdic = 0; - checklinelen = 0; - checklinespace = 0; - } else { - checkebcdic = ebcdicsw; - checklinelen = 1; - checklinespace = 1; + /* + * handle multipart by scanning all subparts + * and then checking their encoding. + */ + if (ct->c_type == CT_MULTIPART) { + struct multipart *m = (struct multipart *) ct->c_ctparams; + struct part *part; + + /* initially mark the domain of enclosing multipart as 7bit */ + ct->c_encoding = CE_7BIT; + + for (part = m->mp_parts; part; part = part->mp_next) { + CT p = part->mp_part; + + if (scan_content (p) == NOTOK) /* choose encoding for subpart */ + return NOTOK; + + /* if necessary, enlarge encoding for enclosing multipart */ + if (p->c_encoding == CE_BINARY) + ct->c_encoding = CE_BINARY; + if (p->c_encoding == CE_8BIT && ct->c_encoding != CE_BINARY) + ct->c_encoding = CE_8BIT; + } + + return OK; } - break; - case CT_APPLICATION: - check8bit = 1; - checkebcdic = ebcdicsw; - checklinelen = 1; - checklinespace = 1; - checkboundary = 1; - break; + /* + * Decide what to check while scanning this content. + */ + switch (ct->c_type) { + case CT_TEXT: + check8bit = 1; + checkboundary = 1; + if (ct->c_subtype == TEXT_PLAIN) { + checkebcdic = 0; + checklinelen = 0; + checklinespace = 0; + } else { + checkebcdic = ebcdicsw; + checklinelen = 1; + checklinespace = 1; + } + break; - case CT_MESSAGE: - check8bit = 0; - checkebcdic = 0; - checklinelen = 0; - checklinespace = 0; - - /* don't check anything for message/external */ - if (ct->c_subtype == MESSAGE_EXTERNAL) - checkboundary = 0; - else - checkboundary = 1; - break; + case CT_APPLICATION: + check8bit = 1; + checkebcdic = ebcdicsw; + checklinelen = 1; + checklinespace = 1; + checkboundary = 1; + break; + + case CT_MESSAGE: + check8bit = 0; + checkebcdic = 0; + checklinelen = 0; + checklinespace = 0; + + /* don't check anything for message/external */ + if (ct->c_subtype == MESSAGE_EXTERNAL) + checkboundary = 0; + else + checkboundary = 1; + break; + + case CT_AUDIO: + case CT_IMAGE: + case CT_VIDEO: + /* + * Don't check anything for these types, + * since we are forcing use of base64. + */ + check8bit = 0; + checkebcdic = 0; + checklinelen = 0; + checklinespace = 0; + checkboundary = 0; + break; + } - case CT_AUDIO: - case CT_IMAGE: - case CT_VIDEO: /* - * Don't check anything for these types, - * since we are forcing use of base64. + * Scan the unencoded content */ - check8bit = 0; - checkebcdic = 0; - checklinelen = 0; - checklinespace = 0; - checkboundary = 0; - break; - } + if (check8bit || checklinelen || checklinespace || checkboundary) { + if ((in = fopen (ce->ce_file, "r")) == NULL) + adios (ce->ce_file, "unable to open for reading"); + len = strlen (prefix); - /* - * Scan the unencoded content - */ - if (check8bit || checklinelen || checklinespace || checkboundary) { - if ((in = fopen (ce->ce_file, "r")) == NULL) - adios (ce->ce_file, "unable to open for reading"); - len = strlen (prefix); - - while (fgets (buffer, sizeof(buffer) - 1, in)) { - /* - * Check for 8bit data. - */ - if (check8bit) { - for (cp = buffer; *cp; cp++) { - if (!isascii (*cp)) { - 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 */ - } - } - } - - /* - * Check line length. - */ - if (checklinelen && (strlen (buffer) > CPERLIN + 1)) { - linelen = 1; - checklinelen = 0; /* no need to keep checking */ - } - - /* - * Check if line ends with a space. - */ - if (checklinespace && (cp = buffer + strlen (buffer) - 2) > buffer && isspace (*cp)) { - linespace = 1; - checklinespace = 0; /* no need to keep checking */ - } - - /* - * Check if content contains a line that clashes - * with our standard boundary for multipart messages. - */ - if (checkboundary && buffer[0] == '-' && buffer[1] == '-') { - for (cp = buffer + strlen (buffer) - 1; cp >= buffer; cp--) - if (!isspace (*cp)) - break; - *++cp = '\0'; - if (!strncmp(buffer + 2, prefix, len) && isdigit(buffer[2 + len])) { - boundaryclash = 1; - checkboundary = 0; /* no need to keep checking */ + while (fgets (buffer, sizeof(buffer) - 1, in)) { + /* + * Check for 8bit data. + */ + if (check8bit) { + for (cp = buffer; *cp; cp++) { + if (!isascii (*cp)) { + 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 */ + } + } + } + + /* + * Check line length. + */ + if (checklinelen && (strlen (buffer) > CPERLIN + 1)) { + linelen = 1; + checklinelen = 0; /* no need to keep checking */ + } + + /* + * Check if line ends with a space. + */ + if (checklinespace && (cp = buffer + strlen (buffer) - 2) > buffer && isspace (*cp)) { + linespace = 1; + checklinespace = 0; /* no need to keep checking */ + } + + /* + * Check if content contains a line that clashes + * with our standard boundary for multipart messages. + */ + if (checkboundary && buffer[0] == '-' && buffer[1] == '-') { + for (cp = buffer + strlen (buffer) - 1; cp >= buffer; cp--) + if (!isspace (*cp)) + break; + *++cp = '\0'; + if (!strncmp(buffer + 2, prefix, len) && isdigit(buffer[2 + len])) { + boundaryclash = 1; + checkboundary = 0; /* no need to keep checking */ + } + } } - } + fclose (in); } - fclose (in); - } - /* - * Decide which transfer encoding to use. - */ - switch (ct->c_type) { - case CT_TEXT: /* - * If the text content didn't specify a character - * set, we need to figure out which one was used. + * Decide which transfer encoding to use. */ - t = (struct text *) ct->c_ctparams; - if (t->tx_charset == CHARSET_UNSPECIFIED) { - CI ci = &ct->c_ctinfo; - char **ap, **ep; - - for (ap = ci->ci_attrs, ep = ci->ci_values; *ap; ap++, ep++) - continue; - - if (contains8bit) { - t->tx_charset = CHARSET_UNKNOWN; - *ap = concat ("charset=", write_charset_8bit(), NULL); - } else { - t->tx_charset = CHARSET_USASCII; - *ap = add ("charset=us-ascii", NULL); - } - - cp = strchr(*ap++, '='); - *ap = NULL; - *cp++ = '\0'; - *ep = cp; - } + switch (ct->c_type) { + case CT_TEXT: + /* + * If the text content didn't specify a character + * set, we need to figure out which one was used. + */ + t = (struct text *) ct->c_ctparams; + if (t->tx_charset == CHARSET_UNSPECIFIED) { + CI ci = &ct->c_ctinfo; + char **ap, **ep; + + for (ap = ci->ci_attrs, ep = ci->ci_values; *ap; ap++, ep++) + continue; + + if (contains8bit) { + t->tx_charset = CHARSET_UNKNOWN; + *ap = concat ("charset=", write_charset_8bit(), NULL); + } else { + t->tx_charset = CHARSET_USASCII; + *ap = add ("charset=us-ascii", NULL); + } - if (contains8bit || ebcdicunsafe || linelen || linespace || checksw) - ct->c_encoding = CE_QUOTED; - else - ct->c_encoding = CE_7BIT; - break; + cp = strchr(*ap++, '='); + *ap = NULL; + *cp++ = '\0'; + *ep = cp; + } - case CT_APPLICATION: - /* For application type, use base64, except when postscript */ - if (contains8bit || ebcdicunsafe || linelen || linespace || checksw) - ct->c_encoding = (ct->c_subtype == APPLICATION_POSTSCRIPT) - ? CE_QUOTED : CE_BASE64; - else - ct->c_encoding = CE_7BIT; - break; + if (contains8bit || ebcdicunsafe || linelen || linespace || checksw) + ct->c_encoding = CE_QUOTED; + else + ct->c_encoding = CE_7BIT; + break; - case CT_MESSAGE: - ct->c_encoding = CE_7BIT; - break; + case CT_APPLICATION: + /* For application type, use base64, except when postscript */ + if (contains8bit || ebcdicunsafe || linelen || linespace || checksw) + ct->c_encoding = (ct->c_subtype == APPLICATION_POSTSCRIPT) + ? CE_QUOTED : CE_BASE64; + else + ct->c_encoding = CE_7BIT; + break; - case CT_AUDIO: - case CT_IMAGE: - case CT_VIDEO: - /* For audio, image, and video contents, just use base64 */ - ct->c_encoding = CE_BASE64; - break; - } + case CT_MESSAGE: + ct->c_encoding = CE_7BIT; + break; + + case CT_AUDIO: + case CT_IMAGE: + case CT_VIDEO: + /* For audio, image, and video contents, just use base64 */ + ct->c_encoding = CE_BASE64; + break; + } - return (boundaryclash ? NOTOK : OK); + return (boundaryclash ? NOTOK : OK); } @@ -1381,227 +1380,227 @@ scan_content (CT ct) static int build_headers (CT ct) { - int cc, mailbody, len; - char **ap, **ep; - char *np, *vp, buffer[BUFSIZ]; - CI ci = &ct->c_ctinfo; - - /* - * If message is type multipart, then add the multipart - * boundary to the list of attribute/value pairs. - */ - if (ct->c_type == CT_MULTIPART) { - char *cp; - static int level = 0; /* store nesting level */ - - ap = ci->ci_attrs; - ep = ci->ci_values; - snprintf (buffer, sizeof(buffer), "boundary=%s%d", prefix, level++); - cp = strchr(*ap++ = add (buffer, NULL), '='); - *ap = NULL; - *cp++ = '\0'; - *ep = cp; - } - - /* - * Skip the output of Content-Type, parameters, content - * description and disposition, and Content-ID if the - * content is of type "message" and the rfc934 compatibility - * flag is set (which means we are inside multipart/digest - * and the switch -rfc934mode was given). - */ - if (ct->c_type == CT_MESSAGE && ct->c_rfc934) - goto skip_headers; - - /* - * output the content type and subtype - */ - np = add (TYPE_FIELD, NULL); - vp = concat (" ", ci->ci_type, "/", ci->ci_subtype, NULL); - - /* keep track of length of line */ - len = strlen (TYPE_FIELD) + strlen (ci->ci_type) + int cc, mailbody, len; + char **ap, **ep; + char *np, *vp, buffer[BUFSIZ]; + CI ci = &ct->c_ctinfo; + + /* + * If message is type multipart, then add the multipart + * boundary to the list of attribute/value pairs. + */ + if (ct->c_type == CT_MULTIPART) { + char *cp; + static int level = 0; /* store nesting level */ + + ap = ci->ci_attrs; + ep = ci->ci_values; + snprintf (buffer, sizeof(buffer), "boundary=%s%d", prefix, level++); + cp = strchr(*ap++ = add (buffer, NULL), '='); + *ap = NULL; + *cp++ = '\0'; + *ep = cp; + } + + /* + * Skip the output of Content-Type, parameters, content + * description and disposition, and Content-ID if the + * content is of type "message" and the rfc934 compatibility + * flag is set (which means we are inside multipart/digest + * and the switch -rfc934mode was given). + */ + if (ct->c_type == CT_MESSAGE && ct->c_rfc934) + goto skip_headers; + + /* + * output the content type and subtype + */ + np = add (TYPE_FIELD, NULL); + vp = concat (" ", ci->ci_type, "/", ci->ci_subtype, NULL); + + /* keep track of length of line */ + 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; - - /* - * Append the attribute/value pairs to - * the end of the Content-Type line. - */ - for (ap = ci->ci_attrs, ep = ci->ci_values; *ap; ap++, ep++) { - if (mailbody && !mh_strcasecmp (*ap, "body")) - continue; - - vp = add (";", vp); - len++; - - snprintf (buffer, sizeof(buffer), "%s=\"%s\"", *ap, *ep); - if (len + 1 + (cc = strlen (buffer)) >= CPERLIN) { - vp = add ("\n\t", vp); - len = 8; - } else { - vp = add (" ", vp); - len++; + mailbody = ct->c_type == CT_MESSAGE + && ct->c_subtype == MESSAGE_EXTERNAL + && ((struct exbody *) ct->c_ctparams)->eb_body; + + /* + * Append the attribute/value pairs to + * the end of the Content-Type line. + */ + for (ap = ci->ci_attrs, ep = ci->ci_values; *ap; ap++, ep++) { + if (mailbody && !mh_strcasecmp (*ap, "body")) + continue; + + vp = add (";", vp); + len++; + + snprintf (buffer, sizeof(buffer), "%s=\"%s\"", *ap, *ep); + if (len + 1 + (cc = strlen (buffer)) >= CPERLIN) { + vp = add ("\n\t", vp); + len = 8; + } else { + vp = add (" ", vp); + len++; + } + vp = add (buffer, vp); + len += cc; } - vp = add (buffer, vp); - len += cc; - } - - /* - * Append any RFC-822 comment to the end of - * the Content-Type line. - */ - if (ci->ci_comment) { - snprintf (buffer, sizeof(buffer), "(%s)", ci->ci_comment); - if (len + 1 + (cc = 2 + strlen (ci->ci_comment)) >= CPERLIN) { - vp = add ("\n\t", vp); - len = 8; - } else { - vp = add (" ", vp); - len++; + + /* + * Append any RFC-822 comment to the end of + * the Content-Type line. + */ + if (ci->ci_comment) { + snprintf (buffer, sizeof(buffer), "(%s)", ci->ci_comment); + if (len + 1 + (cc = 2 + strlen (ci->ci_comment)) >= CPERLIN) { + vp = add ("\n\t", vp); + len = 8; + } else { + vp = add (" ", vp); + len++; + } + vp = add (buffer, vp); + len += cc; } - vp = add (buffer, vp); - len += cc; - } - vp = add ("\n", vp); - add_header (ct, np, vp); - - /* - * output the Content-ID, unless disabled by -nocontentid - */ - if (contentidsw && ct->c_id) { - np = add (ID_FIELD, NULL); - vp = concat (" ", ct->c_id, NULL); + vp = add ("\n", vp); add_header (ct, np, vp); - } - - /* - * output the Content-Description - */ - if (ct->c_descr) { - np = add (DESCR_FIELD, NULL); - vp = concat (" ", ct->c_descr, NULL); - add_header (ct, np, vp); - } - - /* - * output the Content-Disposition - */ - if (ct->c_dispo) { - np = add (DISPO_FIELD, NULL); - vp = concat (" ", ct->c_dispo, NULL); - add_header (ct, np, vp); - } + + /* + * output the Content-ID, unless disabled by -nocontentid + */ + if (contentidsw && ct->c_id) { + np = add (ID_FIELD, NULL); + vp = concat (" ", ct->c_id, NULL); + add_header (ct, np, vp); + } + + /* + * output the Content-Description + */ + if (ct->c_descr) { + np = add (DESCR_FIELD, NULL); + vp = concat (" ", ct->c_descr, NULL); + add_header (ct, np, vp); + } + + /* + * output the Content-Disposition + */ + if (ct->c_dispo) { + np = add (DISPO_FIELD, NULL); + vp = concat (" ", ct->c_dispo, NULL); + add_header (ct, np, vp); + } skip_headers: - /* - * If this is the internal content structure for a - * "message/external", then we are done with the - * headers (since it has no body). - */ - if (ct->c_ctexbody) - return OK; + /* + * If this is the internal content structure for a + * "message/external", then we are done with the + * headers (since it has no body). + */ + if (ct->c_ctexbody) + return OK; - /* - * output the Content-MD5 - */ - if (checksw) { - np = add (MD5_FIELD, NULL); - vp = calculate_digest (ct, (ct->c_encoding == CE_QUOTED) ? 1 : 0); - add_header (ct, np, vp); - } - - /* - * output the Content-Transfer-Encoding - */ - switch (ct->c_encoding) { - case CE_7BIT: - /* Nothing to output */ + /* + * output the Content-MD5 + */ + if (checksw) { + np = add (MD5_FIELD, NULL); + vp = calculate_digest (ct, (ct->c_encoding == CE_QUOTED) ? 1 : 0); + add_header (ct, np, vp); + } + + /* + * output the Content-Transfer-Encoding + */ + switch (ct->c_encoding) { + case CE_7BIT: + /* Nothing to output */ #if 0 - np = add (ENCODING_FIELD, NULL); - vp = concat (" ", "7bit", "\n", NULL); - add_header (ct, np, vp); + np = add (ENCODING_FIELD, NULL); + vp = concat (" ", "7bit", "\n", NULL); + add_header (ct, np, vp); #endif - break; + break; - case CE_8BIT: - if (ct->c_type == CT_MESSAGE) - adios (NULL, "internal error, invalid encoding"); + case CE_8BIT: + if (ct->c_type == CT_MESSAGE) + adios (NULL, "internal error, invalid encoding"); - np = add (ENCODING_FIELD, NULL); - vp = concat (" ", "8bit", "\n", NULL); - add_header (ct, np, vp); - break; + np = add (ENCODING_FIELD, NULL); + vp = concat (" ", "8bit", "\n", NULL); + add_header (ct, np, vp); + break; - case CE_QUOTED: - if (ct->c_type == CT_MESSAGE || ct->c_type == CT_MULTIPART) - adios (NULL, "internal error, invalid encoding"); + case CE_QUOTED: + if (ct->c_type == CT_MESSAGE || ct->c_type == CT_MULTIPART) + adios (NULL, "internal error, invalid encoding"); - np = add (ENCODING_FIELD, NULL); - vp = concat (" ", "quoted-printable", "\n", NULL); - add_header (ct, np, vp); - break; + np = add (ENCODING_FIELD, NULL); + vp = concat (" ", "quoted-printable", "\n", NULL); + add_header (ct, np, vp); + break; - case CE_BASE64: - if (ct->c_type == CT_MESSAGE || ct->c_type == CT_MULTIPART) - adios (NULL, "internal error, invalid encoding"); + case CE_BASE64: + if (ct->c_type == CT_MESSAGE || ct->c_type == CT_MULTIPART) + adios (NULL, "internal error, invalid encoding"); - np = add (ENCODING_FIELD, NULL); - vp = concat (" ", "base64", "\n", NULL); - add_header (ct, np, vp); - break; + np = add (ENCODING_FIELD, NULL); + vp = concat (" ", "base64", "\n", NULL); + add_header (ct, np, vp); + break; - case CE_BINARY: - if (ct->c_type == CT_MESSAGE) - adios (NULL, "internal error, invalid encoding"); + case CE_BINARY: + if (ct->c_type == CT_MESSAGE) + adios (NULL, "internal error, invalid encoding"); - np = add (ENCODING_FIELD, NULL); - vp = concat (" ", "binary", "\n", NULL); - add_header (ct, np, vp); - break; + np = add (ENCODING_FIELD, NULL); + vp = concat (" ", "binary", "\n", NULL); + add_header (ct, np, vp); + break; - default: - adios (NULL, "unknown transfer encoding in content"); - break; - } - - /* - * Additional content specific header processing - */ - switch (ct->c_type) { - case CT_MULTIPART: - { - struct multipart *m; - struct part *part; + default: + adios (NULL, "unknown transfer encoding in content"); + break; + } + + /* + * Additional content specific header processing + */ + switch (ct->c_type) { + case CT_MULTIPART: + { + struct multipart *m; + struct part *part; - m = (struct multipart *) ct->c_ctparams; - for (part = m->mp_parts; part; part = part->mp_next) { - CT p; + m = (struct multipart *) ct->c_ctparams; + for (part = m->mp_parts; part; part = part->mp_next) { + CT p; - p = part->mp_part; - build_headers (p); + p = part->mp_part; + build_headers (p); + } } - } - break; + break; - case CT_MESSAGE: - if (ct->c_subtype == MESSAGE_EXTERNAL) { - struct exbody *e; + case CT_MESSAGE: + if (ct->c_subtype == MESSAGE_EXTERNAL) { + struct exbody *e; - e = (struct exbody *) ct->c_ctparams; - build_headers (e->eb_content); - } - break; + e = (struct exbody *) ct->c_ctparams; + build_headers (e->eb_content); + } + break; - default: - /* Nothing to do */ - break; - } + default: + /* Nothing to do */ + break; + } - return OK; + return OK; } @@ -1611,85 +1610,85 @@ static char nib2b64[0x40+1] = static char * calculate_digest (CT ct, int asciiP) { - int cc; - char buffer[BUFSIZ], *vp, *op; - unsigned char *dp; - unsigned char digest[16]; - unsigned char outbuf[25]; - FILE *in; - MD5_CTX mdContext; - CE ce = ct->c_cefile; - - /* open content */ - if ((in = fopen (ce->ce_file, "r")) == NULL) - adios (ce->ce_file, "unable to open for reading"); - - /* Initialize md5 context */ - MD5Init (&mdContext); - - /* calculate md5 message digest */ - if (asciiP) { - while (fgets (buffer, sizeof(buffer) - 1, in)) { - char c, *cp; - - cp = buffer + strlen (buffer) - 1; - if ((c = *cp) == '\n') - *cp = '\0'; + int cc; + char buffer[BUFSIZ], *vp, *op; + unsigned char *dp; + unsigned char digest[16]; + unsigned char outbuf[25]; + FILE *in; + MD5_CTX mdContext; + CE ce = ct->c_cefile; + + /* open content */ + if ((in = fopen (ce->ce_file, "r")) == NULL) + adios (ce->ce_file, "unable to open for reading"); + + /* Initialize md5 context */ + MD5Init (&mdContext); + + /* calculate md5 message digest */ + if (asciiP) { + while (fgets (buffer, sizeof(buffer) - 1, in)) { + char c, *cp; - MD5Update (&mdContext, (unsigned char *) buffer, - (unsigned int) strlen (buffer)); + cp = buffer + strlen (buffer) - 1; + if ((c = *cp) == '\n') + *cp = '\0'; - if (c == '\n') - MD5Update (&mdContext, (unsigned char *) "\r\n", 2); + MD5Update (&mdContext, (unsigned char *) buffer, + (unsigned int) strlen (buffer)); + + if (c == '\n') + MD5Update (&mdContext, (unsigned char *) "\r\n", 2); + } + } else { + while ((cc = fread (buffer, sizeof(*buffer), sizeof(buffer), in)) > 0) + MD5Update (&mdContext, (unsigned char *) buffer, (unsigned int) cc); } - } else { - while ((cc = fread (buffer, sizeof(*buffer), sizeof(buffer), in)) > 0) - MD5Update (&mdContext, (unsigned char *) buffer, (unsigned int) cc); - } - - /* md5 finalization. Write digest and zero md5 context */ - MD5Final (digest, &mdContext); - - /* close content */ - fclose (in); - - /* print debugging info */ - if (debugsw) { - unsigned char *ep; - - fprintf (stderr, "MD5 digest="); - for (ep = (dp = digest) + sizeof(digest) / sizeof(digest[0]); - dp < ep; dp++) - fprintf (stderr, "%02x", *dp & 0xff); - fprintf (stderr, "\n"); - } - - /* encode the digest using base64 */ - for (dp = digest, op = outbuf, cc = sizeof(digest) / sizeof(digest[0]); - cc > 0; cc -= 3, op += 4) { - unsigned long bits; - char *bp; - - bits = (*dp++ & 0xff) << 16; - if (cc > 1) { - bits |= (*dp++ & 0xff) << 8; - if (cc > 2) - bits |= *dp++ & 0xff; + + /* md5 finalization. Write digest and zero md5 context */ + MD5Final (digest, &mdContext); + + /* close content */ + fclose (in); + + /* print debugging info */ + if (debugsw) { + unsigned char *ep; + + fprintf (stderr, "MD5 digest="); + for (ep = (dp = digest) + sizeof(digest) / sizeof(digest[0]); + dp < ep; dp++) + fprintf (stderr, "%02x", *dp & 0xff); + fprintf (stderr, "\n"); } - for (bp = op + 4; bp > op; bits >>= 6) - *--bp = nib2b64[bits & 0x3f]; - if (cc < 3) { - *(op + 3) = '='; - if (cc < 2) - *(op + 2) = '='; + /* encode the digest using base64 */ + for (dp = digest, op = outbuf, cc = sizeof(digest) / sizeof(digest[0]); + cc > 0; cc -= 3, op += 4) { + unsigned long bits; + char *bp; + + bits = (*dp++ & 0xff) << 16; + if (cc > 1) { + bits |= (*dp++ & 0xff) << 8; + if (cc > 2) + bits |= *dp++ & 0xff; + } + + for (bp = op + 4; bp > op; bits >>= 6) + *--bp = nib2b64[bits & 0x3f]; + if (cc < 3) { + *(op + 3) = '='; + if (cc < 2) + *(op + 2) = '='; + } } - } - /* null terminate string */ - outbuf[24] = '\0'; + /* null terminate string */ + outbuf[24] = '\0'; - /* now make copy and return string */ - vp = concat (" ", outbuf, "\n", NULL); - return vp; + /* now make copy and return string */ + vp = concat (" ", outbuf, "\n", NULL); + return vp; }