void content_error (char *, CT, char *, ...);
void flush_errors (void);
-/* mhlistsbr.c */
-int list_switch (CT, int, int, int, int);
-int list_content (CT, int, int, int, int);
-
/*
* prototypes
*/
static int parse_display_string (CT, char *, int *, int *, int *, int *, char *,
char *, size_t, int multipart);
static int convert_content_charset (CT, char **);
-static const char *parameter_value (CI, const char *);
static void intrser (int);
char prompt[BUFSIZ];
if (ct->c_type == CT_MULTIPART)
- list_content (ct, -1, 1, 0, 0);
+ list_content (ct, -1, 1, 0, 0, 0);
else
- list_switch (ct, -1, 1, 0, 0);
+ list_switch (ct, -1, 1, 0, 0, 0);
if (xpause && isatty (fileno (stdout))) {
int intr;
* if it is not a text part of a multipart/alternative
*/
if (!alternate || ct->c_subtype == TEXT_PLAIN) {
- snprintf (buffer, sizeof(buffer), "%%p%s '%%F'", progsw ? progsw :
+ snprintf (buffer, sizeof(buffer), "%%p%s %%F", progsw ? progsw :
moreproc && *moreproc ? moreproc : DEFAULT_PAGER);
cp = (ct->c_showproc = add (buffer, NULL));
return show_content_aux (ct, serial, alternate, cp, NULL);
if ((*p->c_ceopenfnx) (p, &file) == NOTOK)
return NOTOK;
- /* I'm not sure if this is necessary? */
p->c_storage = add (file, NULL);
if (p->c_showproc && !strcmp (p->c_showproc, "true"))
/* default method for message/rfc822 */
if (ct->c_subtype == MESSAGE_RFC822) {
- cp = (ct->c_showproc = add ("%pshow -file '%F'", NULL));
+ cp = (ct->c_showproc = add ("%pecho -file %F", NULL));
return show_content_aux (ct, serial, alternate, cp, NULL);
}
case 'a':
/* insert parameters from Content-Type field */
{
- char **ap, **ep;
+ PM pm;
char *s = "";
- 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,
+ get_param_value(pm, '?'));
len = strlen (bp);
bp += len;
buflen -= len;
for (part = m->mp_parts; part; part = part->mp_next) {
p = part->mp_part;
- /* Don't quote filename if it's already quoted. */
- if (p->c_storage && *(p->c_storage-1) == '\'') {
- /* If there isn't a matching close quote, bail
- out. */
- if (*(cp+1) != '\'') {
- adios(NULL, "%%f/%%F not properly escaped: "
- "%s%s\n",
- buffer, cp);
- }
- snprintf (bp, buflen, "%s%s", s, p->c_storage);
- } else {
- if (*(cp+1) != '\0' && *(cp+1) == '\'') {
- adios(NULL, "%%f/%%F not properly escaped: "
- "%s%s\n",
- buffer, cp);
- }
- snprintf (bp, buflen, "%s'%s'", s, p->c_storage);
- }
-
+ snprintf (bp, buflen, "%s%s", s, p->c_storage);
len = strlen (bp);
bp += len;
buflen -= len;
}
} else {
/* insert filename containing content */
- if (bp > buffer && *(bp-1) == '\'') {
- /* Don't quote filename if it's already quoted. */
- /* If there isn't a matching close quote, bail
- out. */
- if (*(cp+1) != '\'') {
- adios(NULL, "%%f/%%F not properly escaped: %s%s\n",
- buffer, cp);
- }
- snprintf (bp, buflen, "%s", file);
- } else {
- if (*(cp+1) != '\0' && *(cp+1) == '\'') {
- adios(NULL, "%%f/%%F not properly escaped: %s%s\n",
- buffer, cp);
- }
- snprintf (bp, buflen, "'%s'", file);
- }
+ snprintf (bp, buflen, "%s", file);
+ /*
+ * Old comments below are left here for posterity.
+ * This was/is tricky.
+ */
/* since we've quoted the file argument, set things up
* to look past it, to avoid problems with the quoting
* logic below. (I know, I should figure out what's
* code below.
* The fix was to always quote the filename. But
* that broke '%F' because it expanded to ''filename''.
- * That's why I added the condition above to not
- * quote if the escape was wrapped with single
- * quotes. It would be (much) better to rely on
- * the quoting code below, but until I understand
- * what is wrong with it, I won't do that.
*/
- len = strlen(bp);
- bp += len;
- buflen -= len;
+ /*
+ * Old comments above are left here for posterity.
+ * The quoting below should work properly now.
+ */
}
-
- /* set our starting pointer back to bp, to avoid
- * requoting the filenames we just added
- */
- pp = bp;
break;
case 'p':
if (closing_brace) {
const size_t param_len = closing_brace - cp - 1;
char *param = mh_xmalloc(param_len + 1);
- const char *value;
+ char *value;
(void) strncpy(param, cp + 1, param_len);
param[param_len] = '\0';
- value = parameter_value(ci, param);
+ value = get_param(ci->ci_first_pm, param, '?', 0);
free(param);
cp += param_len + 1; /* Skip both braces, too. */
/* %{param} is set in the Content-Type header.
After the break below, quote it if necessary. */
(void) strncpy(bp, value, buflen);
+ free(value);
} else {
/* %{param} not found, so skip it completely. cp
was advanced above. */
len = strlen (bp);
bp += len;
buflen -= len;
+ *bp = '\0';
/* Did we actually insert something? */
if (bp != pp) {
/* Insert single quote if not inside quotes already */
if (!quoted && buflen) {
len = strlen (pp);
- memmove (pp + 1, pp, len);
+ memmove (pp + 1, pp, len+1);
*pp++ = '\'';
buflen--;
bp++;
+ quoted = 1;
}
/* Escape existing quotes */
while ((pp = strchr (pp, '\'')) && buflen > 3) {
len = strlen (pp++);
- memmove (pp + 3, pp, len);
- *pp++ = '\\';
- *pp++ = '\'';
- *pp++ = '\'';
- buflen -= 3;
- bp += 3;
+ if (quoted) {
+ /* Quoted. Let this quote close that quoting.
+ Insert an escaped quote to replace it and
+ another quote to reopen quoting, which will be
+ closed below. */
+ memmove (pp + 2, pp, len);
+ *pp++ = '\\';
+ *pp++ = '\'';
+ buflen -= 2;
+ bp += 2;
+ quoted = 0;
+ } else {
+ /* Not quoted. This should not be reached with
+ the current code, but handle the condition
+ in case the code changes. Just escape the
+ quote. */
+ memmove (pp, pp-1, len+1);
+ *(pp++-1) = '\\';
+ buflen -= 1;
+ bp += 1;
+ }
}
/* If pp is still set, that means we ran out of space. */
if (pp)
buflen = 0;
- if (!quoted && buflen) {
- *bp++ = '\'';
- *bp = '\0';
- buflen--;
+ /* Close quoting. */
+ if (quoted && buflen) {
+ /* See if we need to close the quote by looking
+ for an odd number of unescaped close quotes in
+ the remainder of the display string. */
+ int found_quote = 0, escaped = 0;
+ char *c;
+
+ for (c = cp+1; *c; ++c) {
+ if (*c == '\\') {
+ escaped = ! escaped;
+ } else {
+ if (escaped) {
+ escaped = 0;
+ } else {
+ if (*c == '\'') {
+ found_quote = ! found_quote;
+ }
+ }
+ }
+ }
+ if (! found_quote) {
+ *bp++ = '\'';
+ buflen--;
+ quoted = 0;
+ }
}
}
} else {
raw:
*bp++ = *cp;
- *bp = '\0';
buflen--;
if (*cp == '\'')
quoted = !quoted;
}
+
+ *bp = '\0';
}
if (buflen <= 0 ||
++*message_mods;
- /* Update ci_attrs. */
- src_charset = dest_charset;
-
/* Update ct->c_ctline. */
if (ct->c_ctline) {
- char *ctline =
- update_attr (ct->c_ctline, "charset=", dest_charset);
+ char *ctline = concat(" ", ct->c_ctinfo.ci_type, "/",
+ ct->c_ctinfo.ci_subtype, NULL);
+ char *outline;
+
+ replace_param(&ct->c_ctinfo.ci_first_pm,
+ &ct->c_ctinfo.ci_last_pm, "charset",
+ dest_charset, 0);
+ outline = output_params(strlen(TYPE_FIELD) + 1 + strlen(ctline),
+ ct->c_ctinfo.ci_first_pm, NULL, 0);
+ if (outline) {
+ ctline = add(outline, ctline);
+ free(outline);
+ }
free (ct->c_ctline);
ct->c_ctline = ctline;
/* Update Content-Type header field. */
for (hf = ct->c_first_hf; hf; hf = hf->next) {
if (! strcasecmp (TYPE_FIELD, hf->name)) {
- char *ctline_less_newline =
- update_attr (hf->value, "charset=", dest_charset);
- char *ctline = concat (ctline_less_newline, "\n", NULL);
- free (ctline_less_newline);
+ char *ctline = concat (ct->c_ctline, "\n", NULL);
free (hf->value);
hf->value = ctline;
}
-/*
- * If a Content-Type parameter named param exists, returns its value.
- * Otherwise, returns NULL.
- */
-static const char *
-parameter_value (CI ci, const char *param) {
- const char *value = NULL;
- char **ap, **vp;
-
- for (ap = ci->ci_attrs, vp = ci->ci_values; *ap; ++ap, ++vp) {
- if (! strcasecmp (*ap, param)) {
- value = *vp;
- break;
- }
- }
-
- return value;
-}
-
-
static void
intrser (int i)
{