-/*
- * mime_type.c -- routine to determine the MIME Content-Type of a file
+/* mime_type.c -- routine to determine the MIME Content-Type of a file
*
* This code is Copyright (c) 2014, by the authors of nmh. See the
* COPYRIGHT file in the root directory of the nmh distribution for
#include <h/mh.h>
#include <h/utils.h>
#include <h/tws.h>
+#include "mime_type.h"
#ifdef MIMETYPEPROC
static char *get_file_info(const char *, const char *);
/* 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);
- }
+ if (!strncasecmp(mimetype, "text", 4) &&
+ (mimeencoding = get_file_info(MIMEENCODINGPROC, file_name))) {
+ content_type = concat(mimetype, "; charset=", mimeencoding, NULL);
+ free(mimeencoding);
+ free(mimetype);
+ } else
+ content_type = mimetype;
#else /* MIMEENCODINGPROC */
- content_type = strdup(mimetype);
+ content_type = mimetype;
#endif /* MIMEENCODINGPROC */
}
#endif /* MIMETYPEPROC */
if ((p = strrchr(file_name, '.')) != NULL) {
for (np = m_defs; np; np = np->n_next) {
if (strncasecmp(np->n_name, "mhshow-suffix-", 14) == 0 &&
- strcasecmp(p, np->n_field ? np->n_field : "") == 0) {
+ strcasecmp(p, FENDNULL(np->n_field)) == 0) {
content_type = strdup(np->n_name + 14);
break;
}
int binary = 0, c;
if (!(fp = fopen(file_name, "r"))) {
- advise (NULL, "unable to access file \"%s\"", file_name);
+ inform("unable to access file \"%s\"", file_name);
return NULL;
}
while ((c = getc(fp)) != EOF) {
- if (! isascii(c)) {
+ if (! isascii(c) || c == 0) {
binary = 1;
break;
}
#ifdef MIMETYPEPROC
/*
* Get information using proc about a file.
- */
+ * Non-null return value must be free(3)'d. */
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. */
+get_file_info(const char *proc, const char *file_name)
+{
+ char *quotec;
+ char *cmd;
+ FILE *fp;
+ bool ok;
+ char buf[max(BUFSIZ, 2048)];
+ char *info;
+ char *needle;
+
+ if (strchr(file_name, '\'')) {
if (strchr(file_name, '"')) {
- advise(NULL, "filenames containing both single and double quotes "
- "are unsupported for attachment");
+ inform("filenames containing both single and double quotes "
+ "are unsupported for attachment");
return NULL;
- } else {
- quotec = "\"";
}
- }
+ quotec = "\"";
+ } 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. */
- if ((cp = strchr(buf, ':')) != NULL) {
- ++cp;
- while (*cp && isblank((unsigned char) *cp)) {
- ++cp;
- }
- } else {
- cp = buf;
- }
-
- /* Truncate at newline (LF or CR), if present. */
- if ((eol = strpbrk(cp, "\n\r")) != NULL) {
- *eol = '\0';
- }
- } 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 {
- advise(NULL, "no output from %s", cmd);
- }
+ if (!cmd) {
+ inform("concat with \"%s\" failed, out of memory?", proc);
+ return NULL;
+ }
+ if ((fp = popen(cmd, "r")) == NULL) {
+ inform("no output from %s", cmd);
free(cmd);
- } else {
- advise(NULL, "concat with \"%s\" failed, out of memory?", proc);
+ return NULL;
}
- return cp ? strdup(cp) : NULL;
+ ok = fgets(buf, sizeof buf, fp);
+ free(cmd);
+ (void)pclose(fp);
+ if (!ok)
+ return NULL;
+
+ /* s#^.*:[ \t]*##. */
+ info = buf;
+ if ((needle = strchr(info, ':'))) {
+ info = needle + 1;
+ while (isblank((unsigned char)*info))
+ info++;
+ }
+
+ /* s#[\n\r].*##. */
+ if ((needle = strpbrk(info, "\n\r")))
+ *needle = '\0';
+
+ return strdup(info);
}
#endif /* MIMETYPEPROC */