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
This commit is contained in:
Rob Kendrick 2007-05-29 23:53:35 +00:00
parent 01316168fc
commit 7bc1a41ea0
4 changed files with 218 additions and 3 deletions

199
gtk/gtk_filetype.c Normal file
View File

@ -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 <rjek@netsurf-browser.org>
* Copyright 2007 Vincent Sanders <vince@debian.org>
*/
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#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

12
gtk/gtk_filetype.h Normal file
View File

@ -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 <rjek@netsurf-browser.org>
* Copyright 2007 Vincent Sanders <vince@debian.org>
*/
void gtk_fetch_filetype_init(const char *mimefile);
void gtk_fetch_filetype_fin(void);

View File

@ -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();
}

View File

@ -65,14 +65,13 @@ OBJECTS_DEBUGRO += artworks.o awrender.o bitmap.o draw.o \
sprite.o # riscos/
OBJECTS_GTK = $(OBJECTS_COMMON) $(OBJECTS_IMAGE)
OBJECTS_GTK += filetyped.o # debug/
OBJECTS_GTK += browser.o frames.o history_core.o netsurf.o \
selection.o textinput.o gesture_core.o # desktop/
OBJECTS_GTK += font_pango.o gtk_bitmap.o gtk_gui.o \
gtk_schedule.o gtk_thumbnail.o gtk_options.o \
gtk_plotters.o gtk_treeview.o gtk_scaffolding.o \
gtk_completion.o gtk_login.o gtk_throbber.o \
gtk_history.o gtk_window.o # gtk/
gtk_history.o gtk_window.o gtk_filetype.o # gtk/
OBJDIR_RISCOS = arm-riscos-aof
@ -132,7 +131,7 @@ CFLAGS_GTK = -std=c99 -Dgtk -Dnsgtk \
-D_BSD_SOURCE \
-DGTK_DISABLE_DEPRECATED \
-D_POSIX_C_SOURCE \
$(WARNFLAGS) -I.. -g -O0 -Wformat=2 \
$(WARNFLAGS) -I.. -g -O2 -Wformat=2 \
`pkg-config --cflags libglade-2.0 gtk+-2.0` `xml2-config --cflags`
# Stop GCC under Cygwin throwing a fit