]> diplodocus.org Git - nmh/blobdiff - uip/mhstoresbr.c
First basic test of extended parameter output: working!
[nmh] / uip / mhstoresbr.c
index 6badafeb9ffcbf2454dedc71d40a61506919fd3d..799bdb4287f217177831e9022d244b7439791442 100644 (file)
@@ -11,8 +11,6 @@
 #include <fcntl.h>
 #include <h/signals.h>
 #include <h/md5.h>
-#include <errno.h>
-#include <signal.h>
 #include <h/mts.h>
 #include <h/tws.h>
 #include <h/mime.h>
@@ -137,13 +135,11 @@ store_switch (CT ct)
     switch (ct->c_type) {
        case CT_MULTIPART:
            return store_multi (ct);
-           break;
 
        case CT_MESSAGE:
            switch (ct->c_subtype) {
                case MESSAGE_PARTIAL:
                    return store_partial (ct);
-                   break;
 
                case MESSAGE_EXTERNAL:
                    return store_external (ct);
@@ -151,24 +147,19 @@ store_switch (CT ct)
                case MESSAGE_RFC822:
                default:
                    return store_generic (ct);
-                   break;
            }
-           break;
 
        case CT_APPLICATION:
            return store_application (ct);
-           break;
 
        case CT_TEXT:
        case CT_AUDIO:
        case CT_IMAGE:
        case CT_VIDEO:
            return store_generic (ct);
-           break;
 
        default:
            adios (NULL, "unknown content type %d", ct->c_type);
-           break;
     }
 
     return OK; /* NOT REACHED */
@@ -202,8 +193,8 @@ store_generic (CT ct)
 static int
 store_application (CT ct)
 {
-    char **ap, **ep;
     CI ci = &ct->c_ctinfo;
+    PM pm;
 
     /* Check if the content specifies a filename */
     if (autosw)
@@ -217,10 +208,10 @@ store_application (CT ct)
     if (!ct->c_storeproc && ct->c_subtype == APPLICATION_OCTETS) {
        int tarP = 0, zP = 0, gzP = 0;
 
-       for (ap = ci->ci_attrs, ep = ci->ci_values; *ap; ap++, ep++) {
+       for (pm = ci->ci_first_pm; pm; pm = pm->pm_next) {
            /* check for "type=tar" attribute */
-           if (!mh_strcasecmp (*ap, "type")) {
-               if (mh_strcasecmp (*ep, "tar"))
+           if (!strcasecmp (pm->pm_name, "type")) {
+               if (strcasecmp (pm->pm_value, "tar"))
                    break;
 
                tarP = 1;
@@ -228,14 +219,18 @@ store_application (CT ct)
            }
 
            /* 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 ((!strcasecmp (pm->pm_name, "conversions") ||
+                !strcasecmp (pm->pm_name, "x-conversions"))
+               && (!strcasecmp (pm->pm_value, "compress") ||
+                   !strcasecmp (pm->pm_value, "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 ((!strcasecmp (pm->pm_name, "conversions") ||
+                !strcasecmp (pm->pm_name, "x-conversions"))
+               && (!strcasecmp (pm->pm_value, "gzip") ||
+                   !strcasecmp (pm->pm_value, "x-gzip"))) {
                gzP = 1;
                continue;
            }
@@ -280,7 +275,15 @@ store_multi (CT ct)
        CT  p = part->mp_part;
 
        if (part_ok (p, 1) && 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;
+           }
            result = store_switch (p);
+           p->c_storage = NULL;
+
            if (result == OK && ct->c_subtype == MULTI_ALTERNATE)
                break;
        }
@@ -440,7 +443,13 @@ store_external (CT ct)
     p->c_partno = ct->c_partno;
 
     /* we probably need to check if content is really there */
+    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;
+    }
     result = store_switch (p);
+    p->c_storage = NULL;
 
     p->c_partno = NULL;
     return result;
@@ -514,11 +523,13 @@ store_content (CT ct, CT p)
         */
        if (p) {
            appending = 1;
-           ct->c_storage = add (p->c_storage, NULL);
+            if (! ct->c_storage) {
+               ct->c_storage = add (p->c_storage, NULL);
 
-           /* record the folder name */
-           if (p->c_folder) {
-               ct->c_folder = add (p->c_folder, NULL);
+               /* record the folder name */
+               if (p->c_folder) {
+                   ct->c_folder = add (p->c_folder, NULL);
+               }
            }
            goto got_filename;
        }
@@ -546,51 +557,62 @@ store_content (CT ct, CT p)
        }
     }
 
-    /*
-     * Check the beginning of storage formatting string
-     * to see if we are saving content to a folder.
-     */
-    if (*cp == '+' || *cp == '@') {
-       char *tmpfilenam, *folder;
+    if (! ct->c_storage) {
+       /*
+        * Check the beginning of storage formatting string
+        * to see if we are saving content to a folder.
+        */
+       if (*cp == '+' || *cp == '@') {
+           char *tmpfilenam, *folder;
 
-       /* Store content in temporary file for now */
-       tmpfilenam = m_mktemp(invo_name, NULL, NULL);
-       ct->c_storage = add (tmpfilenam, NULL);
+           /* Store content in temporary file for now */
+           if ((tmpfilenam = m_mktemp(invo_name, NULL, NULL)) == NULL) {
+               adios(NULL, "unable to create temporary file in %s",
+                     get_temp_dir());
+           }
+           ct->c_storage = add (tmpfilenam, NULL);
 
-       /* Get the folder name */
-       if (cp[1])
-           folder = pluspath (cp);
-       else
-           folder = getfolder (1);
+           /* Get the folder name */
+           if (cp[1])
+               folder = pluspath (cp);
+           else
+               folder = getfolder (1);
 
-       /* Check if folder exists */
-       create_folder(m_mailpath(folder), 0, exit);
+           /* Check if folder exists */
+           create_folder(m_mailpath(folder), 0, exit);
 
-       /* Record the folder name */
-       ct->c_folder = add (folder, NULL);
+           /* Record the folder name */
+           ct->c_folder = add (folder, NULL);
 
-       if (cp[1])
-           free (folder);
+           if (cp[1])
+               free (folder);
 
-       goto got_filename;
-    }
+           goto got_filename;
+       }
 
-    /*
-     * Parse and expand the storage formatting string
-     * in `cp' into `buffer'.
-     */
-    parse_format_string (ct, cp, buffer, sizeof(buffer), dir);
+       /*
+        * 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 (buffer[0] == '|' || buffer[0] == '!')
-       return show_content_aux (ct, 1, 0, buffer + 1, dir);
+       /*
+        * 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);
 
-    /* record the filename */
-    if ((ct->c_storage = clobber_check (add (buffer, NULL))) == NULL) {
-      return NOTOK;
+        /* record the filename */
+       if ((ct->c_storage = clobber_check (add (buffer, NULL))) == NULL) {
+           return NOTOK;
+       }
+    } else {
+        /* The output filename was explicitly specified, so use it. */
+       if ((ct->c_storage = clobber_check (add (ct->c_storage, NULL))) ==
+            NULL) {
+           return NOTOK;
+       }
     }
 
 got_filename:
@@ -608,7 +630,7 @@ got_filename:
      */
     if (ct->c_folder && (!is_partial || last_partial)) {
        msgnum = output_content_folder (ct->c_folder, ct->c_storage);
-       unlink (ct->c_storage);
+       (void) m_unlink (ct->c_storage);
        if (msgnum == NOTOK)
            return NOTOK;
     }
@@ -943,12 +965,12 @@ parse_format_string (CT ct, char *cp, char *buffer, int buflen, char *dir)
                        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, pm->pm_value);
                            len = strlen (bp);
                            bp += len;
                            buflen -= len;
@@ -1020,8 +1042,9 @@ raw:
 static void
 get_storeproc (CT ct)
 {
-    char **ap, **ep, *cp;
-    CI ci = &ct->c_ctinfo;
+    char *cp;
+    CI ci;
+    PM pm;
 
     /*
      * If the storeproc has already been defined,
@@ -1031,14 +1054,37 @@ get_storeproc (CT ct)
     if (ct->c_storeproc)
        return;
 
+    /*
+     * If there's a Content-Disposition header and it has a filename,
+     * use that (RFC-2183).
+     */
+    if (ct->c_dispo) {
+       int found_filename = 0;
+
+       for (pm = ct->c_dispo_first; pm; pm = pm->pm_next) {
+           if (! strcasecmp (pm->pm_name, "filename")
+                   && *(cp = pm->pm_value) != '/'
+                   && *cp != '.'
+                   && *cp != '|'
+                   && *cp != '!'
+                   && !strchr (cp, '%')) {
+               ct->c_storeproc = add (cp, NULL);
+               found_filename = 1;
+           }
+       }
+
+       if (found_filename) return;
+    }
+
     /*
      * 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) != '/'
+    ci = &ct->c_ctinfo;
+    for (pm = ci->ci_first_pm; pm; pm = pm->pm_next) {
+       if (! strcasecmp (pm->pm_name, "name")
+           && *(cp = pm->pm_value) != '/'
            && *cp != '.'
            && *cp != '|'
            && *cp != '!'
@@ -1068,10 +1114,10 @@ copy_some_headers (FILE *out, CT ct)
         * messages are not copied.
         */
        if (!uprf (hp->name, XXX_FIELD_PRF)
-               && mh_strcasecmp (hp->name, VRSN_FIELD)
-               && mh_strcasecmp (hp->name, "Subject")
-               && mh_strcasecmp (hp->name, "Encrypted")
-               && mh_strcasecmp (hp->name, "Message-ID"))
+               && strcasecmp (hp->name, VRSN_FIELD)
+               && strcasecmp (hp->name, "Subject")
+               && strcasecmp (hp->name, "Encrypted")
+               && strcasecmp (hp->name, "Message-ID"))
            fprintf (out, "%s:%s", hp->name, hp->value);
        hp = hp->next;  /* next header field */
     }
@@ -1096,15 +1142,15 @@ int files_not_clobbered = 0;
 
 int
 save_clobber_policy (const char *value) {
-  if (! mh_strcasecmp (value, "always")) {
+  if (! strcasecmp (value, "always")) {
     clobber_policy = NMH_CLOBBER_ALWAYS;
-  } else if (! mh_strcasecmp (value, "auto")) {
+  } else if (! strcasecmp (value, "auto")) {
     clobber_policy = NMH_CLOBBER_AUTO;
-  } else if (! mh_strcasecmp (value, "suffix")) {
+  } else if (! strcasecmp (value, "suffix")) {
     clobber_policy = NMH_CLOBBER_SUFFIX;
-  } else if (! mh_strcasecmp (value, "ask")) {
+  } else if (! strcasecmp (value, "ask")) {
     clobber_policy = NMH_CLOBBER_ASK;
-  } else if (! mh_strcasecmp (value, "never")) {
+  } else if (! strcasecmp (value, "never")) {
     clobber_policy = NMH_CLOBBER_NEVER;
   } else {
     return 1;
@@ -1181,11 +1227,11 @@ static char *
 clobber_check (char *original_file) {
   /* clobber policy        return value
    * --------------        ------------
-   *   -always                 file
-   *   -auto           file-<digits>.extension
-   *   -suffix             file.<digits>
-   *   -ask          file, 0, or another filename/path
-   *   -never                   0
+   *   -always             original_file
+   *   -auto               original_file-<digits>.extension
+   *   -suffix             original_file.<digits>
+   *   -ask                original_file, 0, or another filename/path
+   *   -never              0
    */
 
   char *file;