text content.
AC_SUBST([MAIL_SPOOL_GRP])dnl
NMH_MIMETYPEPROC
+NMH_MIMEENCODINGPROC
dnl ------------------
dnl CHECK HEADER FILES
dnl Try to see if we have a program that can determine the MIME type
dnl of a particular file
dnl
+dnl Assume that if file(1) doesn't support --mime-type, then it's
+dnl unusable. The --mime option to file 4.17 on CentOS 5.9, for
+dnl example, prints out a long description after the mime type. We
+dnl don't want that.
AC_DEFUN([NMH_MIMETYPEPROC],
[AC_CACHE_CHECK([for a program to provide a MIME type string],
for mprog in 'file --brief --mime-type' 'file --mime-type'
do
AS_IF([$mprog "${srcdir}/configure" > /dev/null 2>&1],
- [nmh_cv_mimetype_proc="$mprog"; break])
+ [nmh_cv_mimetype_proc="$mprog"; break])
done])
AS_IF([test X"$nmh_cv_mimetype_proc" != X],
[mimetype_proc="\"${nmh_cv_mimetype_proc}\""
AC_DEFINE_UNQUOTED([MIMETYPEPROC], [$mimetype_proc],
- [Program, with arguments, that provides MIME type string.])])])
+ [Program, with arguments, to provides MIME type.])])])
+
+AC_DEFUN([NMH_MIMEENCODINGPROC],
+[AC_CACHE_CHECK([for a program to provide a MIME encoding string],
+ [nmh_cv_mimeencoding_proc],
+ [nmh_cv_mimeencoding_proc=
+ for mprog in 'file --brief --mime-encoding' 'file --mime-encoding'
+ do
+ AS_IF([$mprog "${srcdir}/configure" > /dev/null 2>&1],
+ [nmh_cv_mimeencoding_proc="$mprog"; break])
+ done])
+AS_IF([test X"$nmh_cv_mimeencoding_proc" != X],
+ [mimeencoding_proc="\"${nmh_cv_mimeencoding_proc}\""
+ AC_DEFINE_UNQUOTED([MIMEENCODINGPROC], [$mimeencoding_proc],
+ [Program, with arguments, to provides MIME encoding.])])])
. "${srcdir}/test/post/test-post-common.sh"
-# Find MIME type string, using mimetypeproc if configured with it.
+# Find MIME type string, using configured procs if available.
MIMETYPEPROC=`mhparam mimetypeproc`
+MIMEENCODINGPROC=`mhparam mimeencodingproc`
content_type_string() {
- if test -z "$MIMETYPEPROC"; then
+ if test -z "$MIMETYPEPROC" -o -z "$MIMEENCODINGPROC"; then
+ #### This should be the order of name and charset.
echo "text/plain; name=\"`basename $1`\"; charset=\"us-ascii\""
else
- # 1) Excise leading filename followed by : and any whitespace.
- # 2) Wrap charset value in double quotes. Assume that it isn't already.
- printf "%s%s" \
- `$MIMETYPEPROC $1` "; name=\"`basename $1`\"; charset=\"us-ascii\""
+ #### Excise any leading filename followed by : and whitespace.
+ printf '%s; charset="%s"; name="%s"' \
+ `$MIMETYPEPROC $1 | sed -e 's/.*: *//'` \
+ `$MIMEENCODINGPROC $1 | sed -e 's/.*: *//'` `basename $1`
fi
}
#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,
* 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 cmd[2 * PATH_MAX + 2]; /* file command buffer */
+ 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 buf[BUFSIZ >= 2048 ? BUFSIZ : 2048];
- FILE *fp; /* content and pipe file pointer */
- char mimetypeproc[] = MIMETYPEPROC " '%s'";
+ char *cmd, *cp;
+ char *quotec = "'";
+ FILE *fp;
+
+ 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 = "\"";
+ }
+ }
- 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;
+ cmd = concat(proc, " ", quotec, file_name, quotec, NULL);
+ if ((cmd = concat(proc, " ", quotec, file_name, quotec, NULL))) {
+ if ((fp = popen(cmd, "r")) != NULL) {
+ if (fgets(buf, sizeof buf, fp)) {
+ char *eol;
/* 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 {
- content_type = buf;
+ cp = buf;
}
/* 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");
+ advise(NULL, "unable to read mime type");
}
+
+ (void) pclose(fp);
} else {
- advise (NULL, "unable to run %s", buf);
+ advise(NULL, "no output from %s", cmd);
}
+
+ free(cmd);
} 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 */
/*
"";
#endif
+char *mimeencodingproc =
+#ifdef MIMEENCODINGPROC
+ MIMEENCODINGPROC;
+#else
+ "";
+#endif
+
struct proc {
char *p_name;
char **p_field;
};
static struct proc procs [] = {
- { "context", &context },
- { "mh-sequences", &mh_seq },
- { "buildmimeproc", &buildmimeproc },
- { "fileproc", &fileproc },
- { "foldprot", &foldprot },
- { "formatproc", &formatproc },
- { "incproc", &incproc },
- { "lproc", &lproc },
- { "mailproc", &mailproc },
- { "mhlproc", &mhlproc },
- { "mimetypeproc", &mimetypeproc },
- { "moreproc", &moreproc },
- { "msgprot", &msgprot },
- { "mshproc", &mshproc },
- { "packproc", &packproc },
- { "postproc", &postproc },
- { "rmmproc", &rmmproc },
- { "sendproc", &sendproc },
- { "showmimeproc", &showmimeproc },
- { "showproc", &showproc },
- { "version", &version_num },
- { "vmhproc", &vmhproc },
- { "whatnowproc", &whatnowproc },
- { "whomproc", &whomproc },
- { "etcdir", &mhetcdir },
- { "libdir", &mhlibdir },
- { "sbackup", &sbackup },
- { "lockmethod", &lockmethod },
- { "sasl", &sasl },
- { "tls", &tls },
- { NULL, NULL },
+ { "context", &context },
+ { "mh-sequences", &mh_seq },
+ { "buildmimeproc", &buildmimeproc },
+ { "fileproc", &fileproc },
+ { "foldprot", &foldprot },
+ { "formatproc", &formatproc },
+ { "incproc", &incproc },
+ { "lproc", &lproc },
+ { "mailproc", &mailproc },
+ { "mhlproc", &mhlproc },
+ { "mimetypeproc", &mimetypeproc },
+ { "mimeencodingproc", &mimeencodingproc },
+ { "moreproc", &moreproc },
+ { "msgprot", &msgprot },
+ { "mshproc", &mshproc },
+ { "packproc", &packproc },
+ { "postproc", &postproc },
+ { "rmmproc", &rmmproc },
+ { "sendproc", &sendproc },
+ { "showmimeproc", &showmimeproc },
+ { "showproc", &showproc },
+ { "version", &version_num },
+ { "vmhproc", &vmhproc },
+ { "whatnowproc", &whatnowproc },
+ { "whomproc", &whomproc },
+ { "etcdir", &mhetcdir },
+ { "libdir", &mhlibdir },
+ { "sbackup", &sbackup },
+ { "lockmethod", &lockmethod },
+ { "sasl", &sasl },
+ { "tls", &tls },
+ { NULL, NULL },
};