#include <h/mh.h>
#include <fcntl.h>
-#include <h/signals.h>
#include <h/md5.h>
#include <h/mts.h>
#include <h/tws.h>
enum clobber_policy_t clobber_policy; /* -clobber selection */
};
-typedef struct mhstoreinfo *mhstoreinfo_t;
+static bool use_param_as_filename(const char *p);
mhstoreinfo_t
mhstoreinfo_create (CT *ct, char *pwd, const char *csw, int asw, int vsw) {
- mhstoreinfo_t info = mh_xmalloc (sizeof *info);
+ mhstoreinfo_t info;
+ NEW(info);
info->cts = ct;
info->cwd = pwd;
info->autosw = asw;
void
mhstoreinfo_free (mhstoreinfo_t info) {
free (info->cwd);
+ free (info->dir);
free (info);
}
/* mhmisc.c */
-int part_ok (CT, int);
+int part_ok (CT);
int type_ok (CT, int);
void flush_errors (void);
-/* mhshowsbr.c */
-int show_content_aux (CT, int, int, char *, char *);
-
-/*
- * prototypes
- */
-void store_all_messages (mhstoreinfo_t);
-
/*
* static prototypes
*/
* store any contents.
*/
if ((cp = context_find (nmhstorage)) && *cp)
- info->dir = getcpy (cp);
+ info->dir = mh_xstrdup(cp);
else
info->dir = getcpy (info->cwd);
}
case CT_APPLICATION:
+ default:
return store_application (ct, info);
case CT_TEXT:
case CT_IMAGE:
case CT_VIDEO:
return store_generic (ct, info);
-
- default:
- adios (NULL, "unknown content type %d", ct->c_type);
}
return OK; /* NOT REACHED */
static int
store_application (CT ct, mhstoreinfo_t info)
{
- char **ap, **ep;
CI ci = &ct->c_ctinfo;
/* Check if the content specifies a filename */
*/
if (!ct->c_storeproc && ct->c_subtype == APPLICATION_OCTETS) {
int tarP = 0, zP = 0, gzP = 0;
+ char *cp;
- for (ap = ci->ci_attrs, ep = ci->ci_values; *ap; ap++, ep++) {
- /* check for "type=tar" attribute */
- if (!strcasecmp (*ap, "type")) {
- if (strcasecmp (*ep, "tar"))
- break;
-
+ if ((cp = get_param(ci->ci_first_pm, "type", ' ', 1))) {
+ if (strcasecmp (cp, "tar") == 0)
tarP = 1;
- continue;
- }
+ }
- /* check for "conversions=compress" attribute */
- if ((!strcasecmp (*ap, "conversions") || !strcasecmp (*ap, "x-conversions"))
- && (!strcasecmp (*ep, "compress") || !strcasecmp (*ep, "x-compress"))) {
+ /* check for "conversions=compress" attribute */
+ if ((cp = get_param(ci->ci_first_pm, "conversions", ' ', 1)) ||
+ (cp = get_param(ci->ci_first_pm, "x-conversions", ' ', 1))) {
+ if (strcasecmp (cp, "compress") == 0 ||
+ strcasecmp (cp, "x-compress") == 0) {
zP = 1;
- continue;
}
- /* check for "conversions=gzip" attribute */
- if ((!strcasecmp (*ap, "conversions") || !strcasecmp (*ap, "x-conversions"))
- && (!strcasecmp (*ep, "gzip") || !strcasecmp (*ep, "x-gzip"))) {
+ if (strcasecmp (cp, "gzip") == 0 ||
+ strcasecmp (cp, "x-gzip") == 0) {
gzP = 1;
- continue;
}
}
for (part = m->mp_parts; part; part = part->mp_next) {
CT p = part->mp_part;
- if (part_ok (p, 1) && type_ok (p, 1)) {
+ if (part_ok (p) && type_ok (p, 1)) {
if (ct->c_storage) {
/* Support mhstore -outfile. The MIME parser doesn't
load c_storage, so we know that p->c_storage is
NULL here. */
- p->c_storage = ct->c_storage;
+ p->c_storage = mh_xstrdup(ct->c_storage);
}
result = store_switch (p, info);
- p->c_storage = NULL;
if (result == OK && ct->c_subtype == MULTI_ALTERNATE)
break;
return NOTOK;
}
- if ((base = (CT *) calloc ((size_t) (i + 1), sizeof(*base))) == NULL)
- adios (NULL, "out of memory");
-
+ base = mh_xcalloc(i + 1, sizeof *base);
ctq = base;
for (ctp = info->cts; *ctp; ctp++) {
p = *ctp;
ct = *ctq++;
if (store_content (ct, NULL, info) == NOTOK) {
losing:
- free ((char *) base);
+ free(base);
return NOTOK;
}
goto losing;
}
- free ((char *) base);
+ free(base);
return OK;
}
if (info->autosw) {
char *cp;
- if ((cp = e->eb_name)
- && *cp != '/'
- && *cp != '.'
- && *cp != '|'
- && *cp != '!'
- && !strchr (cp, '%')) {
+ if ((cp = e->eb_name) && use_param_as_filename(cp)) {
if (!ct->c_storeproc)
- ct->c_storeproc = add (cp, NULL);
+ ct->c_storeproc = mh_xstrdup(cp);
if (!p->c_storeproc)
- p->c_storeproc = add (cp, NULL);
+ p->c_storeproc = mh_xstrdup(cp);
}
}
if (ct->c_storage) {
/* Support mhstore -outfile. The MIME parser doesn't load
c_storage, so we know that p->c_storage is NULL here. */
- p->c_storage = ct->c_storage;
+ p->c_storage = mh_xstrdup(ct->c_storage);
}
result = store_switch (p, info);
- p->c_storage = NULL;
p->c_partno = NULL;
return result;
/* record the folder name */
if (p->c_folder) {
- ct->c_folder = add (p->c_folder, NULL);
+ ct->c_folder = mh_xstrdup(p->c_folder);
}
}
goto got_filename;
if ((cp = ct->c_storeproc) == NULL || *cp == '\0') {
CI ci = &ct->c_ctinfo;
- snprintf (buffer, sizeof(buffer), "%s-store-%s/%s",
- invo_name, ci->ci_type, ci->ci_subtype);
- if ((cp = context_find (buffer)) == NULL || *cp == '\0') {
- snprintf (buffer, sizeof(buffer), "%s-store-%s", invo_name, ci->ci_type);
- if ((cp = context_find (buffer)) == NULL || *cp == '\0') {
- cp = ct->c_type == CT_MESSAGE ? "+" : "%m%P.%s";
- }
+ cp = context_find_by_type ("store", ci->ci_type, ci->ci_subtype);
+ if (cp == NULL) {
+ cp = ct->c_type == CT_MESSAGE ? "+" : "%m%P.%s";
}
}
adios(NULL, "unable to create temporary file in %s",
get_temp_dir());
}
- ct->c_storage = add (tmpfilenam, NULL);
+ ct->c_storage = mh_xstrdup(tmpfilenam);
/* Get the folder name */
if (cp[1])
* content to standard input of a command and return.
*/
if (buffer[0] == '|' || buffer[0] == '!')
- return show_content_aux (ct, 1, 0, buffer + 1, info->dir);
+ return show_content_aux (ct, 0, buffer + 1, info->dir, NULL);
/* record the filename */
- if ((ct->c_storage = clobber_check (add (buffer, NULL), info)) ==
+ if ((ct->c_storage = clobber_check (mh_xstrdup(buffer), info)) ==
NULL) {
return NOTOK;
}
} else {
/* The output filename was explicitly specified, so use it. */
- if ((ct->c_storage = clobber_check (add (ct->c_storage, NULL), info)) ==
+ if ((ct->c_storage = clobber_check (ct->c_storage, info)) ==
NULL) {
return NOTOK;
}
if (first_partial)
fprintf (stderr, "reassembling partials ");
if (last_partial)
- fprintf (stderr, "%s", ct->c_file);
+ fputs(ct->c_file, stderr);
else
fprintf (stderr, "%s,", ct->c_file);
} else {
int cwdlen = strlen (info->cwd);
fprintf (stderr, " as file %s\n",
- strncmp (ct->c_storage, info->cwd, cwdlen)
+ !has_prefix(ct->c_storage, info->cwd)
|| ct->c_storage[cwdlen] != '/'
? ct->c_storage : ct->c_storage + cwdlen + 1);
}
break;
default:
- fwrite (buffer, sizeof(*buffer), cc, fp);
+ if ((int) fwrite (buffer, sizeof(*buffer), cc, fp) < cc) {
+ advise ("output_content_file", "fwrite");
+ }
continue;
}
break;
}
}
- while (fgets (buffer, sizeof(buffer) - 1, ct->c_fp)) {
+ while (fgets (buffer, sizeof buffer, ct->c_fp)) {
if ((pos += strlen (buffer)) > last) {
int diff;
/* Read the folder. */
if ((mp = folder_read (folder, 0))) {
/* Link file into folder */
- msgnum = folder_addmsg (&mp, filename, 0, 0, 0, 0, (char *)0);
+ msgnum = folder_addmsg (&mp, filename, 0, 0, 0, 0, NULL);
} else {
advise (NULL, "unable to read folder %s", folder);
return NOTOK;
buflen--;
continue;
} else {
- 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;
static void
get_storeproc (CT ct)
{
- char **ap, **ep, *cp;
+ char *cp;
CI ci;
/*
* use that (RFC-2183).
*/
if (ct->c_dispo) {
- char *cp = strchr (ct->c_dispo, ';');
- CI ci = calloc (1, sizeof *ci);
- int status;
- int found_filename = 0;
-
- if (cp && parse_header_attrs (ct->c_file, strlen (invo_name) + 2, &cp,
- ci, &status) == OK) {
- for (ap = ci->ci_attrs, ep = ci->ci_values; *ap; ap++, ep++) {
- if (! strcasecmp (*ap, "filename")
- && *(cp = *ep) != '/'
- && *cp != '.'
- && *cp != '|'
- && *cp != '!'
- && !strchr (cp, '%')) {
- ct->c_storeproc = add (cp, NULL);
- found_filename = 1;
- }
- free (*ap);
- }
+ if ((cp = get_param(ct->c_dispo_first, "filename", '_', 0)) &&
+ use_param_as_filename(cp)) {
+ ct->c_storeproc = mh_xstrdup(cp);
+ free(cp);
+ return;
}
-
- free (ci);
- if (found_filename) return;
+ mh_xfree(cp);
}
/*
* the storeproc.
*/
ci = &ct->c_ctinfo;
- for (ap = ci->ci_attrs, ep = ci->ci_values; *ap; ap++, ep++) {
- if (! strcasecmp (*ap, "name")
- && *(cp = *ep) != '/'
- && *cp != '.'
- && *cp != '|'
- && *cp != '!'
- && !strchr (cp, '%')) {
- ct->c_storeproc = add (cp, NULL);
- return;
- }
+ if ((cp = get_param(ci->ci_first_pm, "name", '_', 0)) &&
+ use_param_as_filename(cp)) {
+ ct->c_storeproc = mh_xstrdup(cp);
+
}
+ mh_xfree(cp);
}
enum clobber_policy_t
clobber_policy (const char *value) {
if (value == NULL || ! strcasecmp (value, "always")) {
- } else if (! strcasecmp (value, "auto")) {
+ return NMH_CLOBBER_ALWAYS;
+ }
+ if (! strcasecmp (value, "auto")) {
return NMH_CLOBBER_AUTO;
- } else if (! strcasecmp (value, "suffix")) {
+ }
+ if (! strcasecmp (value, "suffix")) {
return NMH_CLOBBER_SUFFIX;
- } else if (! strcasecmp (value, "ask")) {
+ }
+ if (! strcasecmp (value, "ask")) {
return NMH_CLOBBER_ASK;
- } else if (! strcasecmp (value, "never")) {
+ }
+ if (! strcasecmp (value, "never")) {
return NMH_CLOBBER_NEVER;
- } else {
- adios (NULL, "invalid argument, %s, to clobber", value);
}
- return NMH_CLOBBER_ALWAYS;
+ adios (NULL, "invalid argument, %s, to clobber", value);
}
char *cwd = NULL;
int check_again;
+ if (! strcmp (original_file, "-")) {
+ return original_file;
+ }
+
if (info->clobber_policy == NMH_CLOBBER_ASK) {
/* Save cwd for possible use in loop below. */
char *slash;
- cwd = add (original_file, NULL);
+ cwd = mh_xstrdup(original_file);
slash = strrchr (cwd, '/');
if (slash) {
*slash = '\0';
} else {
- /* original_file wasn't a full path, which shouldn't happen. */
+ /* original_file isn't a full path, which should only happen if
+ it is -. */
+ free (cwd);
cwd = NULL;
}
}
if (isatty (fileno (stdin))) {
char *prompt =
concat ("Overwrite \"", file, "\" [y/n/rename]? ", NULL);
- ans = getans (prompt, answer);
+ ans = read_switch_multiword (prompt, answer);
free (prompt);
} else {
/* Overwrite, that's what nmh used to do. And warn. */
file = NULL;
++info->files_not_clobbered;
} else {
- char *newline = strchr (buf, '\n');
- if (newline) {
- *newline = '\0';
- }
+ trim_suffix_c(buf, '\n');
}
free (file);
if (buf[0] == '/') {
/* Full path, use it. */
- file = add (buf, NULL);
+ file = mh_xstrdup(buf);
} else {
/* Relative path. */
- file = cwd ? concat (cwd, "/", buf, NULL) : add (buf, NULL);
+ file = cwd ? concat (cwd, "/", buf, NULL) : mh_xstrdup(buf);
}
check_again = 1;
original_file = file;
} while (check_again);
- if (cwd) {
- free (cwd);
- }
+ free (cwd);
return file;
}
+static bool use_param_as_filename(const char *p)
+{
+ /* Preserve result of original test that considered an empty string
+ * OK. */
+ return !*p || (!strchr("/.|!", *p) && !strchr(p, '%'));
+}
+
/* -clobber support */
/******************************************************************************/