Handle mailcap's copiousoutput without an external pager.
[elinks.git] / src / mime / backend / default.c
blob2f21dd9c035bd6cfdb881f098933c54f2d48675f
1 /* Option system based mime backend */
3 #ifdef HAVE_CONFIG_H
4 #include "config.h"
5 #endif
7 #include <string.h>
9 #include "elinks.h"
11 #include "config/options.h"
12 #include "intl/gettext/libintl.h"
13 #include "main/module.h"
14 #include "mime/backend/common.h"
15 #include "mime/backend/default.h"
16 #include "mime/mime.h"
17 #include "osdep/osdep.h" /* For get_system_str() */
18 #include "terminal/terminal.h"
19 #include "util/conv.h"
20 #include "util/memory.h"
21 #include "util/string.h"
24 static struct option_info default_mime_options[] = {
25 INIT_OPT_TREE("mime", N_("MIME type associations"),
26 "type", OPT_AUTOCREATE,
27 N_("Handler <-> MIME type association. The first sub-tree is "
28 "the MIME class while the second sub-tree is the MIME type "
29 "(ie. image/gif handler will reside at mime.type.image.gif). "
30 "Each MIME type option should contain (case-sensitive) name "
31 "of the MIME handler (its properties are stored at "
32 "mime.handler.<name>).")),
34 INIT_OPT_TREE("mime.type", NULL,
35 "_template_", OPT_AUTOCREATE,
36 N_("Handler matching this MIME-type class "
37 "('*' is used here in place of '.').")),
39 INIT_OPT_STRING("mime.type._template_", NULL,
40 "_template_", 0, "",
41 N_("Handler matching this MIME-type name "
42 "('*' is used here in place of '.').")),
45 INIT_OPT_TREE("mime", N_("File type handlers"),
46 "handler", OPT_AUTOCREATE,
47 N_("A file type handler is a set of information about how to "
48 "use an external program to view a file. It is possible to "
49 "refer to it for several MIME types -- e.g., you can define "
50 "an 'image' handler to which mime.type.image.png, "
51 "mime.type.image.jpeg, and so on will refer; or one might "
52 "define a handler for a more specific type of file -- e.g., "
53 "PDF files. Note you must define both a MIME handler "
54 "and a MIME type association for it to work.")),
56 INIT_OPT_TREE("mime.handler", NULL,
57 "_template_", OPT_AUTOCREATE,
58 N_("Description of this handler.")),
60 INIT_OPT_TREE("mime.handler._template_", NULL,
61 "_template_", 0,
62 N_("System-specific handler description "
63 "(ie. unix, unix-xwin, ...).")),
65 INIT_OPT_BOOL("mime.handler._template_._template_", N_("Ask before opening"),
66 "ask", 0, 1,
67 N_("Ask before opening.")),
69 INIT_OPT_BOOL("mime.handler._template_._template_", N_("Block terminal"),
70 "block", 0, 1,
71 N_("Block the terminal when the handler is running.")),
73 INIT_OPT_STRING("mime.handler._template_._template_", N_("Program"),
74 "program", 0, "",
75 /* xgettext:no-c-format */
76 N_("External viewer for this file type. "
77 "'%' in this string will be substituted by a file name. "
78 "Do _not_ put single- or double-quotes around the % sign.")),
81 INIT_OPT_TREE("mime", N_("File extension associations"),
82 "extension", OPT_AUTOCREATE,
83 N_("Extension <-> MIME type association.")),
85 INIT_OPT_STRING("mime.extension", NULL,
86 "_template_", 0, "",
87 N_("MIME-type matching this file extension "
88 "('*' is used here in place of '.').")),
90 #define INIT_OPT_MIME_EXTENSION(extension, type) \
91 INIT_OPT_STRING("mime.extension", NULL, extension, 0, type, NULL)
93 INIT_OPT_MIME_EXTENSION("gif", "image/gif"),
94 INIT_OPT_MIME_EXTENSION("jpg", "image/jpg"),
95 INIT_OPT_MIME_EXTENSION("jpeg", "image/jpeg"),
96 INIT_OPT_MIME_EXTENSION("png", "image/png"),
97 INIT_OPT_MIME_EXTENSION("txt", "text/plain"),
98 INIT_OPT_MIME_EXTENSION("htm", "text/html"),
99 INIT_OPT_MIME_EXTENSION("html", "text/html"),
100 #ifdef CONFIG_BITTORRENT
101 INIT_OPT_MIME_EXTENSION("torrent", "application/x-bittorrent"),
102 #endif
103 #ifdef CONFIG_DOM
104 INIT_OPT_MIME_EXTENSION("rss", "application/rss+xml"),
105 INIT_OPT_MIME_EXTENSION("xbel", "application/xbel+xml"),
106 INIT_OPT_MIME_EXTENSION("sgml", "application/docbook+xml"),
107 #endif
109 NULL_OPTION_INFO,
112 static unsigned char *
113 get_content_type_default(unsigned char *extension)
115 struct option *opt_tree;
116 struct option *opt;
117 unsigned char *extend = extension + strlen(extension) - 1;
119 if (extend < extension) return NULL;
121 opt_tree = get_opt_rec_real(config_options, "mime.extension");
122 assert(opt_tree);
124 foreach (opt, *opt_tree->value.tree) {
125 unsigned char *namepos = opt->name + strlen(opt->name) - 1;
126 unsigned char *extpos = extend;
128 /* Match the longest possible part of URL.. */
130 #define star2dot(achar) ((achar) == '*' ? '.' : (achar))
132 while (extension <= extpos && opt->name <= namepos
133 && *extpos == star2dot(*namepos)) {
134 extpos--;
135 namepos--;
138 #undef star2dot
140 /* If we matched whole extension and it is really an
141 * extension.. */
142 if (namepos < opt->name
143 && (extpos < extension || *extpos == '.'))
144 return stracpy(opt->value.string);
147 return NULL;
150 static struct option *
151 get_mime_type_option(unsigned char *type)
153 struct option *opt;
154 struct string name;
156 opt = get_opt_rec_real(config_options, "mime.type");
157 if (!opt) return NULL;
159 if (!init_string(&name)) return NULL;
161 if (add_optname_to_string(&name, type, strlen(type))) {
162 /* Search for end of the base type. */
163 unsigned char *pos = strchr(name.source, '/');
165 if (pos) {
166 *pos = '.';
167 opt = get_opt_rec_real(opt, name.source);
168 done_string(&name);
170 return opt;
174 done_string(&name);
175 return NULL;
178 static inline struct option *
179 get_mime_handler_option(struct option *type_opt, int xwin)
181 struct option *handler_opt;
183 assert(type_opt);
185 handler_opt = get_opt_rec_real(config_options, "mime.handler");
186 if (!handler_opt) return NULL;
188 handler_opt = get_opt_rec_real(handler_opt, type_opt->value.string);
189 if (!handler_opt) return NULL;
191 return get_opt_rec_real(handler_opt, get_system_str(xwin));
194 static struct mime_handler *
195 get_mime_handler_default(unsigned char *type, int have_x)
197 struct option *type_opt = get_mime_type_option(type);
198 struct option *handler_opt;
200 if (!type_opt) return NULL;
202 handler_opt = get_mime_handler_option(type_opt, have_x);
203 if (!handler_opt) return NULL;
205 return init_mime_handler(get_opt_str_tree(handler_opt, "program", NULL),
206 type_opt->value.string,
207 default_mime_module.name,
208 get_opt_bool_tree(handler_opt, "ask", NULL),
209 get_opt_bool_tree(handler_opt, "block", NULL));
213 const struct mime_backend default_mime_backend = {
214 /* get_content_type: */ get_content_type_default,
215 /* get_mime_handler: */ get_mime_handler_default,
218 struct module default_mime_module = struct_module(
219 /* name: */ N_("Option system"),
220 /* options: */ default_mime_options,
221 /* hooks: */ NULL,
222 /* submodules: */ NULL,
223 /* data: */ NULL,
224 /* init: */ NULL,
225 /* done: */ NULL