X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/ea61b6fbcec3d7109dcbd8c74848d1a4aff1fe57..dee554266d7247f6c9d4ddd77aa8173e5111e428:/uip/mhparse.c diff --git a/uip/mhparse.c b/uip/mhparse.c index 0d8bf41f..75414667 100644 --- a/uip/mhparse.c +++ b/uip/mhparse.c @@ -23,8 +23,6 @@ extern int debugsw; -extern pid_t xpid; /* mhshowsbr.c */ - /* cache policies */ extern int rcachesw; /* mhcachesbr.c */ extern int wcachesw; /* mhcachesbr.c */ @@ -183,19 +181,6 @@ struct str2init str2methods[] = { }; -int -pidcheck (int status) -{ - if ((status & 0xff00) == 0xff00 || (status & 0x007f) != SIGQUIT) - return status; - - fflush (stdout); - fflush (stderr); - done (1); - return 1; -} - - /* * Main entry point for parsing a MIME message or file. * It returns the Content structure for the top level @@ -209,6 +194,7 @@ parse_mime (char *file) char buffer[BUFSIZ]; FILE *fp; CT ct; + size_t n; /* * Check if file is actually standard input @@ -222,8 +208,13 @@ parse_mime (char *file) } file = add (tfile, NULL); - while (fgets (buffer, sizeof(buffer), stdin)) - fputs (buffer, fp); + while ((n = fread(buffer, 1, sizeof(buffer), stdin)) > 0) { + if (fwrite(buffer, 1, n, fp) != n) { + (void) m_unlink (file); + advise (file, "error copying to temporary file"); + return NULL; + } + } fflush (fp); if (ferror (stdin)) { @@ -838,7 +829,7 @@ magic_skip: if (ct->c_dispo_type && !get_param(ct->c_dispo_first, "filename", '_', 1)) { add_param(&ct->c_dispo_first, &ct->c_dispo_last, "filename", - r1bindex(ci->ci_magic, '/')); + r1bindex(ci->ci_magic, '/'), 0); } } else @@ -1072,7 +1063,10 @@ InitMultiPart (CT ct) long last, pos; char *cp, *dp; PM pm; - char *bp, buffer[BUFSIZ]; + char *bp; + char *bufp = NULL; + size_t buflen; + ssize_t gotlen; struct multipart *m; struct k2v *kv; struct part *part, **next; @@ -1166,15 +1160,15 @@ InitMultiPart (CT ct) part = NULL; inout = 1; - while (fgets (buffer, sizeof(buffer) - 1, fp)) { + while ((gotlen = getline(&bufp, &buflen, fp)) != -1) { if (pos > last) break; - pos += strlen (buffer); - if (buffer[0] != '-' || buffer[1] != '-') + pos += gotlen; + if (bufp[0] != '-' || bufp[1] != '-') continue; if (inout) { - if (strcmp (buffer + 2, m->mp_start)) + if (strcmp (bufp + 2, m->mp_start)) continue; next_part: if ((part = (struct part *) calloc (1, sizeof(*part))) == NULL) @@ -1184,6 +1178,8 @@ next_part: if (!(p = get_content (fp, ct->c_file, ct->c_subtype == MULTI_DIGEST ? -1 : 0))) { + free(bufp); + fclose (ct->c_fp); ct->c_fp = NULL; return NOTOK; } @@ -1193,18 +1189,18 @@ next_part: fseek (fp, pos, SEEK_SET); inout = 0; } else { - if (strcmp (buffer + 2, m->mp_start) == 0) { + if (strcmp (bufp + 2, m->mp_start) == 0) { inout = 1; end_part: p = part->mp_part; - p->c_end = ftell(fp) - (strlen(buffer) + 1); + p->c_end = ftell(fp) - (gotlen + 1); if (p->c_end < p->c_begin) p->c_begin = p->c_end; if (inout) goto next_part; goto last_part; } else { - if (strcmp (buffer + 2, m->mp_stop) == 0) + if (strcmp (bufp + 2, m->mp_stop) == 0) goto end_part; } } @@ -1259,6 +1255,7 @@ last_part: /* initialize the content of the subparts */ if (p->c_ctinitfnx && (*p->c_ctinitfnx) (p) == NOTOK) { + free(bufp); fclose (ct->c_fp); ct->c_fp = NULL; return NOTOK; @@ -1269,6 +1266,7 @@ last_part: get_leftover_mp_content (ct, 1); get_leftover_mp_content (ct, 0); + free(bufp); fclose (ct->c_fp); ct->c_fp = NULL; return OK; @@ -1713,15 +1711,7 @@ openBase64 (CT ct, char **file) /* sbeck@cise.ufl.edu -- handle suffixes */ ci = &ct->c_ctinfo; - snprintf (buffer, sizeof(buffer), "%s-suffix-%s/%s", - invo_name, ci->ci_type, ci->ci_subtype); - cp = context_find (buffer); - if (cp == NULL || *cp == '\0') { - snprintf (buffer, sizeof(buffer), "%s-suffix-%s", invo_name, - ci->ci_type); - cp = context_find (buffer); - } - if (cp != NULL && *cp != '\0') { + if ((cp = context_find_by_type ("suffix", ci->ci_type, ci->ci_subtype))) { if (ce->ce_unlink) { /* Create temporary file with filename extension. */ if ((ce->ce_file = m_mktemps(invo_name, cp, NULL, NULL)) == NULL) { @@ -1923,7 +1913,9 @@ openQuoted (CT ct, char **file) { int cc, digested, len, quoted, own_ct_fp = 0; char *cp, *ep; - char buffer[BUFSIZ]; + char *bufp = NULL; + size_t buflen; + ssize_t gotlen; unsigned char mask; CE ce = &ct->c_cefile; /* sbeck -- handle suffixes */ @@ -1952,15 +1944,7 @@ openQuoted (CT ct, char **file) /* sbeck@cise.ufl.edu -- handle suffixes */ ci = &ct->c_ctinfo; - snprintf (buffer, sizeof(buffer), "%s-suffix-%s/%s", - invo_name, ci->ci_type, ci->ci_subtype); - cp = context_find (buffer); - if (cp == NULL || *cp == '\0') { - snprintf (buffer, sizeof(buffer), "%s-suffix-%s", invo_name, - ci->ci_type); - cp = context_find (buffer); - } - if (cp != NULL && *cp != '\0') { + if ((cp = context_find_by_type ("suffix", ci->ci_type, ci->ci_subtype))) { if (ce->ce_unlink) { /* Create temporary file with filename extension. */ if ((ce->ce_file = m_mktemps(invo_name, cp, NULL, NULL)) == NULL) { @@ -2005,16 +1989,16 @@ openQuoted (CT ct, char **file) fseek (ct->c_fp, ct->c_begin, SEEK_SET); while (len > 0) { - if (fgets (buffer, sizeof(buffer) - 1, ct->c_fp) == NULL) { + if ((gotlen = getline(&bufp, &buflen, ct->c_fp)) == -1) { content_error (NULL, ct, "premature eof"); goto clean_up; } - if ((cc = strlen (buffer)) > len) + if ((cc = gotlen) > len) cc = len; len -= cc; - for (ep = (cp = buffer) + cc - 1; cp <= ep; ep--) + for (ep = (cp = bufp) + cc - 1; cp <= ep; ep--) if (!isspace ((unsigned char) *ep)) break; *++ep = '\n', ep++; @@ -2178,15 +2162,7 @@ open7Bit (CT ct, char **file) /* sbeck@cise.ufl.edu -- handle suffixes */ ci = &ct->c_ctinfo; - snprintf (buffer, sizeof(buffer), "%s-suffix-%s/%s", - invo_name, ci->ci_type, ci->ci_subtype); - cp = context_find (buffer); - if (cp == NULL || *cp == '\0') { - snprintf (buffer, sizeof(buffer), "%s-suffix-%s", invo_name, - ci->ci_type); - cp = context_find (buffer); - } - if (cp != NULL && *cp != '\0') { + if ((cp = context_find_by_type ("suffix", ci->ci_type, ci->ci_subtype))) { if (ce->ce_unlink) { /* Create temporary file with filename extension. */ if ((ce->ce_file = m_mktemps(invo_name, cp, NULL, NULL)) == NULL) { @@ -2478,13 +2454,6 @@ openFTP (CT ct, char **file) return NOTOK; } - if (xpid) { - if (xpid < 0) - xpid = -xpid; - pidcheck (pidwait (xpid, NOTOK)); - xpid = 0; - } - /* Get the buffer ready to go */ bp = buffer; buflen = sizeof(buffer); @@ -2684,13 +2653,6 @@ openMail (CT ct, char **file) return NOTOK; } - if (xpid) { - if (xpid < 0) - xpid = -xpid; - pidcheck (pidwait (xpid, NOTOK)); - xpid = 0; - } - /* Get buffer ready to go */ bp = buffer; buflen = sizeof(buffer); @@ -2821,13 +2783,6 @@ openURL (CT ct, char **file) return NOTOK; } - if (xpid) { - if (xpid < 0) - xpid = -xpid; - pidcheck (pidwait (xpid, NOTOK)); - xpid = 0; - } - ce->ce_unlink = (*file == NULL); caching = 0; cachefile[0] = '\0'; @@ -2996,12 +2951,15 @@ invalid_digest: after the last subpart that hasn't been stored anywhere else, so do that. */ int -get_leftover_mp_content (CT ct, int before /* or after */) { +get_leftover_mp_content (CT ct, int before /* or after */) +{ struct multipart *m = (struct multipart *) ct->c_ctparams; char *boundary; int found_boundary = 0; - char buffer[BUFSIZ]; int max = BUFSIZ; + char *bufp = NULL; + size_t buflen; + ssize_t gotlen; int read = 0; char *content = NULL; @@ -3034,18 +2992,18 @@ get_leftover_mp_content (CT ct, int before /* or after */) { } /* Back up by 1 to pick up the newline. */ - while (fgets (buffer, sizeof(buffer) - 1, ct->c_fp)) { - read += strlen (buffer); + while ((gotlen = getline(&bufp, &buflen, ct->c_fp)) != -1) { + read += gotlen; /* Don't look beyond beginning of first subpart (before) or next part (after). */ - if (read > max) buffer[read-max] = '\0'; + if (read > max) bufp[read-max] = '\0'; if (before) { - if (! strcmp (buffer, boundary)) { + if (! strcmp (bufp, boundary)) { found_boundary = 1; } } else { - if (! found_boundary && ! strcmp (buffer, boundary)) { + if (! found_boundary && ! strcmp (bufp, boundary)) { found_boundary = 1; continue; } @@ -3054,12 +3012,12 @@ get_leftover_mp_content (CT ct, int before /* or after */) { if ((before && ! found_boundary) || (! before && found_boundary)) { if (content) { char *old_content = content; - content = concat (content, buffer, NULL); + content = concat (content, bufp, NULL); free (old_content); } else { content = before - ? concat ("\n", buffer, NULL) - : concat (buffer, NULL); + ? concat ("\n", bufp, NULL) + : concat (bufp, NULL); } } @@ -3093,6 +3051,7 @@ get_leftover_mp_content (CT ct, int before /* or after */) { } free (boundary); + free (bufp); return OK; } @@ -3414,7 +3373,7 @@ parse_header_attrs (const char *filename, const char *fieldname, * length so we can allocate the correct buffer size. */ - for (len = 0; istoken(*vp); vp++) { + for (vp = dp, len = 0; istoken(*vp); vp++) { if (*vp == '%') { if (*(vp + 1) == '\0' || !isxdigit((unsigned char) *(vp + 1)) || @@ -3590,9 +3549,7 @@ bad_quote: pp->lang = lang; } } else { - pm = add_param(param_head, param_tail, nameptr, valptr); - free(nameptr); - free(valptr); + pm = add_param(param_head, param_tail, nameptr, valptr, 1); pm->pm_charset = charset; pm->pm_lang = lang; } @@ -3637,11 +3594,9 @@ bad_quote: p[tlen] = '\0'; - pm = add_param(param_head, param_tail, pp->name, p); + pm = add_param(param_head, param_tail, pp->name, p, 1); pm->pm_charset = pp->charset; pm->pm_lang = pp->lang; - free(pp->name); - free(p); pp2 = pp->next; free(pp); pp = pp2; @@ -3651,6 +3606,25 @@ bad_quote: return OK; } +/* + * Return the charset for a particular content type. Return pointer is + * only valid until the next call to content_charset(). + */ + +char * +content_charset (CT ct) { + static char *ret_charset = NULL; + + if (ret_charset != NULL) { + free(ret_charset); + } + + ret_charset = get_param(ct->c_ctinfo.ci_first_pm, "charset", '?', 0); + + return ret_charset ? ret_charset : "US-ASCII"; +} + + /* * Create a string based on a list of output parameters. Assume that this * parameter string will be appended to an existing header, so start out @@ -3877,8 +3851,12 @@ param_len(PM pm, int index, size_t valueoff, int *encode, int *cont, * add them now. */ - if (! pm->pm_charset) + if (! pm->pm_charset) { pm->pm_charset = getcpy(write_charset_8bit()); + if (strcasecmp(pm->pm_charset, "US-ASCII") == 0) + adios(NULL, "8-bit characters in parameter \"%s\", but " + "local character set is US-ASCII", pm->pm_name); + } if (! pm->pm_lang) pm->pm_lang = getcpy(NULL); /* Default to a blank lang tag */ @@ -4058,14 +4036,14 @@ normal_param(PM pm, char *output, size_t len, size_t valuelen, */ PM -add_param(PM *first, PM *last, const char *name, const char *value) +add_param(PM *first, PM *last, char *name, char *value, int nocopy) { PM pm = mh_xmalloc(sizeof(*pm)); memset(pm, 0, sizeof(*pm)); - pm->pm_name = getcpy(name); - pm->pm_value = getcpy(value); + pm->pm_name = nocopy ? name : getcpy(name); + pm->pm_value = nocopy ? value : getcpy(value); if (*first) { (*last)->pm_next = pm; @@ -4078,6 +4056,33 @@ add_param(PM *first, PM *last, const char *name, const char *value) return pm; } +/* + * Either replace a current parameter with a new value, or add the parameter + * to the parameter linked list. + */ + +PM +replace_param(PM *first, PM *last, char *name, char *value, int nocopy) +{ + PM pm; + + for (pm = *first; pm != NULL; pm = pm->pm_next) { + if (strcasecmp(name, pm->pm_name) == 0) { + /* + * If nocopy is set, it's assumed that we own both name + * and value. We don't need name, so we discard it now. + */ + if (nocopy) + free(name); + free(pm->pm_value); + pm->pm_value = nocopy ? value : getcpy(value); + return pm; + } + } + + return add_param(first, last, name, value, nocopy); +} + /* * Retrieve a parameter value from a parameter linked list. If the parameter * value needs converted to the local character set, do that now. @@ -4113,7 +4118,10 @@ char *get_param_value(PM pm, char replace) int utf8; iconv_t cd; ICONV_CONST char *p; +#else /* HAVE_ICONV */ + char *p; #endif /* HAVE_ICONV */ + char *q; /* @@ -4188,9 +4196,10 @@ char *get_param_value(PM pm, char replace) *q = '\0'; return buffer; -#endif /* HAVE_ICONV */ noiconv: +#endif /* HAVE_ICONV */ + /* * Take everything non-ASCII and substituite the replacement character */