]> diplodocus.org Git - nmh/blobdiff - uip/attach.c
Replaced use of mkstemp() with m_mktemp() in lock_file.c.
[nmh] / uip / attach.c
index d4902d551abc2df47e0d5c9adb5c94caeca8fd14..9ff7d0955598dbe73cc736173478f48c165fb8be 100644 (file)
@@ -11,6 +11,9 @@
 #include <h/tws.h>
 
 static int get_line(FILE *, char *, size_t);
 #include <h/tws.h>
 
 static int get_line(FILE *, char *, size_t);
+#ifdef MIMETYPEPROC
+static char *get_file_info(const char *, const char *);
+#endif /* MIMETYPEPROC */
 
 int
 attach(char *attachment_header_field_name, char *draft_file_name,
 
 int
 attach(char *attachment_header_field_name, char *draft_file_name,
@@ -25,7 +28,6 @@ attach(char *attachment_header_field_name, char *draft_file_name,
     int         length;                 /* of attachment header field name */
     char        *p;                     /* miscellaneous string pointer */
     struct stat st;                     /* file status buffer */
     int         length;                 /* of attachment header field name */
     char        *p;                     /* miscellaneous string pointer */
     struct stat st;                     /* file status buffer */
-    FILE        *fp;                    /* pointer for mhn.defaults */
     FILE        *body_file = NULL;      /* body file pointer */
     FILE        *draft_file;            /* draft file pointer */
     int         field_size;             /* size of header field buffer */
     FILE        *body_file = NULL;      /* body file pointer */
     FILE        *draft_file;            /* draft file pointer */
     int         field_size;             /* size of header field buffer */
@@ -98,12 +100,15 @@ attach(char *attachment_header_field_name, char *draft_file_name,
      * Make names for the temporary files.
      */
 
      * Make names for the temporary files.
      */
 
-    (void)strncpy(body_file_name,
-                  m_mktemp(m_maildir(invo_name), NULL, NULL),
-                  body_file_name_len);
-    (void)strncpy(composition_file_name,
-                  m_mktemp(m_maildir(invo_name), NULL, NULL),
-                  composition_file_name_len);
+    if ((p = m_mktemp2(NULL, invo_name, NULL, NULL)) == NULL) {
+       adios(NULL, "unable to create temporary file in %s", get_temp_dir());
+    }
+    (void)strncpy(body_file_name, p, body_file_name_len);
+    if ((p = m_mktemp2(NULL, invo_name, NULL, NULL)) == NULL) {
+        unlink(body_file_name);
+       adios(NULL, "unable to create temporary file in %s", get_temp_dir());
+    }
+    (void)strncpy(composition_file_name, p, composition_file_name_len);
 
     if (has_body)
        body_file = fopen(body_file_name, "w");
 
     if (has_body)
        body_file = fopen(body_file_name, "w");
@@ -174,11 +179,6 @@ attach(char *attachment_header_field_name, char *draft_file_name,
      * composition file for each.
      */
 
      * composition file for each.
      */
 
-    if ((fp = fopen (p = etcpath ("mhn.defaults"), "r"))) {
-       readconfig ((struct node **) NULL, fp, p, 0);
-       fclose(fp);
-    }
-
     rewind(draft_file);
 
     while (get_line(draft_file, field, field_size) != EOF && *field != '\0' &&
     rewind(draft_file);
 
     while (get_line(draft_file, field, field_size) != EOF && *field != '\0' &&
@@ -285,69 +285,105 @@ get_line(FILE *draft_file, char *field, size_t field_size)
  * encoding.  Caller is responsible for free'ing returned memory.
  */
 char *
  * encoding.  Caller is responsible for free'ing returned memory.
  */
 char *
-mime_type (const char *file_name) {
+mime_type(const char *file_name) {
     char *content_type = NULL;  /* mime content type */
 
 #ifdef MIMETYPEPROC
     char *content_type = NULL;  /* mime content type */
 
 #ifdef MIMETYPEPROC
-    char cmd[2 * PATH_MAX + 2]; /* file command buffer */
-    char buf[BUFSIZ >= 2048  ?  BUFSIZ  : 2048];
-    FILE *fp;                   /* content and pipe file pointer */
-    char mimetypeproc[] = MIMETYPEPROC " '%s'";
-
-    if ((int) snprintf (cmd, sizeof cmd, mimetypeproc, file_name) <
-        (int) sizeof cmd) {
-        if ((fp = popen (cmd, "r")) != NULL) {
-            /* Make sure that buf has space for one additional
-               character, the semicolon that might be added below. */
-            if (fgets (buf, sizeof buf - 1, fp)) {
-                char *cp, *space;
+    char *mimetype;
+
+    if ((mimetype = get_file_info(MIMETYPEPROC, file_name))) {
+#ifdef MIMEENCODINGPROC
+        /* Try to append charset for text content. */
+        char *mimeencoding;
+
+        if (strncasecmp(mimetype, "text", 4) == 0) {
+            if ((mimeencoding = get_file_info(MIMEENCODINGPROC, file_name))) {
+                content_type = concat(mimetype, "; charset=", mimeencoding,
+                                      NULL);
+            } else {
+                content_type = strdup(mimetype);
+            }
+        } else {
+            content_type = strdup(mimetype);
+        }
+#else  /* MIMEENCODINGPROC */
+        content_type = strdup(mimetype);
+#endif /* MIMEENCODINGPROC */
+    }
+#else  /* MIMETYPEPROC */
+    NMH_UNUSED(file_name);
+#endif /* MIMETYPEPROC */
+
+    return content_type;
+}
+
+
+#ifdef MIMETYPEPROC
+/*
+ * Get information using proc about a file.
+ */
+static char *
+get_file_info(const char *proc, const char *file_name) {
+    char *cmd, *cp;
+    char *quotec = "'";
+
+    if ((cp = strchr(file_name, '\''))) {
+        /* file_name contains a single quote. */
+        if (strchr(file_name, '"')) {
+            advise(NULL, "filenames containing both single and double quotes "
+                   "are unsupported for attachment");
+            return NULL;
+        } else {
+            quotec = "\"";
+        }
+    }
+
+    cmd = concat(proc, " ", quotec, file_name, quotec, NULL);
+    if ((cmd = concat(proc, " ", quotec, file_name, quotec, NULL))) {
+        FILE *fp;
+
+        if ((fp = popen(cmd, "r")) != NULL) {
+            char buf[BUFSIZ >= 2048  ?  BUFSIZ  : 2048];
+
+            buf[0] = '\0';
+            if (fgets(buf, sizeof buf, fp)) {
+                char *eol;
 
                 /* Skip leading <filename>:<whitespace>, if present. */
 
                 /* Skip leading <filename>:<whitespace>, if present. */
-                if ((content_type = strchr (buf, ':')) != NULL) {
-                    ++content_type;
-                    while (*content_type  &&  isblank (*content_type)) {
-                        ++content_type;
+                if ((cp = strchr(buf, ':')) != NULL) {
+                    ++cp;
+                    while (*cp  &&  isblank((unsigned char) *cp)) {
+                        ++cp;
                     }
                 } else {
                     }
                 } else {
-                    content_type = buf;
+                    cp = buf;
                 }
 
                 /* Truncate at newline (LF or CR), if present. */
                 }
 
                 /* Truncate at newline (LF or CR), if present. */
-                if ((cp = strpbrk (content_type, "\n\n")) != NULL) {
-                    *cp = '\0';
-                }
-
-                /* If necessary, insert semicolon between content type
-                   and charset.  Assume that the first space is between
-                   them. */
-                if ((space = strchr (content_type, ' ')) != NULL) {
-                    ssize_t len = strlen (content_type);
-
-                    if (space - content_type > 0  &&
-                        len > space - content_type + 1) {
-                        if (*(space - 1) != ';') {
-                            /* The +1 is for the terminating NULL. */
-                            memmove (space + 1, space,
-                                     len - (space - content_type) + 1);
-                            *space = ';';
-                        }
-                    }
+                if ((eol = strpbrk(cp, "\n\r")) != NULL) {
+                    *eol = '\0';
                 }
                 }
-            } else {
-                advise (NULL, "unable to read mime type");
+            } else if (buf[0] == '\0') {
+                /* This can happen on Cygwin if the popen()
+                   mysteriously fails.  Return NULL so that the caller
+                   will use another method to determine the info. */
+                free (cp);
+                cp = NULL;
             }
             }
+
+            (void) pclose(fp);
         } else {
         } else {
-            advise (NULL, "unable to run %s", buf);
+            advise(NULL, "no output from %s", cmd);
         }
         }
+
+        free(cmd);
     } else {
     } else {
-        advise (NULL, "filename too large to deduce mime type");
+        advise(NULL, "concat with \"%s\" failed, out of memory?", proc);
     }
     }
-#else
-    NMH_UNUSED (file_name);
-#endif
 
 
-    return content_type ? strdup (content_type) : NULL;
+    return cp  ?  strdup(cp)  :  NULL;
 }
 }
+#endif /* MIMETYPEPROC */
 
 
 /*
 
 
 /*
@@ -365,7 +401,6 @@ construct_build_directive (char *file_name, const char *default_content_type,
     char  cmd[PATH_MAX + 8];       /* file command buffer */
     struct stat st;                /* file status buffer */
     char *p;                       /* miscellaneous temporary variables */
     char  cmd[PATH_MAX + 8];       /* file command buffer */
     struct stat st;                /* file status buffer */
     char *p;                       /* miscellaneous temporary variables */
-    FILE *fp;
     int   c;                       /* current character */
 
     if ((content_type = mime_type (file_name)) == NULL) {
     int   c;                       /* current character */
 
     if ((content_type = mime_type (file_name)) == NULL) {
@@ -378,6 +413,12 @@ construct_build_directive (char *file_name, const char *default_content_type,
          * have the suffix in the field, including the dot.
          */
         struct node *np;          /* context scan node pointer */
          * have the suffix in the field, including the dot.
          */
         struct node *np;          /* context scan node pointer */
+        static FILE *fp = NULL;   /* pointer for mhn.defaults */
+
+        if (fp == NULL  &&  (fp = fopen (p = etcpath ("mhn.defaults"), "r"))) {
+            readconfig ((struct node **) NULL, fp, p, 0);
+            fclose(fp);
+        }
 
         if ((p = strrchr(file_name, '.')) != NULL) {
             for (np = m_defs; np; np = np->n_next) {
 
         if ((p = strrchr(file_name, '.')) != NULL) {
             for (np = m_defs; np; np = np->n_next) {
@@ -402,6 +443,7 @@ construct_build_directive (char *file_name, const char *default_content_type,
      */
     if (content_type == NULL) {
         int  binary; /* binary character found flag */
      */
     if (content_type == NULL) {
         int  binary; /* binary character found flag */
+        FILE *fp;
 
         if ((fp = fopen(file_name, "r")) == (FILE *)0) {
             advise(NULL, "unable to access file \"%s\"", file_name);
 
         if ((fp = fopen(file_name, "r")) == (FILE *)0) {
             advise(NULL, "unable to access file \"%s\"", file_name);
@@ -426,6 +468,7 @@ construct_build_directive (char *file_name, const char *default_content_type,
     switch (attachformat) {
     case 0: {
         struct stat st;
     switch (attachformat) {
     case 0: {
         struct stat st;
+        FILE *fp;
         char m[4];
 
         /* Insert name, file mode, and Content-Id. */
         char m[4];
 
         /* Insert name, file mode, and Content-Id. */