extern int debugsw;
-extern int verbosw;
extern int listsw;
extern int rfc934sw;
extern int rcachesw; /* mhcachesbr.c */
extern int wcachesw; /* mhcachesbr.c */
-pid_t xpid = 0;
-
static char prefix[] = "----- =_aaaaaaaaaa";
struct attach_list {
/*
* static prototypes
*/
-static int init_decoded_content (CT);
+static int init_decoded_content (CT, const char *);
static void setup_attach_content(CT, char *);
static char *fgetstr (char *, int, FILE *);
-static int user_content (FILE *, char *, CT *);
+static int user_content (FILE *, char *, CT *, const char *infilename);
static void set_id (CT, int);
-static int compose_content (CT);
+static int compose_content (CT, int);
static int scan_content (CT, size_t);
-static int build_headers (CT);
+static int build_headers (CT, int);
static char *calculate_digest (CT, int);
CT
build_mime (char *infile, int autobuild, int dist, int directives,
- int header_encoding, size_t maxunencoded)
+ int header_encoding, size_t maxunencoded, int verbose)
{
int compnum, state;
char buf[BUFSIZ], name[NAMESZ];
* for this part. We don't really need this, but
* allocate it to remain consistent.
*/
- init_decoded_content (ct);
+ init_decoded_content (ct, infile);
/*
* Parse some of the header fields in the composition
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");
struct part *part;
CT p;
- if (user_content (in, buf, &p) == DONE) {
+ if (user_content (in, buf, &p, infile) == DONE) {
admonish (NULL, "ignoring spurious #end");
continue;
}
if ((p = (CT) calloc (1, sizeof(*p))) == NULL)
adios(NULL, "out of memory");
- init_decoded_content(p);
+ init_decoded_content(p, infile);
/*
* Initialize our content structure based on the filename,
if ((p = (CT) calloc (1, sizeof(*p))) == NULL)
adios(NULL, "out of memory");
- init_decoded_content(p);
+ init_decoded_content(p, infile);
if (get_ctinfo ("text/plain", p, 0) == NOTOK)
done (1);
p->c_type = CT_TEXT;
p->c_subtype = TEXT_PLAIN;
p->c_encoding = CE_7BIT;
- p->c_file = getcpy(infile);
/*
* Sigh. ce_file contains the "decoded" contents of this part.
* So this seems like the best option available since we're going
* Fill out, or expand directives. Parse and execute
* commands specified by profile composition strings.
*/
- compose_content (ct);
+ compose_content (ct, verbose);
if ((cp = strchr(prefix, 'a')) == NULL)
adios (NULL, "internal error(4)");
/* Build the rest of the header field structures */
if (! dist)
- build_headers (ct);
+ build_headers (ct, header_encoding);
return ct;
}
*/
static int
-init_decoded_content (CT ct)
+init_decoded_content (CT ct, const char *filename)
{
ct->c_ceopenfnx = open7Bit; /* since unencoded */
ct->c_ceclosefnx = close_encoding;
ct->c_cesizefnx = NULL; /* since unencoded */
+ ct->c_encoding = CE_7BIT; /* Seems like a reasonable default */
+ ct->c_file = add(filename, NULL);
return OK;
}
*/
static int
-user_content (FILE *in, char *buf, CT *ctp)
+user_content (FILE *in, char *buf, CT *ctp, const char *infilename)
{
int extrnal, vrsn;
char *cp, **ap;
*ctp = ct;
/* allocate basic structure for handling decoded content */
- init_decoded_content (ct);
+ init_decoded_content (ct, infilename);
ce = &ct->c_cefile;
ci = &ct->c_ctinfo;
if ((p = (CT) calloc (1, sizeof(*p))) == NULL)
adios (NULL, "out of memory");
- init_decoded_content (p);
+ init_decoded_content (p, infilename);
pe = &p->c_cefile;
if (get_ctinfo ("message/rfc822", p, 0) == NOTOK)
done (1);
struct part *part;
CT p;
- if (user_content (in, buffer, &p) == DONE) {
+ if (user_content (in, buffer, &p, infilename) == DONE) {
if (!m->mp_parts)
adios (NULL, "empty \"#begin ... #end\" sequence");
return OK;
*/
static int
-compose_content (CT ct)
+compose_content (CT ct, int verbose)
{
CE ce = &ct->c_cefile;
sprintf (pp, "%d", partnum);
p->c_partno = add (partnam, NULL);
- if (compose_content (p) == NOTOK)
+ if (compose_content (p, verbose) == NOTOK)
return NOTOK;
}
for (pm = ci->ci_first_pm; pm; pm = pm->pm_next) {
snprintf (bp, buflen, "%s%s=\"%s\"", s,
- pm->pm_name, pm->pm_value);
+ pm->pm_name, get_param_value(pm, '?'));
len = strlen (bp);
bp += len;
buflen -= len;
}
}
- if (verbosw)
+ if (verbose)
printf ("composing content %s/%s from command\n\t%s\n",
ci->ci_type, ci->ci_subtype, buffer);
break;
case CT_MESSAGE:
- check8bit = 0;
checklinelen = 0;
checklinespace = 0;
/* don't check anything for message/external */
- if (ct->c_subtype == MESSAGE_EXTERNAL)
+ if (ct->c_subtype == MESSAGE_EXTERNAL) {
checkboundary = 0;
- else
+ check8bit = 0;
+ } else {
checkboundary = 1;
+ check8bit = 1;
+ }
break;
case CT_AUDIO:
if (!isascii ((unsigned char) *cp)) {
contains8bit = 1;
check8bit = 0; /* no need to keep checking */
+ break;
}
}
}
CI ci = &ct->c_ctinfo;
add_param(&ci->ci_first_pm, &ci->ci_last_pm, "charset",
- contains8bit ? write_charset_8bit() : "us-ascii");
+ contains8bit ? write_charset_8bit() : "us-ascii", 0);
t->tx_charset = CHARSET_SPECIFIED;
}
}
break;
case CT_MESSAGE:
- ct->c_encoding = CE_7BIT;
+ ct->c_encoding = contains8bit ? CE_8BIT : CE_7BIT;
break;
case CT_AUDIO:
*/
static int
-build_headers (CT ct)
+build_headers (CT ct, int header_encoding)
{
int cc, mailbody, extbody, len;
char *np, *vp, buffer[BUFSIZ];
CI ci = &ct->c_ctinfo;
- PM pm;
/*
* If message is type multipart, then add the multipart
static int level = 0; /* store nesting level */
snprintf (buffer, sizeof(buffer), "%s%d", prefix, level++);
- add_param(&ci->ci_first_pm, &ci->ci_last_pm, "boundary", buffer);
+ add_param(&ci->ci_first_pm, &ci->ci_last_pm, "boundary", buffer, 0);
}
/*
* Append the attribute/value pairs to
* the end of the Content-Type line.
*/
- for (pm = ci->ci_first_pm; pm; pm = pm->pm_next) {
- if (mailbody && !strcasecmp (pm->pm_name, "body"))
- continue;
-
- 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 && strcasecmp (pm->pm_name, "url") == 0) {
- char *value = pm->pm_value;
-
- /* 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;
+ if (ci->ci_first_pm) {
+ char *s = output_params(len, ci->ci_first_pm, &len, mailbody);
- 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;
- }
+ if (!s)
+ adios(NULL, "Internal error: failed outputting Content-Type "
+ "parameters");
- snprintf (buffer, sizeof(buffer), "%s=\"%s\"", pm->pm_name, pm->pm_value);
- 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 (s, vp);
+ free(s);
}
/*
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);
+ if (encode_rfc2047(DESCR_FIELD, &vp, header_encoding, NULL))
+ adios(NULL, "Unable to encode %s header", DESCR_FIELD);
add_header (ct, np, vp);
}
/*
- * output the Content-Disposition
+ * output the Content-Disposition. If it's NULL but c_dispo_type is
+ * set, then we need to build it.
*/
if (ct->c_dispo) {
np = add (DISPO_FIELD, NULL);
vp = concat (" ", ct->c_dispo, NULL);
add_header (ct, np, vp);
+ } else if (ct->c_dispo_type) {
+ vp = concat (" ", ct->c_dispo_type, NULL);
+ len = strlen(DISPO_FIELD) + strlen(vp) + 1;
+ np = output_params(len, ct->c_dispo_first, NULL, 0);
+ vp = add(np, vp);
+ vp = add("\n", vp);
+ if (np)
+ free(np);
+ add_header (ct, getcpy(DISPO_FIELD), vp);
}
skip_headers:
break;
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);
CT p;
p = part->mp_part;
- build_headers (p);
+ build_headers (p, header_encoding);
}
}
break;
struct exbody *e;
e = (struct exbody *) ct->c_ctparams;
- build_headers (e->eb_content);
+ build_headers (e->eb_content, header_encoding);
}
break;
if (pm == NULL)
add_param(&ct->c_ctinfo.ci_first_pm, &ct->c_ctinfo.ci_last_pm,
- "name", simplename);
+ "name", simplename, 0);
ct->c_descr = getcpy(simplename);
ct->c_descr = add("\n", ct->c_descr);
if (strcasecmp(ct->c_ctinfo.ci_type, "text") == 0 &&
strcasecmp(ct->c_ctinfo.ci_subtype, "calendar") == 0) {
- ct->c_dispo = getcpy("inline; filename=\"");
+ ct->c_dispo_type = getcpy("inline");
} else {
- ct->c_dispo = getcpy("attachment; filename=\"");
+ ct->c_dispo_type = getcpy("attachment");
}
- ct->c_dispo = add(simplename, ct->c_dispo);
- ct->c_dispo = add("\"\n", ct->c_dispo);
+ add_param(&ct->c_dispo_first, &ct->c_dispo_last, "filename", simplename, 0);
}