* static prototypes
*/
static CT get_content (FILE *, char *, int);
-static int get_comment (const char *, CI, char **, int);
+static int get_comment (const char *, const char *, char **, char **);
static int InitGeneric (CT);
static int InitText (CT);
static size_t param_len(PM, int, size_t, int *);
static size_t encode_param(PM, char *, size_t, size_t, size_t, int);
static size_t normal_param(PM, char *, size_t, size_t, size_t);
+static int get_dispo (char *, CT, int);
struct str2init str2cts[] = {
{ "application", CT_APPLICATION, InitApplication },
fprintf (stderr, "%s: %s\n", VRSN_FIELD, cp);
if (*cp == '(' &&
- get_comment (ct->c_file, &ct->c_ctinfo, &cp, 0) == NOTOK)
+ get_comment (ct->c_file, VRSN_FIELD, &cp, NULL) == NOTOK)
goto out;
for (dp = cp; istoken (*dp); dp++)
fprintf (stderr, "%s: %s\n", MD5_FIELD, cp);
if (*cp == '(' &&
- get_comment (ct->c_file, &ct->c_ctinfo, &cp, 0) == NOTOK) {
+ get_comment (ct->c_file, MD5_FIELD, &cp, NULL) == NOTOK) {
free (ep);
goto out;
}
}
else if (!strcasecmp (hp->name, DISPO_FIELD)) {
/* Get Content-Disposition field */
- ct->c_dispo = add (hp->value, ct->c_dispo);
+ if (get_dispo(hp->value, ct, 0) == NOTOK)
+ goto out;
}
next_header:
int
get_ctinfo (char *cp, CT ct, int magic)
{
- int i;
char *dp;
char c;
CI ci;
int status;
ci = &ct->c_ctinfo;
- i = strlen (invo_name) + 2;
/* store copy of Content-Type line */
cp = ct->c_ctline = add (cp, NULL);
if (debugsw)
fprintf (stderr, "%s: %s\n", TYPE_FIELD, cp);
- if (*cp == '(' && get_comment (ct->c_file, &ct->c_ctinfo, &cp, 1) == NOTOK)
+ if (*cp == '(' && get_comment (ct->c_file, TYPE_FIELD, &cp,
+ &ci->ci_comment) == NOTOK)
return NOTOK;
for (dp = cp; istoken (*dp); dp++)
while (isspace ((unsigned char) *cp))
cp++;
- if (*cp == '(' && get_comment (ct->c_file, &ct->c_ctinfo, &cp, 1) == NOTOK)
+ if (*cp == '(' && get_comment (ct->c_file, TYPE_FIELD, &cp,
+ &ci->ci_comment) == NOTOK)
return NOTOK;
if (*cp != '/') {
while (isspace ((unsigned char) *cp))
cp++;
- if (*cp == '(' && get_comment (ct->c_file, &ct->c_ctinfo, &cp, 1) == NOTOK)
+ if (*cp == '(' && get_comment (ct->c_file, TYPE_FIELD, &cp,
+ &ci->ci_comment) == NOTOK)
return NOTOK;
for (dp = cp; istoken (*dp); dp++)
while (isspace ((unsigned char) *cp))
cp++;
- if (*cp == '(' && get_comment (ct->c_file, &ct->c_ctinfo, &cp, 1) == NOTOK)
+ if (*cp == '(' && get_comment (ct->c_file, TYPE_FIELD, &cp,
+ &ci->ci_comment) == NOTOK)
return NOTOK;
- if (parse_header_attrs (ct->c_file, i, &cp, ci, &status) == NOTOK) {
- return status;
+ if ((status = parse_header_attrs (ct->c_file, TYPE_FIELD, &cp,
+ &ci->ci_first_pm, &ci->ci_last_pm,
+ &ci->ci_comment)) != OK) {
+ return status == NOTOK ? NOTOK : OK;
}
/*
* Get any {Content-Disposition} given in buffer.
*/
if (magic && *cp == '{') {
- ct->c_dispo = ++cp;
+ ++cp;
for (dp = cp + strlen (cp) - 1; dp >= cp; dp--)
if (*dp == '}')
break;
c = *dp;
*dp = '\0';
- if (*ct->c_dispo)
- ct->c_dispo = concat (ct->c_dispo, "\n", NULL);
- else
- ct->c_dispo = NULL;
+
+ if (get_dispo(cp, ct, 1) != OK)
+ return NOTOK;
+
*dp++ = c;
cp = dp;
}
else
advise (NULL,
- "extraneous information in message %s's %s: field\n%*.*s(%s)",
- ct->c_file, TYPE_FIELD, i, i, "", cp);
+ "extraneous information in message %s's %s: field\n%*s(%s)",
+ ct->c_file, TYPE_FIELD, strlen(invo_name) + 2, "", cp);
+ }
+
+ return OK;
+}
+
+
+/*
+ * Parse out a Content-Disposition header. A lot of this is cribbed from
+ * get_ctinfo().
+ */
+static int
+get_dispo (char *cp, CT ct, int buildflag)
+{
+ char *dp, *dispoheader;
+ char c;
+ int status;
+
+ /*
+ * Save the whole copy of the Content-Disposition header, unless we're
+ * processing a mhbuild directive. A NULL c_dispo will be a flag to
+ * mhbuild that the disposition header needs to be generated at that
+ * time.
+ */
+
+ dispoheader = cp = add(cp, NULL);
+
+ while (isspace ((unsigned char) *cp)) /* trim leading spaces */
+ cp++;
+
+ /* change newlines to spaces */
+ for (dp = strchr(cp, '\n'); dp; dp = strchr(dp, '\n'))
+ *dp++ = ' ';
+
+ /* trim trailing spaces */
+ for (dp = cp + strlen (cp) - 1; dp >= cp; dp--)
+ if (!isspace ((unsigned char) *dp))
+ break;
+ *++dp = '\0';
+
+ if (debugsw)
+ fprintf (stderr, "%s: %s\n", DISPO_FIELD, cp);
+
+ if (*cp == '(' && get_comment (ct->c_file, DISPO_FIELD, &cp, NULL) ==
+ NOTOK) {
+ free(dispoheader);
+ return NOTOK;
+ }
+
+ for (dp = cp; istoken (*dp); dp++)
+ continue;
+ c = *dp, *dp = '\0';
+ ct->c_dispo_type = add (cp, NULL); /* store disposition type */
+ *dp = c, cp = dp;
+
+ if (*cp == '(' && get_comment (ct->c_file, DISPO_FIELD, &cp, NULL) == NOTOK)
+ return NOTOK;
+
+ if ((status = parse_header_attrs (ct->c_file, DISPO_FIELD, &cp,
+ &ct->c_dispo_first, &ct->c_dispo_last,
+ NULL)) != OK) {
+ if (status == NOTOK) {
+ free(dispoheader);
+ return NOTOK;
+ }
+ } else if (*cp) {
+ advise (NULL,
+ "extraneous information in message %s's %s: field\n%*s(%s)",
+ ct->c_file, DISPO_FIELD, strlen(invo_name) + 2, "", cp);
}
+ if (buildflag)
+ free(dispoheader);
+ else
+ ct->c_dispo = dispoheader;
+
return OK;
}
static int
-get_comment (const char *filename, CI ci, char **ap, int istype)
+get_comment (const char *filename, const char *fieldname, char **ap,
+ char **commentp)
{
int i;
char *bp, *cp;
case '\0':
invalid:
advise (NULL, "invalid comment in message %s's %s: field",
- filename, istype ? TYPE_FIELD : VRSN_FIELD);
+ filename, fieldname);
return NOTOK;
case '\\':
}
*bp = '\0';
- if (istype) {
- if ((dp = ci->ci_comment)) {
- ci->ci_comment = concat (dp, " ", buffer, NULL);
+ if (commentp) {
+ if ((dp = *commentp)) {
+ *commentp = concat (dp, " ", buffer, NULL);
free (dp);
} else {
- ci->ci_comment = add (buffer, NULL);
+ *commentp = add (buffer, NULL);
}
}
}
int
-parse_header_attrs (const char *filename, int len, char **header_attrp, CI ci,
- int *status) {
- char **attr = ci->ci_attrs;
+parse_header_attrs (const char *filename, const char *fieldname,
+ char **header_attrp, PM *param_head, PM *param_tail,
+ char **commentp)
+{
char *cp = *header_attrp;
+ PM pm;
while (*cp == ';') {
char *dp, *vp, *up, c;
- /* Relies on knowledge of this declaration:
- * char *ci_attrs[NPARMS + 2];
- */
- if (attr >= ci->ci_attrs + sizeof ci->ci_attrs/sizeof (char *) - 2) {
- advise (NULL,
- "too many parameters in message %s's %s: field (%d max)",
- filename, TYPE_FIELD, NPARMS);
- *status = NOTOK;
- return NOTOK;
- }
-
cp++;
while (isspace ((unsigned char) *cp))
cp++;
if (*cp == '(' &&
- get_comment (filename, ci, &cp, 1) == NOTOK) {
- *status = NOTOK;
+ get_comment (filename, fieldname, &cp, commentp) == NOTOK) {
return NOTOK;
}
advise (NULL,
"extraneous trailing ';' in message %s's %s: "
"parameter list",
- filename, TYPE_FIELD);
- *status = OK;
- return NOTOK;
+ filename, fieldname);
+ return DONE;
}
/* down case the attribute name */
if (dp == cp || *dp != '=') {
advise (NULL,
"invalid parameter in message %s's %s: "
- "field\n%*.*sparameter %s (error detected at offset %d)",
- filename, TYPE_FIELD, len, len, "", cp, dp - cp);
- *status = NOTOK;
+ "field\n%*sparameter %s (error detected at offset %d)",
+ filename, fieldname, strlen(invo_name) + 2, "",cp, dp - cp);
return NOTOK;
}
- vp = (*attr = add (cp, NULL)) + (up - cp);
+ pm = mh_xmalloc(sizeof(*pm));
+ memset(pm, 0, sizeof(*pm));
+
+ /* This is all mega-bozo and needs cleanup */
+ vp = (pm->pm_name = add (cp, NULL)) + (up - cp);
*vp = '\0';
for (dp++; isspace ((unsigned char) *dp);)
dp++;
/* Now store the attribute value. */
- ci->ci_values[attr - ci->ci_attrs] = vp = *attr + (dp - cp);
+
+ vp = pm->pm_name + (dp - cp);
if (*dp == '"') {
for (cp = ++dp, dp = vp;;) {
bad_quote:
advise (NULL,
"invalid quoted-string in message %s's %s: "
- "field\n%*.*s(parameter %s)",
- filename, TYPE_FIELD, len, len, "", *attr);
- *status = NOTOK;
+ "field\n%*s(parameter %s)",
+ filename, fieldname, strlen(invo_name) + 2, "",
+ pm->pm_name);
return NOTOK;
case '\\':
continue;
*dp = '\0';
}
+ pm->pm_value = getcpy(vp);
if (!*vp) {
advise (NULL,
"invalid parameter in message %s's %s: "
- "field\n%*.*s(parameter %s)",
- filename, TYPE_FIELD, len, len, "", *attr);
- *status = NOTOK;
+ "field\n%*s(parameter %s)",
+ filename, fieldname, strlen(invo_name) + 2, "",
+ pm->pm_name);
return NOTOK;
}
cp++;
if (*cp == '(' &&
- get_comment (filename, ci, &cp, 1) == NOTOK) {
- *status = NOTOK;
+ get_comment (filename, fieldname, &cp, commentp) == NOTOK) {
return NOTOK;
}
- ++attr;
+ if (*param_head == NULL) {
+ *param_head = pm;
+ *param_tail = pm;
+ } else {
+ (*param_tail)->pm_next = pm;
+ *param_tail = pm;
+ }
}
*header_attrp = cp;
output_params(size_t initialwidth, PM params, int *offsetout)
{
char *paramout = NULL;
- char line[CPERLIN * 2], *p, *q;
+ char line[CPERLIN * 2], *q;
int curlen, index, eightbit, encode, i;
size_t valoff;
while (curlen + 8 > CPERLIN - 1) {
int curvallen = strlen(params->pm_value + valoff) -
- (initialwidth + curlen - (CPERLIN - 1));
+ (curlen + 8 - (CPERLIN - 1));
*q++ = ';';
*q++ = '\n';
q += snprintf(q, sizeof(line) - (q - line), "%s*%d",
params->pm_name, index);
} else {
- q = strncpy(q, params->pm_name, sizeof(line) - (q - line));
+ strncpy(q, params->pm_name, sizeof(line) - (q - line));
+ q += strlen(q);
}
if (eightbit)
normal_param(PM pm, char *output, size_t len, size_t valuelen,
size_t valueoff)
{
- size_t outlen = 0, n;
+ size_t outlen = 0;
char *endptr = output + len, *p;
*output++ = '=';
return outlen + 1;
}
+
+/*
+ * Add a parameter to the parameter linked list
+ */
+
+PM
+add_param(PM *first, PM *last, const char *name, const char *value)
+{
+ PM pm = mh_xmalloc(sizeof(*pm));
+
+ memset(pm, 0, sizeof(*pm));
+
+ pm->pm_name = getcpy(name);
+ pm->pm_value = getcpy(value);
+
+ if (*first) {
+ (*last)->pm_next = pm;
+ *last = pm;
+ } else {
+ *first = pm;
+ *last = pm;
+ }
+
+ return pm;
+}