From: Ken Hornstein Date: Fri, 21 Feb 2014 19:49:07 +0000 (-0500) Subject: Getting closer to getting something working. X-Git-Url: https://diplodocus.org/git/nmh/commitdiff_plain/9dc534e5b5cb8489e1918820284fdccadc6b13a5?hp=162842264a2f69f4346fa8f6046fdc245e0bd78f Getting closer to getting something working. --- diff --git a/h/mhparse.h b/h/mhparse.h index 3c0756de..0d4ef467 100644 --- a/h/mhparse.h +++ b/h/mhparse.h @@ -341,7 +341,28 @@ char *ct_subtype_str (int, int); const struct str2init *get_ct_init (int); const char *ce_str (int); const struct str2init *get_ce_method (const char *); -int parse_header_attrs (const char *, int, char **, CI, int *); + +/* + * Parse a series of MIME attributes (or parameters) given a header as + * input. + * + * Arguments include: + * + * filename - Name of input file (for error messages) + * fieldname - Name of field being processed + * headerp - Pointer to pointer of the beginning of the MIME attributes. + * Updated to point to end of attributes when finished. + * param_head - Pointer to head of parameter list + * param_tail - Pointer to tail of parameter list + * commentp - Pointer to header comment pointer (may be NULL) + * + * Returns OK if parsing was successful, NOTOK if parsing failed, and + * DONE to indicate a benign error (minor parsing error, but the program + * should continue). + */ +int parse_header_attrs (const char *filename, const char *fieldname, + char **headerp, PM *param_head, PM *param_tail, + char **commentp); /* * Given a linked list of parameters, build an output string for them. This @@ -361,4 +382,18 @@ int parse_header_attrs (const char *, int, char **, CI, int *); */ char *output_params(size_t initialwidth, PM params, int *offsetout); +/* + * Add a parameter to the parameter linked list. + * + * Arguments are: + * + * first - Pointer to head of linked list + * last - Pointer to tail of linked list + * name - Name of parameter + * value - Value of parameter + * + * Returned allocated parameter element + */ +PM add_param(PM *first, PM *last, const char *name, const char *value); + extern int checksw; /* Add Content-MD5 field */ diff --git a/uip/mhbuildsbr.c b/uip/mhbuildsbr.c index b2949c39..6798bba5 100644 --- a/uip/mhbuildsbr.c +++ b/uip/mhbuildsbr.c @@ -1159,11 +1159,12 @@ compose_content (CT ct) case 'a': { /* insert parameters from directive */ - char **ep; char *s = ""; + PM pm; - for (ap = ci->ci_attrs, ep = ci->ci_values; *ap; ap++, ep++) { - snprintf (bp, buflen, "%s%s=\"%s\"", s, *ap, *ep); + for (pm = ci->ci_first_pm; pm; pm = pm->pm_next) { + snprintf (bp, buflen, "%s%s=\"%s\"", s, + pm->pm_name, pm->pm_value); len = strlen (bp); bp += len; buflen -= len; @@ -1466,22 +1467,10 @@ scan_content (CT ct, size_t maxunencoded) 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) { - *ap = concat ("charset=", write_charset_8bit(), NULL); - } else { - *ap = add ("charset=us-ascii", NULL); - } + add_param(&ci->ci_first_pm, &ci->ci_last_pm, "charset", + contains8bit ? write_charset_8bit() : "us-ascii"); t->tx_charset = CHARSET_SPECIFIED; - - cp = strchr(*ap++, '='); - *ap = NULL; - *cp++ = '\0'; - *ep = cp; } } @@ -1537,25 +1526,19 @@ static int build_headers (CT ct) { int cc, mailbody, extbody, len; - char **ap, **ep; char *np, *vp, buffer[BUFSIZ]; CI ci = &ct->c_ctinfo; + PM pm; /* * 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; + snprintf (buffer, sizeof(buffer), "%s%d", prefix, level++); + add_param(&ci->ci_first_pm, &ci->ci_last_pm, "boundary", buffer); } /* @@ -1585,8 +1568,8 @@ build_headers (CT ct) * 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 && !strcasecmp (*ap, "body")) + for (pm = ci->ci_first_pm; pm; pm = pm->pm_next) { + if (mailbody && !strcasecmp (pm->pm_name, "body")) continue; vp = add (";", vp); @@ -1597,8 +1580,8 @@ build_headers (CT ct) * we have to break it across multiple lines */ - if (extbody && strcasecmp (*ap, "url") == 0) { - char *value = *ep; + 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)) >= @@ -1628,7 +1611,7 @@ build_headers (CT ct) continue; } - snprintf (buffer, sizeof(buffer), "%s=\"%s\"", *ap, *ep); + 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; @@ -1889,8 +1872,9 @@ calculate_digest (CT ct, int asciiP) static void setup_attach_content(CT ct, char *filename) { - char *type, **ap, **ep, *simplename = r1bindex(filename, '/'); + char *type, *simplename = r1bindex(filename, '/'); struct str2init *s2i; + PM pm; if (! (type = mime_type(filename))) { adios(NULL, "Unable to determine MIME type of \"%s\"", filename); @@ -1946,20 +1930,18 @@ setup_attach_content(CT ct, char *filename) * content-description, and the content-disposition. */ - for (ap = ct->c_ctinfo.ci_attrs, ep = ct->c_ctinfo.ci_values; *ap; - ap++, ep++) { - if (strcasecmp(*ap, "name") == 0) { - if (*ep) - free(*ep); - *ep = getcpy(simplename); + for (pm = ct->c_ctinfo.ci_first_pm; pm; pm = pm->pm_next) { + if (strcasecmp(pm->pm_name, "name") == 0) { + if (pm->pm_value) + free(pm->pm_value); + pm->pm_value = getcpy(simplename); break; } } - if (*ap == NULL) { - *ap = getcpy("name"); - *ep = getcpy(simplename); - } + if (pm == NULL) + add_param(&ct->c_ctinfo.ci_first_pm, &ct->c_ctinfo.ci_last_pm, + "name", simplename); ct->c_descr = getcpy(simplename); ct->c_descr = add("\n", ct->c_descr); diff --git a/uip/mhfixmsg.c b/uip/mhfixmsg.c index 20162508..a5787ff2 100644 --- a/uip/mhfixmsg.c +++ b/uip/mhfixmsg.c @@ -1073,19 +1073,19 @@ divide_part (CT ct) { static void copy_ctinfo (CI dest, CI src) { - char **s_ap, **d_ap, **s_vp, **d_vp; + PM s_pm, d_pm; dest->ci_type = src->ci_type ? add (src->ci_type, NULL) : NULL; dest->ci_subtype = src->ci_subtype ? add (src->ci_subtype, NULL) : NULL; - for (s_ap = src->ci_attrs, d_ap = dest->ci_attrs, - s_vp = src->ci_values, d_vp = dest->ci_values; - *s_ap; - ++s_ap, ++d_ap, ++s_vp, ++d_vp) { - *d_ap = add (*s_ap, NULL); - *d_vp = *s_vp; + for (s_pm = src->ci_first_pm; s_pm; s_pm = s_pm->pm_next) { + d_pm = add_param(&dest->ci_first_pm, &dest->ci_last_pm, s_pm->pm_name, + s_pm->pm_value); + if (s_pm->pm_charset) + d_pm->pm_charset = getcpy(s_pm->pm_charset); + if (s_pm->pm_lang) + d_pm->pm_lang = getcpy(s_pm->pm_lang); } - *d_ap = NULL; dest->ci_comment = src->ci_comment ? add (src->ci_comment, NULL) : NULL; dest->ci_magic = src->ci_magic ? add (src->ci_magic, NULL) : NULL; diff --git a/uip/mhfree.c b/uip/mhfree.c index 29756876..3f62482e 100644 --- a/uip/mhfree.c +++ b/uip/mhfree.c @@ -30,6 +30,7 @@ static void free_text (CT); static void free_multi (CT); static void free_partial (CT); static void free_external (CT); +static void free_pmlist (PM); /* @@ -103,6 +104,7 @@ free_content (CT ct) free (ct->c_descr); if (ct->c_dispo) free (ct->c_dispo); + free_pmlist (ct->c_dispo_first); if (ct->c_file) { if (ct->c_unlink) @@ -162,10 +164,7 @@ free_ctinfo (CT ct) free (ci->ci_subtype); ci->ci_subtype = NULL; } - for (ap = ci->ci_attrs; *ap; ap++) { - free (*ap); - *ap = NULL; - } + free_pmlist(ci->ci_first_pm); if (ci->ci_comment) { free (ci->ci_comment); ci->ci_comment = NULL; @@ -253,6 +252,27 @@ free_external (CT ct) } +static void +free_pmlist (PM pm) +{ + PM pm2; + + while (pm != NULL) { + if (pm->pm_name) + free (pm->pm_name); + if (pm->pm_value) + free (pm->pm_value); + if (pm->pm_charset) + free (pm->pm_charset); + if (pm->pm_lang) + free (pm->pm_lang); + pm2 = pm->pm_next; + free(pm); + pm = pm2; + } +} + + /* * Free data structures related to encoding/decoding * Content-Transfer-Encodings. diff --git a/uip/mhlistsbr.c b/uip/mhlistsbr.c index 9380c3d7..a3ac0c24 100644 --- a/uip/mhlistsbr.c +++ b/uip/mhlistsbr.c @@ -199,11 +199,11 @@ list_content (CT ct, int toplevel, int realsize, int verbose, int debug) printf ("\n"); if (verbose) { - char **ap, **ep; CI ci = &ct->c_ctinfo; + PM pm; - for (ap = ci->ci_attrs, ep = ci->ci_values; *ap; ap++, ep++) - printf ("\t %s=\"%s\"\n", *ap, *ep); + for (pm = ci->ci_first_pm; pm; pm = pm->pm_next) + printf ("\t %s=\"%s\"\n", pm->pm_name, pm->pm_value); /* * If verbose, print any RFC-822 comments in the @@ -233,8 +233,8 @@ list_content (CT ct, int toplevel, int realsize, int verbose, int debug) static int list_debug (CT ct) { - char **ap, **ep; CI ci = &ct->c_ctinfo; + PM pm; fflush (stdout); fprintf (stderr, " partno \"%s\"\n", empty (ct->c_partno)); @@ -255,8 +255,8 @@ list_debug (CT ct) /* print parsed parameters attached to content type */ fprintf (stderr, " parameters\n"); - for (ap = ci->ci_attrs, ep = ci->ci_values; *ap; ap++, ep++) - fprintf (stderr, " %s=\"%s\"\n", *ap, *ep); + for (pm = ci->ci_first_pm; pm; pm = pm->pm_next) + fprintf (stderr, " %s=\"%s\"\n", pm->pm_name, pm->pm_value); /* print internal flags for type/subtype */ fprintf (stderr, " type 0x%x subtype 0x%x params 0x%x\n", diff --git a/uip/mhparse.c b/uip/mhparse.c index 4db22d8e..043effdc 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); @@ -380,7 +380,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 +490,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; } @@ -686,7 +686,6 @@ get_ctinfo (char *cp, CT ct, int magic) 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 +706,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 +730,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 +744,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 +770,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; } /* @@ -926,7 +931,8 @@ magic_skip: 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 +947,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 +974,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 +3233,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 +3256,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 +3270,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); + + pm->pm_value = vp = pm->pm_name + (dp - cp); if (*dp == '"') { for (cp = ++dp, dp = vp;;) { @@ -3296,9 +3295,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 '\\': @@ -3325,9 +3324,9 @@ bad_quote: 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 +3334,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; @@ -3698,3 +3702,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(name); + + if (*first) { + (*last)->pm_next = pm; + *last = pm; + } else { + *first = pm; + *last = pm; + } + + return pm; +}