NetSurf
filetype.c
Go to the documentation of this file.
1/*
2 * Copyright 2004 James Bursa <bursa@users.sourceforge.net>
3 *
4 * This file is part of NetSurf, http://www.netsurf-browser.org/
5 *
6 * NetSurf is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * NetSurf is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <stdlib.h>
20#include <string.h>
21#include <unixlib/local.h>
22#include "oslib/mimemap.h"
23#include "oslib/osfile.h"
24
25#include "utils/config.h"
26#include "utils/log.h"
27#include "netsurf/content.h"
28
29#include "riscos/filetype.h"
30#include "riscos/gui.h"
31
32/* type_map must be in sorted order by file_type */
33struct type_entry {
35 char mime_type[40];
36};
37static const struct type_entry type_map[] = {
38 {0x132, "image/ico"},
39 {0x188, "application/x-shockwave-flash"},
40 {0x695, "image/gif"},
41 {0x69c, "image/x-ms-bmp"},
42 {0xa66, "image/webp"},
43 {0xaad, "image/svg+xml"},
44 {0xaff, "image/x-drawfile"},
45 {0xb60, "image/png"},
46 {0xc85, "image/jpeg"},
47 {0xd94, "image/x-artworks"},
48 {0xf78, "image/jng"},
49 {0xf79, "text/css"},
50 {0xf81, "application/javascript"},
51 {0xf83, "image/mng"},
52 {0xfaf, "text/html"},
53 {0xff9, "image/x-riscos-sprite"},
54 {0xfff, "text/plain"},
55};
56#define TYPE_MAP_COUNT (sizeof(type_map) / sizeof(type_map[0]))
57
58#define BUF_SIZE (256)
59static char type_buf[BUF_SIZE];
60
61
62static int cmp_type(const void *x, const void *y);
63
64/* exported interface documented in riscos/filetype.h */
65const char *fetch_filetype(const char *unix_path)
66{
67 struct type_entry *t;
68 unsigned int len = strlen(unix_path) + 100;
69 char *path = calloc(len, 1);
70 char *r;
71 os_error *error;
72 bits file_type, temp;
73 int objtype;
74
75 if (!path) {
76 NSLOG(netsurf, INFO, "Insufficient memory for calloc");
77 ro_warn_user("NoMemory", 0);
78 return "application/riscos";
79 }
80
81 /* convert path to RISC OS format and read file type */
82 r = __riscosify(unix_path, 0, __RISCOSIFY_NO_SUFFIX, path, len, 0);
83 if (r == 0) {
84 NSLOG(netsurf, INFO, "__riscosify failed");
85 free(path);
86 return "application/riscos";
87 }
88
89 error = xosfile_read_stamped_no_path(path, &objtype, 0, 0, 0, 0,
90 &file_type);
91 if (error) {
92 NSLOG(netsurf, INFO,
93 "xosfile_read_stamped_no_path failed: %s",
94 error->errmess);
95 free(path);
96 return "application/riscos";
97 }
98
99 if (objtype == osfile_IS_DIR) {
100 sprintf(type_buf, "application/x-netsurf-directory");
101 free(path);
102 return (const char *)type_buf;
103 }
104
105 /* If filetype is text or data, and the file has an extension, try to
106 * map the extension to a filetype via the MimeMap file. */
107 if (file_type == osfile_TYPE_TEXT || file_type == osfile_TYPE_DATA) {
108 char *slash = strrchr(path, '/');
109 if (slash) {
110 error = xmimemaptranslate_extension_to_filetype(
111 slash+1, &temp);
112 if (error)
113 /* ignore error and leave file_type alone */
114 NSLOG(netsurf, INFO,
115 "xmimemaptranslate_extension_to_filetype: ""0x%x %s",
116 error->errnum,
117 error->errmess);
118 else
119 file_type = temp;
120 }
121 }
122
123 /* search for MIME type in our internal table */
124 t = bsearch(&file_type, type_map, TYPE_MAP_COUNT,
125 sizeof(type_map[0]), cmp_type);
126 if (t) {
127 /* found, so return it */
128 free(path);
129 return t->mime_type;
130 }
131
132 /* not in internal table, so ask MimeMap */
133 error = xmimemaptranslate_filetype_to_mime_type(file_type, type_buf);
134 if (error) {
135 NSLOG(netsurf, INFO, "0x%x %s", error->errnum, error->errmess);
136 free(path);
137 return "application/riscos";
138 }
139 /* make sure we're NULL terminated. If we're not, the MimeMap
140 * module's probably written past the end of the buffer from
141 * SVC mode. Short of rewriting MimeMap with an incompatible API,
142 * there's nothing we can do about it.
143 */
144 type_buf[BUF_SIZE - 1] = '\0';
145
146 free(path);
147
148 NSLOG(netsurf, INFO, "mime type '%s'", type_buf);
149 return (const char *)type_buf;
150
151}
152
153/* exported interface documented in riscos/filetype.h */
154char *fetch_mimetype(const char *ro_path)
155{
156 os_error *e;
157 bits filetype = 0, load;
158 int objtype;
159 char *mime = calloc(BUF_SIZE, sizeof(char));
160 char *slash;
161 struct type_entry *t;
162
163 if (!mime) {
164 NSLOG(netsurf, INFO, "Insufficient memory for calloc");
165 ro_warn_user("NoMemory", 0);
166 return 0;
167 }
168
169 e = xosfile_read_no_path(ro_path, &objtype, &load, 0, 0, 0);
170 if (e) {
171 NSLOG(netsurf, INFO, "xosfile_read_no_path: 0x%x: %s",
172 e->errnum, e->errmess);
173 free(mime);
174 return 0;
175 }
176
177 if (objtype == osfile_IS_DIR) {
178 free(mime);
179 return 0; /* directories are pointless */
180 }
181
182 if ((load >> 20) & 0xFFF) {
183 filetype = (load>>8) & 0x000FFF;
184 }
185 else {
186 free(mime);
187 return 0; /* no idea */
188 }
189
190 /* If filetype is text and the file has an extension, try to map the
191 * extension to a filetype via the MimeMap file. */
192 slash = strrchr(ro_path, '/');
193 if (slash && filetype == osfile_TYPE_TEXT) {
194 e = xmimemaptranslate_extension_to_filetype(slash+1, &load);
195 if (e)
196 /* if we get an error here, simply ignore it and
197 * leave filetype unchanged */
198 NSLOG(netsurf, INFO, "0x%x %s", e->errnum, e->errmess);
199 else
200 filetype = load;
201 }
202
203 /* search for MIME type in our internal table */
204 t = bsearch(&filetype, type_map, TYPE_MAP_COUNT,
205 sizeof(type_map[0]), cmp_type);
206 if (t) {
207 /* found, so return it */
208 strncpy(mime, t->mime_type, BUF_SIZE);
209 return mime;
210 }
211
212 /* not in internal table, so ask MimeMap */
213 e = xmimemaptranslate_filetype_to_mime_type(filetype, mime);
214 if (e) {
215 NSLOG(netsurf, INFO,
216 "xmimemaptranslate_filetype_to_mime_type: 0x%x: %s",
217 e->errnum,
218 e->errmess);
219 free(mime);
220 return 0;
221 }
222 /* make sure we're NULL terminated. If we're not, the MimeMap
223 * module's probably written past the end of the buffer from
224 * SVC mode. Short of rewriting MimeMap with an incompatible API,
225 * there's nothing we can do about it.
226 */
227 mime[BUF_SIZE - 1] = '\0';
228
229 return mime;
230}
231
232/**
233 * Comparison function for bsearch
234 */
235int cmp_type(const void *x, const void *y)
236{
237 const bits *p = x;
238 const struct type_entry *q = y;
239 return *p < q->file_type ? -1 : (*p == q->file_type ? 0 : +1);
240}
241
242/* exported interface documented in riscos/filetype.h */
244{
245 lwc_string *mime_type;
246 int file_type;
247
249 if (file_type != 0)
250 return file_type;
251
253
255
256 lwc_string_unref(mime_type);
257
258 return file_type;
259}
260
261
262/* exported interface documented in riscos/filetype.h */
264{
265 switch (ro_content_filetype(c)) {
266 case FILETYPE_JPEG: /* jpeg */
267 case FILETYPE_JNG: /* jng */
268 case FILETYPE_MNG: /* mng */
269 case FILETYPE_GIF: /* gif */
270 case FILETYPE_BMP: /* bmp */
271 case FILETYPE_ICO: /* ico */
272 case FILETYPE_PNG: /* png */
273 case FILETYPE_WEBP: /* webp */
274 case 0xff9: /* sprite */
275 return osfile_TYPE_SPRITE;
276 case FILETYPE_SVG: /* svg */
277 case 0xaff: /* draw */
278 return osfile_TYPE_DRAW;
279 default:
280 break;
281 }
282
283 return osfile_TYPE_DATA;
284}
285
286
287/* exported interface documented in riscos/filetype.h */
289{
290 int file_type, index;
291 os_error *error;
292
293 /* Search internal type map */
294 for (index = TYPE_MAP_COUNT; index > 0; index--) {
295 const struct type_entry *e = &type_map[index - 1];
296
297 if (strlen(e->mime_type) == lwc_string_length(mime_type) &&
298 strncasecmp(e->mime_type,
299 lwc_string_data(mime_type),
300 lwc_string_length(mime_type)) == 0)
301 return e->file_type;
302 }
303
304 /* Ask MimeMap module */
305 error = xmimemaptranslate_mime_type_to_filetype(
306 lwc_string_data(mime_type), (bits *) &file_type);
307 if (error)
308 file_type = 0xffd;
309
310 return file_type;
311}
312
313
314/* exported interface documented in riscos/filetype.h */
316 switch (type) {
317 case CONTENT_HTML: return FILETYPE_HTML;
318 case CONTENT_TEXTPLAIN: return 0xfff;
319 case CONTENT_CSS: return 0xf79;
320 default: break;
321 }
322 return 0;
323}
324
325
326/* exported interface documented in riscos/filetype.h */
327bits ro_filetype_from_unix_path(const char *unix_path)
328{
329 unsigned int len = strlen(unix_path) + 100;
330 char *path = calloc(len, 1);
331 char *r;
332 os_error *error;
333 bits file_type;
334
335 if (!path) {
336 NSLOG(netsurf, INFO, "Insufficient memory for calloc");
337 ro_warn_user("NoMemory", 0);
338 return osfile_TYPE_DATA;
339 }
340
341 /* convert path to RISC OS format and read file type */
342 r = __riscosify(unix_path, 0, __RISCOSIFY_NO_SUFFIX, path, len, 0);
343 if (r == 0) {
344 NSLOG(netsurf, INFO, "__riscosify failed");
345 free(path);
346 return osfile_TYPE_DATA;
347 }
348
349 error = xosfile_read_stamped_no_path(path, 0, 0, 0, 0, 0,
350 &file_type);
351 if (error) {
352 NSLOG(netsurf, INFO,
353 "xosfile_read_stamped_no_path failed: %s",
354 error->errmess);
355 free(path);
356 return osfile_TYPE_DATA;
357 }
358
359 free(path);
360
361 return file_type;
362}
363
const char * fetch_filetype(const char *unix_path)
Determine the MIME type of a local file.
Definition: filetype.c:58
content_type
The type of a content.
Definition: content_type.h:53
@ CONTENT_CSS
content is CSS
Definition: content_type.h:64
@ CONTENT_HTML
content is HTML
Definition: content_type.h:58
@ CONTENT_TEXTPLAIN
content is plain text
Definition: content_type.h:61
const char * type
Definition: filetype.cpp:44
Public content interface.
lwc_string * content_get_mime_type(struct hlcache_handle *h)
Retrieve mime-type of content.
Definition: content.c:1073
content_type content_get_type(struct hlcache_handle *h)
Retrieve computed type of content.
Definition: content.c:1061
#define NSLOG(catname, level, logmsg, args...)
Definition: log.h:116
int ro_content_filetype_from_mime_type(lwc_string *mime_type)
Determine the RISC OS filetype for a MIME type.
Definition: filetype.c:288
char * fetch_mimetype(const char *ro_path)
Find a MIME type for a local file.
Definition: filetype.c:154
static const struct type_entry type_map[]
Definition: filetype.c:37
bits ro_filetype_from_unix_path(const char *unix_path)
Determine the type of a local file.
Definition: filetype.c:327
int ro_content_filetype(struct hlcache_handle *c)
Determine the RISC OS filetype for a content.
Definition: filetype.c:243
static int cmp_type(const void *x, const void *y)
Comparison function for bsearch.
Definition: filetype.c:235
int ro_content_filetype_from_type(content_type type)
Determine the RISC OS filetype from a content type.
Definition: filetype.c:315
int ro_content_native_type(struct hlcache_handle *c)
Determine the native RISC OS filetype to export a content as.
Definition: filetype.c:263
#define TYPE_MAP_COUNT
Definition: filetype.c:56
#define BUF_SIZE
Definition: filetype.c:58
static char type_buf[BUF_SIZE]
Definition: filetype.c:59
RISC OS filetpe interface.
#define FILETYPE_HTML
Definition: filetype.h:38
#define FILETYPE_PNG
Definition: filetype.h:59
#define FILETYPE_GIF
Definition: filetype.h:50
#define FILETYPE_ICO
Definition: filetype.h:56
#define FILETYPE_JPEG
Definition: filetype.h:62
#define FILETYPE_WEBP
Definition: filetype.h:71
#define FILETYPE_JNG
Definition: filetype.h:41
#define FILETYPE_MNG
Definition: filetype.h:47
#define FILETYPE_BMP
Definition: filetype.h:53
#define FILETYPE_SVG
Definition: filetype.h:68
nserror ro_warn_user(const char *warning, const char *detail)
Display a warning for a serious problem (eg memory exhaustion).
Definition: gui.c:2076
Interface to utility string handling.
High-level cache handle.
Definition: hlcache.c:66
Definition: filetype.c:33
bits file_type
Definition: filetype.c:34
char mime_type[40]
Definition: filetype.c:35
static nserror path(const struct redraw_context *ctx, const plot_style_t *pstyle, const float *p, unsigned int n, const float transform[6])
Plots a path.
Definition: plot.c:821