X-Git-Url: http://git.marmaro.de/?a=blobdiff_plain;f=uip%2Fmhparse.c;h=67717890cb31595feaf961b5c98b663948b53177;hb=a139e1ddbbe5e7fe89d7eb4a5dc16d4b9698960a;hp=fc24f5e13e8c30a832c6929a0bc45585ab6038fe;hpb=81a21a9a97d8633f6d6231e31fdb6e328d0d3ff2;p=mmh diff --git a/uip/mhparse.c b/uip/mhparse.c index fc24f5e..6771789 100644 --- a/uip/mhparse.c +++ b/uip/mhparse.c @@ -127,8 +127,8 @@ CT parse_mime (char *); */ static CT get_content (FILE *, char *, int); static int add_header (CT, char *, char *); -static int get_ctinfo (char *, CT); -static int get_comment (CT, char **, int); +static int get_ctinfo (unsigned char *, CT); +static int get_comment (CT, unsigned char **, int); static int InitGeneric (CT); static int InitText (CT); static int InitMultiPart (CT); @@ -209,7 +209,8 @@ pidcheck (int status) fflush (stdout); fflush (stderr); - return done (1); + done (1); + return 1; } @@ -375,9 +376,10 @@ get_content (FILE *in, char *file, int toplevel) hp = ct->c_first_hf; /* start at first header field */ while (hp) { /* Get MIME-Version field */ - if (!strcasecmp (hp->name, VRSN_FIELD)) { + if (!mh_strcasecmp (hp->name, VRSN_FIELD)) { int ucmp; - char c, *cp, *dp; + char c; + unsigned char *cp, *dp; if (ct->c_vrsn) { advise (NULL, "message %s has multiple %s: fields", @@ -407,14 +409,14 @@ get_content (FILE *in, char *file, int toplevel) continue; c = *dp; *dp = '\0'; - ucmp = !strcasecmp (cp, VRSN_VALUE); + ucmp = !mh_strcasecmp (cp, VRSN_VALUE); *dp = c; if (!ucmp) { admonish (NULL, "message %s has unknown value for %s: field (%s)", ct->c_file, VRSN_FIELD, cp); } } - else if (!strcasecmp (hp->name, TYPE_FIELD)) { + else if (!mh_strcasecmp (hp->name, TYPE_FIELD)) { /* Get Content-Type field */ struct str2init *s2i; CI ci = &ct->c_ctinfo; @@ -435,16 +437,17 @@ get_content (FILE *in, char *file, int toplevel) * flag for this content type. */ for (s2i = str2cts; s2i->si_key; s2i++) - if (!strcasecmp (ci->ci_type, s2i->si_key)) + if (!mh_strcasecmp (ci->ci_type, s2i->si_key)) break; if (!s2i->si_key && !uprf (ci->ci_type, "X-")) s2i++; ct->c_type = s2i->si_val; ct->c_ctinitfnx = s2i->si_init; } - else if (!strcasecmp (hp->name, ENCODING_FIELD)) { + else if (!mh_strcasecmp (hp->name, ENCODING_FIELD)) { /* Get Content-Transfer-Encoding field */ - char c, *cp, *dp; + char c; + unsigned char *cp, *dp; struct str2init *s2i; /* @@ -472,7 +475,7 @@ get_content (FILE *in, char *file, int toplevel) * for this transfer encoding. */ for (s2i = str2ces; s2i->si_key; s2i++) - if (!strcasecmp (cp, s2i->si_key)) + if (!mh_strcasecmp (cp, s2i->si_key)) break; if (!s2i->si_key && !uprf (cp, "X-")) s2i++; @@ -483,9 +486,10 @@ get_content (FILE *in, char *file, int toplevel) if (s2i->si_init && (*s2i->si_init) (ct) == NOTOK) goto out; } - else if (!strcasecmp (hp->name, MD5_FIELD)) { + else if (!mh_strcasecmp (hp->name, MD5_FIELD)) { /* Get Content-MD5 field */ - char *cp, *dp, *ep; + unsigned char *cp, *dp; + char *ep; if (!checksw) goto next_header; @@ -522,11 +526,11 @@ get_content (FILE *in, char *file, int toplevel) free (ep); ct->c_digested++; } - else if (!strcasecmp (hp->name, ID_FIELD)) { + else if (!mh_strcasecmp (hp->name, ID_FIELD)) { /* Get Content-ID field */ ct->c_id = add (hp->value, ct->c_id); } - else if (!strcasecmp (hp->name, DESCR_FIELD)) { + else if (!mh_strcasecmp (hp->name, DESCR_FIELD)) { /* Get Content-Description field */ ct->c_descr = add (hp->value, ct->c_descr); } @@ -611,10 +615,11 @@ add_header (CT ct, char *name, char *value) */ static int -get_ctinfo (char *cp, CT ct) +get_ctinfo (unsigned char *cp, CT ct) { int i; - char *dp, **ap, **ep; + unsigned char *dp; + char **ap, **ep; char c; CI ci; @@ -708,7 +713,8 @@ magic_skip: */ ep = (ap = ci->ci_attrs) + NPARMS; while (*cp == ';') { - char *vp, *up; + char *vp; + unsigned char *up; if (ap >= ep) { advise (NULL, @@ -812,10 +818,11 @@ bad_quote: static int -get_comment (CT ct, char **ap, int istype) +get_comment (CT ct, unsigned char **ap, int istype) { int i; - char *bp, *cp; + char *bp; + unsigned char *cp; char c, buffer[BUFSIZ], *dp; CI ci; @@ -907,7 +914,7 @@ InitText (CT ct) /* match subtype */ for (kv = SubText; kv->kv_key; kv++) - if (!strcasecmp (ci->ci_subtype, kv->kv_key)) + if (!mh_strcasecmp (ci->ci_subtype, kv->kv_key)) break; ct->c_subtype = kv->kv_value; @@ -918,7 +925,7 @@ InitText (CT ct) /* scan for charset parameter */ for (ap = ci->ci_attrs, ep = ci->ci_values; *ap; ap++, ep++) - if (!strcasecmp (*ap, "charset")) + if (!mh_strcasecmp (*ap, "charset")) break; if (*ap) @@ -928,7 +935,7 @@ InitText (CT ct) /* match character set, or set to unknown */ for (kv = Charset; kv->kv_key; kv++) - if (!strcasecmp (chset, kv->kv_key)) + if (!mh_strcasecmp (chset, kv->kv_key)) break; t->tx_charset = kv->kv_value; @@ -956,7 +963,8 @@ InitMultiPart (CT ct) { int inout; long last, pos; - char *cp, *dp, **ap, **ep; + unsigned char *cp, *dp; + char **ap, **ep; char *bp, buffer[BUFSIZ]; struct multipart *m; struct k2v *kv; @@ -979,7 +987,7 @@ InitMultiPart (CT ct) /* match subtype */ for (kv = SubMultiPart; kv->kv_key; kv++) - if (!strcasecmp (ci->ci_subtype, kv->kv_key)) + if (!mh_strcasecmp (ci->ci_subtype, kv->kv_key)) break; ct->c_subtype = kv->kv_value; @@ -989,7 +997,7 @@ InitMultiPart (CT ct) */ bp = 0; for (ap = ci->ci_attrs, ep = ci->ci_values; *ap; ap++, ep++) { - if (!strcasecmp (*ap, "boundary")) { + if (!mh_strcasecmp (*ap, "boundary")) { bp = *ep; break; } @@ -1112,7 +1120,7 @@ last_part: char partnam[BUFSIZ]; if (ct->c_partno) { - snprintf (partnam, sizeof(partnum), "%s.", ct->c_partno); + snprintf (partnam, sizeof(partnam), "%s.", ct->c_partno); pp = partnam + strlen (partnam); } else { pp = partnam; @@ -1209,7 +1217,7 @@ InitMessage (CT ct) /* match subtype */ for (kv = SubMessage; kv->kv_key; kv++) - if (!strcasecmp (ci->ci_subtype, kv->kv_key)) + if (!mh_strcasecmp (ci->ci_subtype, kv->kv_key)) break; ct->c_subtype = kv->kv_value; @@ -1228,11 +1236,11 @@ InitMessage (CT ct) /* scan for parameters "id", "number", and "total" */ for (ap = ci->ci_attrs, ep = ci->ci_values; *ap; ap++, ep++) { - if (!strcasecmp (*ap, "id")) { + if (!mh_strcasecmp (*ap, "id")) { p->pm_partid = add (*ep, NULL); continue; } - if (!strcasecmp (*ap, "number")) { + if (!mh_strcasecmp (*ap, "number")) { if (sscanf (*ep, "%d", &p->pm_partno) != 1 || p->pm_partno < 1) { invalid_param: @@ -1244,7 +1252,7 @@ invalid_param: } continue; } - if (!strcasecmp (*ap, "total")) { + if (!mh_strcasecmp (*ap, "total")) { if (sscanf (*ep, "%d", &p->pm_maxno) != 1 || p->pm_maxno < 1) goto invalid_param; @@ -1364,12 +1372,12 @@ params_external (CT ct, int composing) CI ci = &ct->c_ctinfo; for (ap = ci->ci_attrs, ep = ci->ci_values; *ap; ap++, ep++) { - if (!strcasecmp (*ap, "access-type")) { + if (!mh_strcasecmp (*ap, "access-type")) { struct str2init *s2i; CT p = e->eb_content; for (s2i = str2methods; s2i->si_key; s2i++) - if (!strcasecmp (*ep, s2i->si_key)) + if (!mh_strcasecmp (*ep, s2i->si_key)) break; if (!s2i->si_key) { e->eb_access = *ep; @@ -1386,39 +1394,39 @@ params_external (CT ct, int composing) return NOTOK; continue; } - if (!strcasecmp (*ap, "name")) { + if (!mh_strcasecmp (*ap, "name")) { e->eb_name = *ep; continue; } - if (!strcasecmp (*ap, "permission")) { + if (!mh_strcasecmp (*ap, "permission")) { e->eb_permission = *ep; continue; } - if (!strcasecmp (*ap, "site")) { + if (!mh_strcasecmp (*ap, "site")) { e->eb_site = *ep; continue; } - if (!strcasecmp (*ap, "directory")) { + if (!mh_strcasecmp (*ap, "directory")) { e->eb_dir = *ep; continue; } - if (!strcasecmp (*ap, "mode")) { + if (!mh_strcasecmp (*ap, "mode")) { e->eb_mode = *ep; continue; } - if (!strcasecmp (*ap, "size")) { + if (!mh_strcasecmp (*ap, "size")) { sscanf (*ep, "%lu", &e->eb_size); continue; } - if (!strcasecmp (*ap, "server")) { + if (!mh_strcasecmp (*ap, "server")) { e->eb_server = *ep; continue; } - if (!strcasecmp (*ap, "subject")) { + if (!mh_strcasecmp (*ap, "subject")) { e->eb_subject = *ep; continue; } - if (composing && !strcasecmp (*ap, "body")) { + if (composing && !mh_strcasecmp (*ap, "body")) { e->eb_body = getcpy (*ep); continue; } @@ -1447,7 +1455,7 @@ InitApplication (CT ct) /* match subtype */ for (kv = SubApplication; kv->kv_key; kv++) - if (!strcasecmp (ci->ci_subtype, kv->kv_key)) + if (!mh_strcasecmp (ci->ci_subtype, kv->kv_key)) break; ct->c_subtype = kv->kv_value; @@ -1568,7 +1576,8 @@ openBase64 (CT ct, char **file) int fd, len, skip; unsigned long bits; unsigned char value, *b, *b1, *b2, *b3; - char *cp, *ep, buffer[BUFSIZ]; + unsigned char *cp, *ep; + char buffer[BUFSIZ]; /* sbeck -- handle prefixes */ CI ci; CE ce; @@ -1779,7 +1788,7 @@ static int openQuoted (CT ct, char **file) { int cc, digested, len, quoted; - char *cp, *ep; + unsigned char *cp, *ep; char buffer[BUFSIZ]; unsigned char mask; CE ce; @@ -1850,8 +1859,6 @@ openQuoted (CT ct, char **file) fseek (ct->c_fp, ct->c_begin, SEEK_SET); while (len > 0) { - char *dp; - if (fgets (buffer, sizeof(buffer) - 1, ct->c_fp) == NULL) { content_error (NULL, ct, "premature eof"); goto clean_up; @@ -1867,79 +1874,67 @@ openQuoted (CT ct, char **file) *++ep = '\n', ep++; for (; cp < ep; cp++) { - if (quoted) { - if (quoted > 1) { - if (!isxdigit (*cp)) { -invalid_hex: - dp = "expecting hexidecimal-digit"; - goto invalid_encoding; - } + if (quoted > 0) { + /* in an escape sequence */ + if (quoted == 1) { + /* at byte 1 of an escape sequence */ + mask = hex2nib[*cp & 0x7f]; + /* next is byte 2 */ + quoted = 2; + } else { + /* at byte 2 of an escape sequence */ mask <<= 4; mask |= hex2nib[*cp & 0x7f]; putc (mask, ce->ce_fp); if (digested) MD5Update (&mdContext, &mask, 1); - } else { - switch (*cp) { - case ':': - putc (*cp, ce->ce_fp); - if (digested) - MD5Update (&mdContext, (unsigned char *) ":", 1); - break; - - default: - if (!isxdigit (*cp)) - goto invalid_hex; - mask = hex2nib[*cp & 0x7f]; - quoted = 2; - continue; + if (ferror (ce->ce_fp)) { + content_error (ce->ce_file, ct, "error writing to"); + goto clean_up; } + /* finished escape sequence; next may be literal or a new + * escape sequence */ + quoted = 0; } - - if (ferror (ce->ce_fp)) { - content_error (ce->ce_file, ct, "error writing to"); - goto clean_up; - } - quoted = 0; + /* on to next byte */ continue; } - switch (*cp) { - default: - if (*cp < '!' || *cp > '~') { - int i; - dp = "expecting character in range [!..~]"; - -invalid_encoding: - i = strlen (invo_name) + 2; - content_error (NULL, ct, - "invalid QUOTED-PRINTABLE encoding -- %s,\n%*.*sbut got char 0x%x", - dp, i, i, "", *cp); - goto clean_up; - } - /* and fall...*/ - case ' ': - case '\t': - case '\n': - putc (*cp, ce->ce_fp); - if (digested) { - if (*cp == '\n') - MD5Update (&mdContext, (unsigned char *) "\r\n",2); - else - MD5Update (&mdContext, (unsigned char *) cp, 1); + /* not in an escape sequence */ + if (*cp == '=') { + /* starting an escape sequence, or invalid '='? */ + if (cp + 1 < ep && cp[1] == '\n') { + /* "=\n" soft line break, eat the \n */ + cp++; + continue; } - if (ferror (ce->ce_fp)) { - content_error (ce->ce_file, ct, "error writing to"); - goto clean_up; + if (cp + 1 >= ep || cp + 2 >= ep) { + /* We don't have 2 bytes left, so this is an invalid + * escape sequence; just show the raw bytes (below). */ + } else if (isxdigit (cp[1]) && isxdigit (cp[2])) { + /* Next 2 bytes are hex digits, making this a valid escape + * sequence; let's decode it (above). */ + quoted = 1; + continue; + } else { + /* One or both of the next 2 is out of range, making this + * an invalid escape sequence; just show the raw bytes + * (below). */ } - break; + } - case '=': - if (*++cp != '\n') { - quoted = 1; - cp--; + /* Just show the raw byte. */ + putc (*cp, ce->ce_fp); + if (digested) { + if (*cp == '\n') { + MD5Update (&mdContext, (unsigned char *) "\r\n",2); + } else { + MD5Update (&mdContext, (unsigned char *) cp, 1); } - break; + } + if (ferror (ce->ce_fp)) { + content_error (ce->ce_file, ct, "error writing to"); + goto clean_up; } } } @@ -2225,7 +2220,7 @@ openFile (CT ct, char **file) return NOTOK; } - if ((!e->eb_permission || strcasecmp (e->eb_permission, "read-write")) + if ((!e->eb_permission || mh_strcasecmp (e->eb_permission, "read-write")) && find_cache (NULL, wcachesw, &cachetype, e->eb_content->c_id, cachefile, sizeof(cachefile)) != NOTOK) { int mask; @@ -2373,7 +2368,7 @@ openFTP (CT ct, char **file) ce->ce_unlink = (*file == NULL); caching = 0; cachefile[0] = '\0'; - if ((!e->eb_permission || strcasecmp (e->eb_permission, "read-write")) + if ((!e->eb_permission || mh_strcasecmp (e->eb_permission, "read-write")) && find_cache (NULL, wcachesw, &cachetype, e->eb_content->c_id, cachefile, sizeof(cachefile)) != NOTOK) { if (*file == NULL) { @@ -2409,7 +2404,7 @@ openFTP (CT ct, char **file) vec[vecp++] = e->eb_dir; vec[vecp++] = e->eb_name; vec[vecp++] = ce->ce_file, - vec[vecp++] = e->eb_mode && !strcasecmp (e->eb_mode, "ascii") + vec[vecp++] = e->eb_mode && !mh_strcasecmp (e->eb_mode, "ascii") ? "ascii" : "binary"; vec[vecp] = NULL; @@ -2446,7 +2441,7 @@ losing_ftp: else if (ftp_get (e->eb_site, user, pass, e->eb_dir, e->eb_name, ce->ce_file, - e->eb_mode && !strcasecmp (e->eb_mode, "ascii"), 0) + e->eb_mode && !mh_strcasecmp (e->eb_mode, "ascii"), 0) == NOTOK) goto losing_ftp; #endif @@ -2675,7 +2670,7 @@ invalid_digest: while (*cp) cp++; fprintf (stderr, "invalid MD5 digest (got %d octets)\n", - cp - bp); + (int)(cp - bp)); } return NOTOK;