Better mime types for attachments. Use some command; e.g. `file --mime'.
[mmh] / uip / sendsbr.c
index 9c335bd..f8b415c 100644 (file)
@@ -30,7 +30,6 @@ int debugsw = 0;  /* global */
 int forwsw  = 1;
 int inplace = 1;
 int pushsw  = 0;
-int unique  = 0;
 int verbsw  = 0;
 
 char *altmsg   = NULL;  /*  .. */
@@ -79,7 +78,7 @@ int
 sendsbr(char **vec, int vecp, char *drft, struct stat *st, int rename_drft)
 {
        int status;
-       char buffer[BUFSIZ], file[BUFSIZ];
+       char buffer[BUFSIZ];
        char *original_draft;  /* name of original draft file */
        char *p;  /* string pointer for building file name */
 
@@ -115,23 +114,7 @@ sendsbr(char **vec, int vecp, char *drft, struct stat *st, int rename_drft)
        done=armed_done;
        switch (setjmp(env)) {
        case OK:
-               /*
-               ** If given -push and -unique (which is undocumented), then
-               ** rename the draft file.  I'm not quite sure why.
-               */
-               if (pushsw && unique) {
-                       char *cp = m_mktemp2(drft, invo_name, NULL, NULL);
-                       if (cp == NULL) {
-                               adios("sendsbr", "unable to create temporary file");
-                       }
-                       if (rename(drft, strncpy(file, cp, sizeof(file)))
-                                       == NOTOK)
-                               adios(file, "unable to rename %s to", drft);
-                       drft = file;
-               }
-
                status = sendaux(vec, vecp, drft, st) ? NOTOK : OK;
-
                /* rename the original draft */
                if (rename_drft && status == OK &&
                                rename(original_draft, strncpy(buffer,
@@ -214,15 +197,16 @@ attach(char *draft_file_name)
 
        has_attachment = 0;
 
-       while (get_line() != EOF && *field != '\0' && *field != '-')
+       while (get_line() != EOF && *field != '\0' && *field != '-') {
                if (strncasecmp(field, attach_hdr, length) == 0 &&
-                               field[length] == ':')
+                               field[length] == ':') {
                        has_attachment = 1;
+               }
+       }
 
        /*
-       ** We have at least one attachment.  Look for at least one
-       ** non-blank line in the body of the message which indicates
-       ** content in the body.
+       ** Look for at least one non-blank line in the body of the
+       ** message which indicates content in the body.
        ** Check if body contains at least one non-blank (= not empty)
        ** and if it contains any non-ASCII chars (= need MIME).
        */
@@ -267,8 +251,7 @@ attach(char *draft_file_name)
 
        composition_file = fopen(composition_file_name, "w");
 
-       if ((has_body && body_file == (FILE *)0) ||
-                       composition_file == (FILE *)0) {
+       if ((has_body && !body_file) || !composition_file) {
                clean_up_temporary_files();
                adios(NULL, "unable to open all of the temporary files.");
        }
@@ -279,27 +262,22 @@ attach(char *draft_file_name)
        ** Then add the dashed line separator.
        */
        rewind(draft_file);
-       while (get_line() != EOF && *field != '\0' && *field != '-')
+       while (get_line() != EOF && *field && *field != '-') {
                if (strncasecmp(field, attach_hdr, length) != 0 ||
-                               field[length] != ':')
+                               field[length] != ':') {
                        fprintf(composition_file, "%s\n", field);
+               }
+       }
        fputs("--------\n", composition_file);
 
-       /*
-       ** Copy the message body to a temporary file.
-       */
        if (has_body) {
-               while ((c = getc(draft_file)) != EOF)
-                               putc(c, body_file);
+               /* Copy the message body to the temporary file. */
+               while ((c = getc(draft_file)) != EOF) {
+                       putc(c, body_file);
+               }
                fclose(body_file);
-       }
 
-       /*
-       ** Add a mhbuild MIME composition file line for the body if
-       ** there was one.
-       */
-       if (has_body) {
-               /* old: make_mime_composition_file_entry(body_file_name); */
+               /* Add a mhbuild MIME composition file line for the body */
                /* charset will be discovered/guessed by buildmimeproc */
                fprintf(composition_file, "#text/plain %s\n", body_file_name);
        }
@@ -310,7 +288,7 @@ attach(char *draft_file_name)
        ** composition file for each.
        */
        rewind(draft_file);
-       while (get_line() != EOF && *field != '\0' && *field != '-') {
+       while (get_line() != EOF && *field && *field != '-') {
                if (strncasecmp(field, attach_hdr, length) == 0 &&
                                field[length] == ':') {
                        for (p = field+length+1; *p==' ' || *p=='\t'; p++) {
@@ -387,99 +365,46 @@ get_line(void)
 static void
 make_mime_composition_file_entry(char *file_name)
 {
-       int binary;  /* binary character found flag */
-       int c;  /* current character */
-       char *content_type;  /* mime content type */
-       FILE *fp;  /* content and pipe file pointer */
-       struct node *np;  /* context scan node pointer */
-       char *p;  /* miscellaneous string pointer */
-
-       content_type = NULL;
-
-       /*
-       ** Check the file name for a suffix.  Scan the context for that
-       ** suffix on a mhshow-suffix- entry.  We use these entries to
-       ** be compatible with mhshow, and there's no reason to make the
-       ** user specify each suffix twice.  Context entries of the form
-       ** "mhshow-suffix-contenttype" in the name have the suffix in
-       ** the field, including the dot.
-       */
-
-       if ((p = strrchr(file_name, '.')) != NULL) {
-               for (np = m_defs; np; np = np->n_next) {
-                       if (strncasecmp(np->n_name, "mhshow-suffix-", 14) == 0
-                                       && mh_strcasecmp(p, np->n_field) == 0)
-                                       {
-                               content_type = np->n_name + 14;
-                               break;
-                       }
+       FILE *fp;
+       struct node *np;
+       char *cp;
+       char content_type[BUFSIZ];
+       char cmdbuf[BUFSIZ];
+       char *cmd = mimetypequeryproc;
+
+       for (np = m_defs; np; np = np->n_next) {
+               if (strcasecmp(np->n_name, mimetypequery)==0) {
+                       cmd = np->n_field;
+                       break;
                }
        }
+       snprintf(cmdbuf, sizeof cmdbuf, "%s %s", cmd, file_name);
 
-       /*
-       ** No content type was found, either because there was no matching
-       ** entry in the context or because the file name has no suffix.
-       ** Open the file and check for non-ASCII characters.  Choose the
-       ** content type based on this check.
-       */
-
-       if (content_type == NULL) {
-               if ((fp = fopen(file_name, "r")) == (FILE *)0) {
-                       clean_up_temporary_files();
-                       adios(NULL, "unable to access file \"%s\"",
-                                       file_name);
-               }
-
-               binary = 0;
-
-               while ((c = getc(fp)) != EOF) {
-                       if (c > 127 || c < 0) {
-                               binary = 1;
-                               break;
-                       }
-               }
-
-               fclose(fp);
-
-               content_type = binary ?
-                               "application/octet-stream" : "text/plain";
+       if (!(fp = popen(cmdbuf, "r"))) {
+               clean_up_temporary_files();
+               adios(NULL, "unable to determine content type with `%s'",
+                               cmdbuf);
        }
+       if (fgets(content_type, sizeof content_type, fp) &&
+                       (cp = strrchr(content_type, '\n'))) {
+               *cp = '\0';
+       } else {
+               strcpy(content_type, "application/octet-stream");
+               admonish(NULL, "problems with `%s', using fall back type `%s'",
+                               cmdbuf, content_type);
+       }
+       pclose(fp);
 
-       /*
-       ** Make sure that the attachment file exists and is readable.
-       ** Append a mhbuild directive to the draft file.  This starts with
-       ** the content type.  Append a file name attribute and a private
-       ** x-unix-mode attribute.  Also append a description obtained
-       ** (if possible) by running the "file" command on the file.
-       */
-
+       /* TODO: don't use access(2) because it checks for ruid, not euid */
        if (access(file_name, R_OK) != 0) {
                clean_up_temporary_files();
-               adios(NULL, "unable to access file \"%s\"", file_name);
+               adios(NULL, "unable to access file `%s'", file_name);
        }
 
+       fprintf(composition_file, "#%s; name=\"%s\" <>{attachment}",
+               content_type,
+               (!(cp = strrchr(file_name, '/'))) ? file_name : cp + 1);
 
-       if (stringdex(toabsdir(invo_name), file_name) == 0) {
-               /*
-               ** Content had been placed by send into a temp file.
-               ** Don't generate Content-Disposition header, because
-               ** it confuses Microsoft Outlook, Build 10.0.6626, at
-               ** least.
-               */
-               fprintf(composition_file, "#%s <>", content_type);
-       } else {
-               /*
-               ** Suppress Content-Id, insert simple
-               ** Content-Disposition.
-               */
-               fprintf(composition_file,
-                       "#%s; name=\"%s\" <>{attachment}",
-                       content_type,
-                       ((p = strrchr(file_name, '/')) == NULL) ?
-                       file_name : p + 1);
-       }
-
-       /* Finish up with the file name. */
        fprintf(composition_file, " %s\n", file_name);
 
        return;
@@ -495,20 +420,14 @@ sendaux(char **vec, int vecp, char *drft, struct stat *st)
 {
        pid_t child_id;
        int i, status, fd, fd2;
-       char backup[BUFSIZ], buf[BUFSIZ];
+       char backup[BUFSIZ];
 
        fd = pushsw ? tmp_fd() : NOTOK;
        fd2 = NOTOK;
 
        vec[vecp++] = drft;
-       if (annotext) {
-               if ((fd2 = tmp_fd()) != NOTOK) {
-                       vec[vecp++] = "-idanno";
-                       snprintf(buf, sizeof(buf), "%d", fd2);
-                       vec[vecp++] = buf;
-               } else {
-                       admonish(NULL, "unable to create file for annotation list");
-               }
+       if (annotext && (fd2 = tmp_fd()) == NOTOK) {
+               admonish(NULL, "unable to create file for annotation list");
        }
        if (distfile && distout(drft, distfile, backup) == NOTOK)
                done(1);
@@ -785,7 +704,7 @@ annoaux(int fd)
                if (is_selected(mp, msgnum)) {
                        if (debugsw)
                                advise(NULL, "annotate message %d", msgnum);
-                       annotate(m_name (msgnum), annotext, cp, inplace,
+                       annotate(m_name(msgnum), annotext, cp, inplace,
                                        1, -2, 0);
                }
        }