add resource handling

move gtk and framebuffer to use generic resource handling

svn path=/trunk/netsurf/; revision=11772
This commit is contained in:
Vincent Sanders 2011-02-23 22:27:55 +00:00
parent b49669d17e
commit 0231675abf
23 changed files with 663 additions and 306 deletions

View File

@ -253,16 +253,18 @@ ifeq ($(TARGET),framebuffer)
NETSURF_FB_FONTLIB := internal NETSURF_FB_FONTLIB := internal
# freetype compiled in font locations # freetype compiled in font locations
NETSURF_FB_FONT_SANS_SERIF := /usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf NETSURF_FB_FONTPATH := /usr/share/fonts/truetype/ttf-dejavu:/usr/share/fonts/truetype/msttcorefonts
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 := DejaVuSans.ttf
NETSURF_FB_FONT_SANS_SERIF_ITALIC_BOLD := /usr/share/fonts/truetype/ttf-dejavu/DejaVuSans-BoldOblique.ttf NETSURF_FB_FONT_SANS_SERIF_BOLD := DejaVuSans-Bold.ttf
NETSURF_FB_FONT_SERIF := /usr/share/fonts/truetype/ttf-dejavu/DejaVuSerif.ttf NETSURF_FB_FONT_SANS_SERIF_ITALIC := DejaVuSans-Oblique.ttf
NETSURF_FB_FONT_SERIF_BOLD := /usr/share/fonts/truetype/ttf-dejavu/DejaVuSerif-Bold.ttf NETSURF_FB_FONT_SANS_SERIF_ITALIC_BOLD := DejaVuSans-BoldOblique.ttf
NETSURF_FB_FONT_MONOSPACE := /usr/share/fonts/truetype/ttf-dejavu/DejaVuSansMono.ttf NETSURF_FB_FONT_SERIF := DejaVuSerif.ttf
NETSURF_FB_FONT_MONOSPACE_BOLD := /usr/share/fonts/truetype/ttf-dejavu/DejaVuSansMono-Bold.ttf NETSURF_FB_FONT_SERIF_BOLD := DejaVuSerif-Bold.ttf
NETSURF_FB_FONT_CURSIVE := /usr/share/fonts/truetype/msttcorefonts/Comic_Sans_MS.ttf NETSURF_FB_FONT_MONOSPACE := DejaVuSansMono.ttf
NETSURF_FB_FONT_FANTASY := /usr/share/fonts/truetype/msttcorefonts/Impact.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 # Framebuffer frontends may have differing root paths for resources
# As such, these specify the resource path and config path. # As such, these specify the resource path and config path.

View File

@ -6,7 +6,7 @@
S_CONTENT := content.c dirlist.c fetch.c hlcache.c llcache.c urldb.c 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 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 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 \ 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 \ 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 \ mouse.c options.c plot_style.c print.c search.c searchweb.c \

View File

@ -34,6 +34,7 @@
#include "utils/utf8.h" #include "utils/utf8.h"
#include "utils/utils.h" #include "utils/utils.h"
#include "utils/url.h" #include "utils/url.h"
#include "content/fetchers/resource.h"
/* NetSurf Amiga platform includes */ /* NetSurf Amiga platform includes */
#include "amiga/arexx.h" #include "amiga/arexx.h"
@ -412,6 +413,11 @@ void ami_amiupdate(void)
/* end Amiupdate */ /* end Amiupdate */
} }
char* gui_find_resource(const char *filename)
{
return NULL;
}
void gui_init(int argc, char** argv) void gui_init(int argc, char** argv)
{ {
BPTR lock = 0; BPTR lock = 0;

View File

@ -34,6 +34,7 @@
#include "content/urldb.h" #include "content/urldb.h"
#include "content/fetch.h" #include "content/fetch.h"
#include "content/fetchers/resource.h"
#include "css/utils.h" #include "css/utils.h"
#include "desktop/gui.h" #include "desktop/gui.h"
#include "desktop/history_core.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) static void gui_init(int argc, char** argv)
{ {
char buf[PATH_MAX], sbuf[PATH_MAX]; char buf[PATH_MAX], sbuf[PATH_MAX];

View File

@ -46,6 +46,7 @@ extern "C" {
#include "content/content_protected.h" #include "content/content_protected.h"
#include "content/fetch.h" #include "content/fetch.h"
#include "content/fetchers/curl.h" #include "content/fetchers/curl.h"
#include "content/fetchers/resource.h"
#include "content/urldb.h" #include "content/urldb.h"
#include "desktop/401login.h" #include "desktop/401login.h"
#include "desktop/browser.h" #include "desktop/browser.h"
@ -421,6 +422,11 @@ static int32 bapp_thread(void *arg)
return 0; return 0;
} }
char* gui_find_resource(const char *filename)
{
return NULL;
}
static void gui_init2(int argc, char** argv) static void gui_init2(int argc, char** argv)
{ {
CALLED(); CALLED();

View File

@ -34,6 +34,7 @@
#import "desktop/401login.h" #import "desktop/401login.h"
#import "utils/utils.h" #import "utils/utils.h"
#import "image/ico.h" #import "image/ico.h"
#import "content/fetchers/resource.h"
char *default_stylesheet_url; char *default_stylesheet_url;
char *adblock_stylesheet_url; char *adblock_stylesheet_url;
@ -49,6 +50,11 @@ NSString * const kAlwaysCloseMultipleTabs = @"AlwaysCloseMultipleTabs";
#define UNIMPL() NSLog( @"Function '%s' unimplemented", __func__ ) #define UNIMPL() NSLog( @"Function '%s' unimplemented", __func__ )
char* gui_find_resource(const char *filename)
{
return NULL;
}
void gui_multitask(void) void gui_multitask(void)
{ {
// nothing to do // nothing to do

View File

@ -38,6 +38,7 @@
#include "utils/config.h" #include "utils/config.h"
#include "content/fetch.h" #include "content/fetch.h"
#include "content/fetchers/resource.h"
#include "content/fetchers/about.h" #include "content/fetchers/about.h"
#include "content/fetchers/curl.h" #include "content/fetchers/curl.h"
#include "content/fetchers/data.h" #include "content/fetchers/data.h"
@ -112,6 +113,7 @@ void fetch_init(void)
fetch_curl_register(); fetch_curl_register();
fetch_data_register(); fetch_data_register();
fetch_file_register(); fetch_file_register();
fetch_resource_register();
fetch_about_register(); fetch_about_register();
fetch_active = false; fetch_active = false;
} }

View File

@ -127,52 +127,16 @@ fetch_about_blank_handler_aborted:
return false; 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) static bool fetch_about_credits_handler(struct fetch_about_context *ctx)
{ {
char buffer[4096]; /* content is going to return redirect */
int code = 200; fetch_set_http_code(ctx->fetchh, 302);
int slen;
int auth_loop = 0;
/* content is going to return ok */ fetch_about_send_callback(FETCH_REDIRECT, ctx, "resource:credits.html",
fetch_set_http_code(ctx->fetchh, code); 0, FETCH_ERROR_NO_ERROR);
/* content type */
if (fetch_about_send_header(ctx, "Content-Type: text/html"))
goto fetch_about_credits_handler_aborted;
slen = snprintf(buffer, sizeof buffer,
"<html><head><title>NetSurf Browser Credits</title></head>"
"<body><h1>NetSurf Browser Credits</h1>"
"<p>Authors</p>"
"<ul>");
while (authors[auth_loop] != NULL) {
slen += snprintf(buffer + slen, sizeof buffer - slen,
"<li>%s</li>", authors[auth_loop]);
auth_loop++;
}
slen += snprintf(buffer + slen, sizeof buffer - slen,
"</ul></body></html>");
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);
return true; return true;
fetch_about_credits_handler_aborted:
return false;
} }
static bool fetch_about_config_handler(struct fetch_about_context *ctx) static bool fetch_about_config_handler(struct fetch_about_context *ctx)

277
content/fetchers/resource.c Normal file
View File

@ -0,0 +1,277 @@
/*
* Copyright 2011 Vincent Sanders <vince@netsurf-browser.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
/* resource: URL handling. Based on the data fetcher by Rob Kendrick */
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <assert.h>
#include <errno.h>
#include <stdbool.h>
#include <inttypes.h>
#include <string.h>
#include <strings.h>
#include <time.h>
#include <stdio.h>
#include <dirent.h>
#include <limits.h>
#include <stdarg.h>
#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, "<html><head><title>%s</title></head>"
"<body><h1>%s</h1>"
"<p>Error %d while fetching file %s</p></body></html>",
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);
}

View File

@ -0,0 +1,38 @@
/*
* Copyright 2011 Vincent Sanders <vince@netsurf-browser.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
/** \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

View File

@ -1952,6 +1952,7 @@ nserror llcache_fetch_redirect(llcache_object *object, const char *target,
const llcache_post_data *post = object->fetch.post; const llcache_post_data *post = object->fetch.post;
char *url, *absurl; char *url, *absurl;
char *scheme; char *scheme;
char *object_scheme;
url_func_result result; url_func_result result;
/* Extract HTTP response code from the fetch object */ /* Extract HTTP response code from the fetch object */
long http_code = fetch_http_code(object->fetch.fetch); 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; return NSERROR_NOMEM;
} }
/* Ensure that redirects to file:/// don't happen */ /* 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;
}
result = url_scheme(url, &scheme); result = url_scheme(url, &scheme);
if (result != URL_FUNC_OK) { if (result != URL_FUNC_OK) {
free(url); free(url);
return NSERROR_NOMEM; return NSERROR_NOMEM;
} }
if (strcasecmp(scheme, "file") == 0) { /* resource is allowed to redirect anywhere */
free(scheme); if ((strcasecmp(object_scheme, "resource") != 0) &&
free(url); (strcasecmp(object_scheme, "about") != 0)) {
return NSERROR_OK; /* 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(scheme);
free(object_scheme);
/* Bail out if we've no way of handling this URL */ /* Bail out if we've no way of handling this URL */
if (fetch_can_fetch(url) == false) { if (fetch_can_fetch(url) == false) {

View File

@ -24,6 +24,7 @@ CFLAGS += -Dnsframebuffer
CFLAGS += '-DNETSURF_FB_RESPATH="$(NETSURF_FB_RESPATH_$(NETSURF_FB_FRONTEND))"' CFLAGS += '-DNETSURF_FB_RESPATH="$(NETSURF_FB_RESPATH_$(NETSURF_FB_FRONTEND))"'
# compile time font locations # 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="$(NETSURF_FB_FONT_SANS_SERIF)"'
CFLAGS += '-DNETSURF_FB_FONT_SANS_SERIF_BOLD="$(NETSURF_FB_FONT_SANS_SERIF_BOLD)"' 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)"' CFLAGS += '-DNETSURF_FB_FONT_SANS_SERIF_ITALIC="$(NETSURF_FB_FONT_SANS_SERIF_ITALIC)"'

View File

@ -33,6 +33,8 @@ const char *fetch_filetype(const char *unix_path)
l = strlen(unix_path); l = strlen(unix_path);
if (2 < l && strcasecmp(unix_path + l - 3, "css") == 0) if (2 < l && strcasecmp(unix_path + l - 3, "css") == 0)
return "text/css"; 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) if (2 < l && strcasecmp(unix_path + l - 3, "jpg") == 0)
return "image/jpeg"; return "image/jpeg";
if (3 < l && strcasecmp(unix_path + l - 4, "jpeg") == 0) if (3 < l && strcasecmp(unix_path + l - 4, "jpeg") == 0)

View File

@ -27,9 +27,45 @@
#include "utils/log.h" #include "utils/log.h"
#include "utils/url.h" #include "utils/url.h"
#include "utils/resource.h"
#include "content/fetchers/resource.h"
#include "framebuffer/findfile.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) char *path_to_url(const char *path)
{ {
int urllen = strlen(path) + FILE_SCHEME_PREFIX_LEN + 1; int urllen = strlen(path) + FILE_SCHEME_PREFIX_LEN + 1;
@ -65,67 +101,12 @@ char *url_to_path(const char *url)
return respath; return respath;
} }
/** char* gui_find_resource(const char *filename)
* 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 *cdir = getenv("HOME"); char buf[PATH_MAX];
char t[PATH_MAX]; return path_to_url(resource_sfind(respaths, buf, filename));
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;
} }
/* /*
* Local Variables: * Local Variables:
* c-basic-offset: 8 * c-basic-offset: 8

View File

@ -19,6 +19,14 @@
#ifndef NETSURF_FB_FINDFILE_H #ifndef NETSURF_FB_FINDFILE_H
#define 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 */ #endif /* NETSURF_FB_FINDFILE_H */

View File

@ -27,6 +27,7 @@
#include "render/font.h" #include "render/font.h"
#include "utils/utf8.h" #include "utils/utf8.h"
#include "utils/log.h" #include "utils/log.h"
#include "utils/resource.h"
#include "desktop/options.h" #include "desktop/options.h"
#include "framebuffer/gui.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 */ /* create new framebuffer face and cause it to be loaded to check its ok */
static fb_faceid_t * 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; fb_faceid_t *newf;
FT_Error error; FT_Error error;
@ -124,13 +125,13 @@ fb_new_face(const char *option, const char *resname, const char *fontfile)
if (option != NULL) { if (option != NULL) {
newf->fontfile = strdup(option); newf->fontfile = strdup(option);
} else { } else {
fb_find_resource(buf, resname, fontfile); resource_sfind(respaths, buf, fontname);
newf->fontfile = strdup(buf); newf->fontfile = strdup(buf);
} }
error = FTC_Manager_LookupFace(ft_cmanager, (FTC_FaceID)newf, &aface); error = FTC_Manager_LookupFace(ft_cmanager, (FTC_FaceID)newf, &aface);
if (error) { 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); free(newf);
newf = NULL; newf = NULL;
} }

View File

@ -37,6 +37,7 @@
#include "desktop/netsurf.h" #include "desktop/netsurf.h"
#include "desktop/options.h" #include "desktop/options.h"
#include "desktop/shape.h" #include "desktop/shape.h"
#include "utils/resource.h"
#include "utils/log.h" #include "utils/log.h"
#include "utils/url.h" #include "utils/url.h"
#include "utils/messages.h" #include "utils/messages.h"
@ -63,7 +64,6 @@
char *default_stylesheet_url; char *default_stylesheet_url;
char *quirks_stylesheet_url; char *quirks_stylesheet_url;
char *adblock_stylesheet_url; char *adblock_stylesheet_url;
char *options_file_location;
fbtk_widget_t *fbtk; fbtk_widget_t *fbtk;
@ -435,33 +435,31 @@ process_cmdline(int argc, char** argv)
return true; return true;
} }
static void static void
gui_init(int argc, char** argv) gui_init(int argc, char** argv)
{ {
char buf[PATH_MAX];
nsfb_t *nsfb; nsfb_t *nsfb;
option_core_select_menu = true; option_core_select_menu = true;
/* set up stylesheet urls */ /* set up stylesheet urls */
fb_find_resource(buf, "default.css", "./framebuffer/res/default.css"); default_stylesheet_url = strdup("resource:default.css");
default_stylesheet_url = path_to_url(buf);
LOG(("Using '%s' as Default CSS URL", default_stylesheet_url)); LOG(("Using '%s' as Default CSS URL", default_stylesheet_url));
fb_find_resource(buf, "quirks.css", "./framebuffer/res/quirks.css"); quirks_stylesheet_url = strdup("resource:quirks.css");
quirks_stylesheet_url = path_to_url(buf); 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) { if (option_cookie_file == NULL) {
fb_find_resource(buf, "Cookies", "~/.netsurf/Cookies"); option_cookie_file = resource_find(respaths, "Cookies");
LOG(("Using '%s' as Cookies file", buf)); LOG(("Using '%s' as Cookies file", option_cookie_file));
option_cookie_file = strdup(buf);
} }
if (option_cookie_jar == NULL) { if (option_cookie_jar == NULL) {
fb_find_resource(buf, "Cookies", "~/.netsurf/Cookies"); option_cookie_jar = resource_find(respaths, "Cookies");
LOG(("Using '%s' as Cookie Jar file", buf)); LOG(("Using '%s' as Cookie Jar file", option_cookie_jar));
option_cookie_jar = strdup(buf);
} }
if (option_cookie_file == NULL || option_cookie_jar == NULL) if (option_cookie_file == NULL || option_cookie_jar == NULL)
@ -496,17 +494,21 @@ int
main(int argc, char** argv) main(int argc, char** argv)
{ {
struct browser_window *bw; struct browser_window *bw;
char options[PATH_MAX]; char *options;
char messages[PATH_MAX]; char *messages;
setbuf(stderr, NULL); setbuf(stderr, NULL);
fb_find_resource(messages, "messages", "./framebuffer/res/messages"); respaths = fb_init_resource("${HOME}/.netsurf/:${NETSURFRES}:"NETSURF_FB_RESPATH":./framebuffer/res:"NETSURF_FB_FONTPATH);
fb_find_resource(options, "Choices-fb", "~/.netsurf/Choices-fb");
options_file_location = strdup(options); options = resource_find(respaths, "Choices");
messages = resource_find(respaths, "messages");
netsurf_init(&argc, &argv, options, messages); netsurf_init(&argc, &argv, options, messages);
free(messages);
free(options);
gui_init(argc, argv); gui_init(argc, argv);
LOG(("calling browser_window_create")); LOG(("calling browser_window_create"));

View File

@ -155,11 +155,17 @@ const char *fetch_filetype(const char *unix_path)
const char *ptr; const char *ptr;
char *lowerchar; char *lowerchar;
const char *type; const char *type;
int l;
stat(unix_path, &statbuf); stat(unix_path, &statbuf);
if (S_ISDIR(statbuf.st_mode)) if (S_ISDIR(statbuf.st_mode))
return "application/x-netsurf-directory"; 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) { if (strchr(unix_path, '.') == NULL) {
/* no extension anywhere! */ /* no extension anywhere! */
return "text/plain"; return "text/plain";

183
gtk/gui.c
View File

@ -43,6 +43,7 @@
#include "content/content.h" #include "content/content.h"
#include "content/fetch.h" #include "content/fetch.h"
#include "content/fetchers/curl.h" #include "content/fetchers/curl.h"
#include "content/fetchers/resource.h"
#include "content/hlcache.h" #include "content/hlcache.h"
#include "content/urldb.h" #include "content/urldb.h"
#include "desktop/browser.h" #include "desktop/browser.h"
@ -78,7 +79,7 @@
#include "utils/url.h" #include "utils/url.h"
#include "utils/utf8.h" #include "utils/utf8.h"
#include "utils/utils.h" #include "utils/utils.h"
#include "utils/findresource.h" #include "utils/resource.h"
char *default_stylesheet_url; char *default_stylesheet_url;
char *quirks_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 THROBBER_FRAMES 9
#define MAX_RESPATH 128 /* maximum number of elements in the resource vector */ char **respaths; /** resource search path 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;
}
/** Create an array of valid paths to search for resources. /** 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 **pathv; /* resource path string vector */
char **respath; /* resource paths vector */ char **respath; /* resource paths vector */
pathv = path_to_strvec(resource_path); pathv = resource_path_to_strvec(resource_path);
langv = g_get_language_names(); langv = g_get_language_names();
respath = findresource_generate(pathv, langv); respath = resource_generate(pathv, langv);
free(pathv[0]); resource_free_strvec(pathv);
free(pathv);
return respath; return respath;
} }
@ -259,7 +165,7 @@ static bool nsgtk_throbber_init(char **respath, int framec)
for (frame_num = 0; frame_num < framec; frame_num++) { for (frame_num = 0; frame_num < framec; frame_num++) {
snprintf(targetname, PATH_MAX, "throbber/throbber%d.png", 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); 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); snprintf(resname, PATH_MAX, "%s.glade", name);
filepath = findresource(respath, resname); filepath = resource_find(respath, resname);
if (filepath == NULL) { if (filepath == NULL) {
snprintf(errorstr, NEW_GLADE_ERROR_SIZE, snprintf(errorstr, NEW_GLADE_ERROR_SIZE,
"Unable to locate %s glade template file.\n", name); "Unable to locate %s glade template file.\n", name);
@ -362,12 +268,12 @@ static void check_options(char **respath)
* values! * values!
*/ */
if (!option_cookie_file) { if (!option_cookie_file) {
sfindresourcedef(respath, buf, "Cookies", "~/.netsurf/"); resource_sfinddef(respath, buf, "Cookies", "~/.netsurf/");
LOG(("Using '%s' as Cookies file", buf)); LOG(("Using '%s' as Cookies file", buf));
option_cookie_file = strdup(buf); option_cookie_file = strdup(buf);
} }
if (!option_cookie_jar) { if (!option_cookie_jar) {
sfindresourcedef(respath, buf, "Cookies", "~/.netsurf/"); resource_sfinddef(respath, buf, "Cookies", "~/.netsurf/");
LOG(("Using '%s' as Cookie Jar file", buf)); LOG(("Using '%s' as Cookie Jar file", buf));
option_cookie_jar = strdup(buf); option_cookie_jar = strdup(buf);
} }
@ -375,13 +281,13 @@ static void check_options(char **respath)
die("Failed initialising cookie options"); die("Failed initialising cookie options");
if (!option_url_file) { if (!option_url_file) {
sfindresourcedef(respath, buf, "URLs", "~/.netsurf/"); resource_sfinddef(respath, buf, "URLs", "~/.netsurf/");
LOG(("Using '%s' as URL file", buf)); LOG(("Using '%s' as URL file", buf));
option_url_file = strdup(buf); option_url_file = strdup(buf);
} }
if (!option_ca_path) { if (!option_ca_path) {
sfindresourcedef(respath, buf, "certs", "/etc/ssl/"); resource_sfinddef(respath, buf, "certs", "/etc/ssl/");
LOG(("Using '%s' as certificate path", buf)); LOG(("Using '%s' as certificate path", buf));
option_ca_path = strdup(buf); option_ca_path = strdup(buf);
} }
@ -391,12 +297,12 @@ static void check_options(char **respath)
option_downloads_directory = hdir; option_downloads_directory = hdir;
} }
sfindresourcedef(respath, buf, "icons/", "~/.netsurf/"); resource_sfinddef(respath, buf, "icons/", "~/.netsurf/");
LOG(("Using '%s' as Tree icons dir", buf)); LOG(("Using '%s' as Tree icons dir", buf));
tree_set_icon_dir(strdup(buf)); tree_set_icon_dir(strdup(buf));
if (!option_hotlist_path) { if (!option_hotlist_path) {
sfindresourcedef(respath, buf, "Hotlist", "~/.netsurf/"); resource_sfinddef(respath, buf, "Hotlist", "~/.netsurf/");
LOG(("Using '%s' as Hotlist file", buf)); LOG(("Using '%s' as Hotlist file", buf));
option_hotlist_path = strdup(buf); option_hotlist_path = strdup(buf);
} }
@ -404,7 +310,7 @@ static void check_options(char **respath)
die("Failed initialising hotlist option"); die("Failed initialising hotlist option");
sfindresourcedef(respath, buf, "Print", "~/.netsurf/"); resource_sfinddef(respath, buf, "Print", "~/.netsurf/");
LOG(("Using '%s' as Print Settings file", buf)); LOG(("Using '%s' as Print Settings file", buf));
print_options_file_location = strdup(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. * 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 * however these may be translated which breaks things
* relying on res_dir_location. * relying on res_dir_location.
*/ */
resource_filename = findresource(respath, "languages"); resource_filename = resource_find(respath, "languages");
resource_filename[strlen(resource_filename) - 9] = 0; resource_filename[strlen(resource_filename) - 9] = 0;
res_dir_location = resource_filename; res_dir_location = resource_filename;
/* languages file */ /* languages file */
languages_file_location = findresource(respath, "languages"); languages_file_location = resource_find(respath, "languages");
/* initialise the glade templates */ /* initialise the glade templates */
nsgtk_init_glade(respath); nsgtk_init_glade(respath);
/* set default icon if its available */ /* set default icon if its available */
resource_filename = findresource(respath, "netsurf.xpm"); resource_filename = resource_find(respath, "netsurf.xpm");
if (resource_filename != NULL) { if (resource_filename != NULL) {
gtk_window_set_default_icon_from_file(resource_filename, NULL); gtk_window_set_default_icon_from_file(resource_filename, NULL);
free(resource_filename); free(resource_filename);
} }
/* Search engine sources */ /* 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)); LOG(("Using '%s' as Search Engines file", search_engines_file_location));
/* Default Icon */ /* 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)); LOG(("Using '%s' as default search ico", search_default_ico_location));
/* Toolbar inicies file */ /* 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)); LOG(("Using '%s' as custom toolbar settings file", toolbar_indices_file_location));
/* load throbber images */ /* load throbber images */
@ -476,19 +389,17 @@ static void gui_init(int argc, char** argv, char **respath)
/* Initialise completions - cannot fail */ /* Initialise completions - cannot fail */
nsgtk_completion_init(); nsgtk_completion_init();
sfindresourcedef(respath, buf, "mime.types", "/etc/"); resource_sfinddef(respath, buf, "mime.types", "/etc/");
gtk_fetch_filetype_init(buf); gtk_fetch_filetype_init(buf);
/* set up stylesheet urls */ /* set up stylesheet urls */
sfindresourcedef(respath, buf, "gtkdefault.css", "./gtk/res/"); default_stylesheet_url = strdup("resource:gtkdefault.css");
default_stylesheet_url = path_to_url(buf);
LOG(("Using '%s' as Default CSS URL", default_stylesheet_url)); LOG(("Using '%s' as Default CSS URL", default_stylesheet_url));
sfindresourcedef(respath, buf, "quirks.css", "./gtk/res/"); quirks_stylesheet_url = strdup("resource:quirks.css");
quirks_stylesheet_url = path_to_url(buf); LOG(("Using '%s' as quirks CSS URL", quirks_stylesheet_url));
sfindresourcedef(respath, buf, "adblock.css", "./gtk/res/"); adblock_stylesheet_url = strdup("resource:adblock.css");
adblock_stylesheet_url = path_to_url(buf);
LOG(("Using '%s' as AdBlock CSS URL", adblock_stylesheet_url)); LOG(("Using '%s' as AdBlock CSS URL", adblock_stylesheet_url));
urldb_load(option_url_file); urldb_load(option_url_file);
@ -560,32 +471,19 @@ int main(int argc, char** argv)
{ {
char *messages; char *messages;
char *options; char *options;
char **respaths;
/* check home directory is available */ /* check home directory is available */
nsgtk_check_homedir(); nsgtk_check_homedir();
respaths = nsgtk_init_resource("${HOME}/.netsurf/:${NETSURFRES}:"GTK_RESPATH":./gtk/res"); 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); gtk_init(&argc, &argv);
/* set standard error to be non-buffering */ /* set standard error to be non-buffering */
setbuf(stderr, NULL); setbuf(stderr, NULL);
options = findresource(respaths, "Choices"); options = resource_find(respaths, "Choices");
messages = resource_find(respaths, "Messages");
messages = findresource(respaths, "Messages");
netsurf_init(&argc, &argv, options, 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) char *path_to_url(const char *path)
{ {
int urllen = strlen(path) + FILE_SCHEME_PREFIX_LEN + 1; int urllen;
char *url = malloc(urllen); char *url;
if (path == NULL) {
return NULL;
}
urllen = strlen(path) + FILE_SCHEME_PREFIX_LEN + 1;
url = malloc(urllen);
if (url == NULL) { if (url == NULL) {
return NULL; return NULL;
} }

View File

@ -54,6 +54,7 @@
#include "content/content.h" #include "content/content.h"
#include "content/hlcache.h" #include "content/hlcache.h"
#include "content/urldb.h" #include "content/urldb.h"
#include "content/fetchers/resource.h"
#include "desktop/cookies.h" #include "desktop/cookies.h"
#include "desktop/gui.h" #include "desktop/gui.h"
#include "desktop/history_global_core.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_msg_window_info(wimp_message *message);
static void ro_gui_view_source_bounce(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). * Initialise the gui (RISC OS specific part).
*/ */

View File

@ -32,12 +32,13 @@
#include <string.h> #include <string.h>
#include "utils/config.h" #include "utils/config.h"
#include "utils/findresource.h" #include "utils/resource.h"
#define MAX_RESPATH 128 /* maximum number of elements in the resource vector */ /** maximum number of elements in the resource vector */
#define MAX_RESPATH 128
/* exported interface documented in findresource.h */ /* exported interface documented in findresource.h */
char *vsfindfile(char *str, const char *format, va_list ap) char *resource_vsfindfile(char *str, const char *format, va_list ap)
{ {
char *realpathname; char *realpathname;
char *pathname; char *pathname;
@ -73,20 +74,20 @@ char *vsfindfile(char *str, const char *format, va_list ap)
} }
/* exported interface documented in findresource.h */ /* exported interface documented in findresource.h */
char *sfindfile(char *str, const char *format, ...) char *resource_sfindfile(char *str, const char *format, ...)
{ {
va_list ap; va_list ap;
char *ret; char *ret;
va_start(ap, format); va_start(ap, format);
ret = vsfindfile(str, format, ap); ret = resource_vsfindfile(str, format, ap);
va_end(ap); va_end(ap);
return ret; return ret;
} }
/* exported interface documented in findresource.h */ /* exported interface documented in findresource.h */
char *findfile(const char *format, ...) char *resource_findfile(const char *format, ...)
{ {
char *str; char *str;
char *ret; char *ret;
@ -97,7 +98,7 @@ char *findfile(const char *format, ...)
return NULL; /* unable to allocate memory */ return NULL; /* unable to allocate memory */
va_start(ap, format); va_start(ap, format);
ret = vsfindfile(str, format, ap); ret = resource_vsfindfile(str, format, ap);
va_end(ap); va_end(ap);
if (ret == NULL) if (ret == NULL)
@ -107,7 +108,7 @@ char *findfile(const char *format, ...)
} }
/* exported interface documented in findresource.h */ /* exported interface documented in findresource.h */
char *sfindresource(char **respathv, char *filepath, const char *filename) char *resource_sfind(char **respathv, char *filepath, const char *filename)
{ {
int respathc = 0; int respathc = 0;
@ -115,7 +116,7 @@ char *sfindresource(char **respathv, char *filepath, const char *filename)
return NULL; return NULL;
while (respathv[respathc] != NULL) { while (respathv[respathc] != NULL) {
if (sfindfile(filepath, "%s/%s", respathv[respathc], filename) != NULL) if (resource_sfindfile(filepath, "%s/%s", respathv[respathc], filename) != NULL)
return filepath; return filepath;
respathc++; respathc++;
@ -125,7 +126,7 @@ char *sfindresource(char **respathv, char *filepath, const char *filename)
} }
/* exported interface documented in findresource.h */ /* exported interface documented in findresource.h */
char *findresource(char **respathv, const char *filename) char *resource_find(char **respathv, const char *filename)
{ {
char *ret; char *ret;
char *filepath; char *filepath;
@ -137,7 +138,7 @@ char *findresource(char **respathv, const char *filename)
if (filepath == NULL) if (filepath == NULL)
return NULL; return NULL;
ret = sfindresource(respathv, filepath, filename); ret = resource_sfind(respathv, filepath, filename);
if (ret == NULL) if (ret == NULL)
free(filepath); free(filepath);
@ -146,7 +147,7 @@ char *findresource(char **respathv, const char *filename)
} }
/* exported interface documented in findresource.h */ /* exported interface documented in findresource.h */
char *sfindresourcedef(char **respathv, char *filepath, const char *filename, const char *def) char *resource_sfinddef(char **respathv, char *filepath, const char *filename, const char *def)
{ {
char t[PATH_MAX]; char t[PATH_MAX];
char *ret; char *ret;
@ -154,10 +155,9 @@ char *sfindresourcedef(char **respathv, char *filepath, const char *filename, co
if ((respathv == NULL) || (respathv[0] == NULL) || (filepath == NULL)) if ((respathv == NULL) || (respathv[0] == NULL) || (filepath == NULL))
return NULL; return NULL;
ret = sfindresource(respathv, filepath, filename); ret = resource_sfind(respathv, filepath, filename);
if ((ret == NULL) && if ((ret == NULL) && (def != NULL)) {
(def != NULL)) {
/* search failed, return the path specified */ /* search failed, return the path specified */
ret = filepath; ret = filepath;
if (def[0] == '~') { if (def[0] == '~') {
@ -174,9 +174,9 @@ char *sfindresourcedef(char **respathv, char *filepath, const char *filename, co
} }
/* exported interface documented in findresource.h */ /* exported interface documented in resource.h */
char ** char **
findresource_generate(char * const *pathv, const char * const *langv) resource_generate(char * const *pathv, const char * const *langv)
{ {
char **respath; /* resource paths vector */ char **respath; /* resource paths vector */
int pathc = 0; int pathc = 0;
@ -193,7 +193,7 @@ findresource_generate(char * const *pathv, const char * const *langv)
/* path element exists and is a directory */ /* path element exists and is a directory */
langc = 0; langc = 0;
while (langv[langc] != NULL) { while (langv[langc] != NULL) {
snprintf(tmppath, PATH_MAX,"%s/%s",pathv[pathc],langv[langc]); snprintf(tmppath, sizeof tmppath, "%s/%s", pathv[pathc],langv[langc]);
if ((stat(tmppath, &dstat) == 0) && if ((stat(tmppath, &dstat) == 0) &&
S_ISDIR(dstat.st_mode)) { S_ISDIR(dstat.st_mode)) {
/* path element exists and is a directory */ /* path element exists and is a directory */
@ -208,3 +208,103 @@ findresource_generate(char * const *pathv, const char * const *langv)
return respath; 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);
}

View File

@ -16,8 +16,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef _NETSURF_UTILS_FINDRESOURCE_H_ /** \file Utility routines to locate file resources. */
#define _NETSURF_UTILS_FINDRESOURCE_H_
#ifndef _NETSURF_UTILS_RESOURCE_H_
#define _NETSURF_UTILS_RESOURCE_H_
/** Create a normalised file name. /** Create a normalised file name.
* *
@ -32,20 +34,20 @@
* @return A pointer to the expanded filename or NULL if the file is * @return A pointer to the expanded filename or NULL if the file is
* not present or accessible. * not present or accessible.
*/ */
char *vsfindfile(char *str, const char *format, va_list ap); char *resource_vsfindfile(char *str, const char *format, va_list ap);
/** Create a normalised file name. /** Create a normalised file name.
* *
* Similar to vsfindfile but takes variadic (printf like) parameters * Similar to vsfindfile but takes variadic (printf like) parameters
*/ */
char *sfindfile(char *str, const char *format, ...); char *resource_sfindfile(char *str, const char *format, ...);
/** Create a normalised file name. /** Create a normalised file name.
* *
* Similar to sfindfile but allocates its own storage for the * Similar to sfindfile but allocates its own storage for the
* returned string. The caller must free this sorage. * returned string. The caller must free this sorage.
*/ */
char *findfile(const char *format, ...); char *resource_findfile(const char *format, ...);
/** Searches an array of resource paths for a file. /** Searches an array of resource paths for a file.
* *
@ -58,23 +60,23 @@ char *findfile(const char *format, ...);
* @param filename The filename of the resource to search for. * @param filename The filename of the resource to search for.
* @return A pointer to filepath if a target is found or NULL if not. * @return A pointer to filepath if a target is found or NULL if not.
*/ */
char *sfindresource(char **respathv, char *filepath, const char *filename); char *resource_sfind(char **respathv, char *filepath, const char *filename);
/** Searches an array of resource paths for a file. /** Searches an array of resource paths for a file.
* *
* Similar to sfindresource except it allocates its own storage for * Similar to resource_sfind except it allocates its own storage for
* the returned string. The caller must free this sorage. * the returned string. The caller must free this sorage.
*/ */
char *findresource(char **respathv, const char *filename); char *resource_find(char **respathv, const char *filename);
/** Searches an array of resource paths for a file optionally forcing a default. /** Searches an array of resource paths for a file optionally forcing a default.
* *
* Similar to sfindresource except if no resource is found the 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 * is used as an additional path element to search, if that still
* fails the returned path is set to the concatination of the default * fails the returned path is set to the concatination of the default
* path and the filename. * path and the filename.
*/ */
char *sfindresourcedef(char **respathv, char *filepath, const char *filename, const char *def); char *resource_sfinddef(char **respathv, char *filepath, const char *filename, const char *def);
/** Merge two string vectors into a resource search path vector. /** Merge two string vectors into a resource search path vector.
* *
@ -83,6 +85,21 @@ char *sfindresourcedef(char **respathv, char *filepath, const char *filename, co
* @return A pointer to a NULL terminated string vector of valid * @return A pointer to a NULL terminated string vector of valid
* resource directories. * resource directories.
*/ */
char **findresource_generate(char * const *pathv, const char * const *langv); char **resource_generate(char * const *pathv, const char * const *langv);
#endif
/** 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_ */

View File

@ -32,6 +32,7 @@
#include "content/urldb.h" #include "content/urldb.h"
#include "content/fetch.h" #include "content/fetch.h"
#include "content/fetchers/resource.h"
#include "css/utils.h" #include "css/utils.h"
#include "desktop/gui.h" #include "desktop/gui.h"
#include "desktop/history_core.h" #include "desktop/history_core.h"
@ -2558,6 +2559,11 @@ void gui_quit(void)
LOG(("gui_quit")); LOG(("gui_quit"));
} }
char* gui_find_resource(const char *filename)
{
return NULL;
}
static void gui_init(int argc, char** argv) static void gui_init(int argc, char** argv)
{ {
char buf[PATH_MAX], sbuf[PATH_MAX]; char buf[PATH_MAX], sbuf[PATH_MAX];