From 0231675abf3b467cff49d1976df882931d91019d Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Wed, 23 Feb 2011 22:27:55 +0000 Subject: add resource handling move gtk and framebuffer to use generic resource handling svn path=/trunk/netsurf/; revision=11772 --- Makefile.defaults | 22 ++-- Makefile.sources | 4 +- amiga/gui.c | 6 + atari/gui.c | 6 + beos/beos_gui.cpp | 6 + cocoa/gui.m | 6 + content/fetch.c | 2 + content/fetchers/about.c | 44 +------ content/fetchers/resource.c | 277 +++++++++++++++++++++++++++++++++++++++ content/fetchers/resource.h | 38 ++++++ content/llcache.c | 25 +++- framebuffer/Makefile.target | 1 + framebuffer/filetype.c | 2 + framebuffer/findfile.c | 97 ++++++-------- framebuffer/findfile.h | 10 +- framebuffer/font_freetype.c | 7 +- framebuffer/gui.c | 38 +++--- gtk/filetype.c | 6 + gtk/gui.c | 183 +++++++------------------- riscos/gui.c | 6 + utils/findresource.c | 210 ------------------------------ utils/findresource.h | 88 ------------- utils/resource.c | 310 ++++++++++++++++++++++++++++++++++++++++++++ utils/resource.h | 105 +++++++++++++++ windows/gui.c | 6 + 25 files changed, 931 insertions(+), 574 deletions(-) create mode 100644 content/fetchers/resource.c create mode 100644 content/fetchers/resource.h delete mode 100644 utils/findresource.c delete mode 100644 utils/findresource.h create mode 100644 utils/resource.c create mode 100644 utils/resource.h diff --git a/Makefile.defaults b/Makefile.defaults index 44ad6fbf8..6722494d1 100644 --- a/Makefile.defaults +++ b/Makefile.defaults @@ -253,16 +253,18 @@ ifeq ($(TARGET),framebuffer) NETSURF_FB_FONTLIB := internal # freetype compiled in font locations - NETSURF_FB_FONT_SANS_SERIF := /usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf - NETSURF_FB_FONT_SANS_SERIF_BOLD := /usr/share/fonts/truetype/ttf-dejavu/DejaVuSans-Bold.ttf - NETSURF_FB_FONT_SANS_SERIF_ITALIC := /usr/share/fonts/truetype/ttf-dejavu/DejaVuSans-Oblique.ttf - NETSURF_FB_FONT_SANS_SERIF_ITALIC_BOLD := /usr/share/fonts/truetype/ttf-dejavu/DejaVuSans-BoldOblique.ttf - NETSURF_FB_FONT_SERIF := /usr/share/fonts/truetype/ttf-dejavu/DejaVuSerif.ttf - NETSURF_FB_FONT_SERIF_BOLD := /usr/share/fonts/truetype/ttf-dejavu/DejaVuSerif-Bold.ttf - NETSURF_FB_FONT_MONOSPACE := /usr/share/fonts/truetype/ttf-dejavu/DejaVuSansMono.ttf - NETSURF_FB_FONT_MONOSPACE_BOLD := /usr/share/fonts/truetype/ttf-dejavu/DejaVuSansMono-Bold.ttf - NETSURF_FB_FONT_CURSIVE := /usr/share/fonts/truetype/msttcorefonts/Comic_Sans_MS.ttf - NETSURF_FB_FONT_FANTASY := /usr/share/fonts/truetype/msttcorefonts/Impact.ttf + NETSURF_FB_FONTPATH := /usr/share/fonts/truetype/ttf-dejavu:/usr/share/fonts/truetype/msttcorefonts + + NETSURF_FB_FONT_SANS_SERIF := DejaVuSans.ttf + NETSURF_FB_FONT_SANS_SERIF_BOLD := DejaVuSans-Bold.ttf + NETSURF_FB_FONT_SANS_SERIF_ITALIC := DejaVuSans-Oblique.ttf + NETSURF_FB_FONT_SANS_SERIF_ITALIC_BOLD := DejaVuSans-BoldOblique.ttf + NETSURF_FB_FONT_SERIF := DejaVuSerif.ttf + NETSURF_FB_FONT_SERIF_BOLD := DejaVuSerif-Bold.ttf + NETSURF_FB_FONT_MONOSPACE := DejaVuSansMono.ttf + NETSURF_FB_FONT_MONOSPACE_BOLD := DejaVuSansMono-Bold.ttf + NETSURF_FB_FONT_CURSIVE := Comic_Sans_MS.ttf + NETSURF_FB_FONT_FANTASY := Impact.ttf # Framebuffer frontends may have differing root paths for resources # As such, these specify the resource path and config path. diff --git a/Makefile.sources b/Makefile.sources index 6ca7cfcab..3b9e11368 100644 --- a/Makefile.sources +++ b/Makefile.sources @@ -6,7 +6,7 @@ S_CONTENT := content.c dirlist.c fetch.c hlcache.c llcache.c urldb.c -S_FETCHERS := curl.c data.c file.c about.c +S_FETCHERS := curl.c data.c file.c about.c resource.c S_CSS := css.c dump.c internal.c select.c utils.c @@ -15,7 +15,7 @@ S_RENDER := box.c box_construct.c box_normalise.c favicon.c \ hubbub_binding.c imagemap.c layout.c list.c table.c textplain.c S_UTILS := base64.c filename.c hashtable.c http.c locale.c messages.c \ - talloc.c url.c utf8.c utils.c useragent.c findresource.c log.c + talloc.c url.c utf8.c utils.c useragent.c resource.c log.c S_DESKTOP := cookies.c history_global_core.c hotlist.c knockout.c \ mouse.c options.c plot_style.c print.c search.c searchweb.c \ diff --git a/amiga/gui.c b/amiga/gui.c index c3d1d8647..f95e2b981 100755 --- a/amiga/gui.c +++ b/amiga/gui.c @@ -34,6 +34,7 @@ #include "utils/utf8.h" #include "utils/utils.h" #include "utils/url.h" +#include "content/fetchers/resource.h" /* NetSurf Amiga platform includes */ #include "amiga/arexx.h" @@ -412,6 +413,11 @@ void ami_amiupdate(void) /* end Amiupdate */ } +char* gui_find_resource(const char *filename) +{ + return NULL; +} + void gui_init(int argc, char** argv) { BPTR lock = 0; diff --git a/atari/gui.c b/atari/gui.c index b8cfdbe0e..e52965ffb 100755 --- a/atari/gui.c +++ b/atari/gui.c @@ -34,6 +34,7 @@ #include "content/urldb.h" #include "content/fetch.h" +#include "content/fetchers/resource.h" #include "css/utils.h" #include "desktop/gui.h" #include "desktop/history_core.h" @@ -1056,6 +1057,11 @@ static inline void create_cursor(int flags, short mode, void * form, MFORM_EX * } } +char* gui_find_resource(const char *filename) +{ + return NULL; +} + static void gui_init(int argc, char** argv) { char buf[PATH_MAX], sbuf[PATH_MAX]; diff --git a/beos/beos_gui.cpp b/beos/beos_gui.cpp index b757c9790..2317b0b0d 100644 --- a/beos/beos_gui.cpp +++ b/beos/beos_gui.cpp @@ -46,6 +46,7 @@ extern "C" { #include "content/content_protected.h" #include "content/fetch.h" #include "content/fetchers/curl.h" +#include "content/fetchers/resource.h" #include "content/urldb.h" #include "desktop/401login.h" #include "desktop/browser.h" @@ -421,6 +422,11 @@ static int32 bapp_thread(void *arg) return 0; } +char* gui_find_resource(const char *filename) +{ + return NULL; +} + static void gui_init2(int argc, char** argv) { CALLED(); diff --git a/cocoa/gui.m b/cocoa/gui.m index 0acd6bcc4..3a10b9143 100644 --- a/cocoa/gui.m +++ b/cocoa/gui.m @@ -34,6 +34,7 @@ #import "desktop/401login.h" #import "utils/utils.h" #import "image/ico.h" +#import "content/fetchers/resource.h" char *default_stylesheet_url; char *adblock_stylesheet_url; @@ -49,6 +50,11 @@ NSString * const kAlwaysCloseMultipleTabs = @"AlwaysCloseMultipleTabs"; #define UNIMPL() NSLog( @"Function '%s' unimplemented", __func__ ) +char* gui_find_resource(const char *filename) +{ + return NULL; +} + void gui_multitask(void) { // nothing to do diff --git a/content/fetch.c b/content/fetch.c index a848e17fa..e521ca2fc 100644 --- a/content/fetch.c +++ b/content/fetch.c @@ -38,6 +38,7 @@ #include "utils/config.h" #include "content/fetch.h" +#include "content/fetchers/resource.h" #include "content/fetchers/about.h" #include "content/fetchers/curl.h" #include "content/fetchers/data.h" @@ -112,6 +113,7 @@ void fetch_init(void) fetch_curl_register(); fetch_data_register(); fetch_file_register(); + fetch_resource_register(); fetch_about_register(); fetch_active = false; } diff --git a/content/fetchers/about.c b/content/fetchers/about.c index 8ed112200..c4a376a29 100644 --- a/content/fetchers/about.c +++ b/content/fetchers/about.c @@ -127,52 +127,16 @@ fetch_about_blank_handler_aborted: return false; } -static const char *authors[] = { - "John-Mark Bell", "James Bursa", "Michael Drake", - "Rob Kendrick", "Adrian Lees", "Vincent Sanders", - "Daniel Silverstone", "Richard Wilson", NULL -}; static bool fetch_about_credits_handler(struct fetch_about_context *ctx) { - char buffer[4096]; - int code = 200; - int slen; - int auth_loop = 0; - - /* content is going to return ok */ - fetch_set_http_code(ctx->fetchh, code); + /* content is going to return redirect */ + fetch_set_http_code(ctx->fetchh, 302); - /* content type */ - if (fetch_about_send_header(ctx, "Content-Type: text/html")) - goto fetch_about_credits_handler_aborted; - - slen = snprintf(buffer, sizeof buffer, - "NetSurf Browser Credits" - "

NetSurf Browser Credits

" - "

Authors

" - ""); - - if (fetch_about_send_callback(FETCH_DATA, ctx, buffer, slen, - FETCH_ERROR_NO_ERROR)) - goto fetch_about_credits_handler_aborted; - - fetch_about_send_callback(FETCH_FINISHED, ctx, 0, 0, - FETCH_ERROR_NO_ERROR); + fetch_about_send_callback(FETCH_REDIRECT, ctx, "resource:credits.html", + 0, FETCH_ERROR_NO_ERROR); return true; - -fetch_about_credits_handler_aborted: - return false; } static bool fetch_about_config_handler(struct fetch_about_context *ctx) diff --git a/content/fetchers/resource.c b/content/fetchers/resource.c new file mode 100644 index 000000000..2818305d0 --- /dev/null +++ b/content/fetchers/resource.c @@ -0,0 +1,277 @@ +/* + * Copyright 2011 Vincent Sanders + * + * This file is part of NetSurf. + * + * 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 . + */ + +/* resource: URL handling. Based on the data fetcher by Rob Kendrick */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "utils/config.h" +#include "content/dirlist.h" +#include "content/fetch.h" +#include "content/fetchers/resource.h" +#include "content/urldb.h" +#include "desktop/netsurf.h" +#include "desktop/options.h" +#include "utils/log.h" +#include "utils/messages.h" +#include "utils/url.h" +#include "utils/utils.h" +#include "utils/ring.h" + +struct fetch_resource_context; + +typedef bool (*fetch_resource_handler)(struct fetch_resource_context *); + +/** Context for an resource fetch */ +struct fetch_resource_context { + struct fetch_resource_context *r_next, *r_prev; + + struct fetch *fetchh; /**< Handle for this fetch */ + + bool aborted; /**< Flag indicating fetch has been aborted */ + bool locked; /**< Flag indicating entry is already entered */ + + char *url; + char *redirect_url; /**< The url the fetch redirects to */ + + fetch_resource_handler handler; +}; + +static struct fetch_resource_context *ring = NULL; + +/** issue fetch callbacks with locking */ +static inline bool fetch_resource_send_callback(fetch_msg msg, + struct fetch_resource_context *ctx, const void *data, + unsigned long size, fetch_error_code errorcode) +{ + ctx->locked = true; + fetch_send_callback(msg, ctx->fetchh, data, size, errorcode); + ctx->locked = false; + + return ctx->aborted; +} + +static bool fetch_resource_send_header(struct fetch_resource_context *ctx, + const char *fmt, ...) +{ + char header[64]; + va_list ap; + + va_start(ap, fmt); + + vsnprintf(header, sizeof header, fmt, ap); + + va_end(ap); + + fetch_resource_send_callback(FETCH_HEADER, ctx, header, strlen(header), + FETCH_ERROR_NO_ERROR); + + return ctx->aborted; +} + + + + +static bool fetch_resource_redirect_handler(struct fetch_resource_context *ctx) +{ + /* content is going to return redirect */ + fetch_set_http_code(ctx->fetchh, 302); + + fetch_resource_send_callback(FETCH_REDIRECT, ctx, ctx->redirect_url, 0, + FETCH_ERROR_NO_ERROR); + + return true; +} + + +static bool fetch_resource_notfound_handler(struct fetch_resource_context *ctx) +{ + int code = 404; + char buffer[1024]; + const char *title; + char key[8]; + + /* content is going to return error code */ + fetch_set_http_code(ctx->fetchh, code); + + /* content type */ + if (fetch_resource_send_header(ctx, "Content-Type: text/html")) + goto fetch_resource_notfound_handler_aborted; + + snprintf(key, sizeof key, "HTTP%03d", code); + title = messages_get(key); + + snprintf(buffer, sizeof buffer, "%s" + "

%s

" + "

Error %d while fetching file %s

", + title, title, code, ctx->url); + + if (fetch_resource_send_callback(FETCH_DATA, ctx, buffer, strlen(buffer), + FETCH_ERROR_NO_ERROR)) + goto fetch_resource_notfound_handler_aborted; + + fetch_resource_send_callback(FETCH_FINISHED, ctx, 0, 0, + FETCH_ERROR_NO_ERROR); + +fetch_resource_notfound_handler_aborted: + return false; +} + + + +/** callback to initialise the resource fetcher. */ +static bool fetch_resource_initialise(const char *scheme) +{ + return true; +} + +/** callback to initialise the resource fetcher. */ +static void fetch_resource_finalise(const char *scheme) +{ +} + +/** callback to set up a resource fetch context. */ +static void * +fetch_resource_setup(struct fetch *fetchh, + const char *url, + bool only_2xx, + const char *post_urlenc, + const struct fetch_multipart_data *post_multipart, + const char **headers) +{ + struct fetch_resource_context *ctx; + struct url_components urlcomp; + + ctx = calloc(1, sizeof(*ctx)); + if (ctx == NULL) + return NULL; + + url_get_components(url, &urlcomp); + + ctx->redirect_url = gui_find_resource(urlcomp.path); + if (ctx->redirect_url == NULL) { + ctx->handler = fetch_resource_notfound_handler; + } else { + ctx->handler = fetch_resource_redirect_handler; + } + + ctx->url = strdup(url); + + url_destroy_components(&urlcomp); + + ctx->fetchh = fetchh; + + RING_INSERT(ring, ctx); + + return ctx; +} + +/** callback to free a resource fetch */ +static void fetch_resource_free(void *ctx) +{ + struct fetch_resource_context *c = ctx; + free(c->redirect_url); + free(c->url); + RING_REMOVE(ring, c); + free(ctx); +} + +/** callback to start a resource fetch */ +static bool fetch_resource_start(void *ctx) +{ + return true; +} + +/** callback to abort a resource fetch */ +static void fetch_resource_abort(void *ctx) +{ + struct fetch_resource_context *c = ctx; + + /* To avoid the poll loop having to deal with the fetch context + * disappearing from under it, we simply flag the abort here. + * The poll loop itself will perform the appropriate cleanup. + */ + c->aborted = true; +} + + +/** callback to poll for additional resource fetch contents */ +static void fetch_resource_poll(const char *scheme) +{ + struct fetch_resource_context *c, *next; + + if (ring == NULL) return; + + /* Iterate over ring, processing each pending fetch */ + c = ring; + do { + /* Take a copy of the next pointer as we may destroy + * the ring item we're currently processing */ + next = c->r_next; + + /* Ignore fetches that have been flagged as locked. + * This allows safe re-entrant calls to this function. + * Re-entrancy can occur if, as a result of a callback, + * the interested party causes fetch_poll() to be called + * again. + */ + if (c->locked == true) { + continue; + } + + /* Only process non-aborted fetches */ + if (c->aborted == false) { + /* resource fetches can be processed in one go */ + c->handler(c); + } + + + fetch_remove_from_queues(c->fetchh); + fetch_free(c->fetchh); + + /* Advance to next ring entry, exiting if we've reached + * the start of the ring or the ring has become empty + */ + } while ( (c = next) != ring && ring != NULL); +} + +void fetch_resource_register(void) +{ + fetch_add_fetcher("resource", + fetch_resource_initialise, + fetch_resource_setup, + fetch_resource_start, + fetch_resource_abort, + fetch_resource_free, + fetch_resource_poll, + fetch_resource_finalise); +} diff --git a/content/fetchers/resource.h b/content/fetchers/resource.h new file mode 100644 index 000000000..6c590d390 --- /dev/null +++ b/content/fetchers/resource.h @@ -0,0 +1,38 @@ +/* + * Copyright 2011 Vincent Sanders + * + * This file is part of NetSurf. + * + * 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 . + */ + +/** \file + * resource: URL method handler + */ + +#ifndef NETSURF_CONTENT_FETCHERS_FETCH_RESOURCE_H +#define NETSURF_CONTENT_FETCHERS_FETCH_RESOURCE_H + +/** + * register the resource scheme. + * + * should only be called from the fetch initialise + */ +void fetch_resource_register(void); + +/** + * callback to translate resource to full url + */ +char* gui_find_resource(const char *filename); + +#endif diff --git a/content/llcache.c b/content/llcache.c index 64e37915a..a7c8cbe06 100644 --- a/content/llcache.c +++ b/content/llcache.c @@ -1952,6 +1952,7 @@ nserror llcache_fetch_redirect(llcache_object *object, const char *target, const llcache_post_data *post = object->fetch.post; char *url, *absurl; char *scheme; + char *object_scheme; url_func_result result; /* Extract HTTP response code from the fetch object */ long http_code = fetch_http_code(object->fetch.fetch); @@ -1999,20 +2000,34 @@ nserror llcache_fetch_redirect(llcache_object *object, const char *target, return NSERROR_NOMEM; } - /* Ensure that redirects to file:/// don't happen */ - result = url_scheme(url, &scheme); + /* Ensure that redirects to file:/// only happen for valid schemes */ + result = url_scheme(object->url, &object_scheme); if (result != URL_FUNC_OK) { free(url); return NSERROR_NOMEM; } - if (strcasecmp(scheme, "file") == 0) { - free(scheme); + result = url_scheme(url, &scheme); + if (result != URL_FUNC_OK) { free(url); - return NSERROR_OK; + return NSERROR_NOMEM; + } + + /* resource is allowed to redirect anywhere */ + if ((strcasecmp(object_scheme, "resource") != 0) && + (strcasecmp(object_scheme, "about") != 0)) { + /* file, about and resource are not valid redirect targets */ + if ((strcasecmp(scheme, "file") == 0) || + (strcasecmp(scheme, "about") == 0) || + (strcasecmp(scheme, "resource") == 0)) { + free(scheme); + free(url); + return NSERROR_OK; + } } free(scheme); + free(object_scheme); /* Bail out if we've no way of handling this URL */ if (fetch_can_fetch(url) == false) { diff --git a/framebuffer/Makefile.target b/framebuffer/Makefile.target index e9dd8a883..98c6427df 100644 --- a/framebuffer/Makefile.target +++ b/framebuffer/Makefile.target @@ -24,6 +24,7 @@ CFLAGS += -Dnsframebuffer CFLAGS += '-DNETSURF_FB_RESPATH="$(NETSURF_FB_RESPATH_$(NETSURF_FB_FRONTEND))"' # compile time font locations +CFLAGS += '-DNETSURF_FB_FONTPATH="$(NETSURF_FB_FONTPATH)"' CFLAGS += '-DNETSURF_FB_FONT_SANS_SERIF="$(NETSURF_FB_FONT_SANS_SERIF)"' CFLAGS += '-DNETSURF_FB_FONT_SANS_SERIF_BOLD="$(NETSURF_FB_FONT_SANS_SERIF_BOLD)"' CFLAGS += '-DNETSURF_FB_FONT_SANS_SERIF_ITALIC="$(NETSURF_FB_FONT_SANS_SERIF_ITALIC)"' diff --git a/framebuffer/filetype.c b/framebuffer/filetype.c index d15890ce4..4b303e5f1 100644 --- a/framebuffer/filetype.c +++ b/framebuffer/filetype.c @@ -33,6 +33,8 @@ const char *fetch_filetype(const char *unix_path) l = strlen(unix_path); if (2 < l && strcasecmp(unix_path + l - 3, "css") == 0) return "text/css"; + if (2 < l && strcasecmp(unix_path + l - 3, "f79") == 0) + return "text/css"; if (2 < l && strcasecmp(unix_path + l - 3, "jpg") == 0) return "image/jpeg"; if (3 < l && strcasecmp(unix_path + l - 4, "jpeg") == 0) diff --git a/framebuffer/findfile.c b/framebuffer/findfile.c index caa910005..130804eed 100644 --- a/framebuffer/findfile.c +++ b/framebuffer/findfile.c @@ -27,9 +27,45 @@ #include "utils/log.h" #include "utils/url.h" +#include "utils/resource.h" +#include "content/fetchers/resource.h" #include "framebuffer/findfile.h" +char **respaths; /** resource search path vector */ + +/** Create an array of valid paths to search for resources. + * + * The idea is that all the complex path computation to find resources + * is performed here, once, rather than every time a resource is + * searched for. + */ +char ** +fb_init_resource(const char *resource_path) +{ + char **pathv; /* resource path string vector */ + char **respath; /* resource paths vector */ + const char *lang = NULL; + char *foo; + int bar=0; + fprintf(stderr, "fb_init_resource:%s\n",resource_path); + + pathv = resource_path_to_strvec(resource_path); + + respath = resource_generate(pathv, &lang); + + resource_free_strvec(pathv); + + foo = respath[bar]; + while (foo != NULL) { + fprintf(stderr, "%s\n",foo); + bar++; + foo = respath[bar]; + } + return respath; +} + + char *path_to_url(const char *path) { int urllen = strlen(path) + FILE_SCHEME_PREFIX_LEN + 1; @@ -65,67 +101,12 @@ char *url_to_path(const char *url) return respath; } -/** - * Locate a shared resource file by searching known places in order. - * - * \param buf buffer to write to. must be at least PATH_MAX chars - * \param filename file to look for - * \param def default to return if file not found - * \return buf - * - * Search order is: ~/.netsurf/, $NETSURFRES/ (where NETSURFRES is an - * environment variable), and finally the path specified by NETSURF_FB_RESPATH - * from the Makefile - */ - -char *fb_find_resource(char *buf, const char *filename, const char *def) +char* gui_find_resource(const char *filename) { - char *cdir = getenv("HOME"); - char t[PATH_MAX]; - - if (cdir != NULL) { - strcpy(t, cdir); - strcat(t, "/.netsurf/"); - strcat(t, filename); - if (realpath(t, buf) != NULL) { - if (access(buf, R_OK) == 0) - return buf; - } - } - - cdir = getenv("NETSURFRES"); - - if (cdir != NULL) { - if (realpath(cdir, buf) != NULL) { - strcat(buf, "/"); - strcat(buf, filename); - if (access(buf, R_OK) == 0) - return buf; - } - } - - strcpy(t, NETSURF_FB_RESPATH); - strcat(t, filename); - if (realpath(t, buf) != NULL) { - if (access(buf, R_OK) == 0) - return buf; - } - - if (def[0] == '~') { - snprintf(t, PATH_MAX, "%s%s", getenv("HOME"), def + 1); - if (realpath(t, buf) == NULL) { - strcpy(buf, t); - } - } else { - if (realpath(def, buf) == NULL) { - strcpy(buf, def); - } - } - - return buf; + char buf[PATH_MAX]; + return path_to_url(resource_sfind(respaths, buf, filename)); } - /* * Local Variables: * c-basic-offset: 8 diff --git a/framebuffer/findfile.h b/framebuffer/findfile.h index 85a2f7074..1f3db6eb1 100644 --- a/framebuffer/findfile.h +++ b/framebuffer/findfile.h @@ -19,6 +19,14 @@ #ifndef NETSURF_FB_FINDFILE_H #define NETSURF_FB_FINDFILE_H -extern char *fb_find_resource(char *buf, const char *filename, const char *def); +extern char **respaths; + +/** Create an array of valid paths to search for resources. + * + * The idea is that all the complex path computation to find resources + * is performed here, once, rather than every time a resource is + * searched for. + */ +char **fb_init_resource(const char *resource_path); #endif /* NETSURF_FB_FINDFILE_H */ diff --git a/framebuffer/font_freetype.c b/framebuffer/font_freetype.c index ea183ea4b..44d6701dc 100644 --- a/framebuffer/font_freetype.c +++ b/framebuffer/font_freetype.c @@ -27,6 +27,7 @@ #include "render/font.h" #include "utils/utf8.h" #include "utils/log.h" +#include "utils/resource.h" #include "desktop/options.h" #include "framebuffer/gui.h" @@ -112,7 +113,7 @@ static FT_Error ft_face_requester(FTC_FaceID face_id, FT_Library library, FT_Po /* create new framebuffer face and cause it to be loaded to check its ok */ static fb_faceid_t * -fb_new_face(const char *option, const char *resname, const char *fontfile) +fb_new_face(const char *option, const char *resname, const char *fontname) { fb_faceid_t *newf; FT_Error error; @@ -124,13 +125,13 @@ fb_new_face(const char *option, const char *resname, const char *fontfile) if (option != NULL) { newf->fontfile = strdup(option); } else { - fb_find_resource(buf, resname, fontfile); + resource_sfind(respaths, buf, fontname); newf->fontfile = strdup(buf); } error = FTC_Manager_LookupFace(ft_cmanager, (FTC_FaceID)newf, &aface); if (error) { - LOG(("Could not find font face %s (code %d)\n", fontfile, error)); + LOG(("Could not find font face %s (code %d)\n", fontname, error)); free(newf); newf = NULL; } diff --git a/framebuffer/gui.c b/framebuffer/gui.c index 6cec4e7fa..abdb0ed9e 100644 --- a/framebuffer/gui.c +++ b/framebuffer/gui.c @@ -37,6 +37,7 @@ #include "desktop/netsurf.h" #include "desktop/options.h" #include "desktop/shape.h" +#include "utils/resource.h" #include "utils/log.h" #include "utils/url.h" #include "utils/messages.h" @@ -63,7 +64,6 @@ char *default_stylesheet_url; char *quirks_stylesheet_url; char *adblock_stylesheet_url; -char *options_file_location; fbtk_widget_t *fbtk; @@ -435,33 +435,31 @@ process_cmdline(int argc, char** argv) return true; } - static void gui_init(int argc, char** argv) { - char buf[PATH_MAX]; nsfb_t *nsfb; option_core_select_menu = true; /* set up stylesheet urls */ - fb_find_resource(buf, "default.css", "./framebuffer/res/default.css"); - default_stylesheet_url = path_to_url(buf); + default_stylesheet_url = strdup("resource:default.css"); LOG(("Using '%s' as Default CSS URL", default_stylesheet_url)); - fb_find_resource(buf, "quirks.css", "./framebuffer/res/quirks.css"); - quirks_stylesheet_url = path_to_url(buf); + quirks_stylesheet_url = strdup("resource:quirks.css"); + LOG(("Using '%s' as quirks CSS URL", quirks_stylesheet_url)); + + adblock_stylesheet_url = strdup("resource:adblock.css"); + LOG(("Using '%s' as AdBlock CSS URL", adblock_stylesheet_url)); if (option_cookie_file == NULL) { - fb_find_resource(buf, "Cookies", "~/.netsurf/Cookies"); - LOG(("Using '%s' as Cookies file", buf)); - option_cookie_file = strdup(buf); + option_cookie_file = resource_find(respaths, "Cookies"); + LOG(("Using '%s' as Cookies file", option_cookie_file)); } if (option_cookie_jar == NULL) { - fb_find_resource(buf, "Cookies", "~/.netsurf/Cookies"); - LOG(("Using '%s' as Cookie Jar file", buf)); - option_cookie_jar = strdup(buf); + option_cookie_jar = resource_find(respaths, "Cookies"); + LOG(("Using '%s' as Cookie Jar file", option_cookie_jar)); } if (option_cookie_file == NULL || option_cookie_jar == NULL) @@ -496,17 +494,21 @@ int main(int argc, char** argv) { struct browser_window *bw; - char options[PATH_MAX]; - char messages[PATH_MAX]; + char *options; + char *messages; setbuf(stderr, NULL); - fb_find_resource(messages, "messages", "./framebuffer/res/messages"); - fb_find_resource(options, "Choices-fb", "~/.netsurf/Choices-fb"); - options_file_location = strdup(options); + respaths = fb_init_resource("${HOME}/.netsurf/:${NETSURFRES}:"NETSURF_FB_RESPATH":./framebuffer/res:"NETSURF_FB_FONTPATH); + + options = resource_find(respaths, "Choices"); + messages = resource_find(respaths, "messages"); netsurf_init(&argc, &argv, options, messages); + free(messages); + free(options); + gui_init(argc, argv); LOG(("calling browser_window_create")); diff --git a/gtk/filetype.c b/gtk/filetype.c index b172f5191..f89f2358c 100644 --- a/gtk/filetype.c +++ b/gtk/filetype.c @@ -155,11 +155,17 @@ const char *fetch_filetype(const char *unix_path) const char *ptr; char *lowerchar; const char *type; + int l; stat(unix_path, &statbuf); if (S_ISDIR(statbuf.st_mode)) return "application/x-netsurf-directory"; + l = strlen(unix_path); + if ((3 < l) && (strcasecmp(unix_path + l - 4, ",f79") == 0)) { + return "text/css"; + } + if (strchr(unix_path, '.') == NULL) { /* no extension anywhere! */ return "text/plain"; diff --git a/gtk/gui.c b/gtk/gui.c index fd2116f21..ce2b4f3bd 100644 --- a/gtk/gui.c +++ b/gtk/gui.c @@ -43,6 +43,7 @@ #include "content/content.h" #include "content/fetch.h" #include "content/fetchers/curl.h" +#include "content/fetchers/resource.h" #include "content/hlcache.h" #include "content/urldb.h" #include "desktop/browser.h" @@ -78,7 +79,7 @@ #include "utils/url.h" #include "utils/utf8.h" #include "utils/utils.h" -#include "utils/findresource.h" +#include "utils/resource.h" char *default_stylesheet_url; char *quirks_stylesheet_url; @@ -122,101 +123,7 @@ static void nsgtk_PDF_no_pass(GtkButton *w, gpointer data); #define THROBBER_FRAMES 9 -#define MAX_RESPATH 128 /* maximum number of elements in the resource vector */ - -/* expand ${} in a string into environment variables */ -static char * -expand_path(const char *path) -{ - char *exp = strdup(path); - int explen; - int cstart = -1; - int cloop = 0; - char *envv; - int envlen; - int replen; /* length of replacement */ - - if (exp == NULL) - return NULL; - - explen = strlen(exp) + 1; - - while (exp[cloop] != 0) { - if ((exp[cloop] == '$') && - (exp[cloop + 1] == '{')) { - cstart = cloop; - cloop++; - } - - if ((cstart != -1) && - (exp[cloop] == '}')) { - replen = cloop - cstart; - exp[cloop] = 0; - envv = getenv(exp + cstart + 2); - if (envv == NULL) { - memmove(exp + cstart, - exp + cloop + 1, - explen - cloop - 1); - explen -= replen; - } else { - envlen = strlen(envv); - exp = realloc(exp, explen + envlen - replen); - memmove(exp + cstart + envlen, - exp + cloop + 1, - explen - cloop - 1); - memmove(exp + cstart, envv, envlen); - explen += envlen - replen; - } - cloop -= replen; - cstart = -1; - } - - cloop++; - } - - return exp; -} - -/* convert a colon separated list of path elements into a string vector */ -static char ** -path_to_strvec(const char *path) -{ - char **strvec; - int strc = 0; - - strvec = calloc(MAX_RESPATH, sizeof(char *)); - if (strvec == NULL) - return NULL; - - strvec[strc] = expand_path(path); - if (strvec[strc] == NULL) { - free(strvec); - return NULL; - } - strc++; - - strvec[strc] = strchr(strvec[0], ':'); - while ((strc < (MAX_RESPATH - 2)) && - (strvec[strc] != NULL)) { - /* null terminate previous entry */ - *strvec[strc] = 0; - strvec[strc]++; - - /* skip colons */ - while (*strvec[strc] == ':') - strvec[strc]++; - - if (*strvec[strc] == 0) - break; /* string is terminated */ - - strc++; - - strvec[strc] = strchr(strvec[strc - 1], ':'); - } - - return strvec; -} - +char **respaths; /** resource search path vector */ /** Create an array of valid paths to search for resources. * @@ -231,14 +138,13 @@ nsgtk_init_resource(const char *resource_path) char **pathv; /* resource path string vector */ char **respath; /* resource paths vector */ - pathv = path_to_strvec(resource_path); + pathv = resource_path_to_strvec(resource_path); langv = g_get_language_names(); - respath = findresource_generate(pathv, langv); + respath = resource_generate(pathv, langv); - free(pathv[0]); - free(pathv); + resource_free_strvec(pathv); return respath; } @@ -259,7 +165,7 @@ static bool nsgtk_throbber_init(char **respath, int framec) for (frame_num = 0; frame_num < framec; frame_num++) { snprintf(targetname, PATH_MAX, "throbber/throbber%d.png", frame_num); - filenames[frame_num] = findresource(respath, targetname); + filenames[frame_num] = resource_find(respath, targetname); } ret = nsgtk_throbber_initialise_from_png(frame_num, filenames); @@ -285,7 +191,7 @@ nsgtk_new_glade(char **respath, const char *name, GladeXML **pglade) snprintf(resname, PATH_MAX, "%s.glade", name); - filepath = findresource(respath, resname); + filepath = resource_find(respath, resname); if (filepath == NULL) { snprintf(errorstr, NEW_GLADE_ERROR_SIZE, "Unable to locate %s glade template file.\n", name); @@ -362,12 +268,12 @@ static void check_options(char **respath) * values! */ if (!option_cookie_file) { - sfindresourcedef(respath, buf, "Cookies", "~/.netsurf/"); + resource_sfinddef(respath, buf, "Cookies", "~/.netsurf/"); LOG(("Using '%s' as Cookies file", buf)); option_cookie_file = strdup(buf); } if (!option_cookie_jar) { - sfindresourcedef(respath, buf, "Cookies", "~/.netsurf/"); + resource_sfinddef(respath, buf, "Cookies", "~/.netsurf/"); LOG(("Using '%s' as Cookie Jar file", buf)); option_cookie_jar = strdup(buf); } @@ -375,13 +281,13 @@ static void check_options(char **respath) die("Failed initialising cookie options"); if (!option_url_file) { - sfindresourcedef(respath, buf, "URLs", "~/.netsurf/"); + resource_sfinddef(respath, buf, "URLs", "~/.netsurf/"); LOG(("Using '%s' as URL file", buf)); option_url_file = strdup(buf); } if (!option_ca_path) { - sfindresourcedef(respath, buf, "certs", "/etc/ssl/"); + resource_sfinddef(respath, buf, "certs", "/etc/ssl/"); LOG(("Using '%s' as certificate path", buf)); option_ca_path = strdup(buf); } @@ -391,12 +297,12 @@ static void check_options(char **respath) option_downloads_directory = hdir; } - sfindresourcedef(respath, buf, "icons/", "~/.netsurf/"); + resource_sfinddef(respath, buf, "icons/", "~/.netsurf/"); LOG(("Using '%s' as Tree icons dir", buf)); tree_set_icon_dir(strdup(buf)); if (!option_hotlist_path) { - sfindresourcedef(respath, buf, "Hotlist", "~/.netsurf/"); + resource_sfinddef(respath, buf, "Hotlist", "~/.netsurf/"); LOG(("Using '%s' as Hotlist file", buf)); option_hotlist_path = strdup(buf); } @@ -404,7 +310,7 @@ static void check_options(char **respath) die("Failed initialising hotlist option"); - sfindresourcedef(respath, buf, "Print", "~/.netsurf/"); + resource_sfinddef(respath, buf, "Print", "~/.netsurf/"); LOG(("Using '%s' as Print Settings file", buf)); print_options_file_location = strdup(buf); @@ -420,6 +326,13 @@ static void check_options(char **respath) } +char* gui_find_resource(const char *filename) +{ + char buf[PATH_MAX]; + return path_to_url(resource_sfind(respaths, buf, filename)); +} + + /** * Initialize GTK interface. */ @@ -440,33 +353,33 @@ static void gui_init(int argc, char** argv, char **respath) * however these may be translated which breaks things * relying on res_dir_location. */ - resource_filename = findresource(respath, "languages"); + resource_filename = resource_find(respath, "languages"); resource_filename[strlen(resource_filename) - 9] = 0; res_dir_location = resource_filename; /* languages file */ - languages_file_location = findresource(respath, "languages"); + languages_file_location = resource_find(respath, "languages"); /* initialise the glade templates */ nsgtk_init_glade(respath); /* set default icon if its available */ - resource_filename = findresource(respath, "netsurf.xpm"); + resource_filename = resource_find(respath, "netsurf.xpm"); if (resource_filename != NULL) { gtk_window_set_default_icon_from_file(resource_filename, NULL); free(resource_filename); } /* Search engine sources */ - search_engines_file_location = findresource(respath, "SearchEngines"); + search_engines_file_location = resource_find(respath, "SearchEngines"); LOG(("Using '%s' as Search Engines file", search_engines_file_location)); /* Default Icon */ - search_default_ico_location = findresource(respath, "default.ico"); + search_default_ico_location = resource_find(respath, "default.ico"); LOG(("Using '%s' as default search ico", search_default_ico_location)); /* Toolbar inicies file */ - toolbar_indices_file_location = findresource(respath, "toolbarIndices"); + toolbar_indices_file_location = resource_find(respath, "toolbarIndices"); LOG(("Using '%s' as custom toolbar settings file", toolbar_indices_file_location)); /* load throbber images */ @@ -476,19 +389,17 @@ static void gui_init(int argc, char** argv, char **respath) /* Initialise completions - cannot fail */ nsgtk_completion_init(); - sfindresourcedef(respath, buf, "mime.types", "/etc/"); + resource_sfinddef(respath, buf, "mime.types", "/etc/"); gtk_fetch_filetype_init(buf); /* set up stylesheet urls */ - sfindresourcedef(respath, buf, "gtkdefault.css", "./gtk/res/"); - default_stylesheet_url = path_to_url(buf); + default_stylesheet_url = strdup("resource:gtkdefault.css"); LOG(("Using '%s' as Default CSS URL", default_stylesheet_url)); - sfindresourcedef(respath, buf, "quirks.css", "./gtk/res/"); - quirks_stylesheet_url = path_to_url(buf); + quirks_stylesheet_url = strdup("resource:quirks.css"); + LOG(("Using '%s' as quirks CSS URL", quirks_stylesheet_url)); - sfindresourcedef(respath, buf, "adblock.css", "./gtk/res/"); - adblock_stylesheet_url = path_to_url(buf); + adblock_stylesheet_url = strdup("resource:adblock.css"); LOG(("Using '%s' as AdBlock CSS URL", adblock_stylesheet_url)); urldb_load(option_url_file); @@ -560,32 +471,19 @@ int main(int argc, char** argv) { char *messages; char *options; - char **respaths; /* check home directory is available */ nsgtk_check_homedir(); respaths = nsgtk_init_resource("${HOME}/.netsurf/:${NETSURFRES}:"GTK_RESPATH":./gtk/res"); - /* Some modern distributions can set ALL_PROXY/all_proxy if configured - * to by the user. Due to a bug in many versions of libcurl - * (including the one shipped in Ubuntu 10.04 LTS), this also takes - * effect on file:// URLs, meaning that NetSurf cannot load its - * default CSS file. Given all examples of distributions I've checked - * also set http_proxy and friends, we can safely unset these. - */ - - unsetenv("ALL_PROXY"); - unsetenv("all_proxy"); - gtk_init(&argc, &argv); /* set standard error to be non-buffering */ setbuf(stderr, NULL); - options = findresource(respaths, "Choices"); - - messages = findresource(respaths, "Messages"); + options = resource_find(respaths, "Choices"); + messages = resource_find(respaths, "Messages"); netsurf_init(&argc, &argv, options, messages); @@ -896,9 +794,16 @@ utf8_convert_ret utf8_from_local_encoding(const char *string, size_t len, char *path_to_url(const char *path) { - int urllen = strlen(path) + FILE_SCHEME_PREFIX_LEN + 1; - char *url = malloc(urllen); + int urllen; + char *url; + + if (path == NULL) { + return NULL; + } + + urllen = strlen(path) + FILE_SCHEME_PREFIX_LEN + 1; + url = malloc(urllen); if (url == NULL) { return NULL; } diff --git a/riscos/gui.c b/riscos/gui.c index 8ebbc4fe6..e7ca63741 100644 --- a/riscos/gui.c +++ b/riscos/gui.c @@ -54,6 +54,7 @@ #include "content/content.h" #include "content/hlcache.h" #include "content/urldb.h" +#include "content/fetchers/resource.h" #include "desktop/cookies.h" #include "desktop/gui.h" #include "desktop/history_global_core.h" @@ -278,6 +279,11 @@ static void ro_msg_save_desktop(wimp_message *message); static void ro_msg_window_info(wimp_message *message); static void ro_gui_view_source_bounce(wimp_message *message); +char* gui_find_resource(const char *filename) +{ + return NULL; +} + /** * Initialise the gui (RISC OS specific part). */ diff --git a/utils/findresource.c b/utils/findresource.c deleted file mode 100644 index cc782682a..000000000 --- a/utils/findresource.c +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright 2010 Vincent Sanders - * - * 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 . - */ - -/** \file - * Provides utility functions for finding readable files. - * - * These functions are intended to make finding resource files more straightforward. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "utils/config.h" -#include "utils/findresource.h" - -#define MAX_RESPATH 128 /* maximum number of elements in the resource vector */ - -/* exported interface documented in findresource.h */ -char *vsfindfile(char *str, const char *format, va_list ap) -{ - char *realpathname; - char *pathname; - int len; - - pathname = malloc(PATH_MAX); - if (pathname == NULL) - return NULL; /* unable to allocate memory */ - - len = vsnprintf(pathname, PATH_MAX, format, ap); - - if ((len < 0) || (len >= PATH_MAX)) { - /* error or output exceeded PATH_MAX length so - * operation is doomed to fail. - */ - free(pathname); - return NULL; - } - - realpathname = realpath(pathname, str); - - free(pathname); - - if (realpathname != NULL) { - /* sucessfully expanded pathname */ - if (access(realpathname, R_OK) != 0) { - /* unable to read the file */ - return NULL; - } - } - - return realpathname; -} - -/* exported interface documented in findresource.h */ -char *sfindfile(char *str, const char *format, ...) -{ - va_list ap; - char *ret; - - va_start(ap, format); - ret = vsfindfile(str, format, ap); - va_end(ap); - - return ret; -} - -/* exported interface documented in findresource.h */ -char *findfile(const char *format, ...) -{ - char *str; - char *ret; - va_list ap; - - str = malloc(PATH_MAX); - if (str == NULL) - return NULL; /* unable to allocate memory */ - - va_start(ap, format); - ret = vsfindfile(str, format, ap); - va_end(ap); - - if (ret == NULL) - free(str); - - return ret; -} - -/* exported interface documented in findresource.h */ -char *sfindresource(char **respathv, char *filepath, const char *filename) -{ - int respathc = 0; - - if ((respathv == NULL) || (respathv[0] == NULL) || (filepath == NULL)) - return NULL; - - while (respathv[respathc] != NULL) { - if (sfindfile(filepath, "%s/%s", respathv[respathc], filename) != NULL) - return filepath; - - respathc++; - } - - return NULL; -} - -/* exported interface documented in findresource.h */ -char *findresource(char **respathv, const char *filename) -{ - char *ret; - char *filepath; - - if ((respathv == NULL) || (respathv[0] == NULL)) - return NULL; - - filepath = malloc(PATH_MAX); - if (filepath == NULL) - return NULL; - - ret = sfindresource(respathv, filepath, filename); - - if (ret == NULL) - free(filepath); - - return ret; -} - -/* exported interface documented in findresource.h */ -char *sfindresourcedef(char **respathv, char *filepath, const char *filename, const char *def) -{ - char t[PATH_MAX]; - char *ret; - - if ((respathv == NULL) || (respathv[0] == NULL) || (filepath == NULL)) - return NULL; - - ret = sfindresource(respathv, filepath, filename); - - if ((ret == NULL) && - (def != NULL)) { - /* search failed, return the path specified */ - ret = filepath; - if (def[0] == '~') { - snprintf(t, PATH_MAX, "%s/%s/%s", getenv("HOME"), def + 1, filename); - } else { - snprintf(t, PATH_MAX, "%s/%s", def, filename); - } - if (realpath(t, ret) == NULL) { - strcpy(ret, t); - } - - } - return ret; -} - - -/* exported interface documented in findresource.h */ -char ** -findresource_generate(char * const *pathv, const char * const *langv) -{ - char **respath; /* resource paths vector */ - int pathc = 0; - int langc = 0; - int respathc = 0; - struct stat dstat; - char tmppath[PATH_MAX]; - - respath = calloc(MAX_RESPATH, sizeof(char *)); - - while (pathv[pathc] != NULL) { - if ((stat(pathv[pathc], &dstat) == 0) && - S_ISDIR(dstat.st_mode)) { - /* path element exists and is a directory */ - langc = 0; - while (langv[langc] != NULL) { - snprintf(tmppath, PATH_MAX,"%s/%s",pathv[pathc],langv[langc]); - if ((stat(tmppath, &dstat) == 0) && - S_ISDIR(dstat.st_mode)) { - /* path element exists and is a directory */ - respath[respathc++] = strdup(tmppath); - } - langc++; - } - respath[respathc++] = strdup(pathv[pathc]); - } - pathc++; - } - - return respath; -} diff --git a/utils/findresource.h b/utils/findresource.h deleted file mode 100644 index 9e499f570..000000000 --- a/utils/findresource.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2010 Vincent Sanders - * - * 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 . - */ - -#ifndef _NETSURF_UTILS_FINDRESOURCE_H_ -#define _NETSURF_UTILS_FINDRESOURCE_H_ - -/** Create a normalised file name. - * - * If the file described by the format exists and is accessible the - * normalised path is placed in str and a pointer to str returned - * otherwise NULL is returned. The string in str is always modified. - * - * @param str A buffer to contain the normalised file name must be at - * least PATH_MAX bytes long. - * @param format A printf format for the filename. - * @param ap The list of arguments for the format. - * @return A pointer to the expanded filename or NULL if the file is - * not present or accessible. - */ -char *vsfindfile(char *str, const char *format, va_list ap); - -/** Create a normalised file name. - * - * Similar to vsfindfile but takes variadic (printf like) parameters - */ -char *sfindfile(char *str, const char *format, ...); - -/** Create a normalised file name. - * - * Similar to sfindfile but allocates its own storage for the - * returned string. The caller must free this sorage. - */ -char *findfile(const char *format, ...); - -/** Searches an array of resource paths for a file. - * - * Iterates through a vector of resource paths and returns the - * normalised file name of the first acessible file or NULL if no file - * can be found in any of the resource paths. - * - * @param respathv The resource path vector to iterate. - * @param filepath The buffer to place the result in. - * @param filename The filename of the resource to search for. - * @return A pointer to filepath if a target is found or NULL if not. - */ -char *sfindresource(char **respathv, char *filepath, const char *filename); - -/** Searches an array of resource paths for a file. - * - * Similar to sfindresource except it allocates its own storage for - * the returned string. The caller must free this sorage. - */ -char *findresource(char **respathv, const char *filename); - -/** Searches an array of resource paths for a file optionally forcing a default. - * - * Similar to sfindresource except if no resource is found the default - * is used as an additional path element to search, if that still - * fails the returned path is set to the concatination of the default - * path and the filename. - */ -char *sfindresourcedef(char **respathv, char *filepath, const char *filename, const char *def); - -/** Merge two string vectors into a resource search path vector. - * - * @param pathv A string vector containing path elemets to scan. - * @param langv A string vector containing language names to enumerate. - * @return A pointer to a NULL terminated string vector of valid - * resource directories. - */ -char **findresource_generate(char * const *pathv, const char * const *langv); - -#endif diff --git a/utils/resource.c b/utils/resource.c new file mode 100644 index 000000000..80b1c8280 --- /dev/null +++ b/utils/resource.c @@ -0,0 +1,310 @@ +/* + * Copyright 2010 Vincent Sanders + * + * 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 . + */ + +/** \file + * Provides utility functions for finding readable files. + * + * These functions are intended to make finding resource files more straightforward. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "utils/config.h" +#include "utils/resource.h" + +/** maximum number of elements in the resource vector */ +#define MAX_RESPATH 128 + +/* exported interface documented in findresource.h */ +char *resource_vsfindfile(char *str, const char *format, va_list ap) +{ + char *realpathname; + char *pathname; + int len; + + pathname = malloc(PATH_MAX); + if (pathname == NULL) + return NULL; /* unable to allocate memory */ + + len = vsnprintf(pathname, PATH_MAX, format, ap); + + if ((len < 0) || (len >= PATH_MAX)) { + /* error or output exceeded PATH_MAX length so + * operation is doomed to fail. + */ + free(pathname); + return NULL; + } + + realpathname = realpath(pathname, str); + + free(pathname); + + if (realpathname != NULL) { + /* sucessfully expanded pathname */ + if (access(realpathname, R_OK) != 0) { + /* unable to read the file */ + return NULL; + } + } + + return realpathname; +} + +/* exported interface documented in findresource.h */ +char *resource_sfindfile(char *str, const char *format, ...) +{ + va_list ap; + char *ret; + + va_start(ap, format); + ret = resource_vsfindfile(str, format, ap); + va_end(ap); + + return ret; +} + +/* exported interface documented in findresource.h */ +char *resource_findfile(const char *format, ...) +{ + char *str; + char *ret; + va_list ap; + + str = malloc(PATH_MAX); + if (str == NULL) + return NULL; /* unable to allocate memory */ + + va_start(ap, format); + ret = resource_vsfindfile(str, format, ap); + va_end(ap); + + if (ret == NULL) + free(str); + + return ret; +} + +/* exported interface documented in findresource.h */ +char *resource_sfind(char **respathv, char *filepath, const char *filename) +{ + int respathc = 0; + + if ((respathv == NULL) || (respathv[0] == NULL) || (filepath == NULL)) + return NULL; + + while (respathv[respathc] != NULL) { + if (resource_sfindfile(filepath, "%s/%s", respathv[respathc], filename) != NULL) + return filepath; + + respathc++; + } + + return NULL; +} + +/* exported interface documented in findresource.h */ +char *resource_find(char **respathv, const char *filename) +{ + char *ret; + char *filepath; + + if ((respathv == NULL) || (respathv[0] == NULL)) + return NULL; + + filepath = malloc(PATH_MAX); + if (filepath == NULL) + return NULL; + + ret = resource_sfind(respathv, filepath, filename); + + if (ret == NULL) + free(filepath); + + return ret; +} + +/* exported interface documented in findresource.h */ +char *resource_sfinddef(char **respathv, char *filepath, const char *filename, const char *def) +{ + char t[PATH_MAX]; + char *ret; + + if ((respathv == NULL) || (respathv[0] == NULL) || (filepath == NULL)) + return NULL; + + ret = resource_sfind(respathv, filepath, filename); + + if ((ret == NULL) && (def != NULL)) { + /* search failed, return the path specified */ + ret = filepath; + if (def[0] == '~') { + snprintf(t, PATH_MAX, "%s/%s/%s", getenv("HOME"), def + 1, filename); + } else { + snprintf(t, PATH_MAX, "%s/%s", def, filename); + } + if (realpath(t, ret) == NULL) { + strcpy(ret, t); + } + + } + return ret; +} + + +/* exported interface documented in resource.h */ +char ** +resource_generate(char * const *pathv, const char * const *langv) +{ + char **respath; /* resource paths vector */ + int pathc = 0; + int langc = 0; + int respathc = 0; + struct stat dstat; + char tmppath[PATH_MAX]; + + respath = calloc(MAX_RESPATH, sizeof(char *)); + + while (pathv[pathc] != NULL) { + if ((stat(pathv[pathc], &dstat) == 0) && + S_ISDIR(dstat.st_mode)) { + /* path element exists and is a directory */ + langc = 0; + while (langv[langc] != NULL) { + snprintf(tmppath, sizeof tmppath, "%s/%s", pathv[pathc],langv[langc]); + if ((stat(tmppath, &dstat) == 0) && + S_ISDIR(dstat.st_mode)) { + /* path element exists and is a directory */ + respath[respathc++] = strdup(tmppath); + } + langc++; + } + respath[respathc++] = strdup(pathv[pathc]); + } + pathc++; + } + + return respath; +} + +/* expand ${} in a string into environment variables */ +static char * +expand_path(const char *path) +{ + char *exp = strdup(path); + int explen; + int cstart = -1; + int cloop = 0; + char *envv; + int envlen; + int replen; /* length of replacement */ + + if (exp == NULL) + return NULL; + + explen = strlen(exp) + 1; + + while (exp[cloop] != 0) { + if ((exp[cloop] == '$') && + (exp[cloop + 1] == '{')) { + cstart = cloop; + cloop++; + } + + if ((cstart != -1) && + (exp[cloop] == '}')) { + replen = cloop - cstart; + exp[cloop] = 0; + envv = getenv(exp + cstart + 2); + if (envv == NULL) { + memmove(exp + cstart, + exp + cloop + 1, + explen - cloop - 1); + explen -= replen; + } else { + envlen = strlen(envv); + exp = realloc(exp, explen + envlen - replen); + memmove(exp + cstart + envlen, + exp + cloop + 1, + explen - cloop - 1); + memmove(exp + cstart, envv, envlen); + explen += envlen - replen; + } + cloop -= replen; + cstart = -1; + } + + cloop++; + } + + return exp; +} + +/* exported interface documented in resource.h */ +char ** +resource_path_to_strvec(const char *path) +{ + char **strvec; + int strc = 0; + + strvec = calloc(MAX_RESPATH, sizeof(char *)); + if (strvec == NULL) + return NULL; + + strvec[strc] = expand_path(path); + if (strvec[strc] == NULL) { + free(strvec); + return NULL; + } + strc++; + + strvec[strc] = strchr(strvec[0], ':'); + while ((strc < (MAX_RESPATH - 2)) && + (strvec[strc] != NULL)) { + /* null terminate previous entry */ + *strvec[strc] = 0; + strvec[strc]++; + + /* skip colons */ + while (*strvec[strc] == ':') + strvec[strc]++; + + if (*strvec[strc] == 0) + break; /* string is terminated */ + + strc++; + + strvec[strc] = strchr(strvec[strc - 1], ':'); + } + + return strvec; +} + +/* exported interface documented in resource.h */ +void resource_free_strvec(char **pathv) +{ + free(pathv[0]); + free(pathv); +} diff --git a/utils/resource.h b/utils/resource.h new file mode 100644 index 000000000..ba1ad1535 --- /dev/null +++ b/utils/resource.h @@ -0,0 +1,105 @@ +/* + * Copyright 2010 Vincent Sanders + * + * 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 . + */ + +/** \file Utility routines to locate file resources. */ + +#ifndef _NETSURF_UTILS_RESOURCE_H_ +#define _NETSURF_UTILS_RESOURCE_H_ + +/** Create a normalised file name. + * + * If the file described by the format exists and is accessible the + * normalised path is placed in str and a pointer to str returned + * otherwise NULL is returned. The string in str is always modified. + * + * @param str A buffer to contain the normalised file name must be at + * least PATH_MAX bytes long. + * @param format A printf format for the filename. + * @param ap The list of arguments for the format. + * @return A pointer to the expanded filename or NULL if the file is + * not present or accessible. + */ +char *resource_vsfindfile(char *str, const char *format, va_list ap); + +/** Create a normalised file name. + * + * Similar to vsfindfile but takes variadic (printf like) parameters + */ +char *resource_sfindfile(char *str, const char *format, ...); + +/** Create a normalised file name. + * + * Similar to sfindfile but allocates its own storage for the + * returned string. The caller must free this sorage. + */ +char *resource_findfile(const char *format, ...); + +/** Searches an array of resource paths for a file. + * + * Iterates through a vector of resource paths and returns the + * normalised file name of the first acessible file or NULL if no file + * can be found in any of the resource paths. + * + * @param respathv The resource path vector to iterate. + * @param filepath The buffer to place the result in. + * @param filename The filename of the resource to search for. + * @return A pointer to filepath if a target is found or NULL if not. + */ +char *resource_sfind(char **respathv, char *filepath, const char *filename); + +/** Searches an array of resource paths for a file. + * + * Similar to resource_sfind except it allocates its own storage for + * the returned string. The caller must free this sorage. + */ +char *resource_find(char **respathv, const char *filename); + +/** Searches an array of resource paths for a file optionally forcing a default. + * + * Similar to resource_sfind except if no resource is found the default + * is used as an additional path element to search, if that still + * fails the returned path is set to the concatination of the default + * path and the filename. + */ +char *resource_sfinddef(char **respathv, char *filepath, const char *filename, const char *def); + +/** Merge two string vectors into a resource search path vector. + * + * @param pathv A string vector containing path elemets to scan. + * @param langv A string vector containing language names to enumerate. + * @return A pointer to a NULL terminated string vector of valid + * resource directories. + */ +char **resource_generate(char * const *pathv, const char * const *langv); + + +/** Convert a colon separated list of path elements into a string vector. + * + * @param path A colon separated path. + * @return A pointer to a NULL terminated string vector of valid + * resource directories. + */ +char **resource_path_to_strvec(const char *path); + +/** Free a string vector + * + * Free a string vector allocated by resource_path_to_strvec + */ +void resource_free_strvec(char **pathv); + +#endif /* _NETSURF_UTILS_RESOURCE_H_ */ diff --git a/windows/gui.c b/windows/gui.c index 81fb04e26..5a2163453 100644 --- a/windows/gui.c +++ b/windows/gui.c @@ -32,6 +32,7 @@ #include "content/urldb.h" #include "content/fetch.h" +#include "content/fetchers/resource.h" #include "css/utils.h" #include "desktop/gui.h" #include "desktop/history_core.h" @@ -2558,6 +2559,11 @@ void gui_quit(void) LOG(("gui_quit")); } +char* gui_find_resource(const char *filename) +{ + return NULL; +} + static void gui_init(int argc, char** argv) { char buf[PATH_MAX], sbuf[PATH_MAX]; -- cgit v1.2.3