]>
diplodocus.org Git - nmh/blob - sbr/mime_type.c
6b4f97254b0ebfdee0ac383941a7b11268b82c57
1 /* mime_type.c -- routine to determine the MIME Content-Type of a file
3 * This code is Copyright (c) 2014, by the authors of nmh. See the
4 * COPYRIGHT file in the root directory of the nmh distribution for
5 * complete copyright information.
12 #include "mime_type.h"
15 static char *get_file_info(const char *, const char *);
16 #endif /* MIMETYPEPROC */
19 * Try to use external command to determine mime type, and possibly
20 * encoding. If that fails try using the filename extension. Caller
21 * is responsible for free'ing returned memory.
24 mime_type(const char *file_name
)
26 char *content_type
= NULL
; /* mime content type */
32 if ((mimetype
= get_file_info(MIMETYPEPROC
, file_name
))) {
33 #ifdef MIMEENCODINGPROC
34 /* Try to append charset for text content. */
37 if (!strncasecmp(mimetype
, "text", 4) &&
38 (mimeencoding
= get_file_info(MIMEENCODINGPROC
, file_name
))) {
39 content_type
= concat(mimetype
, "; charset=", mimeencoding
, NULL
);
43 content_type
= mimetype
;
44 #else /* MIMEENCODINGPROC */
45 content_type
= mimetype
;
46 #endif /* MIMEENCODINGPROC */
48 #endif /* MIMETYPEPROC */
51 * If we didn't get the MIME type from the contents (or we don't support
52 * the necessary command) then use the mhshow suffix.
55 if (content_type
== NULL
) {
56 struct node
*np
; /* Content scan node pointer */
57 FILE *fp
; /* File pointer for mhn.defaults */
59 static bool loaded_defaults
;
60 if (! loaded_defaults
&&
61 (fp
= fopen(p
= etcpath("mhn.defaults"), "r"))) {
62 loaded_defaults
= true;
63 readconfig(NULL
, fp
, p
, 0);
67 if ((p
= strrchr(file_name
, '.')) != NULL
) {
68 for (np
= m_defs
; np
; np
= np
->n_next
) {
69 if (strncasecmp(np
->n_name
, "mhshow-suffix-", 14) == 0 &&
70 strcasecmp(p
, FENDNULL(np
->n_field
)) == 0) {
71 content_type
= strdup(np
->n_name
+ 14);
78 * If we didn't match any filename extension, try to infer the
79 * content type. If we have binary, assume application/octet-stream;
80 * otherwise, assume text/plain.
83 if (content_type
== NULL
) {
87 if (!(fp
= fopen(file_name
, "r"))) {
88 inform("unable to access file \"%s\"", file_name
);
93 while ((c
= getc(fp
)) != EOF
) {
94 if (! isascii(c
) || c
== 0) {
103 strdup(binary
? "application/octet-stream" : "text/plain");
113 * Get information using proc about a file.
114 * Non-null return value must be free(3)'d. */
116 get_file_info(const char *proc
, const char *file_name
)
122 char buf
[max(BUFSIZ
, 2048)];
126 if (strchr(file_name
, '\'')) {
127 if (strchr(file_name
, '"')) {
128 inform("filenames containing both single and double quotes "
129 "are unsupported for attachment");
136 cmd
= concat(proc
, " ", quotec
, file_name
, quotec
, NULL
);
138 inform("concat with \"%s\" failed, out of memory?", proc
);
142 if ((fp
= popen(cmd
, "r")) == NULL
) {
143 inform("no output from %s", cmd
);
148 ok
= fgets(buf
, sizeof buf
, fp
);
154 /* s#^[^:]*:[ \t]*##. */
156 if ((needle
= strchr(info
, ':'))) {
158 while (isblank((unsigned char)*info
))
163 if ((needle
= strpbrk(info
, "\n\r")))
168 #endif /* MIMETYPEPROC */