.B mhstore
will store the contents of the named messages in
\*(lqnative\*(rq (decoded) format. Two things must be determined:
-the directory to store the content, and the filenames. Files are
+the directory to store the content, and the filenames.
+.PP
+By default (or if the
+.B \-auto
+switch is given),
+.B mhstore
+uses filename information, contained in the message, if available.
+(This information should be specified
+as the attribute \*(lqname=filename\*(rq in the \*(lqContent-Type\*(rq header
+for the content you are storing.)
+Only the basename of this filename is considered.
+If it begins with the character '.', '|', or '!',
+or if it contains the character '%', automatic naming won't happen for
+security reasons. (See below for the fall-back.)
+.PP
+Files are
written in the directory given by the \*(lqnmh-storage\*(rq profile
entry, e.g.,
.PP
nmh-storage: /tmp
.RE
.PP
+(Note that \*(lqnmh-storage\*(rq is relative to the folder that contains
+the message.)
If this entry isn't present,
the current working directory is used.
-.PP
-By default (or if the
-.B \-auto
-switch is given), then
-.B mhstore
-will check if
-the message contains information indicating the filename that should
-be used to store the content. This information should be specified
-as the attribute \*(lqname=filename\*(rq in the \*(lqContent-Type\*(rq header
-for the content you are storing. For security reasons, this filename
-will be ignored if it begins with the character '/', '.', '|', or '!',
-or if it contains the character '%'. Now that tar files are not extracted
-automatically anymore, having
-.B \-auto
-as the default is quite safe.
-Attachments are only stored below the current (or the storage)
-directory. In the worst case, existing files there will be overwritten.
+Attachments will get stored in either the `nmh-storage' or the current working
+directory \(en in no case elsewhere.
+Existing files get silently overwritten.
.PP
If the
-.B \-auto
-switch is not given (or is being ignored for security
-reasons) then
+.B \-noauto
+switch is given (or a filename is being ignored for security reasons) then
.B mhstore
will look in the user's profile for a
\*(lqformatting string\*(rq to determine how the different contents
solely of a \*(lq+\*(rq character is interpreted to be the current
folder.
.PP
-If the formatting string consists solely of a \*(lq-\*(rq character,
+If the formatting string consists solely of a \*(lq\-\*(rq character,
then the content is sent to the standard output.
.PP
If the formatting string starts with a '|', then the display string
Otherwise the formatting string will represent a pathname in which
to store the content. If the formatting string starts with a '/',
then the content will be stored in the full path given, else the
-file name will be relative to the value of \*(lqnmh-storage\*(rq or
-the current working directory. Any escapes (given below) will be
-expanded, except for the a-escape. Note that if \*(lqnmh-storage\*(rq
-is not an absolute path, it will be relative to the folder that
-contains the message(s).
+file name will be relative to either the value of \*(lqnmh-storage\*(rq,
+if set, or the current working directory.
+Existing files get silently overwritten.
.PP
A command or pathname formatting string may contain the following
escapes. If the content isn't part of a multipart (of any subtype
.SH BUGS
Partial messages contained within a multipart content are not reassembled.
+.PP
+Existing files get silently overwritten.
static int
store_generic(CT ct)
{
- char **ap, **ep, *cp;
+ char **ap, **vp, *cp;
CI ci = &ct->c_ctinfo;
/*
if (autosw && ct->c_type != CT_MESSAGE && !ct->c_storeproc) {
/*
** Check the attribute/value pairs, for the attribute "name".
- ** If found, do a few sanity checks and copy the value into
- ** the storeproc.
+ ** If found, take the basename, do a few sanity checks and
+ ** copy the value into c_storeproc.
*/
- for (ap = ci->ci_attrs, ep = ci->ci_values; *ap; ap++, ep++) {
- if (mh_strcasecmp(*ap, "name")==0 &&
- *(cp = *ep) != '/' && *cp != '.' &&
- *cp != '|' && *cp != '!' &&
+ for (ap = ci->ci_attrs, vp = ci->ci_values; *ap; ap++,vp++) {
+ if (mh_strcasecmp(*ap, "name")!=0) {
+ continue;
+ }
+ cp = mhbasename(*vp);
+ if (*cp && *cp!='.' && *cp!='|' && *cp!='!' &&
!strchr(cp, '%')) {
+ /* filename looks good: use it */
ct->c_storeproc = getcpy(cp);
- break;
}
+ break;
}
}
if (autosw) {
char *cp;
- if ((cp = e->eb_name) && *cp != '/' && *cp != '.' &&
- *cp != '|' && *cp != '!' && !strchr(cp, '%')) {
+ cp = mhbasename(e->eb_name);
+ if (*cp && *cp!='.' && *cp!='|' && *cp!='!' &&
+ !strchr(cp, '%')) {
+ /* filename looks good: use it */
if (!ct->c_storeproc)
ct->c_storeproc = getcpy(cp);
if (!p->c_storeproc)
FILE *fp;
/*
- ** If the pathname is absolute, make sure
- ** all the relevant directories exist.
+ ** If the pathname contains directories, make sure
+ ** all of them exist.
*/
if (strchr(ct->c_storage, '/') && make_intermediates(ct->c_storage)
== NOTOK)