X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/162842264a2f69f4346fa8f6046fdc245e0bd78f..79f7ee461078bd837632b2ca9fdf94ab4a080a36:/uip/mhparse.c diff --git a/uip/mhparse.c b/uip/mhparse.c index 4db22d8e..c381bb85 100644 --- a/uip/mhparse.c +++ b/uip/mhparse.c @@ -109,7 +109,7 @@ void free_encoding (CT, int); * 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); @@ -138,6 +138,7 @@ static int openURL (CT, char **); 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 }, @@ -380,7 +381,7 @@ get_content (FILE *in, char *file, int toplevel) 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++) @@ -490,7 +491,7 @@ get_content (FILE *in, char *file, int toplevel) 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; } @@ -513,7 +514,8 @@ get_content (FILE *in, char *file, int toplevel) } 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: @@ -679,14 +681,12 @@ extract_name_value (char *name_suffix, char *value) { 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); @@ -707,7 +707,8 @@ get_ctinfo (char *cp, CT ct, int magic) 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++) @@ -730,7 +731,8 @@ get_ctinfo (char *cp, CT ct, int magic) 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 != '/') { @@ -743,7 +745,8 @@ get_ctinfo (char *cp, CT ct, int magic) 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++) @@ -768,11 +771,14 @@ magic_skip: 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; } /* @@ -831,7 +837,7 @@ magic_skip: * 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; @@ -843,10 +849,10 @@ magic_skip: 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; @@ -917,16 +923,90 @@ magic_skip: } 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; @@ -941,7 +1021,7 @@ get_comment (const char *filename, CI ci, char **ap, int istype) case '\0': invalid: advise (NULL, "invalid comment in message %s's %s: field", - filename, istype ? TYPE_FIELD : VRSN_FIELD); + filename, fieldname); return NOTOK; case '\\': @@ -968,12 +1048,12 @@ invalid: } *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); } } @@ -3227,32 +3307,22 @@ get_ce_method (const char *method) { } 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; } @@ -3260,9 +3330,8 @@ parse_header_attrs (const char *filename, int len, char **header_attrp, CI ci, 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 */ @@ -3275,19 +3344,23 @@ parse_header_attrs (const char *filename, int len, char **header_attrp, CI ci, 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;;) { @@ -3296,9 +3369,9 @@ parse_header_attrs (const char *filename, int len, char **header_attrp, CI ci, 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 '\\': @@ -3322,12 +3395,13 @@ bad_quote: 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; } @@ -3335,12 +3409,17 @@ bad_quote: 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; @@ -3357,7 +3436,7 @@ char * 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; @@ -3384,7 +3463,7 @@ output_params(size_t initialwidth, PM params, int *offsetout) while (curlen + 8 > CPERLIN - 1) { int curvallen = strlen(params->pm_value + valoff) - - (initialwidth + curlen - (CPERLIN - 1)); + (curlen + 8 - (CPERLIN - 1)); *q++ = ';'; *q++ = '\n'; @@ -3481,7 +3560,8 @@ output_params(size_t initialwidth, PM params, int *offsetout) 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) @@ -3663,7 +3743,7 @@ static size_t 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++ = '='; @@ -3698,3 +3778,28 @@ normal_param(PM pm, char *output, size_t len, size_t valuelen, 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; +}