2007-05-30 03:53:35 +04:00
|
|
|
/*
|
2016-01-13 19:35:24 +03:00
|
|
|
* Copyright 2007, 2014 Vincent Sanders <vince@netsurf-browser.org>
|
|
|
|
* Copyright 2007 Rob Kendrick <rjek@netsurf-browser.org>
|
2007-08-08 20:16:03 +04:00
|
|
|
*
|
|
|
|
* This file is part of NetSurf, http://www.netsurf-browser.org/
|
|
|
|
*
|
|
|
|
* NetSurf is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; version 2 of the License.
|
|
|
|
*
|
|
|
|
* NetSurf is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2007-05-30 03:53:35 +04:00
|
|
|
*/
|
2007-08-08 20:16:03 +04:00
|
|
|
|
2016-09-07 23:28:02 +03:00
|
|
|
/**
|
|
|
|
* \file
|
|
|
|
* file extension to mimetype mapping for the GTK frontend
|
|
|
|
*
|
|
|
|
* allows GTK frontend to map file extension to mime types using a
|
|
|
|
* default builtin list and /etc/mime.types file if present.
|
|
|
|
*
|
|
|
|
* mime type and content type handling is derived from the BNF in
|
|
|
|
* RFC822 section 3.3, RFC2045 section 5.1 and RFC6838 section
|
|
|
|
* 4.2. Upshot is their charset and parsing is all a strict subset of
|
|
|
|
* ASCII hence not using locale dependant ctype functions for parsing.
|
|
|
|
*/
|
|
|
|
|
2018-04-22 15:10:16 +03:00
|
|
|
#include <stdint.h>
|
2007-05-30 03:53:35 +04:00
|
|
|
#include <stdio.h>
|
2014-02-01 18:23:58 +04:00
|
|
|
#include <stdlib.h>
|
2007-05-30 03:53:35 +04:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <unistd.h>
|
2014-01-30 01:35:53 +04:00
|
|
|
#include <string.h>
|
2014-12-28 01:48:37 +03:00
|
|
|
#include <strings.h>
|
2015-04-12 22:26:53 +03:00
|
|
|
#include <gtk/gtk.h>
|
2007-05-30 03:53:35 +04:00
|
|
|
|
2014-01-26 03:00:22 +04:00
|
|
|
#include "utils/log.h"
|
2018-04-22 15:10:16 +03:00
|
|
|
#include "utils/hashtable.h"
|
2014-01-26 03:00:22 +04:00
|
|
|
#include "utils/filepath.h"
|
2014-05-27 02:43:36 +04:00
|
|
|
#include "utils/file.h"
|
2015-04-12 22:26:53 +03:00
|
|
|
#include "utils/nsurl.h"
|
2016-09-07 23:28:02 +03:00
|
|
|
#include "utils/ascii.h"
|
2016-05-30 13:29:39 +03:00
|
|
|
#include "netsurf/fetch.h"
|
2014-01-26 03:00:22 +04:00
|
|
|
|
|
|
|
#include "gtk/gui.h"
|
2015-06-17 23:29:48 +03:00
|
|
|
#include "gtk/resources.h"
|
2014-01-26 03:00:22 +04:00
|
|
|
#include "gtk/fetch.h"
|
2007-05-30 03:53:35 +04:00
|
|
|
|
2016-01-13 19:35:24 +03:00
|
|
|
#define HASH_SIZE 117
|
|
|
|
#define MAX_LINE_LEN 256
|
|
|
|
|
2007-05-30 03:53:35 +04:00
|
|
|
static struct hash_table *mime_hash = NULL;
|
|
|
|
|
|
|
|
void gtk_fetch_filetype_init(const char *mimefile)
|
|
|
|
{
|
|
|
|
struct stat statbuf;
|
|
|
|
FILE *fh = NULL;
|
|
|
|
|
2016-01-13 19:35:24 +03:00
|
|
|
mime_hash = hash_create(HASH_SIZE);
|
2007-08-08 20:16:03 +04:00
|
|
|
|
2007-06-16 02:03:19 +04:00
|
|
|
/* Some OSes (mentioning no Solarises) have a worthlessly tiny
|
|
|
|
* /etc/mime.types that don't include essential things, so we
|
|
|
|
* pre-seed our hash with the essentials. These will get
|
|
|
|
* over-ridden if they are mentioned in the mime.types file.
|
|
|
|
*/
|
2007-08-08 20:16:03 +04:00
|
|
|
|
2007-06-16 02:03:19 +04:00
|
|
|
hash_add(mime_hash, "css", "text/css");
|
2008-04-28 15:08:35 +04:00
|
|
|
hash_add(mime_hash, "htm", "text/html");
|
|
|
|
hash_add(mime_hash, "html", "text/html");
|
2007-06-16 02:03:19 +04:00
|
|
|
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");
|
2010-10-16 17:50:35 +04:00
|
|
|
hash_add(mime_hash, "mng", "image/mng");
|
|
|
|
hash_add(mime_hash, "webp", "image/webp");
|
2009-03-09 03:58:23 +03:00
|
|
|
hash_add(mime_hash, "spr", "image/x-riscos-sprite");
|
2016-08-16 15:08:44 +03:00
|
|
|
hash_add(mime_hash, "bmp", "image/bmp");
|
2007-06-16 02:03:19 +04:00
|
|
|
|
2016-09-07 23:28:02 +03:00
|
|
|
/* 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");
|
2007-05-30 03:53:35 +04:00
|
|
|
if (fh == NULL) {
|
Use coccinelle to change logging macro calls in c files
for F in $(git ls-files '*.c');do spatch --sp-file foo.cocci --in-place ${F};done
@@ expression E; @@
-LOG(E);
+NSLOG(netsurf, INFO, E);
@@ expression E, E1; @@
-LOG(E, E1);
+NSLOG(netsurf, INFO, E, E1);
@@ expression E, E1, E2; @@
-LOG(E, E1, E2);
+NSLOG(netsurf, INFO, E, E1, E2);
@@ expression E, E1, E2, E3; @@
-LOG(E, E1, E2, E3);
+NSLOG(netsurf, INFO, E, E1, E2, E3);
@@ expression E, E1, E2, E3, E4; @@
-LOG(E, E1, E2, E3, E4);
+NSLOG(netsurf, INFO, E, E1, E2, E3, E4);
@@ expression E, E1, E2, E3, E4, E5; @@
-LOG(E, E1, E2, E3, E4, E5);
+NSLOG(netsurf, INFO, E, E1, E2, E3, E4, E5);
@@ expression E, E1, E2, E3, E4, E5, E6; @@
-LOG(E, E1, E2, E3, E4, E5, E6);
+NSLOG(netsurf, INFO, E, E1, E2, E3, E4, E5, E6);
@@ expression E, E1, E2, E3, E4, E5, E6, E7; @@
-LOG(E, E1, E2, E3, E4, E5, E6, E7);
+NSLOG(netsurf, INFO, E, E1, E2, E3, E4, E5, E6, E7);
2017-09-06 20:28:12 +03:00
|
|
|
NSLOG(netsurf, INFO,
|
|
|
|
"Unable to open a mime.types file, so using a minimal one for you.");
|
2007-05-30 03:53:35 +04:00
|
|
|
return;
|
|
|
|
}
|
2007-08-08 20:16:03 +04:00
|
|
|
|
2016-01-13 19:35:24 +03:00
|
|
|
while (feof(fh) == 0) {
|
|
|
|
char line[MAX_LINE_LEN], *ptr, *type, *ext;
|
2014-01-26 03:00:22 +04:00
|
|
|
|
2016-01-13 19:35:24 +03:00
|
|
|
if (fgets(line, sizeof(line), fh) == NULL)
|
2014-01-26 03:00:22 +04:00
|
|
|
break;
|
|
|
|
|
2016-01-13 19:35:24 +03:00
|
|
|
if ((feof(fh) == 0) && line[0] != '#') {
|
2007-05-30 03:53:35 +04:00
|
|
|
ptr = line;
|
2007-08-08 20:16:03 +04:00
|
|
|
|
2007-05-30 03:53:35 +04:00
|
|
|
/* search for the first non-whitespace character */
|
2016-09-07 23:28:02 +03:00
|
|
|
while (ascii_is_space(*ptr)) {
|
2007-05-30 03:53:35 +04:00
|
|
|
ptr++;
|
2014-01-26 03:00:22 +04:00
|
|
|
}
|
2007-08-08 20:16:03 +04:00
|
|
|
|
2007-05-30 03:53:35 +04:00
|
|
|
/* is this line empty other than leading whitespace? */
|
2014-01-26 03:00:22 +04:00
|
|
|
if (*ptr == '\n' || *ptr == '\0') {
|
2007-05-30 03:53:35 +04:00
|
|
|
continue;
|
2014-01-26 03:00:22 +04:00
|
|
|
}
|
2007-08-08 20:16:03 +04:00
|
|
|
|
2007-05-30 03:53:35 +04:00
|
|
|
type = ptr;
|
2007-08-08 20:16:03 +04:00
|
|
|
|
2007-05-30 03:53:35 +04:00
|
|
|
/* search for the first non-whitespace char or NUL or
|
2007-08-08 20:16:03 +04:00
|
|
|
* NL */
|
2016-09-07 23:28:02 +03:00
|
|
|
while (*ptr &&
|
|
|
|
(!ascii_is_space(*ptr)) &&
|
|
|
|
*ptr != '\n') {
|
2007-05-30 03:53:35 +04:00
|
|
|
ptr++;
|
2014-01-26 03:00:22 +04:00
|
|
|
}
|
2007-08-08 20:16:03 +04:00
|
|
|
|
2007-05-30 03:53:35 +04:00
|
|
|
if (*ptr == '\0' || *ptr == '\n') {
|
|
|
|
/* this mimetype has no extensions - read next
|
|
|
|
* line.
|
|
|
|
*/
|
|
|
|
continue;
|
|
|
|
}
|
2007-08-08 20:16:03 +04:00
|
|
|
|
2007-05-30 03:53:35 +04:00
|
|
|
*ptr++ = '\0';
|
2007-08-08 20:16:03 +04:00
|
|
|
|
2007-05-30 03:53:35 +04:00
|
|
|
/* search for the first non-whitespace character which
|
|
|
|
* will be the first filename extenion */
|
2016-09-07 23:28:02 +03:00
|
|
|
while (ascii_is_space(*ptr)) {
|
2007-05-30 03:53:35 +04:00
|
|
|
ptr++;
|
2014-01-26 03:00:22 +04:00
|
|
|
}
|
2007-08-08 20:16:03 +04:00
|
|
|
|
2016-01-13 19:35:24 +03:00
|
|
|
while (true) {
|
2007-05-30 03:53:35 +04:00
|
|
|
ext = ptr;
|
2007-08-08 20:16:03 +04:00
|
|
|
|
2007-05-30 03:53:35 +04:00
|
|
|
/* search for the first whitespace char or
|
|
|
|
* NUL or NL which is the end of the ext.
|
2007-08-08 20:16:03 +04:00
|
|
|
*/
|
2014-01-26 03:00:22 +04:00
|
|
|
while (*ptr &&
|
2016-09-07 23:28:02 +03:00
|
|
|
(!ascii_is_space(*ptr)) &&
|
2014-01-26 03:00:22 +04:00
|
|
|
*ptr != '\n') {
|
2007-05-30 03:53:35 +04:00
|
|
|
ptr++;
|
2014-01-26 03:00:22 +04:00
|
|
|
}
|
2007-08-08 20:16:03 +04:00
|
|
|
|
2007-05-30 03:53:35 +04:00
|
|
|
if (*ptr == '\0' || *ptr == '\n') {
|
|
|
|
/* special case for last extension on
|
|
|
|
* the line
|
|
|
|
*/
|
|
|
|
*ptr = '\0';
|
|
|
|
hash_add(mime_hash, ext, type);
|
|
|
|
break;
|
|
|
|
}
|
2007-08-08 20:16:03 +04:00
|
|
|
|
2007-05-30 03:53:35 +04:00
|
|
|
*ptr++ = '\0';
|
|
|
|
hash_add(mime_hash, ext, type);
|
2007-08-08 20:16:03 +04:00
|
|
|
|
2007-05-30 03:53:35 +04:00
|
|
|
/* search for the first non-whitespace char or
|
|
|
|
* NUL or NL, to find start of next ext.
|
2007-08-08 20:16:03 +04:00
|
|
|
*/
|
2014-01-26 03:00:22 +04:00
|
|
|
while (*ptr &&
|
2016-09-07 23:28:02 +03:00
|
|
|
(ascii_is_space(*ptr)) &&
|
2014-01-26 03:00:22 +04:00
|
|
|
*ptr != '\n') {
|
2007-08-08 20:16:03 +04:00
|
|
|
ptr++;
|
2014-01-26 03:00:22 +04:00
|
|
|
}
|
2007-05-30 03:53:35 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-08-08 20:16:03 +04:00
|
|
|
|
2007-05-30 03:53:35 +04:00
|
|
|
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;
|
2011-02-24 01:27:55 +03:00
|
|
|
int l;
|
2007-08-08 20:16:03 +04:00
|
|
|
|
2015-06-17 23:29:48 +03:00
|
|
|
/* stat the path to attempt to determine if the file is special */
|
|
|
|
if (stat(unix_path, &statbuf) == 0) {
|
|
|
|
/* stat suceeded so can check for directory */
|
2013-11-28 02:21:59 +04:00
|
|
|
|
2015-06-17 23:29:48 +03:00
|
|
|
if (S_ISDIR(statbuf.st_mode)) {
|
|
|
|
return "application/x-netsurf-directory";
|
|
|
|
}
|
2014-01-26 03:00:22 +04:00
|
|
|
}
|
2007-08-08 20:16:03 +04:00
|
|
|
|
2011-02-24 01:27:55 +03:00
|
|
|
l = strlen(unix_path);
|
2011-03-13 01:28:43 +03:00
|
|
|
|
|
|
|
/* Hacky RISC OS compatibility */
|
2011-02-24 01:27:55 +03:00
|
|
|
if ((3 < l) && (strcasecmp(unix_path + l - 4, ",f79") == 0)) {
|
|
|
|
return "text/css";
|
2011-03-13 01:28:43 +03:00
|
|
|
} else if ((3 < l) && (strcasecmp(unix_path + l - 4, ",faf") == 0)) {
|
|
|
|
return "text/html";
|
|
|
|
} else if ((3 < l) && (strcasecmp(unix_path + l - 4, ",b60") == 0)) {
|
|
|
|
return "image/png";
|
2011-10-15 17:10:54 +04:00
|
|
|
} else if ((3 < l) && (strcasecmp(unix_path + l - 4, ",ff9") == 0)) {
|
|
|
|
return "image/x-riscos-sprite";
|
2011-02-24 01:27:55 +03:00
|
|
|
}
|
|
|
|
|
2007-05-30 03:53:35 +04:00
|
|
|
if (strchr(unix_path, '.') == NULL) {
|
|
|
|
/* no extension anywhere! */
|
|
|
|
return "text/plain";
|
|
|
|
}
|
2007-08-08 20:16:03 +04:00
|
|
|
|
2007-05-30 03:53:35 +04:00
|
|
|
ptr = unix_path + strlen(unix_path);
|
2014-01-26 03:00:22 +04:00
|
|
|
while (*ptr != '.' && *ptr != '/') {
|
2007-05-30 03:53:35 +04:00
|
|
|
ptr--;
|
2014-01-26 03:00:22 +04:00
|
|
|
}
|
2007-08-08 20:16:03 +04:00
|
|
|
|
2014-01-26 03:00:22 +04:00
|
|
|
if (*ptr != '.') {
|
2007-05-30 03:53:35 +04:00
|
|
|
return "text/plain";
|
2014-01-26 03:00:22 +04:00
|
|
|
}
|
2007-08-08 20:16:03 +04:00
|
|
|
|
2007-05-30 03:53:35 +04:00
|
|
|
ext = strdup(ptr + 1); /* skip the . */
|
2007-08-08 20:16:03 +04:00
|
|
|
|
2007-05-30 03:53:35 +04:00
|
|
|
/* the hash table only contains lower-case versions - make sure this
|
|
|
|
* copy is lower case too.
|
|
|
|
*/
|
|
|
|
lowerchar = ext;
|
2014-01-26 03:00:22 +04:00
|
|
|
while (*lowerchar) {
|
2016-09-07 23:28:02 +03:00
|
|
|
*lowerchar = ascii_to_lower(*lowerchar);
|
2007-05-30 03:53:35 +04:00
|
|
|
lowerchar++;
|
|
|
|
}
|
2007-08-08 20:16:03 +04:00
|
|
|
|
2007-05-30 03:53:35 +04:00
|
|
|
type = hash_get(mime_hash, ext);
|
|
|
|
free(ext);
|
2007-08-08 20:16:03 +04:00
|
|
|
|
2014-01-26 03:00:22 +04:00
|
|
|
if (type == NULL) {
|
|
|
|
type = "text/plain";
|
|
|
|
}
|
|
|
|
|
|
|
|
return type;
|
2007-05-30 03:53:35 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-06-17 23:29:48 +03:00
|
|
|
static nsurl *nsgtk_get_resource_url(const char *path)
|
2014-01-26 03:00:22 +04:00
|
|
|
{
|
|
|
|
char buf[PATH_MAX];
|
|
|
|
nsurl *url = NULL;
|
|
|
|
|
|
|
|
/* favicon.ico -> favicon.png */
|
|
|
|
if (strcmp(path, "favicon.ico") == 0) {
|
2015-06-23 13:53:41 +03:00
|
|
|
nsurl_create("resource:favicon.png", &url);
|
|
|
|
} else {
|
|
|
|
netsurf_path_to_nsurl(filepath_sfind(respaths, buf, path), &url);
|
2014-01-26 03:00:22 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return url;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct gui_fetch_table fetch_table = {
|
|
|
|
.filetype = fetch_filetype,
|
|
|
|
|
2015-06-17 23:29:48 +03:00
|
|
|
.get_resource_url = nsgtk_get_resource_url,
|
|
|
|
.get_resource_data = nsgtk_data_from_resname,
|
2014-01-26 03:00:22 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
struct gui_fetch_table *nsgtk_fetch_table = &fetch_table;
|