From 7bc1a41ea0f2188de75445e0e23993b6c6b0006f Mon Sep 17 00:00:00 2001 From: Rob Kendrick Date: Tue, 29 May 2007 23:53:35 +0000 Subject: Add UNIX-specific fetch_filetype() support. Uses /etc/mime.types by default, but can build minimal mappings if it doesn't exist. New code allows file:// directory listings to be generated, although these are not sorted unlike under RISC OS, as POSIX dirent() doesn't specify sorting. svn path=/trunk/netsurf/; revision=3305 --- gtk/gtk_filetype.c | 199 +++++++++++++++++++++++++++++++++++++++++++++++++++++ gtk/gtk_filetype.h | 12 ++++ gtk/gtk_gui.c | 5 ++ 3 files changed, 216 insertions(+) create mode 100644 gtk/gtk_filetype.c create mode 100644 gtk/gtk_filetype.h (limited to 'gtk') diff --git a/gtk/gtk_filetype.c b/gtk/gtk_filetype.c new file mode 100644 index 000000000..667129e05 --- /dev/null +++ b/gtk/gtk_filetype.c @@ -0,0 +1,199 @@ +/* + * This file is part of NetSurf, http://netsurf-browser.org/ + * Licensed under the GNU General Public License, + * http://www.opensource.org/licenses/gpl-license + * Copyright 2007 Rob Kendrick + * Copyright 2007 Vincent Sanders + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "netsurf/gtk/gtk_filetype.h" +#include "netsurf/content/fetch.h" +#include "netsurf/utils/log.h" +#include "netsurf/utils/hashtable.h" + +static struct hash_table *mime_hash = NULL; + +void gtk_fetch_filetype_init(const char *mimefile) +{ + struct stat statbuf; + FILE *fh = NULL; + + mime_hash = hash_create(117); + + /* first, check to see if /etc/mime.types in preference */ + + if ((stat("/etc/mime.types", &statbuf) == 0) && + S_ISREG(statbuf.st_mode)) { + mimefile = "/etc/mime.types"; + + } + + fh = fopen(mimefile, "r"); + + if (fh == NULL) { + LOG(("Unable to open a mime.types file, so building a minimal one for you.")); + hash_add(mime_hash, "css", "text/css"); + hash_add(mime_hash, "jpg", "image/jpeg"); + hash_add(mime_hash, "jpeg", "image/jpeg"); + hash_add(mime_hash, "gif", "image/gif"); + hash_add(mime_hash, "png", "image/png"); + hash_add(mime_hash, "jng", "image/jng"); + + return; + } + + while (!feof(fh)) { + char line[256], *ptr, *type, *ext; + fgets(line, 256, fh); + if (!feof(fh) && line[0] != '#') { + ptr = line; + + /* search for the first non-whitespace character */ + while (isspace(*ptr)) + ptr++; + + /* is this line empty other than leading whitespace? */ + if (*ptr == '\n' || *ptr == '\0') + continue; + + type = ptr; + + /* search for the first non-whitespace char or NUL or + * NL */ + while (*ptr && (!isspace(*ptr)) && *ptr != '\n') + ptr++; + + if (*ptr == '\0' || *ptr == '\n') { + /* this mimetype has no extensions - read next + * line. + */ + continue; + } + + *ptr++ = '\0'; + + /* search for the first non-whitespace character which + * will be the first filename extenion */ + while (isspace(*ptr)) + ptr++; + + while(true) { + ext = ptr; + + /* search for the first whitespace char or + * NUL or NL which is the end of the ext. + */ + while (*ptr && (!isspace(*ptr)) && + *ptr != '\n') + ptr++; + + if (*ptr == '\0' || *ptr == '\n') { + /* special case for last extension on + * the line + */ + *ptr = '\0'; + hash_add(mime_hash, ext, type); + break; + } + + *ptr++ = '\0'; + hash_add(mime_hash, ext, type); + + /* search for the first non-whitespace char or + * NUL or NL, to find start of next ext. + */ + while (*ptr && (isspace(*ptr)) && *ptr != '\n') + ptr++; + } + } + } + + fclose(fh); +} + +void gtk_fetch_filetype_fin(void) +{ + hash_destroy(mime_hash); +} + +const char *fetch_filetype(const char *unix_path) +{ + struct stat statbuf; + char *ext; + const char *ptr; + char *lowerchar; + const char *type; + + stat(unix_path, &statbuf); + if (S_ISDIR(statbuf.st_mode)) + return "application/x-netsurf-directory"; + + if (strchr(unix_path, '.') == NULL) { + /* no extension anywhere! */ + return "text/plain"; + } + + ptr = unix_path + strlen(unix_path); + while (*ptr != '.' && *ptr != '/') + ptr--; + + if (*ptr != '.') + return "text/plain"; + + ext = strdup(ptr + 1); /* skip the . */ + + /* the hash table only contains lower-case versions - make sure this + * copy is lower case too. + */ + lowerchar = ext; + while(*lowerchar) { + *lowerchar = tolower(*lowerchar); + lowerchar++; + } + + type = hash_get(mime_hash, ext); + free(ext); + + return type != NULL ? type : "text/plain"; +} + +char *fetch_mimetype(const char *unix_path) +{ + return strdup(fetch_filetype(unix_path)); +} + +#ifdef TEST_RIG + +int main(int argc, char *argv[]) +{ + unsigned int c1, *c2; + const char *key; + + gtk_fetch_filetype_init("./mime.types"); + + c1 = 0; c2 = 0; + + while ( (key = hash_iterate(mime_hash, &c1, &c2)) != NULL) { + printf("%s ", key); + } + + printf("\n"); + + if (argc > 1) { + printf("%s maps to %s\n", argv[1], fetch_filetype(argv[1])); + } + + gtk_fetch_filetype_fin(); +} + +#endif + diff --git a/gtk/gtk_filetype.h b/gtk/gtk_filetype.h new file mode 100644 index 000000000..e0bab6c3e --- /dev/null +++ b/gtk/gtk_filetype.h @@ -0,0 +1,12 @@ +/* + * This file is part of NetSurf, http://netsurf-browser.org/ + * Licensed under the GNU General Public License, + * http://www.opensource.org/licenses/gpl-license + * Copyright 2007 Rob Kendrick + * Copyright 2007 Vincent Sanders + */ + +void gtk_fetch_filetype_init(const char *mimefile); +void gtk_fetch_filetype_fin(void); + + diff --git a/gtk/gtk_gui.c b/gtk/gtk_gui.c index fe35f1e2f..a2c98b9c5 100644 --- a/gtk/gtk_gui.c +++ b/gtk/gtk_gui.c @@ -35,6 +35,7 @@ #include "netsurf/gtk/options.h" #include "netsurf/gtk/gtk_throbber.h" #include "netsurf/gtk/gtk_history.h" +#include "netsurf/gtk/gtk_filetype.h" #include "netsurf/render/box.h" #include "netsurf/render/form.h" #include "netsurf/render/html.h" @@ -212,6 +213,9 @@ void gui_init(int argc, char** argv) LOG(("Using '%s' as Messages file", buf)); messages_load(buf); + find_resource(buf, "mime.types", "/etc/mime.types"); + gtk_fetch_filetype_init(buf); + /* set up stylesheet urls */ find_resource(buf, "default.css", "./gtk/res/default.css"); default_stylesheet_url = path_to_url(buf); @@ -321,6 +325,7 @@ void gui_quit(void) free(adblock_stylesheet_url); free(option_cookie_file); free(option_cookie_jar); + gtk_fetch_filetype_fin(); } -- cgit v1.2.3