/*
- * mhstoresbr.c -- routines to save/store the contents of MIME messages
- *
- * This code is Copyright (c) 2002, by the authors of nmh. See the
- * COPYRIGHT file in the root directory of the nmh distribution for
- * complete copyright information.
- */
+** mhstoresbr.c -- routines to save/store the contents of MIME messages
+**
+** This code is Copyright (c) 2002, by the authors of nmh. See the
+** COPYRIGHT file in the root directory of the nmh distribution for
+** complete copyright information.
+*/
#include <h/mh.h>
#include <fcntl.h>
/*
- * The list of top-level contents to display
- */
+** The list of top-level contents to display
+*/
extern CT *cts;
int autosw = 0;
/*
- * Cache of current directory. This must be
- * set before these routines are called.
- */
+** Cache of current directory. This must be
+** set before these routines are called.
+*/
char *cwd;
/*
- * The directory in which to store the contents.
- */
+** The directory in which to store the contents.
+*/
static char *dir;
/*
- * Type for a compare function for qsort. This keeps
- * the compiler happy.
- */
+** Type for a compare function for qsort. This keeps
+** the compiler happy.
+*/
typedef int (*qsort_comp) (const void *, const void *);
int show_content_aux (CT, int, int, char *, char *);
/*
- * prototypes
- */
+** prototypes
+*/
void store_all_messages (CT *);
/*
- * static prototypes
- */
+** static prototypes
+*/
static void store_single_message (CT);
static int store_switch (CT);
static int store_generic (CT);
/*
- * Main entry point to store content
- * from a collection of messages.
- */
+** Main entry point to store content
+** from a collection of messages.
+*/
void
store_all_messages (CT *cts)
char *cp;
/*
- * Check for the directory in which to
- * store any contents.
- */
+ ** Check for the directory in which to
+ ** store any contents.
+ */
if (autosw)
dir = getcpy (cwd);
else if ((cp = context_find (nmhstorage)) && *cp)
/*
- * Entry point to store the content
- * in a (single) message
- */
+** Entry point to store the content
+** in a (single) message
+*/
static void
store_single_message (CT ct)
/*
- * Switching routine to store different content types
- */
+** Switching routine to store different content types
+*/
static int
store_switch (CT ct)
/*
- * Generic routine to store a MIME content.
- * (audio, video, image, text, message/rfc922)
- */
+** Generic routine to store a MIME content.
+** (audio, video, image, text, message/rfc922)
+*/
static int
store_generic (CT ct)
{
/*
- * Check if the content specifies a filename.
- * Don't bother with this for type "message"
- * (only "message/rfc822" will use store_generic).
- */
+ ** Check if the content specifies a filename.
+ ** Don't bother with this for type "message"
+ ** (only "message/rfc822" will use store_generic).
+ */
if (autosw && ct->c_type != CT_MESSAGE)
get_storeproc (ct);
/*
- * Store content of type "application"
- */
+** Store content of type "application"
+*/
static int
store_application (CT ct)
get_storeproc (ct);
/*
- * If storeproc is not defined, and the content is type
- * "application/octet-stream", we also check for various
- * attribute/value pairs which specify if this a tar file.
- */
+ ** If storeproc is not defined, and the content is type
+ ** "application/octet-stream", we also check for various
+ ** attribute/value pairs which specify if this a tar file.
+ */
if (!ct->c_storeproc && ct->c_subtype == APPLICATION_OCTETS) {
int tarP = 0, zP = 0, gzP = 0;
}
/* check for "conversions=compress" attribute */
- if ((!mh_strcasecmp (*ap, "conversions") || !mh_strcasecmp (*ap, "x-conversions"))
- && (!mh_strcasecmp (*ep, "compress") || !mh_strcasecmp (*ep, "x-compress"))) {
+ if ((!mh_strcasecmp (*ap, "conversions") ||
+ !mh_strcasecmp (*ap, "x-conversions"))
+ && (!mh_strcasecmp (*ep, "compress") ||
+ !mh_strcasecmp (*ep, "x-compress"))) {
zP = 1;
continue;
}
/* check for "conversions=gzip" attribute */
- if ((!mh_strcasecmp (*ap, "conversions") || !mh_strcasecmp (*ap, "x-conversions"))
- && (!mh_strcasecmp (*ep, "gzip") || !mh_strcasecmp (*ep, "x-gzip"))) {
+ if ((!mh_strcasecmp (*ap, "conversions") ||
+ !mh_strcasecmp (*ap, "x-conversions"))
+ && (!mh_strcasecmp (*ep, "gzip") ||
+ !mh_strcasecmp (*ep, "x-gzip"))) {
gzP = 1;
continue;
}
}
if (tarP) {
- ct->c_showproc = add (zP ? "%euncompress | tar tvf -"
- : (gzP ? "%egzip -dc | tar tvf -"
- : "%etar tvf -"), NULL);
+ ct->c_showproc = add (zP ? "%euncompress | tar tvf -" : (gzP ? "%egzip -dc | tar tvf -" : "%etar tvf -"), NULL);
if (!ct->c_storeproc) {
if (autosw) {
- ct->c_storeproc = add (zP ? "| uncompress | tar xvpf -"
- : (gzP ? "| gzip -dc | tar xvpf -"
- : "| tar xvpf -"), NULL);
+ ct->c_storeproc = add (zP ? "| uncompress | tar xvpf -" : (gzP ? "| gzip -dc | tar xvpf -" : "| tar xvpf -"), NULL);
ct->c_umask = 0022;
} else {
- ct->c_storeproc= add (zP ? "%m%P.tar.Z"
- : (gzP ? "%m%P.tar.gz"
- : "%m%P.tar"), NULL);
+ ct->c_storeproc= add (zP ? "%m%P.tar.Z" : (gzP ? "%m%P.tar.gz" : "%m%P.tar"), NULL);
}
}
}
/*
- * Store the content of a multipart message
- */
+** Store the content of a multipart message
+*/
static int
store_multi (CT ct)
/*
- * Reassemble and store the contents of a collection
- * of messages of type "message/partial".
- */
+** Reassemble and store the contents of a collection
+** of messages of type "message/partial".
+*/
static int
store_partial (CT ct)
pm = (struct partial *) p->c_ctparams;
if (pm->pm_marked != cur) {
if (pm->pm_marked == cur - 1) {
- admonish (NULL,
- "duplicate part %d of %d part multipart message",
- pm->pm_marked, hi);
+ admonish (NULL, "duplicate part %d of %d part multipart message", pm->pm_marked, hi);
continue;
}
missing_part:
- advise (NULL,
- "missing %spart %d of %d part multipart message",
- cur != hi ? "(at least) " : "", cur, hi);
+ advise (NULL, "missing %spart %d of %d part multipart message", cur != hi ? "(at least) " : "", cur, hi);
goto losing;
} else
cur++;
}
/*
- * Now cycle through the sorted list of messages of type
- * "message/partial" and save/append them to a file.
- */
+ ** Now cycle through the sorted list of messages of type
+ ** "message/partial" and save/append them to a file.
+ */
ctq = base;
ct = *ctq++;
/*
- * Store content from a message of type "message/external".
- */
+** Store content from a message of type "message/external".
+*/
static int
store_external (CT ct)
return OK;
/*
- * Check if the parameters for the external body
- * specified a filename.
- */
+ ** Check if the parameters for the external body
+ ** specified a filename.
+ */
if (autosw) {
char *cp;
}
/*
- * Since we will let the Content structure for the
- * external body substitute for the current content,
- * we temporarily change its partno (number inside
- * multipart), so everything looks right.
- */
+ ** Since we will let the Content structure for the
+ ** external body substitute for the current content,
+ ** we temporarily change its partno (number inside
+ ** multipart), so everything looks right.
+ */
p->c_partno = ct->c_partno;
/* we probably need to check if content is really there */
/*
- * Compare the numbering from two different
- * message/partials (needed for sorting).
- */
+** Compare the numbering from two different
+** message/partials (needed for sorting).
+*/
static int
ct_compar (CT *a, CT *b)
/*
- * Store contents of a message or message part to
- * a folder, a file, the standard output, or pass
- * the contents to a command.
- *
- * If the current content to be saved is a followup part
- * to a collection of messages of type "message/partial",
- * then field "p" is a pointer to the Content structure
- * to the first message/partial in the group.
- */
+** Store contents of a message or message part to
+** a folder, a file, the standard output, or pass
+** the contents to a command.
+**
+** If the current content to be saved is a followup part
+** to a collection of messages of type "message/partial",
+** then field "p" is a pointer to the Content structure
+** to the first message/partial in the group.
+*/
static int
store_content (CT ct, CT p)
char *cp, buffer[BUFSIZ];
/*
- * Do special processing for messages of
- * type "message/partial".
- *
- * We first check if this content is of type
- * "message/partial". If it is, then we need to check
- * whether it is the first and/or last in the group.
- *
- * Then if "p" is a valid pointer, it points to the Content
- * structure of the first partial in the group. So we copy
- * the file name and/or folder name from that message. In
- * this case, we also note that we will be appending.
- */
+ ** Do special processing for messages of
+ ** type "message/partial".
+ **
+ ** We first check if this content is of type
+ ** "message/partial". If it is, then we need to check
+ ** whether it is the first and/or last in the group.
+ **
+ ** Then if "p" is a valid pointer, it points to the Content
+ ** structure of the first partial in the group. So we copy
+ ** the file name and/or folder name from that message. In
+ ** this case, we also note that we will be appending.
+ */
if (ct->c_type == CT_MESSAGE && ct->c_subtype == MESSAGE_PARTIAL) {
struct partial *pm = (struct partial *) ct->c_ctparams;
last_partial = 1;
/*
- * If "p" is a valid pointer, then it points to the
- * Content structure for the first message in the group.
- * So we just copy the filename or foldername information
- * from the previous iteration of this function.
- */
+ ** If "p" is a valid pointer, then it points to the
+ ** Content structure for the first message in the group.
+ ** So we just copy the filename or foldername information
+ ** from the previous iteration of this function.
+ */
if (p) {
appending = 1;
ct->c_storage = add (p->c_storage, NULL);
}
/*
- * Get storage formatting string.
- *
- * 1) If we have storeproc defined, then use that
- * 2) Else check for a mhstore-store-<type>/<subtype> entry
- * 3) Else check for a mhstore-store-<type> entry
- * 4) Else if content is "message", use "+" (current folder)
- * 5) Else use string "%m%P.%s".
- */
+ ** Get storage formatting string.
+ **
+ ** 1) If we have storeproc defined, then use that
+ ** 2) Else check for a mhstore-store-<type>/<subtype> entry
+ ** 3) Else check for a mhstore-store-<type> entry
+ ** 4) Else if content is "message", use "+" (current folder)
+ ** 5) Else use string "%m%P.%s".
+ */
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);
+ 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";
}
}
/*
- * Check the beginning of storage formatting string
- * to see if we are saving content to a folder.
- */
+ ** Check the beginning of storage formatting string
+ ** to see if we are saving content to a folder.
+ */
if (*cp == '+' || *cp == '@') {
char *tmpfilenam, *folder;
}
/*
- * Parse and expand the storage formatting string
- * in `cp' into `buffer'.
- */
+ ** Parse and expand the storage formatting string
+ ** in `cp' into `buffer'.
+ */
parse_format_string (ct, cp, buffer, sizeof(buffer), dir);
/*
- * If formatting begins with '|' or '!', then pass
- * content to standard input of a command and return.
- */
+ ** If formatting begins with '|' or '!', then pass
+ ** content to standard input of a command and return.
+ */
if (buffer[0] == '|' || buffer[0] == '!')
return show_content_aux (ct, 1, 0, buffer + 1, dir);
return NOTOK;
/*
- * If necessary, link the file into a folder and remove
- * the temporary file. If this message is a partial,
- * then only do this if it is the last one in the group.
- */
+ ** If necessary, link the file into a folder and remove
+ ** the temporary file. If this message is a partial,
+ ** then only do this if it is the last one in the group.
+ */
if (ct->c_folder && (!is_partial || last_partial)) {
msgnum = output_content_folder (ct->c_folder, ct->c_storage);
unlink (ct->c_storage);
}
/*
- * Now print out the name/number of the message
- * that we are storing.
- */
+ ** Now print out the name/number of the message
+ ** that we are storing.
+ */
if (is_partial) {
if (first_partial)
fprintf (stderr, "reassembling partials ");
}
/*
- * Unless we are in the "middle" of group of message/partials,
- * we now print the name of the file, folder, and/or message
- * to which we are storing the content.
- */
+ ** Unless we are in the "middle" of group of message/partials,
+ ** we now print the name of the file, folder, and/or message
+ ** to which we are storing the content.
+ */
if (!is_partial || last_partial) {
if (ct->c_folder) {
fprintf (stderr, " to folder %s as message %d\n", ct->c_folder, msgnum);
/*
- * Output content to a file
- */
+** Output content to a file
+*/
static int
output_content_file (CT ct, int appending)
FILE *fp;
/*
- * If the pathname is absolute, make sure
- * all the relevant directories exist.
- */
+ ** If the pathname is absolute, make sure
+ ** all the relevant directories exist.
+ */
if (strchr(ct->c_storage, '/')
&& make_intermediates (ct->c_storage) == NOTOK)
return NOTOK;
}
/*
- * Send to standard output
- */
+ ** Send to standard output
+ */
if (!strcmp (ct->c_storage, "-")) {
int gd;
}
} else {
/*
- * Open output file
- */
+ ** Open output file
+ */
if ((fp = fopen (ct->c_storage, appending ? "a" : "w")) == NULL) {
advise (ct->c_storage, "unable to fopen for %s",
appending ? "appending" : "writing");
}
/*
- * Filter the header fields of the initial enclosing
- * message/partial into the file.
- */
+ ** Filter the header fields of the initial enclosing
+ ** message/partial into the file.
+ */
if (ct->c_type == CT_MESSAGE && ct->c_subtype == MESSAGE_PARTIAL) {
struct partial *pm = (struct partial *) ct->c_ctparams;
}
/*
- * Copy a few of the header fields of the initial
- * enclosing message/partial into the file.
- */
+ ** Copy a few of the header fields of the initial
+ ** enclosing message/partial into the file.
+ */
filterstate = 0;
if (ct->c_type == CT_MESSAGE && ct->c_subtype == MESSAGE_PARTIAL) {
struct partial *pm = (struct partial *) ct->c_ctparams;
buffer[diff] = '\0';
}
/*
- * If this is the first content of a group of
- * message/partial contents, then we only copy a few
- * of the header fields of the enclosed message.
- */
+ ** If this is the first content of a group of
+ ** message/partial contents, then we only copy a few
+ ** of the header fields of the enclosed message.
+ */
if (filterstate) {
switch (buffer[0]) {
case ' ':
/*
- * Add a file to a folder.
- *
- * Return the new message number of the file
- * when added to the folder. Return -1, if
- * there is an error.
- */
+** Add a file to a folder.
+**
+** Return the new message number of the file
+** when added to the folder. Return -1, if
+** there is an error.
+*/
static int
output_content_folder (char *folder, char *filename)
folder_free (mp);
/*
- * Return msgnum. We are relying on the fact that
- * msgnum will be -1, if folder_addmsg() had an error.
- */
+ ** Return msgnum. We are relying on the fact that
+ ** msgnum will be -1, if folder_addmsg() had an error.
+ */
return msgnum;
}
/*
- * Parse and expand the storage formatting string
- * pointed to by "cp" into "buffer".
- */
+** Parse and expand the storage formatting string
+** pointed to by "cp" into "buffer".
+*/
static int
parse_format_string (CT ct, char *cp, char *buffer, int buflen, char *dir)
CI ci = &ct->c_ctinfo;
/*
- * If storage string is "-", just copy it, and
- * return (send content to standard output).
- */
+ ** If storage string is "-", just copy it, and
+ ** return (send content to standard output).
+ */
if (cp[0] == '-' && cp[1] == '\0') {
strncpy (buffer, cp, buflen);
return 0;
bp[0] = '\0';
/*
- * If formatting string is a pathname that doesn't
- * begin with '/', then preface the path with the
- * appropriate directory.
- */
+ ** If formatting string is a pathname that doesn't
+ ** begin with '/', then preface the path with the
+ ** appropriate directory.
+ */
if (*cp != '/' && *cp != '|' && *cp != '!') {
snprintf (bp, buflen, "%s/", dir[1] ? dir : "");
len = strlen (bp);
switch (*++cp) {
case 'a':
/*
- * Insert parameters from Content-Type.
- * This is only valid for '|' commands.
- */
+ ** Insert parameters from Content-Type.
+ ** This is only valid for '|' commands.
+ */
if (buffer[0] != '|' && buffer[0] != '!') {
*bp++ = *--cp;
*bp = '\0';
/*
- * Check if the content specifies a filename
- * in its MIME parameters.
- */
+** Check if the content specifies a filename
+** in its MIME parameters.
+*/
static void
get_storeproc (CT ct)
CI ci = &ct->c_ctinfo;
/*
- * If the storeproc has already been defined,
- * we just return (for instance, if this content
- * is part of a "message/external".
- */
+ ** If the storeproc has already been defined,
+ ** we just return (for instance, if this content
+ ** is part of a "message/external".
+ */
if (ct->c_storeproc)
return;
/*
- * Check the attribute/value pairs, for the attribute "name".
- * If found, do a few sanity checks and copy the value into
- * the storeproc.
- */
+ ** Check the attribute/value pairs, for the attribute "name".
+ ** If found, do a few sanity checks and copy the value into
+ ** the storeproc.
+ */
for (ap = ci->ci_attrs, ep = ci->ci_values; *ap; ap++, ep++) {
if (!mh_strcasecmp (*ap, "name")
&& *(cp = *ep) != '/'
/*
- * Copy some of the header fields of the initial message/partial
- * message into the header of the reassembled message.
- */
+** Copy some of the header fields of the initial message/partial
+** message into the header of the reassembled message.
+*/
static int
copy_some_headers (FILE *out, CT ct)
while (hp) {
/*
- * A few of the header fields of the enclosing
- * messages are not copied.
- */
+ ** A few of the header fields of the enclosing
+ ** messages are not copied.
+ */
if (!uprf (hp->name, XXX_FIELD_PRF)
&& mh_strcasecmp (hp->name, VRSN_FIELD)
&& mh_strcasecmp (hp->name, "Subject")