Merge jmb/new-cache; r=dsilvers,rs=vince

svn path=/trunk/netsurf/; revision=10180
This commit is contained in:
Daniel Silverstone 2010-03-28 12:56:39 +00:00
parent 21da4f5bdf
commit 270ef59a98
106 changed files with 6617 additions and 2930 deletions

View File

@ -5,13 +5,13 @@
# for each build.
#
S_CONTENT := content.c fetch.c fetchcache.c urldb.c \
S_CONTENT := content.c fetch.c hlcache.c llcache.c urldb.c \
fetchers/fetch_curl.c fetchers/fetch_data.c
S_CSS := css.c dump.c internal.c select.c utils.c
S_RENDER := box.c box_construct.c box_normalise.c directory.c favicon.c \
font.c form.c html.c html_redraw.c hubbub_binding.c imagemap.c \
layout.c list.c table.c textplain.c
S_UTILS := base64.c filename.c hashtable.c locale.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
S_DESKTOP := knockout.c options.c plot_style.c print.c search.c \
searchweb.c scroll.c textarea.c tree.c version.c

View File

@ -252,14 +252,15 @@ void ami_free_download_list(struct List *dllist)
}while(node=nnode);
}
void gui_window_save_as_link(struct gui_window *g, struct content *c)
void
gui_window_save_link(struct gui_window *g, const char *url, const char *title)
{
BPTR fh = 0;
char fname[1024];
STRPTR openurlstring,linkname;
struct DiskObject *dobj = NULL;
linkname = ASPrintf("Link_to_%s",FilePart(c->url));
linkname = ASPrintf("Link_to_%s",FilePart(url));
if(AslRequestTags(savereq,
ASLFR_TitleText,messages_get("NetSurf"),
@ -272,11 +273,11 @@ void gui_window_save_as_link(struct gui_window *g, struct content *c)
ami_update_pointer(g->shared->win,GUI_POINTER_WAIT);
if(fh = FOpen(fname,MODE_NEWFILE,0))
{
openurlstring = ASPrintf("openurl \"%s\"\n",c->url);
openurlstring = ASPrintf("openurl \"%s\"\n",url);
FWrite(fh,openurlstring,1,strlen(openurlstring));
FClose(fh);
FreeVec(openurlstring);
SetComment(fname,c->url);
SetComment(fname,url);
dobj = GetIconTags(NULL,ICONGETA_GetDefaultName,"url",
ICONGETA_GetDefaultType,WBPROJECT,

View File

@ -56,7 +56,7 @@ static bool ami_fetch_file_initialise(const char *scheme);
static void ami_fetch_file_finalise(const char *scheme);
static void * ami_fetch_file_setup(struct fetch *parent_fetch, const char *url,
bool only_2xx, const char *post_urlenc,
struct form_successful_control *post_multipart,
struct fetch_multipart_data *post_multipart,
const char **headers);
static bool ami_fetch_file_start(void *vfetch);
static void ami_fetch_file_abort(void *vf);
@ -135,7 +135,7 @@ void ami_fetch_file_finalise(const char *scheme)
void * ami_fetch_file_setup(struct fetch *parent_fetch, const char *url,
bool only_2xx, const char *post_urlenc,
struct form_successful_control *post_multipart,
struct fetch_multipart_data *post_multipart,
const char **headers)
{
struct ami_file_fetch_info *fetch;
@ -280,6 +280,7 @@ void ami_fetch_file_poll(const char *scheme_ignored)
if(fetch->fh)
{
char header[64];
struct ExamineData *fib;
if(fib = ExamineObjectTags(EX_FileHandleInput,fetch->fh,TAG_DONE))
{
@ -291,9 +292,18 @@ void ami_fetch_file_poll(const char *scheme_ignored)
fetch->mimetype = fetch_mimetype(fetch->path);
LOG(("mimetype %s len %ld",fetch->mimetype,fetch->len));
ami_fetch_file_send_callback(FETCH_TYPE,
fetch, fetch->mimetype, (ULONG)fetch->len,
errorcode);
snprintf(header, sizeof header,
"Content-Type: %s",
fetch->mimetype);
ami_fetch_file_send_callback(FETCH_HEADER,
fetch, header, strlen(header), errorcode);
snprintf(header, sizeof header,
"Content-Length: %ld",
fetch->len);
ami_fetch_file_send_callback(FETCH_HEADER,
fetch, header, strlen(header), errorcode);
}
else
{

View File

@ -38,7 +38,6 @@ extern "C" {
#include "content/urldb.h"
#include "desktop/netsurf.h"
#include "desktop/options.h"
#include "render/form.h"
#include "utils/log.h"
#include "utils/messages.h"
#include "utils/url.h"
@ -83,7 +82,7 @@ static void fetch_rsrc_finalise(const char *scheme)
static void *fetch_rsrc_setup(struct fetch *parent_fetch, const char *url,
bool only_2xx, const char *post_urlenc,
struct form_successful_control *post_multipart,
struct fetch_multipart_data *post_multipart,
const char **headers)
{
struct fetch_rsrc_context *ctx;
@ -277,6 +276,8 @@ static void fetch_rsrc_poll(const char *scheme)
/* Only process non-aborted fetches */
if (!c->aborted && fetch_rsrc_process(c) == true) {
char header[64];
fetch_set_http_code(c->parent_fetch, 200);
LOG(("setting rsrc: MIME type to %s, length to %zd",
c->mimetype, c->datalen));
@ -284,8 +285,16 @@ static void fetch_rsrc_poll(const char *scheme)
* Therefore, we _must_ check for this after _every_
* call to fetch_rsrc_send_callback().
*/
fetch_rsrc_send_callback(FETCH_TYPE,
c, c->mimetype, c->datalen, FETCH_ERROR_NO_ERROR);
snprintf(header, sizeof header, "Content-Type: %s",
c->mimetype);
fetch_rsrc_send_callback(FETCH_HEADER, c, header,
strlen(header), FETCH_ERROR_NO_ERROR);
snprintf(header, sizeof header, "Content-Length: %zd",
c->datalen);
fetch_rsrc_send_callback(FETCH_HEADER, c, header,
strlen(header), FETCH_ERROR_NO_ERROR);
if (!c->aborted) {
fetch_rsrc_send_callback(FETCH_DATA,
c, c->data, c->datalen, FETCH_ERROR_NO_ERROR);

View File

@ -424,7 +424,15 @@ static int32 bapp_thread(void *arg)
int main(int argc, char** argv)
{
setbuf(stderr, NULL);
return netsurf_main(argc, argv);
/* initialise netsurf */
netsurf_init(argc, argv);
netsurf_main_loop();
netsurf_exit();
return 0;
}
void gui_init(int argc, char** argv)
@ -843,7 +851,8 @@ void gui_create_form_select_menu(struct browser_window *bw,
#endif
}
void gui_window_save_as_link(struct gui_window *g, struct content *c)
void
gui_window_save_link(struct gui_window *g, const char *url, const char *title)
{
}

File diff suppressed because it is too large Load Diff

View File

@ -26,64 +26,31 @@
#ifndef _NETSURF_CONTENT_CONTENT_H_
#define _NETSURF_CONTENT_CONTENT_H_
/* Irritatingly this must come first, or odd include errors
* will occur to do with setjmp.h.
*/
#ifdef WITH_PNG
#include "image/png.h"
#endif
#include <stdbool.h>
#include <stdint.h>
#include <time.h>
#include "utils/config.h"
#include "content/content_type.h"
#include "css/css.h"
#include "render/html.h"
#include "render/textplain.h"
#ifdef WITH_JPEG
#include "image/jpeg.h"
#endif
#ifdef WITH_GIF
#include "image/gif.h"
#endif
#ifdef WITH_BMP
#include "image/bmp.h"
#include "image/ico.h"
#endif
#ifdef WITH_PLUGIN
#include "riscos/plugin.h"
#endif
#ifdef WITH_MNG
#include "image/mng.h"
#endif
#ifdef WITH_SPRITE
#include "riscos/sprite.h"
#endif
#ifdef WITH_NSSPRITE
#include "image/nssprite.h"
#endif
#ifdef WITH_DRAW
#include "riscos/draw.h"
#endif
#ifdef WITH_ARTWORKS
#include "riscos/artworks.h"
#endif
#ifdef WITH_NS_SVG
#include "image/svg.h"
#endif
#ifdef WITH_RSVG
#include "image/rsvg.h"
#endif
#include "desktop/plot_style.h"
struct llcache_handle;
struct bitmap;
struct box;
struct browser_window;
struct content;
struct fetch;
struct hlcache_handle;
struct object_params;
struct ssl_cert_info;
/** Status of a content */
typedef enum {
CONTENT_STATUS_TYPE_UNKNOWN, /**< Type not yet known. */
CONTENT_STATUS_LOADING, /**< Content is being fetched or
converted and is not safe to display. */
CONTENT_STATUS_READY, /**< Some parts of content still being
loaded, but can be displayed. */
CONTENT_STATUS_DONE, /**< All finished. */
CONTENT_STATUS_ERROR /**< Error occurred, content will be
destroyed imminently. */
} content_status;
/** Used in callbacks to indicate what has occurred. */
typedef enum {
@ -129,204 +96,64 @@ union content_msg_data {
} ssl;
};
struct cache_data {
time_t req_time; /**< Time of request */
time_t res_time; /**< Time of response */
time_t date; /**< Date: response header */
time_t expires; /**< Expires: response header */
#define INVALID_AGE -1
int age; /**< Age: response header */
int max_age; /**< Max-age Cache-control parameter */
bool no_cache; /**< no-cache Cache-control parameter */
char *etag; /**< Etag: response header */
time_t last_modified; /**< Last-Modified: response header */
};
/** Linked list of users of a content. */
struct content_user
{
void (*callback)(content_msg msg, struct content *c, intptr_t p1,
intptr_t p2, union content_msg_data data);
intptr_t p1;
intptr_t p2;
bool stop;
struct content_user *next;
};
/** Corresponds to a single URL. */
struct content {
char *url; /**< URL, in standard form as from url_join. */
content_type type; /**< Type of content. */
char *mime_type; /**< Original MIME type of data, or 0. */
enum {
CONTENT_STATUS_TYPE_UNKNOWN, /**< Type not yet known. */
CONTENT_STATUS_LOADING, /**< Content is being fetched or
converted and is not safe to display. */
CONTENT_STATUS_READY, /**< Some parts of content still being
loaded, but can be displayed. */
CONTENT_STATUS_DONE, /**< All finished. */
CONTENT_STATUS_ERROR /**< Error occurred, content will be
destroyed imminently. */
} status; /**< Current status. */
int width, height; /**< Dimensions, if applicable. */
int available_width; /**< Available width (eg window width). */
/** Data dependent on type. */
union {
struct content_html_data html;
struct content_textplain_data textplain;
struct content_css_data css;
#ifdef WITH_JPEG
struct content_jpeg_data jpeg;
#endif
#ifdef WITH_GIF
struct content_gif_data gif;
#endif
#ifdef WITH_BMP
struct content_bmp_data bmp;
struct content_ico_data ico;
#endif
#ifdef WITH_MNG
struct content_mng_data mng;
#endif
#ifdef WITH_SPRITE
struct content_sprite_data sprite;
#endif
#ifdef WITH_NSSPRITE
struct content_nssprite_data nssprite;
#endif
#ifdef WITH_DRAW
struct content_draw_data draw;
#endif
#ifdef WITH_PLUGIN
struct content_plugin_data plugin;
#endif
#ifdef WITH_ARTWORKS
struct content_artworks_data artworks;
#endif
#ifdef WITH_NS_SVG
struct content_svg_data svg;
#endif
#ifdef WITH_RSVG
struct content_rsvg_data rsvg;
#endif
#ifdef WITH_PNG
struct content_png_data png;
#endif
} data;
/**< URL for refresh request, in standard form as from url_join. */
char *refresh;
/** Bitmap, for various image contents. */
struct bitmap *bitmap;
/** This content may be given to new users. Indicates that the content
* was fetched using a simple GET, has not expired, and may be
* shared between users. */
bool fresh;
struct cache_data cache_data; /**< Cache control data */
unsigned int time; /**< Creation time, if TYPE_UNKNOWN,
LOADING or READY,
otherwise total time. */
unsigned int reformat_time; /**< Earliest time to attempt a
period reflow while fetching a
page's objects. */
unsigned int size; /**< Estimated size of all data
associated with this content, except
alloced as talloc children of this. */
off_t talloc_size; /**< Used by content_clean() */
char *title; /**< Title for browser window. */
unsigned int active; /**< Number of child fetches or
conversions currently in progress. */
struct content_user *user_list; /**< List of users. */
char status_message[120]; /**< Full text for status bar. */
char sub_status[80]; /**< Status of content. */
/** Content is being processed: data structures may be inconsistent
* and content must not be redrawn or modified. */
bool locked;
struct fetch *fetch; /**< Associated fetch, or 0. */
char *source_data; /**< Source data, as received. */
unsigned long source_size; /**< Amount of data fetched so far. */
unsigned long source_allocated; /**< Amount of space allocated so far. */
unsigned long total_size; /**< Total data size, 0 if unknown. */
long http_code; /**< HTTP status code, 0 if not HTTP. */
bool no_error_pages; /**< Used by fetchcache(). */
bool download; /**< Used by fetchcache(). */
bool tried_with_auth; /**< Used by fetchcache(). */
unsigned int redirect_count; /**< Used by fetchcache(). */
/** Array of first n rendering errors or warnings. */
struct {
const char *token;
unsigned int line; /**< Line no, 0 if not applicable. */
} error_list[40];
unsigned int error_count; /**< Number of valid error entries. */
struct content *prev; /**< Previous in global content list. */
struct content *next; /**< Next in global content list. */
};
extern struct content *content_list;
extern const char * const content_type_name[];
extern const char * const content_status_name[];
/* The following are for hlcache */
content_type content_lookup(const char *mime_type);
struct content * content_create(const char *url);
struct content * content_get(const char *url);
struct content * content_get_ready(const char *url);
bool content_can_reformat(struct content *c);
bool content_set_type(struct content *c, content_type type,
const char *mime_type, const char *params[],
struct content *parent);
void content_set_status(struct content *c, const char *status_message, ...);
bool content_process_data(struct content *c, const char *data,
unsigned int size);
void content_convert(struct content *c, int width, int height);
void content_set_done(struct content *c);
void content_reformat(struct content *c, int width, int height);
void content_clean(void);
void content_reset(struct content *c);
void content_quit(void);
bool content_redraw(struct content *c, int x, int y,
struct content *content_create(struct llcache_handle *llcache,
const char *fallback_charset, bool quirks);
void content_destroy(struct content *c);
bool content_add_user(struct content *h,
void (*callback)(struct content *c, content_msg msg,
union content_msg_data data, void *pw),
void *pw);
void content_remove_user(struct content *c,
void (*callback)(struct content *c, content_msg msg,
union content_msg_data data, void *pw),
void *pw);
const struct llcache_handle *content_get_llcache_handle(struct content *c);
/* Client functions */
bool content_can_reformat(struct hlcache_handle *h);
void content_reformat(struct hlcache_handle *h, int width, int height);
void content_request_redraw(struct hlcache_handle *h,
int x, int y, int width, int height);
bool content_redraw(struct hlcache_handle *h, int x, int y,
int width, int height,
int clip_x0, int clip_y0, int clip_x1, int clip_y1,
float scale, colour background_colour);
bool content_redraw_tiled(struct content *c, int x, int y,
bool content_redraw_tiled(struct hlcache_handle *h, int x, int y,
int width, int height,
int clip_x0, int clip_y0, int clip_x1, int clip_y1,
float scale, colour background_colour,
bool repeat_x, bool repeat_y);
bool content_add_user(struct content *c,
void (*callback)(content_msg msg, struct content *c,
intptr_t p1, intptr_t p2, union content_msg_data data),
intptr_t p1, intptr_t p2);
struct content_user * content_find_user(struct content *c,
void (*callback)(content_msg msg, struct content *c,
intptr_t p1, intptr_t p2, union content_msg_data data),
intptr_t p1, intptr_t p2);
void content_remove_user(struct content *c,
void (*callback)(content_msg msg, struct content *c,
intptr_t p1, intptr_t p2, union content_msg_data data),
intptr_t p1, intptr_t p2);
void content_broadcast(struct content *c, content_msg msg,
union content_msg_data data);
void content_stop(struct content *c,
void (*callback)(content_msg msg, struct content *c,
intptr_t p1, intptr_t p2, union content_msg_data data),
intptr_t p1, intptr_t p2);
void content_open(struct content *c, struct browser_window *bw,
void content_stop(struct hlcache_handle *h,
void (*callback)(struct content *c, content_msg msg,
union content_msg_data data, void *pw),
void *pw);
void content_open(struct hlcache_handle *h, struct browser_window *bw,
struct content *page, unsigned int index, struct box *box,
struct object_params *params);
void content_close(struct content *c);
void content_add_error(struct content *c, const char *token,
unsigned int line);
void content_close(struct hlcache_handle *h);
/* Member accessors */
content_type content_get_type(struct hlcache_handle *c);
const char *content_get_url(struct hlcache_handle *c);
const char *content_get_title(struct hlcache_handle *c);
content_status content_get_status(struct hlcache_handle *c);
const char *content_get_status_message(struct hlcache_handle *c);
int content_get_width(struct hlcache_handle *c);
int content_get_height(struct hlcache_handle *c);
int content_get_available_width(struct hlcache_handle *c);
const char *content_get_source_data(struct hlcache_handle *c,
unsigned long *size);
void content_invalidate_reuse_data(struct hlcache_handle *c);
const char *content_get_refresh_url(struct hlcache_handle *c);
struct bitmap *content_get_bitmap(struct hlcache_handle *c);
/* Download support */
struct llcache_handle *content_convert_to_download(struct hlcache_handle *c);
#endif

221
content/content_protected.h Normal file
View File

@ -0,0 +1,221 @@
/*
* Copyright 2005-2007 James Bursa <bursa@users.sourceforge.net>
* Copyright 2003 Philip Pemberton <philpem@users.sourceforge.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/** \file
* Content handling (interface).
*
* The content functions manipulate struct contents, which correspond to URLs.
*/
#ifndef _NETSURF_CONTENT_CONTENT_PROTECTED_H_
#define _NETSURF_CONTENT_CONTENT_PROTECTED_H_
/* Irritatingly this must come first, or odd include errors
* will occur to do with setjmp.h.
*/
#ifdef WITH_PNG
#include "image/png.h"
#endif
#include <stdint.h>
#include <time.h>
#include "utils/config.h"
#include "content/content.h"
#include "content/llcache.h"
#include "css/css.h"
#include "render/html.h"
#include "render/textplain.h"
#ifdef WITH_JPEG
#include "image/jpeg.h"
#endif
#ifdef WITH_GIF
#include "image/gif.h"
#endif
#ifdef WITH_BMP
#include "image/bmp.h"
#include "image/ico.h"
#endif
#ifdef WITH_PLUGIN
#include "riscos/plugin.h"
#endif
#ifdef WITH_MNG
#include "image/mng.h"
#endif
#ifdef WITH_SPRITE
#include "riscos/sprite.h"
#endif
#ifdef WITH_NSSPRITE
#include "image/nssprite.h"
#endif
#ifdef WITH_DRAW
#include "riscos/draw.h"
#endif
#ifdef WITH_ARTWORKS
#include "riscos/artworks.h"
#endif
#ifdef WITH_NS_SVG
#include "image/svg.h"
#endif
#ifdef WITH_RSVG
#include "image/rsvg.h"
#endif
struct bitmap;
struct content;
/** Linked list of users of a content. */
struct content_user
{
void (*callback)(struct content *c, content_msg msg,
union content_msg_data data, void *pw);
void *pw;
struct content_user *next;
};
/** Corresponds to a single URL. */
struct content {
llcache_handle *llcache; /**< Low-level cache object */
content_type type; /**< Type of content. */
char *mime_type; /**< Original MIME type of data, or 0. */
content_status status; /**< Current status. */
int width, height; /**< Dimensions, if applicable. */
int available_width; /**< Available width (eg window width). */
bool quirks; /**< Content is in quirks mode */
char *fallback_charset; /**< Fallback charset, or NULL */
/** Data dependent on type. */
union {
struct content_html_data html;
struct content_textplain_data textplain;
struct content_css_data css;
#ifdef WITH_JPEG
struct content_jpeg_data jpeg;
#endif
#ifdef WITH_GIF
struct content_gif_data gif;
#endif
#ifdef WITH_BMP
struct content_bmp_data bmp;
struct content_ico_data ico;
#endif
#ifdef WITH_MNG
struct content_mng_data mng;
#endif
#ifdef WITH_SPRITE
struct content_sprite_data sprite;
#endif
#ifdef WITH_NSSPRITE
struct content_nssprite_data nssprite;
#endif
#ifdef WITH_DRAW
struct content_draw_data draw;
#endif
#ifdef WITH_PLUGIN
struct content_plugin_data plugin;
#endif
#ifdef WITH_ARTWORKS
struct content_artworks_data artworks;
#endif
#ifdef WITH_NS_SVG
struct content_svg_data svg;
#endif
#ifdef WITH_RSVG
struct content_rsvg_data rsvg;
#endif
#ifdef WITH_PNG
struct content_png_data png;
#endif
} data;
/**< URL for refresh request, in standard form as from url_join. */
char *refresh;
/** Bitmap, for various image contents. */
struct bitmap *bitmap;
/** This content may be given to new users. Indicates that the content
* was fetched using a simple GET, has not expired, and may be
* shared between users. */
bool fresh;
unsigned int time; /**< Creation time, if TYPE_UNKNOWN,
LOADING or READY,
otherwise total time. */
unsigned int reformat_time; /**< Earliest time to attempt a
period reflow while fetching a
page's objects. */
unsigned int size; /**< Estimated size of all data
associated with this content, except
alloced as talloc children of this. */
off_t talloc_size; /**< Used by content_clean() */
char *title; /**< Title for browser window. */
unsigned int active; /**< Number of child fetches or
conversions currently in progress. */
struct content_user *user_list; /**< List of users. */
char status_message[120]; /**< Full text for status bar. */
char sub_status[80]; /**< Status of content. */
/** Content is being processed: data structures may be inconsistent
* and content must not be redrawn or modified. */
bool locked;
unsigned long total_size; /**< Total data size, 0 if unknown. */
long http_code; /**< HTTP status code, 0 if not HTTP. */
/** Array of first n rendering errors or warnings. */
struct {
const char *token;
unsigned int line; /**< Line no, 0 if not applicable. */
} error_list[40];
unsigned int error_count; /**< Number of valid error entries. */
};
extern const char * const content_type_name[];
extern const char * const content_status_name[];
void content_set_done(struct content *c);
void content_set_status(struct content *c, const char *status_message, ...);
void content_broadcast(struct content *c, content_msg msg,
union content_msg_data data);
void content_add_error(struct content *c, const char *token,
unsigned int line);
void content__reformat(struct content *c, int width, int height);
content_type content__get_type(struct content *c);
const char *content__get_url(struct content *c);
const char *content__get_title(struct content *c);
content_status content__get_status(struct content *c);
const char *content__get_status_message(struct content *c);
int content__get_width(struct content *c);
int content__get_height(struct content *c);
int content__get_available_width(struct content *c);
const char *content__get_source_data(struct content *c, unsigned long *size);
void content__invalidate_reuse_data(struct content *c);
const char *content__get_refresh_url(struct content *c);
struct bitmap *content__get_bitmap(struct content *c);
#endif

View File

@ -41,7 +41,6 @@
#include "content/urldb.h"
#include "desktop/netsurf.h"
#include "desktop/options.h"
#include "render/form.h"
#include "utils/log.h"
#include "utils/messages.h"
#include "utils/url.h"
@ -213,7 +212,7 @@ void fetch_unref_fetcher(scheme_fetcher *fetcher)
struct fetch * fetch_start(const char *url, const char *referer,
fetch_callback callback,
void *p, bool only_2xx, const char *post_urlenc,
struct form_successful_control *post_multipart,
struct fetch_multipart_data *post_multipart,
bool verifiable, struct content *parent,
char *headers[])
{
@ -598,6 +597,78 @@ bool fetch_get_verifiable(struct fetch *fetch)
return fetch->verifiable;
}
/**
* Clone a linked list of fetch_multipart_data.
*
* \param list List to clone
* \return Pointer to head of cloned list, or NULL on failure
*/
struct fetch_multipart_data *fetch_multipart_data_clone(
const struct fetch_multipart_data *list)
{
struct fetch_multipart_data *clone, *last = NULL;
struct fetch_multipart_data *result = NULL;
for (; list != NULL; list = list->next) {
clone = malloc(sizeof(struct fetch_multipart_data));
if (clone == NULL) {
if (result != NULL)
fetch_multipart_data_destroy(result);
return NULL;
}
clone->file = list->file;
clone->name = strdup(list->name);
if (clone->name == NULL) {
free(clone);
if (result != NULL)
fetch_multipart_data_destroy(result);
return NULL;
}
clone->value = strdup(list->value);
if (clone->value == NULL) {
free(clone->name);
free(clone);
if (result != NULL)
fetch_multipart_data_destroy(result);
return NULL;
}
clone->next = NULL;
if (result == NULL)
result = clone;
else
last->next = clone;
last = clone;
}
return result;
}
/**
* Free a linked list of fetch_multipart_data.
*
* \param list Pointer to head of list to free
*/
void fetch_multipart_data_destroy(struct fetch_multipart_data *list)
{
struct fetch_multipart_data *next;
for (; list != NULL; list = next) {
next = list->next;
free(list->name);
free(list->value);
free(list);
}
}
void
fetch_send_callback(fetch_msg msg, struct fetch *fetch, const void *data,
unsigned long size, fetch_error_code errorcode)
@ -665,8 +736,8 @@ fetch_set_cookie(struct fetch *fetch, const char *data)
* that the request uri and the parent domain match,
* so don't pass in the parent in this case. */
urldb_set_cookie(data, fetch->url,
fetch->verifiable ? NULL
: fetch->parent->url);
fetch->verifiable ? NULL
: content_get_url(fetch->parent));
}
}

View File

@ -54,7 +54,15 @@ typedef enum {
struct content;
struct fetch;
struct form_successful_control;
/** Fetch POST multipart data */
struct fetch_multipart_data {
bool file; /**< Item is a file */
char *name; /**< Name of item */
char *value; /**< Item value */
struct fetch_multipart_data *next; /**< Next in linked list */
};
struct ssl_cert_info {
long version; /**< Certificate version */
@ -77,7 +85,7 @@ void fetch_init(void);
struct fetch * fetch_start(const char *url, const char *referer,
fetch_callback callback,
void *p, bool only_2xx, const char *post_urlenc,
struct form_successful_control *post_multipart,
struct fetch_multipart_data *post_multipart,
bool verifiable, struct content *parent,
char *headers[]);
void fetch_abort(struct fetch *f);
@ -94,12 +102,16 @@ const char *fetch_get_referer(struct fetch *fetch);
struct content *fetch_get_parent(struct fetch *fetch);
bool fetch_get_verifiable(struct fetch *fetch);
void fetch_multipart_data_destroy(struct fetch_multipart_data *list);
struct fetch_multipart_data *fetch_multipart_data_clone(
const struct fetch_multipart_data *list);
/* API for fetchers themselves */
typedef bool (*fetcher_initialise)(const char *);
typedef void* (*fetcher_setup_fetch)(struct fetch *, const char *,
bool, const char *,
struct form_successful_control *,
struct fetch_multipart_data *,
const char **);
typedef bool (*fetcher_start_fetch)(void *);
typedef void (*fetcher_abort_fetch)(void *);

View File

@ -102,7 +102,7 @@ struct content * fetchcache(const char *url,
int width, int height,
bool no_error_pages,
char *post_urlenc,
struct form_successful_control *post_multipart,
struct fetch_multipart_data *post_multipart,
bool verifiable,
bool download)
{
@ -250,7 +250,7 @@ void fetchcache_go(struct content *content, const char *referer,
intptr_t p1, intptr_t p2,
int width, int height,
char *post_urlenc,
struct form_successful_control *post_multipart,
struct fetch_multipart_data *post_multipart,
bool verifiable, struct content *parent)
{
char error_message[500];

View File

@ -30,7 +30,7 @@
#include <stdint.h>
#include "content/content.h"
struct form_successful_control;
struct fetch_multipart_data;
void fetchcache_init(void);
struct content * fetchcache(const char *url,
@ -40,7 +40,7 @@ struct content * fetchcache(const char *url,
int width, int height,
bool no_error_pages,
char *post_urlenc,
struct form_successful_control *post_multipart,
struct fetch_multipart_data *post_multipart,
bool verifiable,
bool download);
void fetchcache_go(struct content *content, const char *referer,
@ -49,7 +49,7 @@ void fetchcache_go(struct content *content, const char *referer,
intptr_t p1, intptr_t p2,
int width, int height,
char *post_urlenc,
struct form_successful_control *post_multipart,
struct fetch_multipart_data *post_multipart,
bool verifiable, struct content *parent);
#endif

View File

@ -30,6 +30,7 @@
#include <assert.h>
#include <errno.h>
#include <inttypes.h>
#include <stdbool.h>
#include <string.h>
#include <strings.h>
@ -43,7 +44,6 @@
#include "content/urldb.h"
#include "desktop/netsurf.h"
#include "desktop/options.h"
#include "render/form.h"
#include "utils/log.h"
#include "utils/messages.h"
#include "utils/url.h"
@ -104,7 +104,7 @@ static bool fetch_curl_initialise(const char *scheme);
static void fetch_curl_finalise(const char *scheme);
static void * fetch_curl_setup(struct fetch *parent_fetch, const char *url,
bool only_2xx, const char *post_urlenc,
struct form_successful_control *post_multipart,
struct fetch_multipart_data *post_multipart,
const char **headers);
static bool fetch_curl_start(void *vfetch);
static bool fetch_curl_initiate_fetch(struct curl_fetch_info *fetch,
@ -132,7 +132,7 @@ static size_t fetch_curl_header(char *data, size_t size, size_t nmemb,
void *_f);
static bool fetch_curl_process_headers(struct curl_fetch_info *f);
static struct curl_httppost *fetch_curl_post_convert(
struct form_successful_control *control);
struct fetch_multipart_data *control);
static int fetch_curl_verify_callback(int preverify_ok,
X509_STORE_CTX *x509_ctx);
static int fetch_curl_cert_verify_callback(X509_STORE_CTX *x509_ctx,
@ -294,7 +294,7 @@ void fetch_curl_finalise(const char *scheme)
void * fetch_curl_setup(struct fetch *parent_fetch, const char *url,
bool only_2xx, const char *post_urlenc,
struct form_successful_control *post_multipart,
struct fetch_multipart_data *post_multipart,
const char **headers)
{
char *host;
@ -1108,10 +1108,7 @@ size_t fetch_curl_header(char *data, size_t size, size_t nmemb,
bool fetch_curl_process_headers(struct curl_fetch_info *f)
{
long http_code;
const char *type;
CURLcode code;
struct stat s;
char *url_path = 0;
f->had_headers = true;
@ -1142,7 +1139,7 @@ bool fetch_curl_process_headers(struct curl_fetch_info *f)
/* handle HTTP 401 (Authentication errors) */
if (http_code == 401) {
fetch_send_callback(FETCH_AUTH, f->fetch_handle, f->realm,0,
fetch_send_callback(FETCH_AUTH, f->fetch_handle, f->realm, 0,
FETCH_ERROR_AUTHENTICATION);
return true;
}
@ -1156,49 +1153,64 @@ bool fetch_curl_process_headers(struct curl_fetch_info *f)
return true;
}
/* find MIME type from headers or filetype for local files */
code = curl_easy_getinfo(f->curl_handle, CURLINFO_CONTENT_TYPE, &type);
assert(code == CURLE_OK);
/* find MIME type from filetype for local files */
if (strncmp(f->url, "file:///", 8) == 0) {
struct stat s;
char *url_path = curl_unescape(f->url + 7,
(int) strlen(f->url + 7));
if (strncmp(f->url, "file:///", 8) == 0)
url_path = curl_unescape(f->url + 7,
(int) strlen(f->url) - 7);
if (url_path != NULL && stat(url_path, &s) == 0) {
/* file: URL and file exists */
char header[64];
const char *type;
if (url_path && stat(url_path, &s) == 0) {
/* file: URL and file exists */
/* create etag */
char etag_buf[20];
snprintf(etag_buf, sizeof etag_buf,
"ETag: \"%10d\"", (int) s.st_mtime);
/* And send it to the header handler */
fetch_send_callback(FETCH_HEADER, f->fetch_handle, etag_buf,
strlen(etag_buf), FETCH_ERROR_NO_ERROR);
/* create etag */
snprintf(header, sizeof header,
"ETag: \"%10" PRId64 "\"",
(int64_t) s.st_mtime);
/* And send it to the header handler */
fetch_send_callback(FETCH_HEADER, f->fetch_handle,
header, strlen(header),
FETCH_ERROR_NO_ERROR);
/* don't set last modified time so as to ensure that local
* files are revalidated at all times. */
/* If performed a conditional request and unmodified ... */
if (f->last_modified && f->file_etag &&
f->last_modified > s.st_mtime &&
f->file_etag == s.st_mtime) {
fetch_send_callback(FETCH_NOTMODIFIED, f->fetch_handle,
0, 0, FETCH_ERROR_NO_ERROR);
curl_free(url_path);
return true;
}
}
if (type == 0) {
type = "text/plain";
if (url_path) {
/* create Content-Type */
type = fetch_filetype(url_path);
snprintf(header, sizeof header,
"Content-Type: %s", type);
/* Send it to the header handler */
fetch_send_callback(FETCH_HEADER, f->fetch_handle,
header, strlen(header),
FETCH_ERROR_NO_ERROR);
/* create Content-Length */
type = fetch_filetype(url_path);
snprintf(header, sizeof header,
"Content-Length: %" PRId64,
(int64_t) s.st_size);
/* Send it to the header handler */
fetch_send_callback(FETCH_HEADER, f->fetch_handle,
header, strlen(header),
FETCH_ERROR_NO_ERROR);
/* don't set last modified time so as to ensure that
* local files are revalidated at all times. */
/* Report not modified, if appropriate */
if (f->last_modified && f->file_etag &&
f->last_modified > s.st_mtime &&
f->file_etag == s.st_mtime) {
fetch_send_callback(FETCH_NOTMODIFIED,
f->fetch_handle, 0, 0,
FETCH_ERROR_NO_ERROR);
curl_free(url_path);
return true;
}
}
if (url_path != NULL)
curl_free(url_path);
}
curl_free(url_path);
LOG(("FETCH_TYPE, '%s'", type));
fetch_send_callback(FETCH_TYPE, f->fetch_handle, type, f->content_length, FETCH_ERROR_NO_ERROR);
if (f->abort)
return true;
@ -1207,11 +1219,11 @@ bool fetch_curl_process_headers(struct curl_fetch_info *f)
/**
* Convert a list of struct ::form_successful_control to a list of
* Convert a list of struct ::fetch_multipart_data to a list of
* struct curl_httppost for libcurl.
*/
struct curl_httppost *
fetch_curl_post_convert(struct form_successful_control *control)
fetch_curl_post_convert(struct fetch_multipart_data *control)
{
struct curl_httppost *post = 0, *last = 0;
CURLFORMcode code;

View File

@ -35,7 +35,6 @@
#include "content/urldb.h"
#include "desktop/netsurf.h"
#include "desktop/options.h"
#include "render/form.h"
#include "utils/log.h"
#include "utils/messages.h"
#include "utils/url.h"
@ -78,7 +77,7 @@ static void fetch_data_finalise(const char *scheme)
static void *fetch_data_setup(struct fetch *parent_fetch, const char *url,
bool only_2xx, const char *post_urlenc,
struct form_successful_control *post_multipart,
struct fetch_multipart_data *post_multipart,
const char **headers)
{
struct fetch_data_context *ctx = calloc(1, sizeof(*ctx));
@ -232,20 +231,9 @@ static bool fetch_data_process(struct fetch_data_context *c)
static void fetch_data_poll(const char *scheme)
{
struct fetch_data_context *c, *next;
struct cache_data cachedata;
if (ring == NULL) return;
cachedata.req_time = time(NULL);
cachedata.res_time = time(NULL);
cachedata.date = 0;
cachedata.expires = 0;
cachedata.age = INVALID_AGE;
cachedata.max_age = 0;
cachedata.no_cache = true;
cachedata.etag = NULL;
cachedata.last_modified = 0;
/* Iterate over ring, processing each pending fetch */
c = ring;
do {
@ -265,6 +253,8 @@ static void fetch_data_poll(const char *scheme)
/* Only process non-aborted fetches */
if (!c->aborted && fetch_data_process(c) == true) {
char header[64];
fetch_set_http_code(c->parent_fetch, 200);
LOG(("setting data: MIME type to %s, length to %zd",
c->mimetype, c->datalen));
@ -272,9 +262,16 @@ static void fetch_data_poll(const char *scheme)
* Therefore, we _must_ check for this after _every_
* call to fetch_data_send_callback().
*/
fetch_data_send_callback(FETCH_TYPE,
c, c->mimetype, c->datalen,
FETCH_ERROR_NO_ERROR);
snprintf(header, sizeof header, "Content-Type: %s",
c->mimetype);
fetch_data_send_callback(FETCH_HEADER, c, header,
strlen(header), FETCH_ERROR_NO_ERROR);
snprintf(header, sizeof header, "Content-Length: %zd",
c->datalen);
fetch_data_send_callback(FETCH_HEADER, c, header,
strlen(header), FETCH_ERROR_NO_ERROR);
if (!c->aborted) {
fetch_data_send_callback(FETCH_DATA,
c, c->data, c->datalen,
@ -282,8 +279,7 @@ static void fetch_data_poll(const char *scheme)
}
if (!c->aborted) {
fetch_data_send_callback(FETCH_FINISHED,
c, &cachedata, 0,
FETCH_ERROR_NO_ERROR);
c, 0, 0, FETCH_ERROR_NO_ERROR);
}
} else {
LOG(("Processing of %s failed!", c->url));

362
content/hlcache.c Normal file
View File

@ -0,0 +1,362 @@
/*
* Copyright 2009 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/** \file
* High-level resource cache (implementation)
*/
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "content/content.h"
#include "content/hlcache.h"
#include "utils/log.h"
#include "utils/url.h"
typedef struct hlcache_entry hlcache_entry;
typedef struct hlcache_retrieval_ctx hlcache_retrieval_ctx;
/** High-level cache retrieval context */
struct hlcache_retrieval_ctx {
llcache_handle *llcache; /**< Low-level cache handle */
hlcache_handle *handle; /**< High-level handle for object */
/* The following are only used if a child content is requested */
const char *charset; /**< Fallback charset, or NULL */
bool quirks; /**< Whether object should be quirky */
};
/** High-level cache handle */
struct hlcache_handle {
hlcache_entry *entry; /**< Pointer to cache entry */
hlcache_handle_callback cb; /**< Client callback */
void *pw; /**< Client data */
};
/** Entry in high-level cache */
struct hlcache_entry {
struct content *content; /**< Pointer to associated content */
hlcache_entry *next; /**< Next sibling */
hlcache_entry *prev; /**< Previous sibling */
};
/** List of cached content objects */
static hlcache_entry *hlcache_content_list;
static nserror hlcache_llcache_callback(llcache_handle *handle,
const llcache_event *event, void *pw);
static nserror hlcache_find_content(hlcache_retrieval_ctx *ctx);
static void hlcache_content_callback(struct content *c,
content_msg msg, union content_msg_data data, void *pw);
/******************************************************************************
* Public API *
******************************************************************************/
/**
* Retrieve a high-level cache handle for an object
*
* \param url URL of the object to retrieve handle for
* \param flags Object retrieval flags
* \param referer Referring URL, or NULL if none
* \param post POST data, or NULL for a GET request
* \param width Available width for content
* \param height Available height for content
* \param cb Callback to handle object events
* \param pw Pointer to client-specific data for callback
* \param child Child retrieval context, or NULL for top-level content
* \param result Pointer to location to recieve cache handle
* \return NSERROR_OK on success, appropriate error otherwise
*
* \todo Is there any way to sensibly reduce the number of parameters here?
*/
nserror hlcache_handle_retrieve(const char *url, uint32_t flags,
const char *referer, llcache_post_data *post,
uint32_t width, uint32_t height,
hlcache_handle_callback cb, void *pw,
hlcache_child_context *child, hlcache_handle **result)
{
hlcache_retrieval_ctx *ctx;
nserror error;
assert(cb != NULL);
ctx = calloc(1, sizeof(hlcache_retrieval_ctx));
if (ctx == NULL)
return NSERROR_NOMEM;
ctx->handle = calloc(1, sizeof(hlcache_handle));
if (ctx->handle == NULL) {
free(ctx);
return NSERROR_NOMEM;
}
if (child != NULL) {
/** \todo Is the charset guaranteed to exist during fetch? */
ctx->charset = child->charset;
ctx->quirks = child->quirks;
}
/** \todo What happens with width/height? */
ctx->handle->cb = cb;
ctx->handle->pw = pw;
error = llcache_handle_retrieve(url, flags, referer, post,
hlcache_llcache_callback, ctx,
&ctx->llcache);
if (error != NSERROR_OK) {
free(ctx->handle);
free(ctx);
return error;
}
*result = ctx->handle;
return NSERROR_OK;
}
/**
* Release a high-level cache handle
*
* \param handle Handle to release
* \return NSERROR_OK on success, appropriate error otherwise
*/
nserror hlcache_handle_release(hlcache_handle *handle)
{
/** \todo What if this is called during fetch? */
if (handle->entry != NULL) {
content_remove_user(handle->entry->content,
hlcache_content_callback, handle);
}
handle->cb = NULL;
handle->pw = NULL;
/** \todo Provide hlcache_poll() to perform cache maintenance */
return NSERROR_OK;
}
/**
* Retrieve a content object from a cache handle
*
* \param handle Cache handle to dereference
* \return Pointer to content object, or NULL if there is none
*
* \todo This may not be correct. Ideally, the client should never need to
* directly access a content object. It may, therefore, be better to provide a
* bunch of veneers here that take a hlcache_handle and invoke the
* corresponding content_ API. If there's no content object associated with the
* hlcache_handle (e.g. because the source data is still being fetched, so it
* doesn't exist yet), then these veneers would behave as a NOP. The important
* thing being that the client need not care about this possibility and can
* just call the functions with impugnity.
*/
struct content *hlcache_handle_get_content(const hlcache_handle *handle)
{
assert(handle != NULL);
if (handle->entry != NULL)
return handle->entry->content;
return NULL;
}
/******************************************************************************
* High-level cache internals *
******************************************************************************/
/**
* Handler for low-level cache events
*
* \param handle Handle for which event is issued
* \param event Event data
* \param pw Pointer to client-specific data
* \return NSERROR_OK on success, appropriate error otherwise
*/
nserror hlcache_llcache_callback(llcache_handle *handle,
const llcache_event *event, void *pw)
{
hlcache_retrieval_ctx *ctx = pw;
nserror error;
assert(ctx->llcache == handle);
switch (event->type) {
case LLCACHE_EVENT_HAD_HEADERS:
error = hlcache_find_content(ctx);
if (error != NSERROR_OK)
return error;
/* No longer require retrieval context */
free(ctx);
break;
case LLCACHE_EVENT_HAD_DATA:
/* fall through */
case LLCACHE_EVENT_DONE:
/* should never happen: the handler must be changed */
break;
case LLCACHE_EVENT_ERROR:
/** \todo handle errors */
break;
case LLCACHE_EVENT_PROGRESS:
break;
}
return NSERROR_OK;
}
/**
* Find a content for the high-level cache handle
*
* \param ctx High-level cache retrieval context
* \return NSERROR_OK on success, appropriate error otherwise
*
* \pre handle::state == HLCACHE_HANDLE_NEW
* \pre Headers must have been received for associated low-level handle
* \post Low-level handle is either released, or associated with new content
* \post High-level handle is registered with content
*/
nserror hlcache_find_content(hlcache_retrieval_ctx *ctx)
{
hlcache_entry *entry;
hlcache_event event;
/* Search list of cached contents for a suitable one */
for (entry = hlcache_content_list; entry != NULL; entry = entry->next) {
const llcache_handle *entry_llcache;
/** \todo Need to ensure that quirks mode matches */
/** \todo Need to ensure that content is shareable */
/** \todo Need to ensure that content can be reused */
if (entry->content == NULL)
continue;
/* Ensure that content uses same low-level object as
* low-level handle */
entry_llcache = content_get_llcache_handle(entry->content);
if (llcache_handle_references_same_object(entry_llcache,
ctx->llcache))
break;
}
if (entry == NULL) {
/* No existing entry, so need to create one */
entry = malloc(sizeof(hlcache_entry));
if (entry == NULL)
return NSERROR_NOMEM;
/* Create content using llhandle */
entry->content = content_create(ctx->llcache,
ctx->charset, ctx->quirks);
if (entry->content == NULL) {
free(entry);
return NSERROR_NOMEM;
}
/* Insert into cache */
entry->prev = NULL;
entry->next = hlcache_content_list;
if (hlcache_content_list != NULL)
hlcache_content_list->prev = entry;
hlcache_content_list = entry;
} else {
/* Found a suitable content: no longer need low-level handle */
llcache_handle_release(ctx->llcache);
}
/* Associate handle with content */
if (content_add_user(entry->content,
hlcache_content_callback, ctx->handle) == false)
return NSERROR_NOMEM;
/* Associate cache entry with handle */
ctx->handle->entry = entry;
/* Catch handle up with state of content */
if (ctx->handle->cb != NULL) {
content_status status = content_get_status(ctx->handle);
if (status == CONTENT_STATUS_LOADING) {
event.type = CONTENT_MSG_LOADING;
ctx->handle->cb(ctx->handle, &event, ctx->handle->pw);
} else if (status == CONTENT_STATUS_READY) {
event.type = CONTENT_MSG_LOADING;
ctx->handle->cb(ctx->handle, &event, ctx->handle->pw);
if (ctx->handle->cb != NULL) {
event.type = CONTENT_MSG_READY;
ctx->handle->cb(ctx->handle, &event,
ctx->handle->pw);
}
} else if (status == CONTENT_STATUS_DONE) {
event.type = CONTENT_MSG_LOADING;
ctx->handle->cb(ctx->handle, &event, ctx->handle->pw);
/** \todo Reflow content to new width
if (content_get_available_width(ctx->handle) != width)
content_reformat(ctx->handle, width, height);
*/
if (ctx->handle->cb != NULL) {
event.type = CONTENT_MSG_READY;
ctx->handle->cb(ctx->handle, &event,
ctx->handle->pw);
}
if (ctx->handle->cb != NULL) {
event.type = CONTENT_MSG_DONE;
ctx->handle->cb(ctx->handle, &event,
ctx->handle->pw);
}
}
}
return NSERROR_OK;
}
/**
* Veneer between content callback API and hlcache callback API
*
* \param c Content to emit message for
* \param msg Message to emit
* \param data Data for message
* \param pw Pointer to private data (hlcache_handle)
*/
void hlcache_content_callback(struct content *c, content_msg msg,
union content_msg_data data, void *pw)
{
hlcache_handle *handle = pw;
hlcache_event event;
nserror error;
event.type = msg;
event.data = data;
error = handle->cb(handle, &event, handle->pw);
if (error != NSERROR_OK)
LOG(("Error in callback: %d", error));
}

110
content/hlcache.h Normal file
View File

@ -0,0 +1,110 @@
/*
* Copyright 2009 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/** \file
* High-level resource cache (interface)
*/
#ifndef NETSURF_CONTENT_HLCACHE_H_
#define NETSURF_CONTENT_HLCACHE_H_
#include "content/content.h"
#include "content/llcache.h"
#include "utils/errors.h"
/** High-level cache handle */
typedef struct hlcache_handle hlcache_handle;
/** Context for retrieving a child object */
typedef struct hlcache_child_context {
const char *charset; /**< Charset of parent */
bool quirks; /**< Whether parent is quirky */
} hlcache_child_context;
/** High-level cache event */
typedef struct {
content_msg type; /**< Event type */
union content_msg_data data; /**< Event data */
} hlcache_event;
/**
* Client callback for high-level cache events
*
* \param handle Handle to object generating event
* \param event Event data
* \param pw Pointer to client-specific data
* \return NSERROR_OK on success, appropriate error otherwise.
*/
typedef nserror (*hlcache_handle_callback)(hlcache_handle *handle,
const hlcache_event *event, void *pw);
/**
* Retrieve a high-level cache handle for an object
*
* \param url URL of the object to retrieve handle for
* \param flags Object retrieval flags
* \param referer Referring URL, or NULL if none
* \param post POST data, or NULL for a GET request
* \param width Available width for content
* \param height Available height for content
* \param cb Callback to handle object events
* \param pw Pointer to client-specific data for callback
* \param child Child retrieval context, or NULL for top-level content
* \param result Pointer to location to recieve cache handle
* \return NSERROR_OK on success, appropriate error otherwise
*
* Child contents are keyed on the tuple < URL, quirks >.
* The quirks field is ignored for child contents whose behaviour is not
* affected by quirks mode.
*
* \todo The above rules should be encoded in the handler_map.
*
* \todo Is there any way to sensibly reduce the number of parameters here?
*/
nserror hlcache_handle_retrieve(const char *url, uint32_t flags,
const char *referer, llcache_post_data *post,
uint32_t width, uint32_t height,
hlcache_handle_callback cb, void *pw,
hlcache_child_context *child, hlcache_handle **result);
/**
* Release a high-level cache handle
*
* \param handle Handle to release
* \return NSERROR_OK on success, appropriate error otherwise
*/
nserror hlcache_handle_release(hlcache_handle *handle);
/**
* Retrieve a content object from a cache handle
*
* \param handle Cache handle to dereference
* \return Pointer to content object, or NULL if there is none
*
* \todo This may not be correct. Ideally, the client should never need to
* directly access a content object. It may, therefore, be better to provide a
* bunch of veneers here that take a hlcache_handle and invoke the
* corresponding content_ API. If there's no content object associated with the
* hlcache_handle (e.g. because the source data is still being fetched, so it
* doesn't exist yet), then these veneers would behave as a NOP. The important
* thing being that the client need not care about this possibility and can
* just call the functions with impugnity.
*/
struct content *hlcache_handle_get_content(const hlcache_handle *handle);
#endif

1815
content/llcache.c Normal file

File diff suppressed because it is too large Load Diff

238
content/llcache.h Normal file
View File

@ -0,0 +1,238 @@
/*
* Copyright 2009 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/** \file
* Low-level resource cache (interface)
*/
#ifndef NETSURF_CONTENT_LLCACHE_H_
#define NETSURF_CONTENT_LLCACHE_H_
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "utils/errors.h"
struct ssl_cert_info;
struct fetch_multipart_data;
/** Handle for low-level cache object */
typedef struct llcache_handle llcache_handle;
/** POST data object for low-level cache requests */
typedef struct {
enum {
LLCACHE_POST_URL_ENCODED,
LLCACHE_POST_MULTIPART
} type; /**< Type of POST data */
union {
char *urlenc; /**< URL encoded data */
struct fetch_multipart_data *multipart; /**< Multipart data */
} data; /**< POST data content */
} llcache_post_data;
/** Low-level cache event types */
typedef enum {
LLCACHE_EVENT_HAD_HEADERS, /**< Received all headers */
LLCACHE_EVENT_HAD_DATA, /**< Received some data */
LLCACHE_EVENT_DONE, /**< Finished fetching data */
LLCACHE_EVENT_ERROR, /**< An error occurred during fetch */
LLCACHE_EVENT_PROGRESS, /**< Fetch progress update */
} llcache_event_type;
/** Low-level cache events */
typedef struct {
llcache_event_type type; /**< Type of event */
union {
struct {
const uint8_t *buf; /**< Buffer of data */
size_t len; /**< Length of buffer, in bytes */
} data; /**< Received data */
const char *msg; /**< Error or progress message */
} data; /**< Event data */
} llcache_event;
/**
* Client callback for low-level cache events
*
* \param handle Handle for which event is issued
* \param event Event data
* \param pw Pointer to client-specific data
* \return NSERROR_OK on success, appropriate error otherwise.
*/
typedef nserror (*llcache_handle_callback)(llcache_handle *handle,
const llcache_event *event, void *pw);
/** Flags for low-level cache object retrieval */
#define LLCACHE_RETRIEVE_FORCE_FETCH (1 << 0) /* Force a new fetch */
#define LLCACHE_RETRIEVE_VERIFIABLE (1 << 1) /* Requested URL was verified */
#define LLCACHE_RETRIEVE_SNIFF_TYPE (1 << 2) /* Permit content-type sniffing */
#define LLCACHE_RETRIEVE_NO_ERROR_PAGES (1 << 3) /* No error pages */
/** Low-level cache query types */
typedef enum {
LLCACHE_QUERY_AUTH, /**< Need authentication details */
LLCACHE_QUERY_REDIRECT, /**< Need permission to redirect */
LLCACHE_QUERY_SSL /**< SSL chain needs inspection */
} llcache_query_type;
/** Low-level cache query */
typedef struct {
llcache_query_type type; /**< Type of query */
const char *url; /**< URL being fetched */
union {
struct {
const char *realm; /**< Authentication realm */
} auth;
struct {
const char *target; /**< Redirect target */
} redirect;
struct {
const struct ssl_cert_info *certs;
size_t num; /**< Number of certs in chain */
} ssl;
} data;
} llcache_query;
/**
* Response handler for fetch-related queries
*
* \param proceed Whether to proceed with the fetch or not
* \param cbpw Opaque value provided to llcache_query_callback
* \return NSERROR_OK on success, appropriate error otherwise
*/
typedef nserror (*llcache_query_response)(bool proceed, void *cbpw);
/**
* Callback to handle fetch-related queries
*
* \param query Object containing details of query
* \param pw Pointer to callback-specific data
* \param cb Callback that client should call once query is satisfied
* \param cbpw Opaque value to pass into \a cb
* \return NSERROR_OK on success, appropriate error otherwise
*
* \note This callback should return immediately. Once a suitable answer to
* the query has been obtained, the provided response callback should be
* called. This is intended to be an entirely asynchronous process.
*/
typedef nserror (*llcache_query_callback)(const llcache_query *query, void *pw,
llcache_query_response cb, void *cbpw);
/**
* Initialise the low-level cache
*
* \param cb Query handler
* \param pw Pointer to query handler data
* \return NSERROR_OK on success, appropriate error otherwise.
*/
nserror llcache_initialise(llcache_query_callback cb, void *pw);
/**
* Poll the low-level cache
*
* \return NSERROR_OK on success, appropriate error otherwise.
*/
nserror llcache_poll(void);
/**
* Retrieve a handle for a low-level cache object
*
* \param url URL of the object to fetch
* \param flags Object retrieval flags
* \param referer Referring URL, or NULL if none
* \param post POST data, or NULL for a GET request
* \param cb Client callback for events
* \param pw Pointer to client-specific data
* \param result Pointer to location to recieve cache handle
* \return NSERROR_OK on success, appropriate error otherwise
*/
nserror llcache_handle_retrieve(const char *url, uint32_t flags,
const char *referer, const llcache_post_data *post,
llcache_handle_callback cb, void *pw,
llcache_handle **result);
/**
* Change the callback associated with a low-level cache handle
*
* \param handle Handle to change callback of
* \param cb New callback
* \param pw Client data for new callback
* \return NSERROR_OK on success, appropriate error otherwise
*/
nserror llcache_handle_change_callback(llcache_handle *handle,
llcache_handle_callback cb, void *pw);
/**
* Release a low-level cache handle
*
* \param handle Handle to release
* \return NSERROR_OK on success, appropriate error otherwise
*/
nserror llcache_handle_release(llcache_handle *handle);
/**
* Retrieve the post-redirect URL of a low-level cache object
*
* \param handle Handle to retrieve URL from
* \return Post-redirect URL of cache object
*/
const char *llcache_handle_get_url(const llcache_handle *handle);
/**
* Retrieve source data of a low-level cache object
*
* \param handle Handle to retrieve source data from
* \param size Pointer to location to receive byte length of data
* \return Pointer to source data
*/
const uint8_t *llcache_handle_get_source_data(const llcache_handle *handle,
size_t *size);
/**
* Retrieve a header value associated with a low-level cache object
*
* \param handle Handle to retrieve header from
* \param key Header name
* \return Header value, or NULL if header does not exist
*
* \todo Make the key an enumeration, to avoid needless string comparisons
* \todo Forcing the client to parse the header value seems wrong.
* Better would be to return the actual value part and an array of
* key-value pairs for any additional parameters.
*/
const char *llcache_handle_get_header(const llcache_handle *handle,
const char *key);
/**
* Determine if the same underlying object is referenced by the given handles
*
* \param a First handle
* \param b Second handle
* \return True if handles reference the same object, false otherwise
*/
bool llcache_handle_references_same_object(const llcache_handle *a,
const llcache_handle *b);
#endif

498
css/css.c
View File

@ -20,17 +20,18 @@
#include <libwapcaplet/libwapcaplet.h>
#include "content/content.h"
#include "content/content_protected.h"
#include "content/fetch.h"
#include "content/fetchcache.h"
#include "content/hlcache.h"
#include "css/css.h"
#include "css/internal.h"
#include "desktop/gui.h"
#include "render/html.h"
#include "utils/http.h"
#include "utils/messages.h"
static void nscss_import(content_msg msg, struct content *c,
intptr_t p1, intptr_t p2, union content_msg_data data);
static nserror nscss_import(hlcache_handle *handle,
const hlcache_event *event, void *pw);
/**
* Allocation callback for libcss
@ -49,119 +50,28 @@ static void *myrealloc(void *ptr, size_t size, void *pw)
* Initialise a CSS content
*
* \param c Content to initialise
* \param parent Parent content, or NULL if top-level
* \param params Content-Type parameters
* \return true on success, false on failure
*/
bool nscss_create(struct content *c, struct content *parent,
const char *params[])
bool nscss_create(struct content *c, const http_parameter *params)
{
const char *charset = NULL;
css_origin origin = CSS_ORIGIN_AUTHOR;
uint64_t media = CSS_MEDIA_ALL;
lwc_context *dict = NULL;
bool quirks = true;
uint32_t i;
union content_msg_data msg_data;
css_error error;
nserror error;
/** \todo what happens about the allocator? */
/** \todo proper error reporting */
/* Find charset specified on HTTP layer, if any */
/** \todo What happens if there isn't one and parent content exists? */
for (i = 0; params[i] != NULL; i += 2) {
if (strcasecmp(params[i], "charset") == 0) {
charset = params[i + 1];
break;
}
error = http_parameter_list_find_item(params, "charset", &charset);
if (error != NSERROR_OK) {
/* No charset specified, use fallback, if any */
/** \todo libcss will take this as gospel, which is wrong */
charset = c->fallback_charset;
}
if (parent != NULL) {
assert(parent->type == CONTENT_HTML ||
parent->type == CONTENT_CSS);
if (parent->type == CONTENT_HTML) {
assert(parent->data.html.dict != NULL);
if (c == parent->data.html.
stylesheets[STYLESHEET_BASE].c ||
c == parent->data.html.
stylesheets[STYLESHEET_QUIRKS].c ||
c == parent->data.html.
stylesheets[STYLESHEET_ADBLOCK].c)
origin = CSS_ORIGIN_UA;
quirks = (parent->data.html.quirks !=
BINDING_QUIRKS_MODE_NONE);
for (i = 0; i < parent->data.html.stylesheet_count;
i++) {
if (parent->data.html.stylesheets[i].c == c) {
media = parent->data.html.
stylesheets[i].media;
break;
}
}
dict = parent->data.html.dict;
} else {
assert(parent->data.css.sheet != NULL);
assert(parent->data.css.dict != NULL);
error = css_stylesheet_get_origin(
parent->data.css.sheet, &origin);
if (error != CSS_OK) {
msg_data.error = "?";
content_broadcast(c, CONTENT_MSG_ERROR,
msg_data);
return false;
}
error = css_stylesheet_quirks_allowed(
parent->data.css.sheet, &quirks);
if (error != CSS_OK) {
msg_data.error = "?";
content_broadcast(c, CONTENT_MSG_ERROR,
msg_data);
return false;
}
for (i = 0; i < parent->data.css.import_count; i++) {
if (parent->data.css.imports[i].c == c) {
media = parent->data.css.
imports[i].media;
break;
}
}
dict = parent->data.css.dict;
}
}
if (dict == NULL) {
lwc_error lerror = lwc_create_context(myrealloc, NULL, &dict);
if (lerror != lwc_error_ok) {
msg_data.error = messages_get("NoMemory");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
}
c->data.css.dict = lwc_context_ref(dict);
c->data.css.import_count = 0;
c->data.css.imports = NULL;
error = css_stylesheet_create(CSS_LEVEL_21, charset,
c->url, NULL, origin, media, quirks, false,
c->data.css.dict,
myrealloc, NULL,
nscss_resolve_url, NULL,
&c->data.css.sheet);
if (error != CSS_OK) {
lwc_context_unref(c->data.css.dict);
c->data.css.dict = NULL;
if (nscss_create_css_data(&c->data.css, content__get_url(c),
charset, c->quirks) != NSERROR_OK) {
msg_data.error = messages_get("NoMemory");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
@ -170,6 +80,35 @@ bool nscss_create(struct content *c, struct content *parent,
return true;
}
/**
* Create a struct content_css_data, creating a stylesheet object
*
* \param c Struct to populate
* \param url URL of stylesheet
* \param charset Stylesheet charset
* \param quirks Stylesheet quirks mode
* \return NSERROR_OK on success, NSERROR_NOMEM on memory exhaustion
*/
nserror nscss_create_css_data(struct content_css_data *c,
const char *url, const char *charset, bool quirks)
{
css_error error;
c->import_count = 0;
c->imports = NULL;
error = css_stylesheet_create(CSS_LEVEL_21, charset,
url, NULL, quirks, false,
myrealloc, NULL,
nscss_resolve_url, NULL,
&c->sheet);
if (error != CSS_OK) {
return NSERROR_NOMEM;
}
return NSERROR_OK;
}
/**
* Process CSS source data
*
@ -183,9 +122,7 @@ bool nscss_process_data(struct content *c, char *data, unsigned int size)
union content_msg_data msg_data;
css_error error;
error = css_stylesheet_append_data(c->data.css.sheet,
(const uint8_t *) data, size);
error = nscss_process_css_data(&c->data.css, data, size);
if (error != CSS_OK && error != CSS_NEEDDATA) {
msg_data.error = "?";
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
@ -194,6 +131,21 @@ bool nscss_process_data(struct content *c, char *data, unsigned int size)
return (error == CSS_OK || error == CSS_NEEDDATA);
}
/**
* Process CSS data
*
* \param c CSS content object
* \param data Data to process
* \param size Number of bytes to process
* \return CSS_OK on success, appropriate error otherwise
*/
css_error nscss_process_css_data(struct content_css_data *c, char *data,
unsigned int size)
{
return css_stylesheet_append_data(c->sheet,
(const uint8_t *) data, size);
}
/**
* Convert a CSS content ready for use
*
@ -209,98 +161,12 @@ bool nscss_convert(struct content *c, int w, int h)
size_t size;
css_error error;
error = css_stylesheet_data_done(c->data.css.sheet);
/* Process pending imports */
while (error == CSS_IMPORTS_PENDING) {
struct nscss_import *imports;
lwc_string *uri;
uint64_t media;
css_stylesheet *sheet;
error = css_stylesheet_next_pending_import(c->data.css.sheet,
&uri, &media);
if (error != CSS_OK && error != CSS_INVALID) {
msg_data.error = "?";
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
c->status = CONTENT_STATUS_ERROR;
return false;
}
/* Give up if there are no more imports */
if (error == CSS_INVALID) {
error = CSS_OK;
break;
}
/* Increase space in table */
imports = realloc(c->data.css.imports,
(c->data.css.import_count + 1) *
sizeof(struct nscss_import));
if (imports == NULL) {
msg_data.error = "?";
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
c->status = CONTENT_STATUS_ERROR;
return false;
}
c->data.css.imports = imports;
/* Create content */
i = c->data.css.import_count;
c->data.css.imports[c->data.css.import_count].media = media;
c->data.css.imports[c->data.css.import_count++].c =
fetchcache(lwc_string_data(uri),
nscss_import, (intptr_t) c, i,
c->width, c->height, true, NULL, NULL,
false, false);
if (c->data.css.imports[i].c == NULL) {
msg_data.error = "?";
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
c->status = CONTENT_STATUS_ERROR;
return false;
}
/* Fetch content */
c->active++;
fetchcache_go(c->data.css.imports[i].c, c->url,
nscss_import, (intptr_t) c, i,
c->width, c->height, NULL, NULL, false, c);
/* Wait for import to fetch + convert */
while (c->active > 0) {
fetch_poll();
gui_multitask();
}
if (c->data.css.imports[i].c != NULL) {
sheet = c->data.css.imports[i].c->data.css.sheet;
c->data.css.imports[i].c->data.css.sheet = NULL;
} else {
error = css_stylesheet_create(CSS_LEVEL_DEFAULT,
NULL, "", NULL, CSS_ORIGIN_AUTHOR,
media, false, false, c->data.css.dict,
myrealloc, NULL,
nscss_resolve_url, NULL,
&sheet);
if (error != CSS_OK) {
msg_data.error = messages_get("NoMemory");
content_broadcast(c, CONTENT_MSG_ERROR,
msg_data);
c->status = CONTENT_STATUS_ERROR;
return false;
}
}
error = css_stylesheet_register_import(
c->data.css.sheet, sheet);
if (error != CSS_OK) {
msg_data.error = "?";
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
c->status = CONTENT_STATUS_ERROR;
return false;
}
error = CSS_IMPORTS_PENDING;
error = nscss_convert_css_data(&c->data.css, w, h);
if (error != CSS_OK) {
msg_data.error = "?";
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
c->status = CONTENT_STATUS_ERROR;
return false;
}
/* Retrieve the size of this sheet */
@ -313,115 +179,223 @@ bool nscss_convert(struct content *c, int w, int h)
}
c->size += size;
/* Add on the size of the imported sheets, removing ourselves from
* their user list as we go (they're of no use to us now, as we've
* inserted the sheet into ourselves) */
/* Add on the size of the imported sheets */
for (i = 0; i < c->data.css.import_count; i++) {
if (c->data.css.imports[i].c != NULL) {
c->size += c->data.css.imports[i].c->size;
struct content *import = hlcache_handle_get_content(
c->data.css.imports[i].c);
content_remove_user(c->data.css.imports[i].c,
nscss_import, (uintptr_t) c, i);
if (import != NULL) {
c->size += import->size;
}
c->data.css.imports[i].c = NULL;
}
/* Remove the imports */
c->data.css.import_count = 0;
free(c->data.css.imports);
c->data.css.imports = NULL;
c->status = CONTENT_STATUS_DONE;
/* Filthy hack to stop this content being reused
* when whatever is using it has finished with it. */
c->fresh = false;
return error == CSS_OK;
}
/**
* Convert CSS data ready for use
*
* \param c CSS data to convert
* \param w Width of area content will be displayed in
* \param h Height of area content will be displayed in
* \return CSS error
*/
css_error nscss_convert_css_data(struct content_css_data *c, int w, int h)
{
const char *referer;
uint32_t i = 0;
css_error error;
nserror nerror;
error = css_stylesheet_get_url(c->sheet, &referer);
if (error != CSS_OK) {
return error;
}
error = css_stylesheet_data_done(c->sheet);
/* Process pending imports */
while (error == CSS_IMPORTS_PENDING) {
hlcache_child_context child;
struct nscss_import *imports;
lwc_string *uri;
uint64_t media;
css_stylesheet *sheet;
error = css_stylesheet_next_pending_import(c->sheet,
&uri, &media);
if (error != CSS_OK && error != CSS_INVALID) {
return error;
}
/* Give up if there are no more imports */
if (error == CSS_INVALID) {
error = CSS_OK;
break;
}
/* Increase space in table */
imports = realloc(c->imports, (c->import_count + 1) *
sizeof(struct nscss_import));
if (imports == NULL) {
return CSS_NOMEM;
}
c->imports = imports;
/** \todo fallback charset */
child.charset = NULL;
error = css_stylesheet_quirks_allowed(c->sheet, &child.quirks);
if (error != CSS_OK) {
return error;
}
/* Create content */
i = c->import_count;
c->imports[c->import_count].media = media;
nerror = hlcache_handle_retrieve(lwc_string_data(uri),
0, referer, NULL, w, h, nscss_import, c,
&child, &c->imports[c->import_count++].c);
if (error != NSERROR_OK) {
return CSS_NOMEM;
}
/* Wait for import to fetch + convert */
/** \todo This blocking approach needs to die */
while (c->imports[i].c != NULL &&
content_get_status(c->imports[i].c) !=
CONTENT_STATUS_DONE) {
fetch_poll();
gui_multitask();
}
if (c->imports[i].c != NULL) {
struct content *s = hlcache_handle_get_content(
c->imports[i].c);
sheet = s->data.css.sheet;
} else {
error = css_stylesheet_create(CSS_LEVEL_DEFAULT,
NULL, "", NULL, false, false,
myrealloc, NULL,
nscss_resolve_url, NULL,
&sheet);
if (error != CSS_OK) {
return error;
}
}
error = css_stylesheet_register_import(c->sheet, sheet);
if (error != CSS_OK) {
return error;
}
error = CSS_IMPORTS_PENDING;
}
return error;
}
/**
* Clean up a CSS content
*
* \param c Content to clean up
*/
void nscss_destroy(struct content *c)
{
nscss_destroy_css_data(&c->data.css);
}
/**
* Clean up CSS data
*
* \param c CSS data to clean up
*/
void nscss_destroy_css_data(struct content_css_data *c)
{
uint32_t i;
for (i = 0; i < c->data.css.import_count; i++) {
if (c->data.css.imports[i].c != NULL) {
content_remove_user(c->data.css.imports[i].c,
nscss_import, (uintptr_t) c, i);
for (i = 0; i < c->import_count; i++) {
if (c->imports[i].c != NULL) {
hlcache_handle_release(c->imports[i].c);
}
c->data.css.imports[i].c = NULL;
c->imports[i].c = NULL;
}
free(c->data.css.imports);
free(c->imports);
if (c->data.css.sheet != NULL) {
css_stylesheet_destroy(c->data.css.sheet);
c->data.css.sheet = NULL;
}
if (c->data.css.dict != NULL) {
lwc_context_unref(c->data.css.dict);
c->data.css.dict = NULL;
if (c->sheet != NULL) {
css_stylesheet_destroy(c->sheet);
c->sheet = NULL;
}
}
/**
* Fetchcache handler for imported stylesheets
* Retrieve imported stylesheets
*
* \param msg Message type
* \param c Content being fetched
* \param p1 Parent content
* \param p2 Index into parent's imported stylesheet array
* \param data Message data
* \param h Stylesheet containing imports
* \param n Pointer to location to receive number of imports
* \return Pointer to array of imported stylesheets
*/
void nscss_import(content_msg msg, struct content *c,
intptr_t p1, intptr_t p2, union content_msg_data data)
struct nscss_import *nscss_get_imports(hlcache_handle *h, uint32_t *n)
{
struct content *parent = (struct content *) p1;
uint32_t i = (uint32_t) p2;
struct content *c = hlcache_handle_get_content(h);
switch (msg) {
assert(c != NULL);
assert(c->type == CONTENT_CSS);
assert(n != NULL);
*n = c->data.css.import_count;
return c->data.css.imports;
}
/**
* Handler for imported stylesheet events
*
* \param handle Handle for stylesheet
* \param event Event object
* \param pw Callback context
* \return NSERROR_OK on success, appropriate error otherwise
*/
nserror nscss_import(hlcache_handle *handle,
const hlcache_event *event, void *pw)
{
struct content_css_data *parent = pw;
uint32_t i = 0;
switch (event->type) {
case CONTENT_MSG_LOADING:
if (c->type != CONTENT_CSS) {
content_remove_user(c, nscss_import, p1, p2);
if (c->user_list->next == NULL) {
fetch_abort(c->fetch);
c->fetch = NULL;
c->status = CONTENT_STATUS_ERROR;
}
if (content_get_type(handle) != CONTENT_CSS) {
hlcache_handle_release(handle);
parent->data.css.imports[i].c = NULL;
parent->active--;
content_add_error(parent, "NotCSS", 0);
for (i = 0; i < parent->import_count; i++) {
if (parent->imports[i].c == handle) {
parent->imports[i].c = NULL;
break;
}
}
}
break;
case CONTENT_MSG_READY:
break;
case CONTENT_MSG_DONE:
parent->active--;
break;
case CONTENT_MSG_AUTH:
case CONTENT_MSG_SSL:
case CONTENT_MSG_LAUNCH:
case CONTENT_MSG_ERROR:
if (parent->data.css.imports[i].c == c) {
parent->data.css.imports[i].c = NULL;
parent->active--;
hlcache_handle_release(handle);
for (i = 0; i < parent->import_count; i++) {
if (parent->imports[i].c == handle) {
parent->imports[i].c = NULL;
break;
}
}
break;
case CONTENT_MSG_STATUS:
break;
case CONTENT_MSG_NEWPTR:
parent->data.css.imports[i].c = c;
break;
default:
assert(0);
}
return NSERROR_OK;
}

View File

@ -23,7 +23,11 @@
#include <libcss/libcss.h>
#include "utils/errors.h"
struct content;
struct hlcache_handle;
struct http_parameter;
struct nscss_import;
/**
@ -31,8 +35,6 @@ struct nscss_import;
*/
struct content_css_data
{
lwc_context *dict; /**< Dictionary to intern strings in */
css_stylesheet *sheet; /**< Stylesheet object */
uint32_t import_count; /**< Number of sheets imported */
@ -43,12 +45,11 @@ struct content_css_data
* Imported stylesheet record
*/
struct nscss_import {
struct content *c; /**< Content containing sheet */
struct hlcache_handle *c; /**< Content containing sheet */
uint64_t media; /**< Media types that sheet applies to */
};
bool nscss_create(struct content *c, struct content *parent,
const char *params[]);
bool nscss_create(struct content *c, const struct http_parameter *params);
bool nscss_process_data(struct content *c, char *data, unsigned int size);
@ -56,5 +57,14 @@ bool nscss_convert(struct content *c, int w, int h);
void nscss_destroy(struct content *c);
nserror nscss_create_css_data(struct content_css_data *c,
const char *url, const char *charset, bool quirks);
css_error nscss_process_css_data(struct content_css_data *c, char *data,
unsigned int size);
css_error nscss_convert_css_data(struct content_css_data *c, int w, int h);
void nscss_destroy_css_data(struct content_css_data *c);
struct nscss_import *nscss_get_imports(struct hlcache_handle *h, uint32_t *n);
#endif

View File

@ -26,7 +26,6 @@
* URL resolution callback for libcss
*
* \param pw Resolution context
* \param ctx Dictionary to intern result in
* \param base Base URI
* \param rel Relative URL
* \param abs Pointer to location to receive resolved URL
@ -34,8 +33,8 @@
* CSS_NOMEM on memory exhaustion,
* CSS_INVALID if resolution failed.
*/
css_error nscss_resolve_url(void *pw, lwc_context *ctx,
const char *base, lwc_string *rel, lwc_string **abs)
css_error nscss_resolve_url(void *pw, const char *base,
lwc_string *rel, lwc_string **abs)
{
lwc_error lerror;
char *abs_url, *norm_url;
@ -57,7 +56,7 @@ css_error nscss_resolve_url(void *pw, lwc_context *ctx,
free(abs_url);
/* Intern it */
lerror = lwc_context_intern(ctx, norm_url, strlen(norm_url), abs);
lerror = lwc_intern_string(norm_url, strlen(norm_url), abs);
if (lerror != lwc_error_ok) {
*abs = NULL;
free(norm_url);

View File

@ -21,7 +21,7 @@
#include "css/css.h"
css_error nscss_resolve_url(void *pw, lwc_context *ctx,
const char *base, lwc_string *rel, lwc_string **abs);
css_error nscss_resolve_url(void *pw, const char *base,
lwc_string *rel, lwc_string **abs);
#endif

View File

@ -21,7 +21,7 @@
#include <string.h>
#include <strings.h>
#include "content/content.h"
#include "content/content_protected.h"
#include "content/urldb.h"
#include "css/internal.h"
#include "css/select.h"
@ -31,12 +31,10 @@
#include "utils/url.h"
#include "utils/utils.h"
static css_error node_name(void *pw, void *node,
lwc_context *dict, lwc_string **name);
static css_error node_name(void *pw, void *node, lwc_string **name);
static css_error node_classes(void *pw, void *node,
lwc_context *dict, lwc_string ***classes, uint32_t *n_classes);
static css_error node_id(void *pw, void *node,
lwc_context *dict, lwc_string **id);
lwc_string ***classes, uint32_t *n_classes);
static css_error node_id(void *pw, void *node, lwc_string **id);
static css_error named_ancestor_node(void *pw, void *node,
lwc_string *name, void **ancestor);
static css_error named_parent_node(void *pw, void *node,
@ -125,21 +123,20 @@ static css_select_handler selection_handler = {
* \param charset Charset of data, or NULL if unknown
* \param url URL of document containing data
* \param allow_quirks True to permit CSS parsing quirks
* \param dict String internment context
* \param alloc Memory allocation function
* \param pw Private word for allocator
* \return Pointer to stylesheet, or NULL on failure.
*/
css_stylesheet *nscss_create_inline_style(const uint8_t *data, size_t len,
const char *charset, const char *url, bool allow_quirks,
lwc_context *dict, css_allocator_fn alloc, void *pw)
css_allocator_fn alloc, void *pw)
{
css_stylesheet *sheet;
css_error error;
error = css_stylesheet_create(CSS_LEVEL_DEFAULT, charset, url, NULL,
CSS_ORIGIN_AUTHOR, CSS_MEDIA_ALL, allow_quirks, true,
dict, alloc, pw, nscss_resolve_url, NULL, &sheet);
allow_quirks, true, alloc, pw, nscss_resolve_url,
NULL, &sheet);
if (error != CSS_OK) {
LOG(("Failed creating sheet: %d", error));
return NULL;
@ -413,18 +410,16 @@ bool nscss_parse_colour(const char *data, css_color *result)
*
* \param pw HTML document
* \param node DOM node
* \param dict Dictionary to intern result in
* \param name Pointer to location to receive node name
* \return CSS_OK on success,
* CSS_NOMEM on memory exhaustion.
*/
css_error node_name(void *pw, void *node,
lwc_context *dict, lwc_string **name)
css_error node_name(void *pw, void *node, lwc_string **name)
{
xmlNode *n = node;
lwc_error lerror;
lerror = lwc_context_intern(dict, (const char *) n->name,
lerror = lwc_intern_string((const char *) n->name,
strlen((const char *) n->name), name);
switch (lerror) {
case lwc_error_oom:
@ -444,7 +439,6 @@ css_error node_name(void *pw, void *node,
*
* \param pw HTML document
* \param node DOM node
* \param dict Dictionary to intern result in
* \param classes Pointer to location to receive class name array
* \param n_classes Pointer to location to receive length of class name array
* \return CSS_OK on success,
@ -454,8 +448,8 @@ css_error node_name(void *pw, void *node,
* be allocated using the same allocator as used by libcss during style
* selection.
*/
css_error node_classes(void *pw, void *node,
lwc_context *dict, lwc_string ***classes, uint32_t *n_classes)
css_error node_classes(void *pw, void *node,
lwc_string ***classes, uint32_t *n_classes)
{
xmlNode *n = node;
xmlAttr *class;
@ -503,8 +497,7 @@ css_error node_classes(void *pw, void *node,
}
result = temp;
lerror = lwc_context_intern(dict, start, p - start,
&result[items]);
lerror = lwc_intern_string(start, p - start, &result[items]);
switch (lerror) {
case lwc_error_oom:
error = CSS_NOMEM;
@ -536,7 +529,7 @@ cleanup:
uint32_t i;
for (i = 0; i < items; i++)
lwc_context_string_unref(dict, result[i]);
lwc_string_unref(result[i]);
free(result);
}
@ -553,13 +546,11 @@ cleanup:
*
* \param pw HTML document
* \param node DOM node
* \param dict Dictionary to intern result in
* \param id Pointer to location to receive id value
* \return CSS_OK on success,
* CSS_NOMEM on memory exhaustion.
*/
css_error node_id(void *pw, void *node,
lwc_context *dict, lwc_string **id)
css_error node_id(void *pw, void *node, lwc_string **id)
{
xmlNode *n = node;
xmlAttr *attr;
@ -590,7 +581,7 @@ css_error node_id(void *pw, void *node,
}
/* Intern value */
lerror = lwc_context_intern(dict, start, strlen(start), id);
lerror = lwc_intern_string(start, strlen(start), id);
switch (lerror) {
case lwc_error_oom:
error = CSS_NOMEM;
@ -1285,9 +1276,7 @@ css_error node_presentational_hint(void *pw, void *node,
lwc_string *iurl;
lwc_error lerror;
lerror = lwc_context_intern(
html->data.html.dict, url,
strlen(url), &iurl);
lerror = lwc_intern_string(url, strlen(url), &iurl);
free(url);

View File

@ -29,7 +29,7 @@ struct content;
css_stylesheet *nscss_create_inline_style(const uint8_t *data, size_t len,
const char *charset, const char *url, bool allow_quirks,
lwc_context *dict, css_allocator_fn alloc, void *pw);
css_allocator_fn alloc, void *pw);
css_computed_style *nscss_get_style(struct content *html, xmlNode *n,
uint32_t pseudo_element, uint64_t media,

View File

@ -21,10 +21,10 @@
#include "utils/config.h"
#include "content/content.h"
#include "desktop/browser.h"
struct hlcache_handle;
struct browser_window;
void gui_401login_open(struct browser_window *bw, struct content *c,
void gui_401login_open(struct browser_window *bw, struct hlcache_handle *c,
const char *realm);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -31,10 +31,9 @@
#include "render/html.h"
struct box;
struct content;
struct hlcache_handle;
struct form;
struct form_control;
struct form_successful_control;
struct gui_window;
struct history;
struct selection;
@ -44,20 +43,20 @@ struct bitmap;
struct scroll_msg_data;
typedef bool (*browser_caret_callback)(struct browser_window *bw,
uint32_t key, void *p);
uint32_t key, void *p);
typedef bool (*browser_paste_callback)(struct browser_window *bw,
const char *utf8, unsigned utf8_len, bool last, void *p);
const char *utf8, unsigned utf8_len, bool last, void *p);
typedef void (*browser_move_callback)(struct browser_window *bw,
void *p);
void *p);
/** Browser window data. */
struct browser_window {
/** Page currently displayed, or 0. Must have status READY or DONE. */
struct content *current_content;
struct hlcache_handle *current_content;
/** Page being loaded, or 0. */
struct content *loading_content;
struct hlcache_handle *loading_content;
/** Window history structure. */
struct history *history;
@ -109,9 +108,6 @@ struct browser_window {
/** Scroll capturing all mouse events */
struct scroll *scroll;
/** Referrer for current fetch, or 0. */
char *referer;
/** Current fetch is download */
bool download;
@ -230,17 +226,17 @@ extern struct browser_window *current_redraw_browser;
extern bool browser_reformat_pending;
struct browser_window * browser_window_create(const char *url,
struct browser_window *clone, const char *referrer,
bool history_add, bool new_tab);
struct browser_window *clone, const char *referrer,
bool history_add, bool new_tab);
void browser_window_initialise_common(struct browser_window *bw,
struct browser_window *clone);
struct browser_window *clone);
void browser_window_go(struct browser_window *bw, const char *url,
const char *referrer, bool history_add);
const char *referrer, bool history_add);
void browser_window_go_unverifiable(struct browser_window *bw,
const char *url, const char *referrer, bool history_add,
struct content *parent);
const char *url, const char *referrer, bool history_add,
struct hlcache_handle *parent);
void browser_window_download(struct browser_window *bw,
const char *url, const char *referrer);
const char *url, const char *referrer);
void browser_window_update(struct browser_window *bw, bool scroll_to_top);
void browser_window_stop(struct browser_window *bw);
void browser_window_reload(struct browser_window *bw, bool all);
@ -250,31 +246,32 @@ void browser_window_reformat(struct browser_window *bw, int width, int height);
void browser_window_set_scale(struct browser_window *bw, float scale, bool all);
void browser_window_refresh_url_bar(struct browser_window *bw, const char *url,
const char *frag);
const char *frag);
void browser_window_mouse_click(struct browser_window *bw,
browser_mouse_state mouse, int x, int y);
browser_mouse_state mouse, int x, int y);
void browser_window_mouse_track(struct browser_window *bw,
browser_mouse_state mouse, int x, int y);
browser_mouse_state mouse, int x, int y);
void browser_window_mouse_drag_end(struct browser_window *bw,
browser_mouse_state mouse, int x, int y);
browser_mouse_state mouse, int x, int y);
bool browser_window_key_press(struct browser_window *bw, uint32_t key);
bool browser_window_paste_text(struct browser_window *bw, const char *utf8,
unsigned utf8_len, bool last);
unsigned utf8_len, bool last);
void browser_window_form_select(struct browser_window *bw,
struct form_control *control, int item);
void browser_redraw_box(struct content *c, struct box *box);
void browser_form_submit(struct browser_window *bw, struct browser_window *target,
struct form *form, struct form_control *submit_button);
struct form_control *control, int item);
void browser_redraw_box(struct hlcache_handle *c, struct box *box);
void browser_form_submit(struct browser_window *bw,
struct browser_window *target, struct form *form,
struct form_control *submit_button);
void browser_scroll_callback(void *client_data,
struct scroll_msg_data *scroll_data);
struct scroll_msg_data *scroll_data);
void browser_select_menu_callback(void *client_data,
int x, int y, int width, int height);
int x, int y, int width, int height);
void browser_window_redraw_rect(struct browser_window *bw, int x, int y,
int width, int height);
int width, int height);
bool browser_window_back_available(struct browser_window *bw);
bool browser_window_forward_available(struct browser_window *bw);
@ -282,7 +279,7 @@ bool browser_window_reload_available(struct browser_window *bw);
bool browser_window_stop_available(struct browser_window *bw);
/* In platform specific hotlist.c. */
void hotlist_visited(struct content *content);
void hotlist_visited(struct hlcache_handle *content);
/* In platform specific global_history.c. */
void global_history_add(const char *url);
@ -290,8 +287,8 @@ void global_history_add_recent(const char *url);
char **global_history_get_recent(int *count);
/* In platform specific thumbnail.c. */
bool thumbnail_create(struct content *content, struct bitmap *bitmap,
const char *url);
bool thumbnail_create(struct hlcache_handle *content, struct bitmap *bitmap,
const char *url);
/* In platform specific schedule.c. */
void schedule(int t, void (*callback)(void *p), void *p);
@ -300,7 +297,7 @@ bool schedule_run(void);
/* In platform specific theme_install.c. */
#ifdef WITH_THEME_INSTALL
void theme_install_start(struct content *c);
void theme_install_start(struct hlcache_handle *c);
#endif
#endif

View File

@ -29,6 +29,7 @@
#include <time.h>
#include <math.h>
#include "utils/config.h"
#include "content/hlcache.h"
#include "desktop/browser.h"
#include "desktop/frames.h"
#include "desktop/history_core.h"
@ -105,8 +106,8 @@ void browser_window_create_iframes(struct browser_window *bw,
window = &(bw->iframes[index++]);
if (cur->url)
browser_window_go_unverifiable(window, cur->url,
bw->current_content->url, false,
bw->current_content);
content_get_url(bw->current_content),
false, bw->current_content);
}
}
@ -155,7 +156,7 @@ void browser_window_create_frameset(struct browser_window *bw,
int row, col, index;
struct content_html_frames *frame;
struct browser_window *window;
struct content *parent;
hlcache_handle *parent;
assert(bw && frameset);
@ -230,8 +231,9 @@ void browser_window_create_frameset(struct browser_window *bw,
/* Use the URL of the first ancestor window containing html content
* as the referer */
for (window = bw; window->parent; window = window->parent) {
if (window->current_content &&
window->current_content->type == CONTENT_HTML)
if (window->current_content &&
content_get_type(window->current_content) ==
CONTENT_HTML)
break;
}
@ -247,8 +249,7 @@ void browser_window_create_frameset(struct browser_window *bw,
if (frame->url) {
browser_window_go_unverifiable(window,
frame->url,
parent != NULL
? parent->url : NULL,
content_get_url(parent),
true,
parent);
}

View File

@ -41,6 +41,7 @@ typedef enum {
GUI_SAVE_CLIPBOARD_CONTENTS
} gui_save_type;
struct fetch;
struct gui_window;
struct gui_download_window;
@ -55,6 +56,7 @@ typedef enum { GUI_POINTER_DEFAULT, GUI_POINTER_POINT, GUI_POINTER_CARET,
#include <stdbool.h>
#include "utils/config.h"
#include "content/content.h"
#include "content/hlcache.h"
#include "desktop/browser.h"
#include "desktop/search.h"
@ -89,8 +91,8 @@ void gui_window_hide_pointer(struct gui_window *g);
void gui_window_set_url(struct gui_window *g, const char *url);
void gui_window_start_throbber(struct gui_window *g);
void gui_window_stop_throbber(struct gui_window *g);
void gui_window_set_icon(struct gui_window *g, struct content *icon);
void gui_window_set_search_ico(struct content *ico);
void gui_window_set_icon(struct gui_window *g, hlcache_handle *icon);
void gui_window_set_search_ico(hlcache_handle *ico);
void gui_window_place_caret(struct gui_window *g, int x, int y, int height);
void gui_window_remove_caret(struct gui_window *g);
void gui_window_new_content(struct gui_window *g);
@ -98,7 +100,8 @@ bool gui_window_scroll_start(struct gui_window *g);
bool gui_window_box_scroll_start(struct gui_window *g,
int x0, int y0, int x1, int y1);
bool gui_window_frame_resize_start(struct gui_window *g);
void gui_window_save_as_link(struct gui_window *g, struct content *c);
void gui_window_save_link(struct gui_window *g, const char *url,
const char *title);
void gui_window_set_scale(struct gui_window *g, float scale);
struct gui_download_window *gui_download_window_create(const char *url,
@ -110,7 +113,7 @@ void gui_download_window_error(struct gui_download_window *dw,
const char *error_msg);
void gui_download_window_done(struct gui_download_window *dw);
void gui_drag_save_object(gui_save_type type, struct content *c,
void gui_drag_save_object(gui_save_type type, hlcache_handle *c,
struct gui_window *g);
void gui_drag_save_selection(struct selection *s, struct gui_window *g);
void gui_start_selection(struct gui_window *g);
@ -133,7 +136,7 @@ bool gui_search_term_highlighted(struct gui_window *g,
struct ssl_cert_info;
void gui_cert_verify(struct browser_window *bw, struct content *c,
void gui_cert_verify(struct browser_window *bw, hlcache_handle *c,
const struct ssl_cert_info *certs, unsigned long num);
#endif

View File

@ -27,6 +27,7 @@
#include <string.h>
#include <time.h>
#include "content/content.h"
#include "content/hlcache.h"
#include "content/urldb.h"
#include "css/css.h"
#include "desktop/gui.h"
@ -220,7 +221,7 @@ struct history_entry *history_clone_entry(struct history *history,
* The page is added after the current entry and becomes current.
*/
void history_add(struct history *history, struct content *content,
void history_add(struct history *history, hlcache_handle *content,
char *frag_id)
{
url_func_result res;
@ -237,14 +238,14 @@ void history_add(struct history *history, struct content *content,
if (entry == NULL)
return;
res = url_normalize(content->url, &url);
res = url_normalize(content_get_url(content), &url);
if (res != URL_FUNC_OK) {
warn_user("NoMemory", 0);
free(entry);
return;
}
title = strdup(content->title ? content->title : url);
title = strdup(content_get_title(content));
if (title == NULL) {
warn_user("NoMemory", 0);
free(url);
@ -303,11 +304,9 @@ void history_add(struct history *history, struct content *content,
* \param content content for current entry
*/
void history_update(struct history *history, struct content *content)
void history_update(struct history *history, hlcache_handle *content)
{
char *title;
char *url;
url_func_result res;
if (!history || !history->current || !history->current->bitmap)
return;
@ -315,19 +314,10 @@ void history_update(struct history *history, struct content *content)
assert(history->current->page.url);
assert(history->current->page.title);
if (content->title) {
title = strdup(content->title);
if (!title) {
warn_user("NoMemory", 0);
return;
}
} else {
res = url_normalize(content->url, &url);
if (res != URL_FUNC_OK) {
warn_user("NoMemory", 0);
return;
}
title = url;
title = strdup(content_get_title(content));
if (!title) {
warn_user("NoMemory", 0);
return;
}
assert(title);

View File

@ -25,15 +25,15 @@
#include <stdbool.h>
struct content;
struct hlcache_handle;
struct history;
struct browser_window;
struct history *history_create(void);
struct history *history_clone(struct history *history);
void history_add(struct history *history, struct content *content,
void history_add(struct history *history, struct hlcache_handle *content,
char *frag_id);
void history_update(struct history *history, struct content *content);
void history_update(struct history *history, struct hlcache_handle *content);
void history_destroy(struct history *history);
void history_back(struct browser_window *bw, struct history *history);
void history_forward(struct browser_window *bw, struct history *history);

View File

@ -28,10 +28,13 @@
#include <libxml/globals.h>
#include <libxml/xmlversion.h>
#include <libwapcaplet/libwapcaplet.h>
#include "utils/config.h"
#include "utils/utsname.h"
#include "content/fetch.h"
#include "content/fetchcache.h"
#include "content/llcache.h"
#include "content/urldb.h"
#include "desktop/netsurf.h"
#include "desktop/browser.h"
@ -44,39 +47,11 @@
bool netsurf_quit = false;
bool verbose_log = false;
static void netsurf_poll(void);
static void lib_init(void);
/**
* Gui NetSurf main().
*/
int netsurf_main(int argc, char** argv)
static void *netsurf_lwc_alloc(void *ptr, size_t len, void *pw)
{
netsurf_init(argc, argv);
netsurf_main_loop();
netsurf_exit();
return EXIT_SUCCESS;
return realloc(ptr, len);
}
/**
* Gui NetSurf main loop.
*/
int netsurf_main_loop(void)
{
while (!netsurf_quit)
netsurf_poll();
return 0;
}
/**
* Initialise components used by gui NetSurf.
*/
@ -126,35 +101,30 @@ void netsurf_init(int argc, char** argv)
utsname.nodename, utsname.release,
utsname.version, utsname.machine));
lib_init();
lwc_initialise(netsurf_lwc_alloc, NULL, 0);
url_init();
gui_init(argc, argv);
setlocale(LC_ALL, "C");
fetch_init();
fetchcache_init();
/** \todo The frontend needs to provide the llcache_query_handler */
llcache_initialise(NULL, NULL);
gui_init2(argc, argv);
}
/**
* Poll components which require it.
* Gui NetSurf main loop.
*/
void netsurf_poll(void)
int netsurf_main_loop(void)
{
static unsigned int last_clean = 0;
unsigned int current_time = wallclock();
/* avoid calling content_clean() more often than once every 5
* seconds.
*/
if (last_clean + 500 < current_time) {
last_clean = current_time;
content_clean();
while (!netsurf_quit) {
gui_poll(fetch_active);
fetch_poll();
llcache_poll();
}
gui_poll(fetch_active);
fetch_poll();
}
return 0;
}
/**
* Clean up components used by gui NetSurf.
@ -164,8 +134,6 @@ void netsurf_exit(void)
{
LOG(("Closing GUI"));
gui_quit();
LOG(("Closing content"));
content_quit();
LOG(("Closing fetches"));
fetch_quit();
LOG(("Closing utf8"));
@ -176,18 +144,3 @@ void netsurf_exit(void)
}
/**
* Initialises the libraries used in NetSurf.
*/
void lib_init(void)
{
LOG(("xmlParserVersion %s, LIBXML_VERSION_STRING %s",
xmlParserVersion, LIBXML_VERSION_STRING));
/* Using encoding "X-SJIS" (unknown to libxmp2/iconv) instead as
* "Shift-JIS" is rather popular.
*/
if (xmlAddEncodingAlias(xmlGetCharEncodingName(
XML_CHAR_ENCODING_SHIFT_JIS), "X-SJIS") != 0)
die("Failed to add encoding alias");
}

View File

@ -29,7 +29,6 @@ extern const int netsurf_version_minor;
extern void netsurf_init(int argc, char** argv);
extern void netsurf_exit(void);
extern int netsurf_main(int argc, char** argv);
extern int netsurf_main_loop(void);
#endif

View File

@ -26,6 +26,7 @@
#include <string.h>
#include "content/content.h"
#include "content/hlcache.h"
#include "css/utils.h"
#include "desktop/options.h"
#include "desktop/print.h"
@ -39,11 +40,11 @@
#define DEFAULT_PAGE_HEIGHT 840
#define DEFAULT_COPIES 1
static struct content *print_init(struct content *, struct print_settings *);
static bool print_apply_settings(struct content *, struct print_settings *);
static hlcache_handle *print_init(hlcache_handle *, struct print_settings *);
static bool print_apply_settings(hlcache_handle *, struct print_settings *);
static float page_content_width, page_content_height;
static struct content *printed_content;
static hlcache_handle *printed_content;
static float done_height;
bool html_redraw_printing = false;
@ -59,7 +60,7 @@ int html_redraw_printing_top_cropped = 0;
* \param settings The settings for printing to use
* \return true if successful, false otherwise
*/
bool print_basic_run(struct content *content,
bool print_basic_run(hlcache_handle *content,
const struct printer *printer,
struct print_settings *settings)
{
@ -69,8 +70,8 @@ bool print_basic_run(struct content *content,
if (!print_set_up(content, printer, settings, NULL))
ret = false;
while (ret && (done_height < printed_content->height) )
while (ret && (done_height < content_get_height(printed_content)) )
ret = print_draw_next_page(printer, settings);
print_cleanup(content, printer, settings);
@ -88,7 +89,7 @@ bool print_basic_run(struct content *content,
* \param height updated to the height of the printed content
* \return true if successful, false otherwise
*/
bool print_set_up(struct content *content,
bool print_set_up(hlcache_handle *content,
const struct printer *printer, struct print_settings *settings,
double *height)
{
@ -100,7 +101,7 @@ bool print_set_up(struct content *content,
print_apply_settings(printed_content, settings);
if (height)
*height = printed_content->height;
*height = content_get_height(printed_content);
printer->print_begin(settings);
@ -158,11 +159,13 @@ bool print_draw_next_page(const struct printer *printer,
* \param settings The settings for printing to use
* \return true if successful, false otherwise
*/
struct content *print_init(struct content *content,
hlcache_handle *print_init(hlcache_handle *content,
struct print_settings *settings)
{
struct content* printed_content;
struct content_user *user_sentinel;
// newcache
#if 0
hlcache_handle* printed_content;
hlcache_handle_user *user_sentinel;
content_add_user(content, NULL, (intptr_t) print_init, 0);
@ -173,7 +176,7 @@ struct content *print_init(struct content *content,
printed_content->data.html.bw = 0;
user_sentinel = talloc(printed_content, struct content_user);
user_sentinel = talloc(printed_content, hlcache_handle_user);
user_sentinel->callback = 0;
user_sentinel->p1 = user_sentinel->p2 = 0;
user_sentinel->next = 0;
@ -194,6 +197,9 @@ struct content *print_init(struct content *content,
printed_content->data.html.font_func = settings->font_func;
return printed_content;
#else
return NULL;
#endif
}
/**
@ -203,7 +209,7 @@ struct content *print_init(struct content *content,
* \param settings The settings for printing to use
* \return true if successful, false otherwise
*/
bool print_apply_settings(struct content *content,
bool print_apply_settings(hlcache_handle *content,
struct print_settings *settings)
{
if (settings == NULL)
@ -222,7 +228,8 @@ bool print_apply_settings(struct content *content,
content_reformat(content, page_content_width, 0);
LOG(("New layout applied.New height = %d ; New width = %d ",
content->height, content->width));
content_get_height(content),
content_get_width(content)));
return true;
}
@ -234,7 +241,7 @@ bool print_apply_settings(struct content *content,
* \param printer The printer interface for the printer to be used
* \return true if successful, false otherwise
*/
bool print_cleanup(struct content *content, const struct printer *printer,
bool print_cleanup(hlcache_handle *content, const struct printer *printer,
struct print_settings *settings)
{
printer->print_end();
@ -242,12 +249,11 @@ bool print_cleanup(struct content *content, const struct printer *printer,
html_redraw_printing = false;
if (printed_content) {
content_remove_user(printed_content, NULL,
(intptr_t) print_init, 0);
content_remove_user(printed_content, NULL, print_init);
talloc_free(printed_content);
}
content_remove_user(content, NULL, (intptr_t)print_init, 0);
content_remove_user(content, NULL, print_init);
free((void *)settings->output);
free(settings);

View File

@ -36,7 +36,7 @@
#include "css/css.h"
struct content;
struct hlcache_handle;
struct printer;
enum { MARGINLEFT = 0, MARGINRIGHT = 1, MARGINTOP = 2, MARGINBOTTOM = 3};
@ -64,13 +64,13 @@ struct print_settings{
};
bool print_basic_run(struct content *, const struct printer *,
bool print_basic_run(struct hlcache_handle *, const struct printer *,
struct print_settings *);
bool print_set_up(struct content *content, const struct printer *printer,
bool print_set_up(struct hlcache_handle *content, const struct printer *printer,
struct print_settings *settings, double *height);
bool print_draw_next_page(const struct printer *printer,
struct print_settings *settings);
bool print_cleanup(struct content *, const struct printer *,
bool print_cleanup(struct hlcache_handle *, const struct printer *,
struct print_settings *settings);
struct print_settings *print_make_settings(print_configuration configuration,

View File

@ -35,6 +35,7 @@
#include <libxml/parserInternals.h>
#include "utils/config.h"
#include "content/content.h"
#include "content/hlcache.h"
#include "css/css.h"
#include "render/box.h"
#include "desktop/save_complete.h"
@ -46,14 +47,14 @@ regex_t save_complete_import_re;
/** An entry in save_complete_list. */
struct save_complete_entry {
struct content *content;
hlcache_handle *content;
struct save_complete_entry *next; /**< Next entry in list */
};
static bool save_complete_html(struct content *c, const char *path,
static bool save_complete_html(hlcache_handle *c, const char *path,
bool index, struct save_complete_entry **list);
static bool save_imported_sheets(struct content *c, const char *path,
struct save_complete_entry **list);
static bool save_imported_sheets(struct nscss_import *imports, uint32_t count,
const char *path, struct save_complete_entry **list);
static char * rewrite_stylesheet_urls(const char *source, unsigned int size,
int *osize, const char *base,
struct save_complete_entry *list);
@ -63,11 +64,11 @@ static bool rewrite_urls(xmlNode *n, const char *base,
struct save_complete_entry *list);
static bool rewrite_url(xmlNode *n, const char *attr, const char *base,
struct save_complete_entry *list);
static bool save_complete_list_add(struct content *content,
static bool save_complete_list_add(hlcache_handle *content,
struct save_complete_entry **list);
static struct content * save_complete_list_find(const char *url,
static hlcache_handle * save_complete_list_find(const char *url,
struct save_complete_entry *list);
static bool save_complete_list_check(struct content *content,
static bool save_complete_list_check(hlcache_handle *content,
struct save_complete_entry *list);
/* static void save_complete_list_dump(void); */
static bool save_complete_inventory(const char *path,
@ -81,7 +82,7 @@ static bool save_complete_inventory(const char *path,
* \return true on success, false on error and error reported
*/
bool save_complete(struct content *c, const char *path)
bool save_complete(hlcache_handle *c, const char *path)
{
bool result;
struct save_complete_entry *list = NULL;
@ -111,50 +112,69 @@ bool save_complete(struct content *c, const char *path)
* \return true on success, false on error and error reported
*/
bool save_complete_html(struct content *c, const char *path, bool index,
bool save_complete_html(hlcache_handle *c, const char *path, bool index,
struct save_complete_entry **list)
{
struct html_stylesheet *sheets;
struct content_html_object *objects;
const char *base_url;
char filename[256];
unsigned int i;
unsigned int i, count;
xmlDocPtr doc;
bool res;
if (c->type != CONTENT_HTML)
if (content_get_type(c) != CONTENT_HTML)
return false;
if (save_complete_list_check(c, *list))
return true;
base_url = html_get_base_url(c);
/* save stylesheets, ignoring the base and adblocking sheets */
for (i = STYLESHEET_START; i != c->data.html.stylesheet_count; i++) {
struct content *css = c->data.html.stylesheets[i].c;
sheets = html_get_stylesheets(c, &count);
for (i = STYLESHEET_START; i != count; i++) {
hlcache_handle *css;
const char *css_data;
unsigned long css_size;
char *source;
int source_len;
bool is_style;
struct nscss_import *imports;
uint32_t import_count;
if (sheets[i].type == HTML_STYLESHEET_INTERNAL) {
if (save_imported_sheets(
sheets[i].data.internal->imports,
sheets[i].data.internal->import_count,
path, list) == false)
return false;
continue;
}
css = sheets[i].data.external;
if (!css)
continue;
if (save_complete_list_check(css, *list))
continue;
is_style = (strcmp(css->url, c->data.html.base_url) == 0);
if (is_style == false) {
if (!save_complete_list_add(css, list)) {
warn_user("NoMemory", 0);
return false;
}
if (!save_complete_list_add(css, list)) {
warn_user("NoMemory", 0);
return false;
}
if (!save_imported_sheets(css, path, list))
imports = nscss_get_imports(css, &import_count);
if (!save_imported_sheets(imports, import_count, path, list))
return false;
if (is_style)
continue; /* don't save <style> elements */
snprintf(filename, sizeof filename, "%p", css);
source = rewrite_stylesheet_urls(css->source_data,
css->source_size, &source_len, css->url,
css_data = content_get_source_data(css, &css_size);
source = rewrite_stylesheet_urls(css_data, css_size,
&source_len, content_get_url(css),
*list);
if (!source) {
warn_user("NoMemory", 0);
@ -168,12 +188,21 @@ bool save_complete_html(struct content *c, const char *path, bool index,
}
/* save objects */
for (i = 0; i != c->data.html.object_count; i++) {
struct content *obj = c->data.html.object[i].content;
objects = html_get_objects(c, &count);
/* skip difficult content types */
if (!obj || obj->type >= CONTENT_OTHER || !obj->source_data)
for (i = 0; i != count; i++) {
hlcache_handle *obj = objects[i].content;
const char *obj_data;
unsigned long obj_size;
if (obj == NULL || content_get_type(obj) >= CONTENT_OTHER)
continue;
obj_data = content_get_source_data(obj, &obj_size);
if (obj_data == NULL)
continue;
if (save_complete_list_check(obj, *list))
continue;
@ -182,7 +211,7 @@ bool save_complete_html(struct content *c, const char *path, bool index,
return false;
}
if (obj->type == CONTENT_HTML) {
if (content_get_type(obj) == CONTENT_HTML) {
if (!save_complete_html(obj, path, false, list))
return false;
continue;
@ -190,7 +219,7 @@ bool save_complete_html(struct content *c, const char *path, bool index,
snprintf(filename, sizeof filename, "%p", obj);
res = save_complete_gui_save(path, filename,
obj->source_size, obj->source_data, obj->type);
obj_size, obj_data, content_get_type(obj));
if(res == false)
return false;
}
@ -198,14 +227,14 @@ bool save_complete_html(struct content *c, const char *path, bool index,
/*save_complete_list_dump();*/
/* copy document */
doc = xmlCopyDoc(c->data.html.document, 1);
doc = xmlCopyDoc(html_get_document(c), 1);
if (doc == NULL) {
warn_user("NoMemory", 0);
return false;
}
/* rewrite all urls we know about */
if (!rewrite_document_urls(doc, c->data.html.base_url, *list)) {
if (!rewrite_document_urls(doc, html_get_base_url(c), *list)) {
xmlFreeDoc(doc);
warn_user("NoMemory", 0);
return false;
@ -237,13 +266,13 @@ bool save_complete_html(struct content *c, const char *path, bool index,
/**
* Save stylesheets imported by a CONTENT_CSS.
*
* \param c a CONTENT_CSS
* \param path path to save to
* \param imports Array of imports
* \param count Number of imports in list
* \param path Path to save to
* \return true on success, false on error and error reported
*/
bool save_imported_sheets(struct content *c, const char *path,
struct save_complete_entry **list)
bool save_imported_sheets(struct nscss_import *imports, uint32_t count,
const char *path, struct save_complete_entry **list)
{
char filename[256];
unsigned int j;
@ -251,10 +280,14 @@ bool save_imported_sheets(struct content *c, const char *path,
int source_len;
bool res;
for (j = 0; j != c->data.css.import_count; j++) {
struct content *css = c->data.css.imports[j].c;
for (j = 0; j != count; j++) {
hlcache_handle *css = imports[j].c;
const char *css_data;
unsigned long css_size;
struct nscss_import *child_imports;
uint32_t child_import_count;
if (!css)
if (css == NULL)
continue;
if (save_complete_list_check(css, *list))
continue;
@ -264,12 +297,17 @@ bool save_imported_sheets(struct content *c, const char *path,
return false;
}
if (!save_imported_sheets(css, path, list))
child_imports = nscss_get_imports(css, &child_import_count);
if (!save_imported_sheets(child_imports, child_import_count,
path, list))
return false;
snprintf(filename, sizeof filename, "%p", css);
source = rewrite_stylesheet_urls(css->source_data,
css->source_size, &source_len, css->url,
css_data = content_get_source_data(css, &css_size);
source = rewrite_stylesheet_urls(css_data, css_size,
&source_len, content_get_url(css),
*list);
if (!source) {
warn_user("NoMemory", 0);
@ -344,7 +382,7 @@ char * rewrite_stylesheet_urls(const char *source, unsigned int size,
char buf[20];
unsigned int offset = 0;
int url_len = 0;
struct content *content;
hlcache_handle *content;
int m;
unsigned int i;
unsigned int imports = 0;
@ -609,7 +647,7 @@ bool rewrite_url(xmlNode *n, const char *attr, const char *base,
{
char *url, *data;
char rel[20];
struct content *content;
hlcache_handle *content;
url_func_result res;
if (!xmlHasProp(n, (const xmlChar *) attr))
@ -654,7 +692,7 @@ bool rewrite_url(xmlNode *n, const char *attr, const char *base,
* \return true on success, false on out of memory
*/
bool save_complete_list_add(struct content *content,
bool save_complete_list_add(hlcache_handle *content,
struct save_complete_entry **list)
{
struct save_complete_entry *entry;
@ -675,12 +713,12 @@ bool save_complete_list_add(struct content *content,
* \return content if found, 0 otherwise
*/
struct content * save_complete_list_find(const char *url,
hlcache_handle * save_complete_list_find(const char *url,
struct save_complete_entry *list)
{
struct save_complete_entry *entry;
for (entry = list; entry; entry = entry->next)
if (strcmp(url, entry->content->url) == 0)
if (strcmp(url, content_get_url(entry->content)) == 0)
return entry->content;
return 0;
}
@ -693,7 +731,7 @@ struct content * save_complete_list_find(const char *url,
* \return true if the content is in the save_complete_list
*/
bool save_complete_list_check(struct content *content,
bool save_complete_list_check(hlcache_handle *content,
struct save_complete_entry *list)
{
struct save_complete_entry *entry;
@ -746,8 +784,10 @@ bool save_complete_inventory(const char *path,
return false;
}
for (entry = list; entry; entry = entry->next)
fprintf(fp, "%p %s\n", entry->content, entry->content->url);
for (entry = list; entry; entry = entry->next) {
fprintf(fp, "%p %s\n", entry->content,
content_get_url(entry->content));
}
fclose(fp);

View File

@ -28,10 +28,10 @@
#include <libxml/HTMLtree.h>
#include "content/content.h"
struct content;
struct hlcache_handle;
void save_complete_init(void);
bool save_complete(struct content *c, const char *path);
bool save_complete(struct hlcache_handle *c, const char *path);
bool save_complete_gui_save(const char *path, const char *filename,
size_t len, const char *sourcedata, content_type type);

View File

@ -30,6 +30,7 @@
#include <hpdf.h>
#include "content/hlcache.h"
#include "desktop/options.h"
#include "desktop/plotters.h"
#include "desktop/print.h"
@ -410,32 +411,37 @@ bool pdf_plot_bitmap_tile(int x, int y, int width, int height,
HPDF_Image pdf_extract_image(struct bitmap *bitmap)
{
HPDF_Image image = NULL;
struct content *content = NULL;
hlcache_handle *content = NULL;
/* TODO - get content from bitmap pointer */
if (content) {
const char *source_data;
unsigned long source_size;
/*Not sure if I don't have to check if downloading has been
finished.
Other way - lock pdf plotting while fetching a website
*/
switch(content->type){
/*Handle "embeddable" types of images*/
case CONTENT_JPEG:
image = HPDF_LoadJpegImageFromMem(pdf_doc,
(const HPDF_BYTE *)content->source_data,
content->source_size);
break;
source_data = content_get_source_data(content, &source_size);
/*Disabled until HARU PNG support will be more stable.
switch(content_get_type(content)){
/*Handle "embeddable" types of images*/
case CONTENT_JPEG:
image = HPDF_LoadJpegImageFromMem(pdf_doc,
(const HPDF_BYTE *) source_data,
source_size);
break;
case CONTENT_PNG:
image = HPDF_LoadPngImageFromMem(pdf_doc,
(const HPDF_BYTE *)content->source_data,
content->total_size);
break;*/
default:
break;
/*Disabled until HARU PNG support will be more stable.
case CONTENT_PNG:
image = HPDF_LoadPngImageFromMem(pdf_doc,
(const HPDF_BYTE *)content->source_data,
content->total_size);
break;*/
default:
break;
}
}

View File

@ -27,6 +27,7 @@
#include "utils/config.h"
#include "content/content.h"
#include "content/hlcache.h"
#include "desktop/save_text.h"
#include "render/box.h"
#include "utils/log.h"
@ -48,7 +49,7 @@ static bool save_text_add_to_buffer(const char *text, size_t length,
* \param path Path to save text file too.
*/
void save_as_text(struct content *c, char *path)
void save_as_text(hlcache_handle *c, char *path)
{
FILE *out;
struct save_text_state save = { NULL, 0, 0 };
@ -57,11 +58,11 @@ void save_as_text(struct content *c, char *path)
utf8_convert_ret ret;
char *result;
if (!c || c->type != CONTENT_HTML) {
if (!c || content_get_type(c) != CONTENT_HTML) {
return;
}
extract_text(c->data.html.layout, &first, &before, &save);
extract_text(html_get_box_tree(c), &first, &before, &save);
if (!save.block)
return;

View File

@ -25,7 +25,7 @@
#define _NETSURF_DESKTOP_SAVE_TEXT_H_
struct box;
struct content;
struct hlcache_handle;
/* text currently being saved */
struct save_text_state {
@ -41,7 +41,7 @@ typedef enum {
WHITESPACE_TWO_NEW_LINES
} save_text_whitespace;
void save_as_text(struct content *c, char *path);
void save_as_text(struct hlcache_handle *c, char *path);
void save_text_solve_whitespace(struct box *box, bool *first,
save_text_whitespace *before, const char **whitespace_text,
size_t *whitespace_length);

View File

@ -26,6 +26,7 @@
#include <ctype.h>
#include <string.h>
#include "content/content.h"
#include "content/hlcache.h"
#include "desktop/browser.h"
#include "desktop/gui.h"
#include "desktop/options.h"
@ -33,6 +34,7 @@
#include "desktop/selection.h"
#include "render/box.h"
#include "render/html.h"
#include "render/textplain.h"
#include "utils/config.h"
#include "utils/log.h"
#include "utils/messages.h"
@ -60,7 +62,7 @@ struct list_entry {
struct search_context {
struct browser_window *bw;
struct content *content;
hlcache_handle *content;
char *string;
bool prev_case_sens;
bool newsearch;
@ -80,7 +82,7 @@ static bool find_occurrences_html(const char *pattern, int p_len,
struct box *cur, bool case_sens,
struct search_context *context);
static bool find_occurrences_text(const char *pattern, int p_len,
struct content *c, bool case_sens,
hlcache_handle *c, bool case_sens,
struct search_context *context);
static struct list_entry *add_entry(unsigned start_idx, unsigned end_idx,
struct search_context *context);
@ -236,7 +238,7 @@ void search_text(const char *string, int string_len,
struct search_context *context, search_flags_t flags)
{
struct rect bounds;
struct content *c;
hlcache_handle *c;
struct box *box;
bool case_sensitive, forwards, showall;
@ -250,11 +252,11 @@ void search_text(const char *string, int string_len,
c = context->bw->current_content;
/* only handle html contents */
if ((!c) || (c->type != CONTENT_HTML &&
c->type != CONTENT_TEXTPLAIN))
if ((!c) || (content_get_type(c) != CONTENT_HTML &&
content_get_type(c) != CONTENT_TEXTPLAIN))
return;
box = c->data.html.layout;
box = html_get_box_tree(c);
if (!box)
return;
@ -282,11 +284,11 @@ void search_text(const char *string, int string_len,
(context->callbacks->hourglass != NULL))
context->callbacks->hourglass(true, context->p);
if (c->type == CONTENT_HTML)
if (content_get_type(c) == CONTENT_HTML)
res = find_occurrences_html(string, string_len,
box, case_sensitive, context);
else {
assert(c->type == CONTENT_TEXTPLAIN);
assert(content_get_type(c) == CONTENT_TEXTPLAIN);
res = find_occurrences_text(string, string_len,
c, case_sensitive, context);
}
@ -342,7 +344,7 @@ void search_text(const char *string, int string_len,
if (context->current == NULL)
return;
switch (c->type) {
switch (content_get_type(c)) {
case CONTENT_HTML:
/* get box position and jump to it */
box_coords(context->current->start_box,
@ -356,7 +358,7 @@ void search_text(const char *string, int string_len,
break;
default:
assert(c->type == CONTENT_TEXTPLAIN);
assert(content_get_type(c) == CONTENT_TEXTPLAIN);
textplain_coords_from_range(c,
context->current->start_idx,
context->current->end_idx, &bounds);
@ -551,7 +553,7 @@ bool find_occurrences_html(const char *pattern, int p_len, struct box *cur,
*/
bool find_occurrences_text(const char *pattern, int p_len,
struct content *c, bool case_sens,
hlcache_handle *c, bool case_sens,
struct search_context *context)
{
int nlines = textplain_line_count(c);
@ -642,15 +644,15 @@ void search_show_all(bool all, struct search_context *context)
if (add && !a->sel) {
a->sel = selection_create(context->bw);
if (a->sel) {
struct content *c = context->bw->
hlcache_handle *c = context->bw->
current_content;
switch (c->type) {
switch (content_get_type(c)) {
case CONTENT_HTML:
selection_init(a->sel,
c->data.html.layout);
html_get_box_tree(c));
break;
default:
assert(c->type ==
assert(content_get_type(c) ==
CONTENT_TEXTPLAIN);
selection_init(a->sel, NULL);
break;

View File

@ -24,8 +24,7 @@
#include <ctype.h>
#include <string.h>
#include "content/content.h"
#include "content/fetchcache.h"
#include "content/fetch.h"
#include "content/hlcache.h"
#include "desktop/browser.h"
#include "desktop/gui.h"
#include "desktop/options.h"
@ -43,10 +42,13 @@ static struct search_provider {
char *ico; /** < location of domain's favicon */
} current_search_provider;
static struct content *search_ico = NULL;
static hlcache_handle *search_ico = NULL;
char *search_engines_file_location;
char *search_default_ico_location;
static nserror search_web_ico_callback(hlcache_handle *ico,
const hlcache_event *event, void *pw);
/**
* creates a new browser window according to the search term
* \param searchterm such as "my search term"
@ -205,7 +207,8 @@ char *search_web_get_url(const char *encsearchterm)
void search_web_retrieve_ico(bool localdefault)
{
char *url;
struct content *icocontent;
nserror error;
if (localdefault) {
if (search_default_ico_location == NULL)
return;
@ -221,26 +224,17 @@ void search_web_retrieve_ico(bool localdefault)
url = search_web_ico_name();
}
icocontent = NULL;
if (url == NULL) {
warn_user(messages_get("NoMemory"), 0);
return;
}
icocontent = fetchcache(url, search_web_ico_callback,
0, 0, 20, 20, true, 0,
0, false, false);
free(url);
if (icocontent == NULL)
return;
fetchcache_go(icocontent, 0, search_web_ico_callback,
0, 0, 20, 20,
0, 0, false, 0);
if (icocontent == NULL)
LOG(("web search ico loading delayed"));
else
search_ico = icocontent;
error = hlcache_handle_retrieve(url, 0, NULL, NULL, 20, 20,
search_web_ico_callback, NULL, NULL, &search_ico);
if (error != NSERROR_OK)
search_ico = NULL;
free(url);
}
/**
@ -249,7 +243,7 @@ void search_web_retrieve_ico(bool localdefault)
* responsibility
*/
struct content *search_web_ico(void)
hlcache_handle *search_web_ico(void)
{
return search_ico;
}
@ -259,20 +253,18 @@ struct content *search_web_ico(void)
* else retry default from local file system
*/
void search_web_ico_callback(content_msg msg, struct content *ico,
intptr_t p1, intptr_t p2, union content_msg_data data)
nserror search_web_ico_callback(hlcache_handle *ico,
const hlcache_event *event, void *pw)
{
switch (msg) {
switch (event->type) {
case CONTENT_MSG_LOADING:
case CONTENT_MSG_READY:
break;
case CONTENT_MSG_DONE:
LOG(("got favicon '%s'", ico->url));
LOG(("got favicon '%s'", content_get_url(ico)));
#ifdef WITH_BMP
if (ico->type == CONTENT_ICO) {
search_ico = ico; /* cache */
if (content_get_type(ico) == CONTENT_ICO) {
gui_window_set_search_ico(search_ico);
} else
#endif
@ -281,20 +273,20 @@ void search_web_ico_callback(content_msg msg, struct content *ico,
}
break;
case CONTENT_MSG_LAUNCH:
case CONTENT_MSG_ERROR:
LOG(("favicon %s error: %s", ico->url, data.error));
ico = 0;
LOG(("favicon %s error: %s",
content_get_url(ico), event->data.error));
hlcache_handle_release(search_ico);
search_ico = NULL;
search_web_retrieve_ico(true);
break;
case CONTENT_MSG_STATUS:
case CONTENT_MSG_NEWPTR:
case CONTENT_MSG_AUTH:
case CONTENT_MSG_SSL:
break;
default:
assert(0);
}
return NSERROR_OK;
}

View File

@ -20,9 +20,11 @@
#define _NETSURF_DESKTOP_SEARCH_WEB_H_
#include <ctype.h>
#include <stdbool.h>
#include <string.h>
#include "content/content.h"
#include "desktop/browser.h"
struct browser_window;
struct hlcache_handle;
extern char *search_engines_file_location;
extern char *search_default_ico_location;
@ -71,9 +73,6 @@ bool search_is_url(const char *url);
void search_web_retrieve_ico(bool localdefault);
struct content *search_web_ico(void);
void search_web_ico_callback(content_msg msg, struct content *ico,
intptr_t p1, intptr_t p2, union content_msg_data data);
struct hlcache_handle *search_web_ico(void);
#endif

View File

@ -27,6 +27,7 @@
#include <stdbool.h>
#include <string.h>
#include "content/hlcache.h"
#include "desktop/gui.h"
#include "desktop/plotters.h"
#include "desktop/save_text.h"
@ -155,8 +156,8 @@ void selection_reinit(struct selection *s, struct box *root)
s->max_idx = selection_label_subtree(root, root_idx);
}
else {
struct content *c = s->bw->current_content;
if (c && c->type == CONTENT_TEXTPLAIN)
hlcache_handle *c = s->bw->current_content;
if (c && content_get_type(c) == CONTENT_TEXTPLAIN)
s->max_idx = textplain_size(c);
else
s->max_idx = 0;
@ -560,7 +561,7 @@ bool traverse_tree(struct box *box, unsigned start_idx, unsigned end_idx,
bool selection_traverse(struct selection *s, seln_traverse_handler handler,
void *handle)
{
struct content *c;
hlcache_handle *c;
save_text_whitespace before = WHITESPACE_NONE;
bool first = true;
const char *text;
@ -664,8 +665,9 @@ void selection_redraw(struct selection *s, unsigned start_idx, unsigned end_idx)
return;
}
else {
struct content *c = s->bw->current_content;
if (c && c->type == CONTENT_TEXTPLAIN && end_idx > start_idx) {
hlcache_handle *c = s->bw->current_content;
if (c && content_get_type(c) == CONTENT_TEXTPLAIN &&
end_idx > start_idx) {
textplain_coords_from_range(c, start_idx,
end_idx, &rdw.r);
rdw.inited = true;
@ -952,7 +954,7 @@ bool save_handler(const char *text, size_t length, struct box *box,
bool selection_save_text(struct selection *s, const char *path)
{
struct content *c = s->bw->current_content;
hlcache_handle *c = s->bw->current_content;
struct save_text_state sv = { NULL, 0, 0 };
utf8_convert_ret ret;
char *result;

View File

@ -2091,11 +2091,14 @@ bool textarea_cut(struct browser_window *bw,
void textarea_reflow(struct browser_window *bw, struct box *textarea,
struct box *inline_container)
{
struct content *c = hlcache_handle_get_content(bw->current_content);
int width = textarea->width;
int height = textarea->height;
assert(c != NULL);
if (!layout_inline_container(inline_container, width,
textarea, 0, 0,
bw->current_content))
textarea, 0, 0, c))
warn_user("NoMemory", 0);
textarea->width = width;
textarea->height = height;

View File

@ -70,15 +70,6 @@ struct gui_window *window_list = NULL;
bool redraws_pending = false;
#ifndef MIN
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#endif
#ifndef MAX
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
#endif
/* private data for browser user widget */
struct browser_widget_s {
struct browser_window *bw; /**< The browser window connected to this gui window */
@ -102,10 +93,10 @@ fb_queue_redraw(struct fbtk_widget_s *widget, int x0, int y0, int x1, int y1)
{
struct browser_widget_s *bwidget = fbtk_get_userpw(widget);
bwidget->redraw_box.x0 = MIN(bwidget->redraw_box.x0, x0);
bwidget->redraw_box.y0 = MIN(bwidget->redraw_box.y0, y0);
bwidget->redraw_box.x1 = MAX(bwidget->redraw_box.x1, x1);
bwidget->redraw_box.y1 = MAX(bwidget->redraw_box.y1, y1);
bwidget->redraw_box.x0 = min(bwidget->redraw_box.x0, x0);
bwidget->redraw_box.y0 = min(bwidget->redraw_box.y0, y0);
bwidget->redraw_box.x1 = max(bwidget->redraw_box.x1, x1);
bwidget->redraw_box.y1 = max(bwidget->redraw_box.y1, y1);
if (fbtk_clip_to_widget(widget, &bwidget->redraw_box)) {
bwidget->redraw_required = true;
@ -121,7 +112,6 @@ static void fb_pan(fbtk_widget_t *widget,
struct browser_widget_s *bwidget,
struct browser_window *bw)
{
struct content *c;
int x;
int y;
int width;
@ -129,13 +119,11 @@ static void fb_pan(fbtk_widget_t *widget,
nsfb_bbox_t srcbox;
nsfb_bbox_t dstbox;
c = bw->current_content;
if ((!c) || (c->locked))
return;
nsfb_t *nsfb = fbtk_get_nsfb(widget);
int content_height = content_get_height(bw->current_content);
int content_width = content_get_width(bw->current_content);
height = fbtk_get_height(widget);
width = fbtk_get_width(widget);
x = fbtk_get_x(widget);
@ -146,16 +134,16 @@ static void fb_pan(fbtk_widget_t *widget,
bwidget->pany = - bwidget->scrolly;
/* do not pan off the bottom of the content */
if ((bwidget->scrolly + bwidget->pany) > (c->height - height))
bwidget->pany = (c->height - height) - bwidget->scrolly;
if ((bwidget->scrolly + bwidget->pany) > (content_height - height))
bwidget->pany = (content_height - height) - bwidget->scrolly;
/* dont pan off the left */
if ((bwidget->scrollx + bwidget->panx) < 0)
bwidget->panx = - bwidget->scrollx;
/* do not pan off the right of the content */
if ((bwidget->scrollx + bwidget->panx) > (c->width - width))
bwidget->panx = (c->width - width) - bwidget->scrollx;
if ((bwidget->scrollx + bwidget->panx) > (content_width - width))
bwidget->panx = (content_width - width) - bwidget->scrollx;
LOG(("panning %d, %d",bwidget->panx, bwidget->pany));
@ -268,16 +256,11 @@ static void fb_redraw(fbtk_widget_t *widget,
struct browser_widget_s *bwidget,
struct browser_window *bw)
{
struct content *c;
int x;
int y;
int width;
int height;
c = bw->current_content;
if ((!c) || (c->locked))
return;
LOG(("redraw box %d,%d to %d,%d",bwidget->redraw_box.x0,bwidget->redraw_box.y0, bwidget->redraw_box.x1, bwidget->redraw_box.y1));
@ -292,13 +275,11 @@ static void fb_redraw(fbtk_widget_t *widget,
bwidget->redraw_box.x0 += x;
bwidget->redraw_box.x1 += x;
nsfb_claim(fbtk_get_nsfb(widget), &bwidget->redraw_box);
/* redraw bounding box is relative to window */
current_redraw_browser = bw;
content_redraw(c,
content_redraw(bw->current_content,
x - bwidget->scrollx, y - bwidget->scrolly,
width, height,
bwidget->redraw_box.x0, bwidget->redraw_box.y0,
@ -328,9 +309,9 @@ fb_browser_window_redraw(fbtk_widget_t *root, fbtk_widget_t *widget, void *pw)
if (bwidget->pan_required) {
int pos;
fb_pan(widget, bwidget, gw->bw);
pos = (bwidget->scrollx * 100) / gw->bw->current_content->width;
pos = (bwidget->scrollx * 100) / content_get_width(gw->bw->current_content);
fbtk_set_scroll_pos(gw->hscroll, pos);
pos = (bwidget->scrolly * 100) / gw->bw->current_content->height;
pos = (bwidget->scrolly * 100) / content_get_height(gw->bw->current_content);
fbtk_set_scroll_pos(gw->vscroll, pos);
}
@ -409,11 +390,23 @@ static bool process_cmdline(int argc, char** argv)
return true;
}
/** Normal entry point from OS */
/** Entry point from OS.
*
* /param argc The number of arguments in the string vector.
* /param argv The argument string vector.
* /return The return code to the OS
*/
int main(int argc, char** argv)
{
setbuf(stderr, NULL);
return netsurf_main(argc, argv);
netsurf_init(argc, argv);
netsurf_main_loop();
netsurf_exit();
return 0;
}
void gui_init(int argc, char** argv)
@ -1176,15 +1169,17 @@ void gui_window_get_dimensions(struct gui_window *g, int *width, int *height,
*height = fbtk_get_height(g->browser);
}
void gui_window_update_extent(struct gui_window *g)
void gui_window_update_extent(struct gui_window *gw)
{
int pct;
pct = (fbtk_get_width(g->browser) * 100) / g->bw->current_content->width;
fbtk_set_scroll(g->hscroll, pct);
pct = (fbtk_get_width(gw->browser) * 100) /
content_get_width(gw->bw->current_content);
fbtk_set_scroll(gw->hscroll, pct);
pct = (fbtk_get_height(g->browser) * 100) / g->bw->current_content->height;
fbtk_set_scroll(g->vscroll, pct);
pct = (fbtk_get_height(gw->browser) * 100) /
content_get_height(gw->bw->current_content);
fbtk_set_scroll(gw->vscroll, pct);
}
@ -1328,7 +1323,8 @@ bool gui_window_frame_resize_start(struct gui_window *g)
return true;
}
void gui_window_save_as_link(struct gui_window *g, struct content *c)
void
gui_window_save_link(struct gui_window *g, const char *url, const char *title)
{
}
@ -1340,7 +1336,8 @@ void gui_window_set_scale(struct gui_window *g, float scale)
/**
* set favicon
*/
void gui_window_set_icon(struct gui_window *g, struct content *icon)
void
gui_window_set_icon(struct gui_window *g, hlcache_handle *icon)
{
}
@ -1349,7 +1346,8 @@ void gui_window_set_icon(struct gui_window *g, struct content *icon)
* \param ico may be NULL for local calls; then access current cache from
* search_web_ico()
*/
void gui_window_set_search_ico(struct content *ico)
void
gui_window_set_search_ico(hlcache_handle *ico)
{
}
@ -1374,8 +1372,8 @@ void gui_download_window_done(struct gui_download_window *dw)
{
}
void gui_drag_save_object(gui_save_type type, struct content *c,
struct gui_window *g)
void gui_drag_save_object(gui_save_type type, hlcache_handle *c,
struct gui_window *w)
{
}
@ -1420,7 +1418,7 @@ void gui_launch_url(const char *url)
{
}
void gui_cert_verify(struct browser_window *bw, struct content *c,
void gui_cert_verify(struct browser_window *bw, struct hlcache_handle *c,
const struct ssl_cert_info *certs, unsigned long num)
{
}

View File

@ -18,6 +18,6 @@
#include "desktop/browser.h"
void hotlist_visited(struct content *content)
void hotlist_visited(struct hlcache_handle *content)
{
}

View File

@ -18,7 +18,7 @@
#include "desktop/401login.h"
void gui_401login_open(struct browser_window *bw, struct content *c,
void gui_401login_open(struct browser_window *bw, struct hlcache_handle *c,
const char *realm)
{
}

View File

@ -18,7 +18,7 @@
#include "desktop/browser.h"
bool thumbnail_create(struct content *content, struct bitmap *bitmap,
bool thumbnail_create(struct hlcache_handle *content, struct bitmap *bitmap,
const char *url)
{
return false;

View File

@ -570,7 +570,7 @@ ENTRY_CHANGED(entryHomePageURL, option_homepage_url)
END_HANDLER
BUTTON_CLICKED(setCurrentPage)
const gchar *url = current_browser->current_content->url;
const gchar *url = content_get_url(current_browser->current_content);
gtk_entry_set_text(GTK_ENTRY(entryHomePageURL), url);
option_homepage_url =
strdup(gtk_entry_get_text(GTK_ENTRY(entryHomePageURL)));

View File

@ -107,7 +107,7 @@ void nsgtk_source_dialog_init(GtkWindow *parent, struct browser_window *bw)
{
char glade_Location[strlen(res_dir_location) + SLEN("source.glade")
+ 1];
if (bw->current_content->type != CONTENT_HTML)
if (content_get_type(bw->current_content) != CONTENT_HTML)
return;
if (option_source_tab) {
@ -121,12 +121,17 @@ void nsgtk_source_dialog_init(GtkWindow *parent, struct browser_window *bw)
LOG(("error loading glade tree"));
}
const char *source_data;
unsigned long source_size;
char *data = NULL;
source_data = content_get_source_data(bw->current_content,
&source_size);
utf8_convert_ret r = utf8_from_enc(
bw->current_content->source_data,
bw->current_content->data.html.encoding,
bw->current_content->source_size,
source_data,
html_get_encoding(bw->current_content),
source_size,
&data);
if (r == UTF8_CONVERT_NOMEM) {
warn_user("NoMemory",0);
@ -160,7 +165,7 @@ void nsgtk_source_dialog_init(GtkWindow *parent, struct browser_window *bw)
return;
}
thiswindow->url = strdup(bw->current_content->url);
thiswindow->url = strdup(content_get_url(bw->current_content));
if (thiswindow->url == NULL) {
free(thiswindow);
free(data);
@ -173,8 +178,8 @@ void nsgtk_source_dialog_init(GtkWindow *parent, struct browser_window *bw)
thiswindow->sourcewindow = wndSource;
thiswindow->bw = bw;
char title[strlen(bw->current_content->url) + SLEN("Source of ") + 1];
sprintf(title, "Source of %s", bw->current_content->url);
char title[strlen(thiswindow->url) + SLEN("Source of ") + 1];
sprintf(title, "Source of %s", thiswindow->url);
thiswindow->next = nsgtk_source_list;
thiswindow->prev = NULL;
@ -209,11 +214,17 @@ void nsgtk_source_dialog_init(GtkWindow *parent, struct browser_window *bw)
}
void nsgtk_source_tab_init(GtkWindow *parent, struct browser_window *bw)
{
const char *source_data;
unsigned long source_size;
char *ndata = 0;
source_data = content_get_source_data(bw->current_content,
&source_size);
utf8_convert_ret r = utf8_from_enc(
bw->current_content->source_data,
bw->current_content->data.html.encoding,
bw->current_content->source_size,
source_data,
html_get_encoding(bw->current_content),
source_size,
&ndata);
if (r == UTF8_CONVERT_NOMEM) {
warn_user("NoMemory",0);
@ -245,18 +256,9 @@ void nsgtk_source_tab_init(GtkWindow *parent, struct browser_window *bw)
warn_user(messages_get("NoMemory"), 0);
return;
}
struct browser_window *newbw = browser_window_create(fileurl, bw,
NULL, false, true);
/* Open tab */
browser_window_create(fileurl, bw, NULL, false, true);
free(fileurl);
if (newbw->current_content) {
newbw->current_content->title = malloc(
strlen(bw->current_content->url) +
SLEN("source of ") + 1);
if (newbw->current_content->title == NULL)
return;
sprintf(newbw->current_content->title, "source of %s",
bw->current_content->url);
}
}

View File

@ -42,6 +42,7 @@
#include "content/content.h"
#include "content/fetch.h"
#include "content/fetchers/fetch_curl.h"
#include "content/hlcache.h"
#include "content/urldb.h"
#include "desktop/401login.h"
#include "desktop/browser.h"
@ -122,7 +123,14 @@ int main(int argc, char** argv)
setbuf(stderr, NULL);
return netsurf_main(argc, argv);
/* initialise netsurf */
netsurf_init(argc, argv);
netsurf_main_loop();
netsurf_exit();
return 0;
}
@ -599,7 +607,8 @@ void gui_create_form_select_menu(struct browser_window *bw,
}
void gui_window_save_as_link(struct gui_window *g, struct content *c)
void gui_window_save_link(struct gui_window *g, const char *url,
const char *title)
{
}
@ -630,12 +639,11 @@ void die(const char * const error)
}
void hotlist_visited(struct content *content)
void hotlist_visited(hlcache_handle *content)
{
}
void gui_cert_verify(struct browser_window *bw, struct content *c,
void gui_cert_verify(struct browser_window *bw, hlcache_handle *c,
const struct ssl_cert_info *certs, unsigned long num)
{
GladeXML *x = glade_xml_new(glade_ssl_file_location, NULL, NULL);
@ -644,7 +652,7 @@ void gui_cert_verify(struct browser_window *bw, struct content *c,
void **session = calloc(sizeof(void *), 4);
session[0] = bw;
session[1] = strdup(c->url);
session[1] = strdup(content_get_url(c));
session[2] = x;
session[3] = wnd;

View File

@ -25,6 +25,7 @@
#include "utils/log.h"
#include "gtk/gtk_gui.h"
#include "content/content.h"
#include "content/hlcache.h"
#include "content/urldb.h"
#include "desktop/browser.h"
#include "desktop/401login.h"
@ -51,16 +52,16 @@ static void nsgtk_login_next(GtkWidget *w, gpointer data);
static void nsgtk_login_ok_clicked(GtkButton *w, gpointer data);
static void nsgtk_login_cancel_clicked(GtkButton *w, gpointer data);
void gui_401login_open(struct browser_window *bw, struct content *c,
void gui_401login_open(struct browser_window *bw, hlcache_handle *c,
const char *realm)
{
char *host;
url_func_result res;
res = url_host(c->url, &host);
res = url_host(content_get_url(c), &host);
assert(res == URL_FUNC_OK);
create_login_window(bw, host, realm, c->url);
create_login_window(bw, host, realm, content_get_url(c));
free(host);
}

View File

@ -32,6 +32,7 @@
#include <gtk/gtk.h>
#include "content/content.h"
#include "content/hlcache.h"
#include "desktop/options.h"
#include "desktop/plotters.h"
#include "desktop/print.h"
@ -48,7 +49,7 @@
/* Globals */
cairo_t *gtk_print_current_cr;
static struct print_settings* settings;
struct content *content_to_print;
hlcache_handle *content_to_print;
static GdkRectangle cliprect;
static inline void nsgtk_print_set_colour(colour c)

View File

@ -26,9 +26,11 @@
#include <gtk/gtk.h>
struct hlcache_handle;
extern cairo_t *gtk_print_current_cr;
extern struct content *content_to_print;
extern struct hlcache_handle *content_to_print;
/*handlers for signals from the GTK print operation*/

View File

@ -30,6 +30,7 @@
#include <libxml/debugXML.h>
#include "gtk/gtk_scaffolding.h"
#include "content/content.h"
#include "content/hlcache.h"
#include "css/utils.h"
#include "desktop/browser.h"
#include "desktop/history_core.h"
@ -271,8 +272,10 @@ void nsgtk_window_update_back_forward(struct gtk_scaffolding *g)
nsgtk_scaffolding_set_sensitivity(g);
/* update the url bar, particularly necessary when tabbing */
if (bw->current_content != NULL && bw->current_content->url != NULL)
browser_window_refresh_url_bar(bw, bw->current_content->url,
if (bw->current_content != NULL &&
content_get_url(bw->current_content) != NULL)
browser_window_refresh_url_bar(bw,
content_get_url(bw->current_content),
bw->frag_id);
/* update the local history window, as well as queuing a redraw
@ -493,8 +496,8 @@ MULTIHANDLER(savepage)
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fc), filter);
gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(fc), filter);
res = url_nice(gui_window_get_browser_window(
g->top_level)->current_content->url, &path, false);
res = url_nice(content_get_url(gui_window_get_browser_window(
g->top_level)->current_content), &path, false);
if (res != URL_FUNC_OK) {
path = strdup(messages_get("SaveText"));
if (path == NULL) {
@ -549,7 +552,7 @@ MULTIHANDLER(pdf)
LOG(("Print preview (generating PDF) started."));
res = url_nice(bw->current_content->url, &url_name, true);
res = url_nice(content_get_url(bw->current_content), &url_name, true);
if (res != URL_FUNC_OK) {
warn_user(messages_get(res == URL_FUNC_NOMEM ? "NoMemory"
: "URIError"), 0);
@ -622,8 +625,8 @@ MULTIHANDLER(plaintext)
char *filename;
url_func_result res;
res = url_nice(gui_window_get_browser_window(
g->top_level)->current_content->url, &filename, false);
res = url_nice(content_get_url(gui_window_get_browser_window(
g->top_level)->current_content), &filename, false);
if (res != URL_FUNC_OK) {
filename = strdup(messages_get("SaveText"));
if (filename == NULL) {
@ -710,7 +713,7 @@ MULTIHANDLER(print)
G_CALLBACK(gtk_print_signal_draw_page), NULL);
g_signal_connect(print_op, "end_print",
G_CALLBACK(gtk_print_signal_end_print), settings);
if (bw->current_content->type != CONTENT_TEXTPLAIN)
if (content_get_type(bw->current_content) != CONTENT_TEXTPLAIN)
res = gtk_print_operation_run(print_op,
GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
g->window,
@ -762,7 +765,7 @@ MENUHANDLER(savelink)
return FALSE;
browser_window_download(bw, current_menu_link_box->href,
bw->current_content->url);
content_get_url(bw->current_content));
return TRUE;
}
@ -1125,11 +1128,11 @@ MULTIHANDLER(saveboxtree)
struct browser_window *bw;
bw = gui_window_get_browser_window(g->top_level);
if (bw->current_content &&
bw->current_content->type ==
if (bw->current_content &&
content_get_type(bw->current_content) ==
CONTENT_HTML) {
box_dump(fh,
bw->current_content->data.html.layout,
html_get_box_tree(bw->current_content),
0);
}
@ -1174,12 +1177,11 @@ MULTIHANDLER(savedomtree)
struct browser_window *bw;
bw = gui_window_get_browser_window(g->top_level);
if (bw->current_content &&
bw->current_content->type ==
if (bw->current_content &&
content_get_type(bw->current_content) ==
CONTENT_HTML) {
xmlDebugDumpDocument(fh,
bw->current_content->
data.html.document);
html_get_document(bw->current_content));
}
fclose(fh);
@ -1871,80 +1873,93 @@ void gui_window_stop_throbber(struct gui_window* _g)
/**
* set favicon
*/
void gui_window_set_icon(struct gui_window *_g, struct content *icon)
void gui_window_set_icon(struct gui_window *_g, hlcache_handle *icon)
{
struct gtk_scaffolding *g = nsgtk_get_scaffold(_g);
GtkImage *iconImage = NULL;
if (g->icoFav != NULL)
g_object_unref(g->icoFav);
struct bitmap *icon_bitmap;
GtkImage *iconImage;
if (icon == NULL)
return;
#ifdef WITH_BMP
if ((icon != NULL) && (icon->type == CONTENT_ICO)) {
if (content_get_type(icon) == CONTENT_ICO)
nsico_set_bitmap_from_size(icon, 16, 16);
}
#endif
if ((icon != NULL) && (icon->bitmap != NULL)) {
GdkPixbuf *pb = gtk_bitmap_get_primary(icon->bitmap);
if ((pb != NULL) && (gdk_pixbuf_get_width(pb) > 0) &&
(gdk_pixbuf_get_height(pb) > 0)) {
pb = gdk_pixbuf_scale_simple(pb, 16, 16,
GDK_INTERP_HYPER);
iconImage = GTK_IMAGE(
gtk_image_new_from_pixbuf(pb));
} else {
iconImage = NULL;
}
}
if (iconImage == NULL) {
char imagepath[strlen(res_dir_location) + SLEN("favicon.png")
+ 1];
icon_bitmap = content_get_bitmap(icon);
if (icon_bitmap == NULL)
return;
GdkPixbuf *pb = gtk_bitmap_get_primary(icon_bitmap);
if (pb != NULL && gdk_pixbuf_get_width(pb) > 0 &&
gdk_pixbuf_get_height(pb) > 0) {
pb = gdk_pixbuf_scale_simple(pb, 16, 16, GDK_INTERP_HYPER);
iconImage = GTK_IMAGE(gtk_image_new_from_pixbuf(pb));
} else {
/** \todo Does pb need cleaning up? */
char imagepath[strlen(res_dir_location) +
SLEN("favicon.png") + 1];
sprintf(imagepath, "%sfavicon.png", res_dir_location);
iconImage = GTK_IMAGE(gtk_image_new_from_file(imagepath));
}
if (iconImage == NULL)
return;
if (g->icoFav != NULL)
g_object_unref(g->icoFav);
g->icoFav = iconImage;
sexy_icon_entry_set_icon(SEXY_ICON_ENTRY(g->url_bar),
sexy_icon_entry_set_icon(SEXY_ICON_ENTRY(g->url_bar),
SEXY_ICON_ENTRY_PRIMARY, GTK_IMAGE(g->icoFav));
gtk_widget_show_all(GTK_WIDGET(g->buttons[URL_BAR_ITEM]->button));
}
void gui_window_set_search_ico(struct content *ico)
void gui_window_set_search_ico(hlcache_handle *ico)
{
GdkPixbuf *pbico = NULL;
GtkImage *searchico = NULL;
GdkPixbuf *pbico;
GtkImage *searchico;
struct bitmap *ico_bitmap;
nsgtk_scaffolding *current;
if (ico == NULL)
ico = search_web_ico();
if (ico == NULL && (ico = search_web_ico()) == NULL)
return;
#ifdef WITH_BMP
if ((ico != NULL) && (ico->type == CONTENT_ICO)) {
if (content_get_type(ico) == CONTENT_ICO)
nsico_set_bitmap_from_size(ico, 20, 20);
}
#endif
if ((ico != NULL) && (ico->bitmap != NULL)) {
pbico = gtk_bitmap_get_primary(ico->bitmap);
if ((pbico != NULL) && (gdk_pixbuf_get_width(pbico) > 0) &&
(gdk_pixbuf_get_height(pbico) > 0)) {
pbico = gdk_pixbuf_scale_simple(pbico, 20, 20,
GDK_INTERP_HYPER);
current = scaf_list;
searchico = GTK_IMAGE(
gtk_image_new_from_pixbuf(pbico));
} else {
searchico = NULL;
}
ico_bitmap = content_get_bitmap(ico);
if (ico_bitmap == NULL)
return;
pbico = gtk_bitmap_get_primary(ico_bitmap);
if (pbico != NULL && gdk_pixbuf_get_width(pbico) > 0 &&
gdk_pixbuf_get_height(pbico) > 0) {
pbico = gdk_pixbuf_scale_simple(pbico, 20, 20,
GDK_INTERP_HYPER);
searchico = GTK_IMAGE(gtk_image_new_from_pixbuf(pbico));
} else {
/** \todo Does pbico need cleaning up? */
return;
}
/* add ico to toolbar */
current = scaf_list;
while (current) {
/* add ico to each window's toolbar */
for (current = scaf_list; current != NULL; current = current->next) {
if (searchico != NULL) {
/** \todo Are we leaking webSearchIco here? */
current->webSearchIco = searchico;
sexy_icon_entry_set_icon(SEXY_ICON_ENTRY(
current->webSearchEntry),
SEXY_ICON_ENTRY_PRIMARY,
current->webSearchIco);
}
searchico = GTK_IMAGE(gtk_image_new_from_pixbuf(pbico));
current = current->next;
if (pbico != NULL)
searchico = GTK_IMAGE(gtk_image_new_from_pixbuf(pbico));
else
searchico = NULL;
}
}
@ -2117,33 +2132,26 @@ void nsgtk_scaffolding_set_top_level (struct gui_window *gw)
nsgtk_get_scaffold(gw)->top_level = gw;
struct browser_window *bw = gui_window_get_browser_window(gw);
assert(bw != NULL);
/* Synchronise the history (will also update the URL bar) */
nsgtk_window_update_back_forward(nsgtk_get_scaffold(gw));
/* clear effects of potential searches */
if ((bw != NULL) && (bw->search_context != NULL))
if (bw->search_context != NULL)
search_destroy_context(bw->search_context);
nsgtk_search_set_forward_state(true, bw);
nsgtk_search_set_back_state(true, bw);
/* Ensure the window's title bar as well as favicon are updated */
if (gui_window_get_browser_window(gw) != NULL &&
gui_window_get_browser_window(gw)->current_content
!= NULL) {
if (gui_window_get_browser_window(gw)->current_content->title
!= NULL) {
gui_window_set_title(gw,
gui_window_get_browser_window(gw)->
current_content->title);
} else {
gui_window_set_title(gw,
gui_window_get_browser_window(gw)->
current_content->url);
}
if (gui_window_get_browser_window(gw)->current_content->type
== CONTENT_HTML)
if (bw->current_content != NULL) {
gui_window_set_title(gw,
content_get_title(bw->current_content));
if (content_get_type(bw->current_content) == CONTENT_HTML)
gui_window_set_icon(gw,
gui_window_get_browser_window(gw)->
current_content->data.html.favicon);
html_get_favicon(bw->current_content));
}
}
@ -2287,7 +2295,8 @@ static guint nsgtk_scaffolding_update_link_operations_sensitivity(
struct browser_window *bw = gui_window_get_browser_window(g->top_level);
current_menu_link_box = NULL;
if (bw->current_content && bw->current_content->type == CONTENT_HTML) {
if (bw->current_content &&
content_get_type(bw->current_content) == CONTENT_HTML) {
current_menu_link_box = box_href_at_point(bw->current_content,
x, y);
}

View File

@ -28,6 +28,7 @@
#include "gtk/gtk_window.h"
#include "utils/config.h"
#include "content/content.h"
#include "content/hlcache.h"
#include "desktop/browser.h"
#include "desktop/gui.h"
#include "desktop/search.h"
@ -99,7 +100,7 @@ gboolean nsgtk_search_back_button_clicked(GtkWidget *widget, gpointer data)
void nsgtk_search_init(struct gtk_scaffolding *g)
{
struct content *c;
hlcache_handle *c;
assert(gui_window_get_browser_window(nsgtk_scaffolding_top_level(g))
!= NULL);
@ -107,7 +108,8 @@ void nsgtk_search_init(struct gtk_scaffolding *g)
c = gui_window_get_browser_window(nsgtk_scaffolding_top_level(g))->
current_content;
if ((!c) || (c->type != CONTENT_HTML && c->type != CONTENT_TEXTPLAIN))
if ((!c) || (content_get_type(c) != CONTENT_HTML &&
content_get_type(c) != CONTENT_TEXTPLAIN))
return;
}

View File

@ -22,6 +22,7 @@
#include <unistd.h>
#include "content/content.h"
#include "content/content_type.h"
#include "content/hlcache.h"
#include "gtk/gtk_gui.h"
#include "gtk/gtk_scaffolding.h"
#include "gtk/gtk_menu.h"
@ -62,10 +63,10 @@ static void nsgtk_theme_cache_searchimage(nsgtk_search_buttons i,
const char *filename, const char *path);
#ifdef WITH_THEME_INSTALL
static struct content *theme_install_content = NULL;
static hlcache_handle *theme_install_content = NULL;
static void theme_install_callback(content_msg msg, struct content *c,
intptr_t p1, intptr_t p2, union content_msg_data data);
static void theme_install_callback(hlcache_handle *c, content_msg msg,
union content_msg_data data, void *pw);
static bool theme_install_read(const char *data, unsigned long len);
#endif
@ -674,14 +675,14 @@ GtkImage *nsgtk_theme_image_default(nsgtk_toolbar_button i, GtkIconSize s)
/**
* when CONTENT_THEME needs handling call this function
*/
void theme_install_start(struct content *c)
void theme_install_start(hlcache_handle *c)
{
assert(c);
assert(c->type == CONTENT_THEME);
assert(content_get_type(c) == CONTENT_THEME);
/* stop theme sitting in memory cache */
c->fresh = false;
if (!content_add_user(c, theme_install_callback, 0, 0)) {
content_invalidate_reuse_data(c);
if (!content_add_user(c, theme_install_callback, NULL)) {
warn_user("NoMemory", 0);
return;
}
@ -692,17 +693,25 @@ void theme_install_start(struct content *c)
* Callback for fetchcache() for theme install fetches.
*/
void theme_install_callback(content_msg msg, struct content *c,
intptr_t p1, intptr_t p2, union content_msg_data data)
void theme_install_callback(hlcache_handle *c, content_msg msg,
union content_msg_data data, void *pw)
{
switch (msg) {
case CONTENT_MSG_READY:
break;
case CONTENT_MSG_DONE:
{
const char *source_data;
unsigned long source_size;
theme_install_content = c;
if (!theme_install_read(c->source_data, c->source_size))
source_data = content_get_source_data(c, &source_size);
if (!theme_install_read(source_data, source_size))
warn_user("ThemeInvalid", 0);
}
break;
case CONTENT_MSG_ERROR:

View File

@ -27,6 +27,7 @@
#include <assert.h>
#include <gtk/gtk.h>
#include "content/content.h"
#include "content/hlcache.h"
#include "content/urldb.h"
#include "desktop/plotters.h"
#include "desktop/browser.h"
@ -45,7 +46,7 @@
* \param bitmap the bitmap to draw to
* \param url the URL the thumnail belongs to, or NULL
*/
bool thumbnail_create(struct content *content, struct bitmap *bitmap,
bool thumbnail_create(hlcache_handle *content, struct bitmap *bitmap,
const char *url)
{
GdkPixbuf *pixbuf;
@ -59,8 +60,8 @@ bool thumbnail_create(struct content *content, struct bitmap *bitmap,
assert(content);
assert(bitmap);
cwidth = min(content->width, 1024);
cheight = min(content->height, 768);
cwidth = min(content_get_width(content), 1024);
cheight = min(content_get_height(content), 768);
pixbuf = gtk_bitmap_get_primary(bitmap);
width = gdk_pixbuf_get_width(pixbuf);
@ -68,7 +69,8 @@ bool thumbnail_create(struct content *content, struct bitmap *bitmap,
depth = (gdk_screen_get_system_visual(gdk_screen_get_default()))->depth;
LOG(("Trying to create a thumbnail pixmap for a content of %dx%d@%d",
content->width, content->width, depth));
content_get_width(content), content_get_height(content),
depth));
pixmap = gdk_pixmap_new(NULL, cwidth, cwidth, depth);
@ -87,7 +89,8 @@ bool thumbnail_create(struct content *content, struct bitmap *bitmap,
/* set the plotting functions up */
plot = nsgtk_plotters;
nsgtk_plot_set_scale((double) cwidth / (double) content->width);
nsgtk_plot_set_scale((double) cwidth /
(double) content_get_width(content));
/* set to plot to pixmap */
current_drawable = pixmap;
@ -98,8 +101,10 @@ bool thumbnail_create(struct content *content, struct bitmap *bitmap,
plot.rectangle(0, 0, cwidth, cwidth, plot_style_fill_white);
/* render the content */
content_redraw(content, 0, 0, content->width, content->width,
0, 0, content->width, content->width, 1.0, 0xFFFFFF);
content_redraw(content, 0, 0, content_get_width(content),
content_get_width(content),
0, 0, content_get_width(content),
content_get_width(content), 1.0, 0xFFFFFF);
/* resample the large plot down to the size of our thumbnail */
big = gdk_pixbuf_get_from_drawable(NULL, pixmap, NULL, 0, 0, 0, 0,

View File

@ -412,15 +412,16 @@ void nsgtk_toolbar_close(nsgtk_scaffolding *g)
NSGTK_WINDOW_SIGNAL_REDRAW));
if ((gui_window_get_browser_window(nsgtk_scaffolding_top_level(
list))->current_content != NULL) &&
(gui_window_get_browser_window(
(content_get_url(gui_window_get_browser_window(
nsgtk_scaffolding_top_level(list))->
current_content->url != NULL))
current_content) != NULL))
browser_window_refresh_url_bar(
gui_window_get_browser_window(
nsgtk_scaffolding_top_level(list)),
content_get_url(
gui_window_get_browser_window(
nsgtk_scaffolding_top_level(list))->
current_content->url,
current_content),
gui_window_get_browser_window(
nsgtk_scaffolding_top_level(list))->
frag_id);

View File

@ -19,6 +19,7 @@
#include <inttypes.h>
#include <string.h>
#include "content/hlcache.h"
#include "gtk/gtk_window.h"
#include "desktop/browser.h"
#include "desktop/options.h"
@ -144,7 +145,7 @@ struct gui_window *gui_create_browser_window(struct browser_window *bw,
struct gui_window *g; /**< what we're creating to return */
GtkPolicyType scrollpolicy;
g = malloc(sizeof(*g));
g = calloc(1, sizeof(*g));
if (!g) {
warn_user("NoMemory", 0);
return 0;
@ -349,7 +350,7 @@ gboolean nsgtk_window_expose_event(GtkWidget *widget,
GdkEventExpose *event, gpointer data)
{
struct gui_window *g = data;
struct content *c;
hlcache_handle *c;
float scale = g->bw->scale;
assert(g);
@ -366,7 +367,7 @@ gboolean nsgtk_window_expose_event(GtkWidget *widget,
return FALSE;
/* HTML rendering handles scale itself */
if (c->type == CONTENT_HTML)
if (content_get_type(c) == CONTENT_HTML)
scale = 1;
current_widget = (GtkWidget *)g->drawing_area;
@ -712,7 +713,7 @@ void gui_window_redraw_window(struct gui_window *g)
void gui_window_update_box(struct gui_window *g,
const union content_msg_data *data)
{
struct content *c = g->bw->current_content;
hlcache_handle *c = g->bw->current_content;
if (c == NULL)
return;
@ -788,8 +789,8 @@ void gui_window_update_extent(struct gui_window *g)
return;
gtk_widget_set_size_request(GTK_WIDGET(g->drawing_area),
g->bw->current_content->width * g->bw->scale,
g->bw->current_content->height * g->bw->scale);
content_get_width(g->bw->current_content) * g->bw->scale,
content_get_height(g->bw->current_content) * g->bw->scale);
gtk_widget_set_size_request(GTK_WIDGET(g->viewport), 0, 0);
@ -958,7 +959,7 @@ bool gui_window_box_scroll_start(struct gui_window *g,
return true;
}
void gui_drag_save_object(gui_save_type type, struct content *c,
void gui_drag_save_object(gui_save_type type, hlcache_handle *c,
struct gui_window *g)
{

View File

@ -30,7 +30,7 @@
#include <stdlib.h>
#include <libnsbmp.h>
#include "utils/config.h"
#include "content/content.h"
#include "content/content_protected.h"
#include "desktop/plotters.h"
#include "image/bitmap.h"
#include "image/bmp.h"
@ -49,8 +49,7 @@ bmp_bitmap_callback_vt bmp_bitmap_callbacks = {
.bitmap_get_bpp = bitmap_get_bpp
};
bool nsbmp_create(struct content *c, struct content *parent,
const char *params[])
bool nsbmp_create(struct content *c, const struct http_parameter *params)
{
union content_msg_data msg_data;
@ -71,12 +70,16 @@ bool nsbmp_convert(struct content *c, int iwidth, int iheight)
bmp_image *bmp;
union content_msg_data msg_data;
uint32_t swidth;
const char *data;
unsigned long size;
/* set the bmp data */
bmp = c->data.bmp.bmp;
data = content__get_source_data(c, &size);
/* analyse the BMP */
res = bmp_analyse(bmp, c->source_size, (unsigned char *)c->source_data);
res = bmp_analyse(bmp, size, (unsigned char *) data);
switch (res) {
case BMP_OK:
break;
@ -98,7 +101,7 @@ bool nsbmp_convert(struct content *c, int iwidth, int iheight)
c->title = malloc(100);
if (c->title)
snprintf(c->title, 100, messages_get("BMPTitle"), c->width,
c->height, c->source_size);
c->height, size);
swidth = bmp->bitmap_callbacks.bitmap_get_bpp(bmp->bitmap) * bmp->width;
c->size += (swidth * bmp->height) + 16 + 44 + 100;

View File

@ -33,6 +33,7 @@
struct content;
struct bitmap;
struct http_parameter;
struct content_bmp_data {
bmp_image *bmp; /** BMP image data */
@ -40,8 +41,7 @@ struct content_bmp_data {
extern bmp_bitmap_callback_vt bmp_bitmap_callbacks; /** Only to be used by ICO code. */
bool nsbmp_create(struct content *c, struct content *parent,
const char *params[]);
bool nsbmp_create(struct content *c, const struct http_parameter *params);
bool nsbmp_convert(struct content *c, int width, int height);
void nsbmp_destroy(struct content *c);
bool nsbmp_redraw(struct content *c, int x, int y,

View File

@ -37,7 +37,7 @@
#include <stdlib.h>
#include <libnsgif.h>
#include "utils/config.h"
#include "content/content.h"
#include "content/content_protected.h"
#include "desktop/browser.h"
#include "desktop/options.h"
#include "desktop/plotters.h"
@ -64,8 +64,7 @@ gif_bitmap_callback_vt gif_bitmap_callbacks = {
};
bool nsgif_create(struct content *c, struct content *parent,
const char *params[])
bool nsgif_create(struct content *c, const struct http_parameter *params)
{
union content_msg_data msg_data;
/* Initialise our data structure */
@ -85,26 +84,28 @@ bool nsgif_convert(struct content *c, int iwidth, int iheight)
int res;
struct gif_animation *gif;
union content_msg_data msg_data;
const char *data;
unsigned long size;
/* Get the animation */
gif = c->data.gif.gif;
data = content__get_source_data(c, &size);
/* Initialise the GIF */
do {
res = gif_initialise(gif, c->source_size,
(unsigned char *)c->source_data);
if (res != GIF_OK && res != GIF_WORKING && res != GIF_INSUFFICIENT_FRAME_DATA) {
switch (res)
{
case GIF_FRAME_DATA_ERROR:
case GIF_INSUFFICIENT_DATA:
case GIF_DATA_ERROR:
msg_data.error = messages_get("BadGIF");
break;
case GIF_INSUFFICIENT_MEMORY:
msg_data.error = messages_get(
"NoMemory");
break;
res = gif_initialise(gif, size, (unsigned char *) data);
if (res != GIF_OK && res != GIF_WORKING &&
res != GIF_INSUFFICIENT_FRAME_DATA) {
switch (res) {
case GIF_FRAME_DATA_ERROR:
case GIF_INSUFFICIENT_DATA:
case GIF_DATA_ERROR:
msg_data.error = messages_get("BadGIF");
break;
case GIF_INSUFFICIENT_MEMORY:
msg_data.error = messages_get("NoMemory");
break;
}
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
@ -125,7 +126,7 @@ bool nsgif_convert(struct content *c, int iwidth, int iheight)
c->title = malloc(100);
if (c->title) {
snprintf(c->title, 100, messages_get("GIFTitle"), c->width,
c->height, c->source_size);
c->height, size);
}
c->size += (gif->width * gif->height * 4) + 16 + 44 + 100;

View File

@ -31,14 +31,14 @@
#include <libnsgif.h>
struct content;
struct http_parameter;
struct content_gif_data {
struct gif_animation *gif; /**< GIF animation data */
int current_frame; /**< current frame to display [0...(max-1)] */
};
bool nsgif_create(struct content *c, struct content *parent,
const char *params[]);
bool nsgif_create(struct content *c, const struct http_parameter *params);
bool nsgif_convert(struct content *c, int width, int height);
void nsgif_destroy(struct content *c);
bool nsgif_redraw(struct content *c, int x, int y,

View File

@ -29,7 +29,8 @@
#include <stdlib.h>
#include <libnsbmp.h>
#include "utils/config.h"
#include "content/content.h"
#include "content/content_protected.h"
#include "content/hlcache.h"
#include "desktop/plotters.h"
#include "image/bitmap.h"
#include "image/ico.h"
@ -37,8 +38,7 @@
#include "utils/messages.h"
#include "utils/utils.h"
bool nsico_create(struct content *c, struct content *parent,
const char *params[])
bool nsico_create(struct content *c, const struct http_parameter *params)
{
union content_msg_data msg_data;
c->data.ico.ico = calloc(sizeof(ico_collection), 1);
@ -58,26 +58,29 @@ bool nsico_convert(struct content *c, int iwidth, int iheight)
bmp_result res;
ico_collection *ico;
union content_msg_data msg_data;
const char *data;
unsigned long size;
/* set the ico data */
ico = c->data.ico.ico;
data = content__get_source_data(c, &size);
/* analyse the ico */
res = ico_analyse(ico, c->source_size, (unsigned char *)
c->source_data);
res = ico_analyse(ico, size, (unsigned char *) data);
switch (res) {
case BMP_OK:
break;
case BMP_INSUFFICIENT_MEMORY:
msg_data.error = messages_get("NoMemory");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
case BMP_INSUFFICIENT_DATA:
case BMP_DATA_ERROR:
msg_data.error = messages_get("BadICO");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
case BMP_OK:
break;
case BMP_INSUFFICIENT_MEMORY:
msg_data.error = messages_get("NoMemory");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
case BMP_INSUFFICIENT_DATA:
case BMP_DATA_ERROR:
msg_data.error = messages_get("BadICO");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
/* Store our content width and description */
@ -86,7 +89,7 @@ bool nsico_convert(struct content *c, int iwidth, int iheight)
c->title = malloc(100);
if (c->title)
snprintf(c->title, 100, messages_get("ICOTitle"), c->width,
c->height, c->source_size);
c->height, size);
c->size += (ico->width * ico->height * 4) + 16 + 44 + 100;
/* exit as a success */
@ -117,14 +120,22 @@ bool nsico_redraw(struct content *c, int x, int y,
/** sets the bitmap for an ico according to the dimensions */
bool nsico_set_bitmap_from_size(struct content *c, int width, int height)
bool nsico_set_bitmap_from_size(hlcache_handle *h, int width, int height)
{
struct bmp_image *bmp = ico_find(c->data.ico.ico, width, height);
struct content *c = hlcache_handle_get_content(h);
struct bmp_image *bmp;
assert(c != NULL);
bmp = ico_find(c->data.ico.ico, width, height);
if (bmp == NULL)
return false;
if ((bmp->decoded == false) && (bmp_decode(bmp) != BMP_OK))
return false;
c->bitmap = bmp->bitmap;
return true;
}

View File

@ -30,13 +30,14 @@
#include <libnsbmp.h>
struct content;
struct hlcache_handle;
struct http_parameter;
struct content_ico_data {
struct ico_collection *ico; /** ICO collection data */
};
bool nsico_create(struct content *c, struct content *parent,
const char *params[]);
bool nsico_create(struct content *c, const struct http_parameter *params);
bool nsico_convert(struct content *c, int width, int height);
void nsico_destroy(struct content *c);
bool nsico_redraw(struct content *c, int x, int y,
@ -48,7 +49,8 @@ bool nsico_redraw_tiled(struct content *c, int x, int y,
int clip_x0, int clip_y0, int clip_x1, int clip_y1,
float scale, colour background_colour,
bool repeat_x, bool repeat_y);
bool nsico_set_bitmap_from_size(struct content *c, int width, int height);
bool nsico_set_bitmap_from_size(struct hlcache_handle *h,
int width, int height);
#endif /* WITH_BMP */

View File

@ -27,7 +27,7 @@
#ifdef WITH_JPEG
/* This must come first due to libpng issues */
#include "content/content.h"
#include "content/content_protected.h"
#include <assert.h>
#include <setjmp.h>
@ -89,6 +89,10 @@ bool nsjpeg_convert(struct content *c, int w, int h)
uint8_t * volatile pixels = NULL;
size_t rowstride;
union content_msg_data msg_data;
const char *data;
unsigned long size;
data = content__get_source_data(c, &size);
cinfo.err = jpeg_std_error(&jerr.pub);
jerr.pub.error_exit = nsjpeg_error_exit;
@ -102,8 +106,8 @@ bool nsjpeg_convert(struct content *c, int w, int h)
return false;
}
jpeg_create_decompress(&cinfo);
source_mgr.next_input_byte = (unsigned char *) c->source_data;
source_mgr.bytes_in_buffer = c->source_size;
source_mgr.next_input_byte = (unsigned char *) data;
source_mgr.bytes_in_buffer = size;
cinfo.src = &source_mgr;
jpeg_read_header(&cinfo, TRUE);
cinfo.out_color_space = JCS_RGB;
@ -161,7 +165,7 @@ bool nsjpeg_convert(struct content *c, int w, int h)
c->title = malloc(100);
if (c->title)
snprintf(c->title, 100, messages_get("JPEGTitle"),
width, height, c->source_size);
width, height, size);
c->size += height * rowstride + 100;
c->status = CONTENT_STATUS_DONE;
/* Done: update status bar */

View File

@ -24,7 +24,7 @@
#ifdef WITH_MNG
/* This must come first due to libpng issues */
#include "content/content.h"
#include "content/content_protected.h"
#include <assert.h>
#include <stdbool.h>
@ -69,8 +69,7 @@ static void nsmng_free(mng_ptr p, mng_size_t n);
#endif
bool nsmng_create(struct content *c, struct content *parent,
const char *params[])
bool nsmng_create(struct content *c, const struct http_parameter *params)
{
mng_retcode code;
union content_msg_data msg_data;
@ -179,6 +178,8 @@ mng_bool nsmng_readdata(mng_handle mng, mng_ptr buffer, mng_uint32 size,
mng_uint32 *bytesread)
{
struct content *c;
const char *data;
unsigned long data_size;
assert(mng != NULL);
assert(buffer != NULL);
@ -186,17 +187,18 @@ mng_bool nsmng_readdata(mng_handle mng, mng_ptr buffer, mng_uint32 size,
/* Get our content back
*/
c = (struct content *)mng_get_userdata(mng);
c = (struct content *) mng_get_userdata(mng);
assert(c != NULL);
/* Copy any data we have (maximum of 'size')
*/
*bytesread = ((c->source_size - c->data.mng.read_size) < size) ?
(c->source_size - c->data.mng.read_size) : size;
data = content__get_source_data(c, &data_size);
*bytesread = ((data_size - c->data.mng.read_size) < size) ?
(data_size - c->data.mng.read_size) : size;
if ((*bytesread) > 0) {
memcpy(buffer, c->source_data + c->data.mng.read_size,
*bytesread);
memcpy(buffer, data + c->data.mng.read_size, *bytesread);
c->data.mng.read_size += *bytesread;
}
@ -302,9 +304,13 @@ bool nsmng_convert(struct content *c, int width, int height)
mng_retcode status;
union content_msg_data msg_data;
const char *data;
unsigned long size;
assert(c != NULL);
data = content__get_source_data(c, &size);
/* by this point, the png should have been parsed
* and the bitmap created, so ensure that's the case
*/
@ -322,13 +328,13 @@ bool nsmng_convert(struct content *c, int width, int height)
if (c->type == CONTENT_MNG) {
snprintf(c->title, 100, messages_get("MNGTitle"),
c->width, c->height, c->source_size);
c->width, c->height, size);
} else if (c->type == CONTENT_PNG) {
snprintf(c->title, 100, messages_get("PNGTitle"),
c->width, c->height, c->source_size);
c->width, c->height, size);
} else {
snprintf(c->title, 100, messages_get("JNGTitle"),
c->width, c->height, c->source_size);
c->width, c->height, size);
}
c->size += c->width * c->height * 4 + 100;
@ -658,7 +664,8 @@ mng_bool nsmng_errorproc(mng_handle mng, mng_int32 code,
chunk[3] = (char)((chunktype ) & 0xFF);
chunk[4] = '\0';
LOG(("error playing '%s' chunk %s (%d):", c->url, chunk, chunkseq));
LOG(("error playing '%s' chunk %s (%d):",
content__get_url(c), chunk, chunkseq));
LOG(("code %d severity %d extra1 %d extra2 %d text:'%s'", code,
severity, extra1, extra2, text));

View File

@ -29,6 +29,7 @@
#include <stdbool.h>
struct content;
struct http_parameter;
struct content_mng_data {
bool opaque_test_pending;
@ -40,8 +41,7 @@ struct content_mng_data {
void *handle;
};
bool nsmng_create(struct content *c, struct content *parent,
const char *params[]);
bool nsmng_create(struct content *c, const struct http_parameter *params);
bool nsmng_process_data(struct content *c, char *data, unsigned int size);
bool nsmng_convert(struct content *c, int width, int height);
void nsmng_destroy(struct content *c);

View File

@ -31,7 +31,7 @@
#include "utils/config.h"
#include "desktop/plotters.h"
#include "image/bitmap.h"
#include "content/content.h"
#include "content/content_protected.h"
#include "utils/log.h"
#include "utils/messages.h"
#include "utils/utils.h"
@ -61,8 +61,13 @@ bool nssprite_convert(struct content *c, int width, int height)
union content_msg_data msg_data;
struct rosprite_mem_context* ctx;
ERRCHK(rosprite_create_mem_context((uint8_t *) c->source_data,
c->source_size, &ctx));
const char *data;
unsigned long size;
data = content__get_source_data(c, &size);
ERRCHK(rosprite_create_mem_context((uint8_t *) data, size, &ctx));
struct rosprite_area* sprite_area;
ERRCHK(rosprite_load(rosprite_mem_reader, ctx, &sprite_area));

View File

@ -30,7 +30,7 @@
#include "desktop/plotters.h"
#include "content/content.h"
#include "content/content_protected.h"
#include "image/bitmap.h"
@ -62,8 +62,7 @@ static void row_callback(png_structp png, png_bytep new_row,
static void end_callback(png_structp png, png_infop info);
bool nspng_create(struct content *c, struct content *parent,
const char *params[])
bool nspng_create(struct content *c, const struct http_parameter *params)
{
union content_msg_data msg_data;
@ -264,16 +263,21 @@ void end_callback(png_structp png, png_infop info)
bool nspng_convert(struct content *c, int width, int height)
{
const char *data;
unsigned long size;
assert(c->data.png.png != NULL);
assert(c->data.png.info != NULL);
data = content__get_source_data(c, &size);
png_destroy_read_struct(&c->data.png.png, &c->data.png.info, 0);
c->title = malloc(NSPNG_TITLE_LEN);
if (c->title != NULL) {
snprintf(c->title, NSPNG_TITLE_LEN, messages_get("PNGTitle"),
c->width, c->height, c->source_size);
c->width, c->height, size);
}
c->size += (c->width * c->height * 4) + NSPNG_TITLE_LEN;

View File

@ -31,6 +31,7 @@
struct content;
struct bitmap;
struct http_parameter;
struct content_png_data {
png_structp png;
@ -41,8 +42,7 @@ struct content_png_data {
size_t rowbytes; /**< Number of bytes per row */
};
bool nspng_create(struct content *c, struct content *parent,
const char *params[]);
bool nspng_create(struct content *c, const struct http_parameter *params);
bool nspng_process_data(struct content *c, char *data, unsigned int size);
bool nspng_convert(struct content *c, int width, int height);
void nspng_destroy(struct content *c);

View File

@ -38,7 +38,7 @@
#include <librsvg/rsvg-cairo.h>
#include "image/rsvg.h"
#include "content/content.h"
#include "content/content_protected.h"
#include "desktop/plotters.h"
#include "image/bitmap.h"
#include "utils/log.h"
@ -49,8 +49,7 @@
static inline void rsvg_argb_to_abgr(uint32_t pixels[], int width, int height,
size_t rowstride);
bool rsvg_create(struct content *c, struct content *parent,
const char *params[])
bool rsvg_create(struct content *c, const struct http_parameter *params)
{
struct content_rsvg_data *d = &c->data.rsvg;
union content_msg_data msg_data;

View File

@ -33,6 +33,7 @@
#include "image/bitmap.h"
struct content;
struct http_parameter;
struct content_rsvg_data {
RsvgHandle *rsvgh; /**< Context handle for RSVG renderer */
@ -41,8 +42,7 @@ struct content_rsvg_data {
struct bitmap *bitmap; /**< Created NetSurf bitmap */
};
bool rsvg_create(struct content *c, struct content *parent,
const char *params[]);
bool rsvg_create(struct content *c, const struct http_parameter *params);
bool rsvg_process_data(struct content *c, char *data, unsigned int size);
bool rsvg_convert(struct content *c, int width, int height);
void rsvg_destroy(struct content *c);

View File

@ -40,7 +40,7 @@
* Create a CONTENT_SVG.
*/
bool svg_create(struct content *c, struct content *parent, const char *params[])
bool svg_create(struct content *c, const struct http_parameter *params)
{
union content_msg_data msg_data;

View File

@ -26,14 +26,14 @@
#include <stdbool.h>
struct content;
struct http_parameter;
struct svgtiny_diagram;
struct content_svg_data {
struct svgtiny_diagram *diagram;
};
bool svg_create(struct content *c, struct content *parent,
const char *params[]);
bool svg_create(struct content *c, const struct http_parameter *params);
bool svg_convert(struct content *c, int width, int height);
void svg_destroy(struct content *c);
bool svg_redraw(struct content *c, int x, int y,

View File

@ -26,7 +26,8 @@
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include "content/content.h"
#include "content/content_protected.h"
#include "content/hlcache.h"
#include "css/css.h"
#include "css/dump.h"
#include "desktop/scroll.h"
@ -312,7 +313,7 @@ void box_bounds(struct box *box, struct rect *r)
struct box *box_at_point(struct box *box, const int x, const int y,
int *box_x, int *box_y,
struct content **content)
hlcache_handle **content)
{
int bx = *box_x, by = *box_y;
struct box *child, *sibling;
@ -321,11 +322,14 @@ struct box *box_at_point(struct box *box, const int x, const int y,
assert(box);
/* drill into HTML objects */
if (box->object) {
if (box->object->type == CONTENT_HTML &&
box->object->data.html.layout) {
if (box->object != NULL) {
struct box *layout;
if (content_get_type(box->object) == CONTENT_HTML &&
(layout = html_get_box_tree(box->object)) !=
NULL) {
*content = box->object;
box = box->object->data.html.layout;
box = layout;
} else {
goto siblings;
}
@ -503,20 +507,24 @@ bool box_contains_point(struct box *box, int x, int y, bool *physically)
/**
* Find the box containing an object at the given coordinates, if any.
*
* \param c content to search, must have type CONTENT_HTML
* \param h content to search, must have type CONTENT_HTML
* \param x coordinates in document units
* \param y coordinates in document units
*/
struct box *box_object_at_point(struct content *c, int x, int y)
struct box *box_object_at_point(hlcache_handle *h, int x, int y)
{
struct box *box = c->data.html.layout;
struct content *c = hlcache_handle_get_content(h);
struct box *box;
int box_x = 0, box_y = 0;
struct content *content = c;
hlcache_handle *content = h;
struct box *object_box = 0;
assert(c != NULL);
assert(c->type == CONTENT_HTML);
box = c->data.html.layout;
while ((box = box_at_point(box, x, y, &box_x, &box_y, &content))) {
if (box->style && css_computed_visibility(box->style) ==
CSS_VISIBILITY_HIDDEN)
@ -533,20 +541,24 @@ struct box *box_object_at_point(struct content *c, int x, int y)
/**
* Find the box containing an href at the given coordinates, if any.
*
* \param c content to search, must have type CONTENT_HTML
* \param h content to search, must have type CONTENT_HTML
* \param x coordinates in document units
* \param y coordinates in document units
*/
struct box *box_href_at_point(struct content *c, int x, int y)
struct box *box_href_at_point(hlcache_handle *h, int x, int y)
{
struct box *box = c->data.html.layout;
struct content *c = hlcache_handle_get_content(h);
struct box *box;
int box_x = 0, box_y = 0;
struct content *content = c;
hlcache_handle *content = h;
struct box *href_box = 0;
assert(c != NULL);
assert(c->type == CONTENT_HTML);
box = c->data.html.layout;
while ((box = box_at_point(box, x, y, &box_x, &box_y, &content))) {
if (box->style && css_computed_visibility(box->style) ==
CSS_VISIBILITY_HIDDEN)
@ -663,8 +675,10 @@ void box_dump(FILE *stream, struct box *box, unsigned int depth)
(int) box->length, box->text);
if (box->space)
fprintf(stream, "space ");
if (box->object)
fprintf(stream, "(object '%s') ", box->object->url);
if (box->object) {
fprintf(stream, "(object '%s') ",
content_get_url(box->object));
}
if (box->gadget)
fprintf(stream, "(gadget) ");
if (box->style)
@ -860,42 +874,42 @@ bool box_duplicate_main_tree(struct box *box, struct content *c, int *count)
box->last = prev;
if (box->object && option_suppress_images && (
if (box->object != NULL && option_suppress_images && (
#ifdef WITH_JPEG
box->object->type == CONTENT_JPEG ||
content_get_type(box->object) == CONTENT_JPEG ||
#endif
#ifdef WITH_GIF
box->object->type == CONTENT_GIF ||
content_get_type(box->object) == CONTENT_GIF ||
#endif
#ifdef WITH_BMP
box->object->type == CONTENT_BMP ||
box->object->type == CONTENT_ICO ||
content_get_type(box->object) == CONTENT_BMP ||
content_get_type(box->object) == CONTENT_ICO ||
#endif
#if defined(WITH_MNG) || defined(WITH_PNG)
box->object->type == CONTENT_PNG ||
content_get_type(box->object) == CONTENT_PNG ||
#endif
#ifdef WITH_MNG
box->object->type == CONTENT_JNG ||
box->object->type == CONTENT_MNG ||
content_get_type(box->object) == CONTENT_JNG ||
content_get_type(box->object) == CONTENT_MNG ||
#endif
#if defined(WITH_SPRITE) || defined(WITH_NSSPRITE)
box->object->type == CONTENT_SPRITE ||
content_get_type(box->object) == CONTENT_SPRITE ||
#endif
#ifdef WITH_DRAW
box->object->type == CONTENT_DRAW ||
content_get_type(box->object) == CONTENT_DRAW ||
#endif
#ifdef WITH_PLUGIN
box->object->type == CONTENT_PLUGIN ||
content_get_type(box->object) == CONTENT_PLUGIN ||
#endif
box->object->type == CONTENT_DIRECTORY ||
content_get_type(box->object) == CONTENT_DIRECTORY ||
#ifdef WITH_THEME_INSTALL
box->object->type == CONTENT_THEME ||
content_get_type(box->object) == CONTENT_THEME ||
#endif
#ifdef WITH_ARTWORKS
box->object->type == CONTENT_ARTWORKS ||
content_get_type(box->object) == CONTENT_ARTWORKS ||
#endif
#if defined(WITH_NS_SVG) || defined(WITH_RSVG)
box->object->type == CONTENT_SVG ||
content_get_type(box->object) == CONTENT_SVG ||
#endif
false))
box->object = NULL;

View File

@ -239,10 +239,10 @@ struct box {
char *id; /**< value of id attribute (or name for anchors) */
/** Background image for this box, or 0 if none */
struct content *background;
struct hlcache_handle *background;
/** Object in this box (usually an image), or 0 if none. */
struct content* object;
struct hlcache_handle* object;
/** Parameters for the object, or 0. */
struct object_params *object_params;
};
@ -307,9 +307,9 @@ void box_free_object_params(struct object_params *op);
void box_bounds(struct box *box, struct rect *r);
void box_coords(struct box *box, int *x, int *y);
struct box *box_at_point(struct box *box, const int x, const int y,
int *box_x, int *box_y, struct content **content);
struct box *box_object_at_point(struct content *c, int x, int y);
struct box *box_href_at_point(struct content *c, int x, int y);
int *box_x, int *box_y, struct hlcache_handle **content);
struct box *box_object_at_point(struct hlcache_handle *h, int x, int y);
struct box *box_href_at_point(struct hlcache_handle *h, int x, int y);
struct box *box_find_by_id(struct box *box, const char *id);
bool box_visible(struct box *box);
void box_dump(FILE *stream, struct box *box, unsigned int depth);

View File

@ -35,7 +35,7 @@
#include <libxml/HTMLparser.h>
#include <libxml/parserInternals.h>
#include "utils/config.h"
#include "content/content.h"
#include "content/content_protected.h"
#include "css/css.h"
#include "css/utils.h"
#include "css/select.h"
@ -841,9 +841,9 @@ css_computed_style *box_get_style(struct content *c,
if ((s = (char *) xmlGetProp(n, (const xmlChar *) "style"))) {
inline_style = nscss_create_inline_style(
(uint8_t *) s, strlen(s),
c->data.html.encoding, c->url,
c->data.html.encoding, content__get_url(c),
c->data.html.quirks != BINDING_QUIRKS_MODE_NONE,
c->data.html.dict, myrealloc, c);
myrealloc, c);
xmlFree(s);

View File

@ -28,7 +28,7 @@
#include <stdlib.h>
#include <sys/stat.h>
#include <time.h>
#include "content/content.h"
#include "content/content_protected.h"
#include "render/directory.h"
#include "render/html.h"
#include "utils/messages.h"
@ -40,9 +40,8 @@ static const char header[] = "<html>\n<head>\n<title>\n";
static const char footer[] = "</pre>\n</body>\n</html>\n";
bool directory_create(struct content *c, struct content *parent,
const char *params[]) {
if (!html_create(c, parent, params))
bool directory_create(struct content *c, const struct http_parameter *params) {
if (!html_create(c, params))
/* html_create() must have broadcast MSG_ERROR already, so we
* don't need to. */
return false;
@ -64,7 +63,7 @@ bool directory_convert(struct content *c, int width, int height) {
bool compare;
char *up;
path = url_to_path(c->url);
path = url_to_path(content__get_url(c));
if (!path) {
msg_data.error = messages_get("NoMemory");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
@ -100,9 +99,9 @@ bool directory_convert(struct content *c, int width, int height) {
binding_parse_chunk(c->data.html.parser_binding,
(uint8_t *) buffer, strlen(buffer));
res = url_parent(c->url, &up);
res = url_parent(content__get_url(c), &up);
if (res == URL_FUNC_OK) {
res = url_compare(c->url, up, false, &compare);
res = url_compare(content__get_url(c), up, false, &compare);
if ((res == URL_FUNC_OK) && !compare) {
snprintf(buffer, sizeof(buffer),
"<a href=\"..\">[..]</a>\n");
@ -124,7 +123,8 @@ bool directory_convert(struct content *c, int width, int height) {
continue;
snprintf(buffer, sizeof(buffer), "<a href=\"%s/%s\">%s</a>\n",
c->url, entry->d_name, entry->d_name);
content__get_url(c), entry->d_name,
entry->d_name);
binding_parse_chunk(c->data.html.parser_binding,
(uint8_t *) buffer, strlen(buffer));

View File

@ -28,9 +28,9 @@
#include <stdbool.h>
#include "content/content_type.h"
struct http_parameter;
bool directory_create(struct content *c, struct content *parent,
const char *params[]);
bool directory_create(struct content *c, const struct http_parameter *params);
bool directory_convert(struct content *c, int width, int height);
void directory_destroy(struct content *c);

View File

@ -18,8 +18,8 @@
*/
#include <string.h>
#include "content/fetch.h"
#include "content/fetchcache.h"
#include "content/content_protected.h"
#include "content/hlcache.h"
#include "render/favicon.h"
#include "render/html.h"
#include "utils/log.h"
@ -29,8 +29,8 @@
#include "utils/utils.h"
static char *favicon_get_icon_ref(struct content *c, xmlNode *html);
static void favicon_callback(content_msg msg, struct content *icon,
intptr_t p1, intptr_t p2, union content_msg_data data);
static nserror favicon_callback(hlcache_handle *icon,
const hlcache_event *event, void *pw);
/**
* retrieve 1 url reference to 1 favicon
@ -39,68 +39,80 @@ static void favicon_callback(content_msg msg, struct content *icon,
*/
char *favicon_get_icon_ref(struct content *c, xmlNode *html)
{
xmlNode *node;
char *rel, *href, *url, *url2;
xmlNode *node = html;
char *rel, *href, *url, *url2 = NULL;
url_func_result res;
union content_msg_data msg_data;
url2 = NULL;
node = html;
while (node) {
if (node->children) { /* children */
if (node->children != NULL) { /* children */
node = node->children;
} else if (node->next) { /* siblings */
} else if (node->next != NULL) { /* siblings */
node = node->next;
} else { /* ancestor siblings */
while (node && !node->next)
while (node != NULL && node->next == NULL)
node = node->parent;
if (!node)
if (node == NULL)
break;
node = node->next;
}
assert(node);
assert(node != NULL);
if (node->type != XML_ELEMENT_NODE)
continue;
if (strcmp((const char *) node->name, "link") == 0) {
/* rel=<space separated list, including 'icon'> */
if ((rel = (char *) xmlGetProp(node,
(const xmlChar *) "rel")) == NULL)
continue;
if (strcasestr(rel, "icon") == 0) {
xmlFree(rel);
continue;
}
LOG(("icon node found"));
if (strcasecmp(rel, "apple-touch-icon") == 0) {
xmlFree(rel);
continue;
}
xmlFree(rel);
if (( href = (char *) xmlGetProp(node,
if ((href = (char *) xmlGetProp(node,
(const xmlChar *) "href")) == NULL)
continue;
res = url_join(href, c->data.html.base_url,
&url);
res = url_join(href, c->data.html.base_url, &url);
xmlFree(href);
if (res != URL_FUNC_OK)
continue;
LOG(("most recent favicon '%s'", url));
if (url2 != NULL) {
free(url2);
url2 = NULL;
}
res = url_normalize(url, &url2);
free(url);
if (res != URL_FUNC_OK) {
url2 = NULL;
if (res == URL_FUNC_NOMEM)
goto no_memory;
return NULL;
continue;
}
}
}
if (url2 == NULL) {
char *scheme;
@ -123,12 +135,8 @@ char *favicon_get_icon_ref(struct content *c, xmlNode *html)
!= URL_FUNC_OK)
return NULL;
}
LOG(("favicon %s", url2));
return url2;
no_memory:
msg_data.error = messages_get("NoMemory");
/* content_broadcast(c, CONTENT_MSG_ERROR, msg_data); */
return false;
}
/**
@ -140,31 +148,27 @@ no_memory:
bool favicon_get_icon(struct content *c, xmlNode *html)
{
char *url = favicon_get_icon_ref(c, html);
struct content *favcontent = NULL;
char *url;
nserror error;
url = favicon_get_icon_ref(c, html);
if (url == NULL)
return false;
favcontent = fetchcache(url, favicon_callback, (intptr_t) c, 0,
c->width, c->height, true, 0, 0, false, false);
error = hlcache_handle_retrieve(url, 0, NULL, NULL, c->width, c->height,
favicon_callback, c, NULL, &c->data.html.favicon);
free(url);
if (favcontent == NULL)
return false;
c->data.html.favicon = favcontent;
fetchcache_go(favcontent, c->url, favicon_callback, (intptr_t) c, 0,
c->width, c->height, 0, 0, false, c);
return true;
return error == NSERROR_OK;
}
/**
* Callback for fetchcache() for linked favicon
*/
void favicon_callback(content_msg msg, struct content *icon,
intptr_t p1, intptr_t p2, union content_msg_data data)
nserror favicon_callback(hlcache_handle *icon,
const hlcache_event *event, void *pw)
{
static const content_type permitted_types[] = {
#ifdef WITH_BMP
@ -178,88 +182,57 @@ void favicon_callback(content_msg msg, struct content *icon,
#endif
CONTENT_UNKNOWN
};
struct content *c = (struct content *) p1;
unsigned int i = p2;
struct content *c = pw;
const content_type *type;
switch (msg) {
switch (event->type) {
case CONTENT_MSG_LOADING:
/* check that the favicon is really a correct image type */
for (type = permitted_types; *type != CONTENT_UNKNOWN; type++)
if (icon->type == *type)
if (content_get_type(icon) == *type)
break;
if (*type == CONTENT_UNKNOWN) {
c->data.html.favicon = 0;
LOG(("%s is not a favicon", icon->url));
union content_msg_data msg_data;
hlcache_handle_release(c->data.html.favicon);
c->data.html.favicon = NULL;
LOG(("%s is not a favicon", content_get_url(icon)));
content_add_error(c, "NotFavIco", 0);
html_set_status(c, messages_get("NotFavIco"));
content_broadcast(c, CONTENT_MSG_STATUS, data);
content_remove_user(icon,
favicon_callback,
(intptr_t) c, i);
if (!icon->user_list->next) {
/* we were the only user and we don't want this
* content, so stop it fetching and mark it as
* having an error so it gets removed from the
* cache next time content_clean() gets called
*/
fetch_abort(icon->fetch);
icon->fetch = 0;
icon->status = CONTENT_STATUS_ERROR;
}
msg_data.error = messages_get("NotFavIco");
content_broadcast(c, CONTENT_MSG_STATUS, msg_data);
}
break;
case CONTENT_MSG_READY:
break;
case CONTENT_MSG_DONE:
LOG(("got favicon '%s'", icon->url));
break;
case CONTENT_MSG_LAUNCH:
/* Fall through */
case CONTENT_MSG_DONE:
break;
case CONTENT_MSG_ERROR:
LOG(("favicon %s failed: %s", icon->url, data.error));
/* The favicon we were fetching may have been
* redirected, in that case, the object pointers
* will differ, so ensure that the object that's
* in error is still in use by us before invalidating
* the pointer */
if (c->data.html.favicon == icon) {
c->data.html.favicon = 0;
content_add_error(c, "?", 0);
}
LOG(("favicon %s failed: %s",
content_get_url(icon), event->data.error));
hlcache_handle_release(c->data.html.favicon);
c->data.html.favicon = NULL;
content_add_error(c, "?", 0);
break;
case CONTENT_MSG_STATUS:
html_set_status(c, icon->status_message);
content_broadcast(c, CONTENT_MSG_STATUS, data);
content_broadcast(c, CONTENT_MSG_STATUS, event->data);
break;
case CONTENT_MSG_NEWPTR:
c->data.html.favicon = icon;
break;
case CONTENT_MSG_AUTH:
c->data.html.favicon = 0;
content_add_error(c, "?", 0);
break;
case CONTENT_MSG_SSL:
c->data.html.favicon = 0;
content_add_error(c, "?", 0);
break;
case CONTENT_MSG_REDRAW:
/* currently no support for favicon animations */
/* Fall through */
case CONTENT_MSG_REFRESH:
break;
/* Fall through */
case CONTENT_MSG_REFORMAT:
/* would be unusual :) */
break;
default:
assert(0);
}
return NSERROR_OK;
}

View File

@ -20,7 +20,8 @@
#define _NETSURF_RENDER_FAVICON_H_
#include <libxml/tree.h>
#include "content/content.h"
struct content;
bool favicon_get_icon(struct content *c, xmlNode *html);

View File

@ -30,6 +30,7 @@
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include "content/fetch.h"
#include "css/css.h"
#include "css/utils.h"
#include "desktop/gui.h"
@ -308,18 +309,18 @@ bool form_add_option(struct form_control *control, char *value, char *text,
* \param form form to search for successful controls
* \param submit_button control used to submit the form, if any
* \param successful_controls updated to point to linked list of
* form_successful_control, 0 if no controls
* fetch_multipart_data, 0 if no controls
* \return true on success, false on memory exhaustion
*
* See HTML 4.01 section 17.13.2.
*/
bool form_successful_controls(struct form *form,
struct form_control *submit_button,
struct form_successful_control **successful_controls)
struct fetch_multipart_data **successful_controls)
{
struct form_control *control;
struct form_option *option;
struct form_successful_control sentinel, *last_success, *success_new;
struct fetch_multipart_data sentinel, *last_success, *success_new;
char *value = NULL;
bool had_submit = false;
char *charset;
@ -603,7 +604,7 @@ bool form_successful_controls(struct form *form,
no_memory:
warn_user("NoMemory", 0);
form_free_successful(sentinel.next);
fetch_multipart_data_destroy(sentinel.next);
return false;
#undef ENCODE_ITEM
@ -659,12 +660,12 @@ char *form_textarea_value(struct form_control *textarea)
* Encode controls using application/x-www-form-urlencoded.
*
* \param form form to which successful controls relate
* \param control linked list of form_successful_control
* \param control linked list of fetch_multipart_data
* \return URL-encoded form, or 0 on memory exhaustion
*/
char *form_url_encode(struct form *form,
struct form_successful_control *control)
struct fetch_multipart_data *control)
{
char *name, *value;
char *s = malloc(1), *s2;
@ -713,24 +714,6 @@ char *form_url_encode(struct form *form,
return s;
}
/**
* Free a linked list of form_successful_control.
*
* \param control Pointer to head of list to free
*/
void form_free_successful(struct form_successful_control *control)
{
struct form_successful_control *next;
for (; control; control = next) {
next = control->next;
free(control->name);
free(control->value);
free(control);
}
}
/**
* Find an acceptable character set encoding with which to submit the form
*

View File

@ -125,14 +125,6 @@ struct form_option {
struct form_option* next;
};
/** Successful control, as defined by HTML 4.01 17.13. */
struct form_successful_control {
bool file; /**< It's a file */
char *name; /**< Control name. */
char *value; /**< Current value. */
struct form_successful_control *next; /**< Next in linked list. */
};
/**
* Called by the select menu when it wants an area to be redrawn. The
* coordinates are menu origin relative.
@ -157,10 +149,9 @@ bool form_add_option(struct form_control *control, char *value, char *text,
bool selected);
bool form_successful_controls(struct form *form,
struct form_control *submit_button,
struct form_successful_control **successful_controls);
struct fetch_multipart_data **successful_controls);
char *form_url_encode(struct form *form,
struct form_successful_control *control);
void form_free_successful(struct form_successful_control *control);
struct fetch_multipart_data *control);
bool form_open_select_menu(void *client_data,
struct form_control *control,

File diff suppressed because it is too large Load Diff

View File

@ -31,11 +31,13 @@
#include "desktop/plot_style.h"
#include "render/parser_binding.h"
struct fetch_multipart_data;
struct box;
struct rect;
struct browser_window;
struct content;
struct form_successful_control;
struct hlcache_handle;
struct http_parameter;
struct imagemap;
struct object_params;
struct plotters;
@ -50,6 +52,18 @@ extern char *default_stylesheet_url;
extern char *adblock_stylesheet_url;
extern char *quirks_stylesheet_url;
/**
* Container for stylesheets used by an HTML document
*/
struct html_stylesheet {
/** Type of sheet */
enum { HTML_STYLESHEET_EXTERNAL, HTML_STYLESHEET_INTERNAL } type;
union {
struct hlcache_handle *external;
struct content_css_data *internal;
} data; /**< Sheet data */
};
struct frame_dimension {
float value;
enum {
@ -68,7 +82,7 @@ typedef enum {
/** An object (<img>, <object>, etc.) in a CONTENT_HTML document. */
struct content_html_object {
struct content *content; /**< Content, or 0. */
struct hlcache_handle *content; /**< Content, or 0. */
struct box *box; /**< Node in box tree containing it. */
/** Pointer to array of permitted content_type, terminated by
* CONTENT_UNKNOWN, or 0 if any type is acceptable. */
@ -120,8 +134,6 @@ struct content_html_data {
xmlDoc *document;
binding_quirks_mode quirks; /**< Quirkyness of document */
lwc_context *dict; /**< Internment context for this document */
char *encoding; /**< Encoding of source, 0 if unknown. */
binding_encoding_source encoding_source;
/**< Source of encoding information. */
@ -133,12 +145,12 @@ struct content_html_data {
colour background_colour; /**< Document background colour. */
const struct font_functions *font_func;
struct content *favicon; /**< the favicon for the page */
struct hlcache_handle *favicon; /**< the favicon for the page */
/** Number of entries in stylesheet_content. */
unsigned int stylesheet_count;
/** Stylesheets. Each may be 0. */
struct nscss_import *stylesheets;
struct html_stylesheet *stylesheets;
/**< Style selection context */
css_select_ctx *select_ctx;
@ -173,8 +185,7 @@ struct content_html_data {
extern bool html_redraw_debug;
bool html_create(struct content *c, struct content *parent,
const char *params[]);
bool html_create(struct content *c, const struct http_parameter *params);
bool html_process_data(struct content *c, char *data, unsigned int size);
bool html_convert(struct content *c, int width, int height);
void html_reformat(struct content *c, int width, int height);
@ -183,9 +194,6 @@ bool html_fetch_object(struct content *c, const char *url, struct box *box,
const content_type *permitted_types,
int available_width, int available_height,
bool background);
bool html_replace_object(struct content *c, unsigned int i, char *url,
char *post_urlenc,
struct form_successful_control *post_multipart);
void html_stop(struct content *c);
void html_open(struct content *c, struct browser_window *bw,
struct content *page, unsigned int index, struct box *box,
@ -212,4 +220,17 @@ bool text_redraw(const char *utf8_text, size_t utf8_len,
float scale,
bool excluded);
xmlDoc *html_get_document(struct hlcache_handle *h);
struct box *html_get_box_tree(struct hlcache_handle *h);
const char *html_get_encoding(struct hlcache_handle *h);
struct content_html_frames *html_get_frameset(struct hlcache_handle *h);
struct content_html_iframe *html_get_iframe(struct hlcache_handle *h);
const char *html_get_base_url(struct hlcache_handle *h);
const char *html_get_base_target(struct hlcache_handle *h);
struct html_stylesheet *html_get_stylesheets(struct hlcache_handle *h,
unsigned int *n);
struct content_html_object *html_get_objects(struct hlcache_handle *h,
unsigned int *n);
struct hlcache_handle *html_get_favicon(struct hlcache_handle *h);
#endif

View File

@ -31,7 +31,7 @@
#include <string.h>
#include <math.h>
#include "utils/config.h"
#include "content/content.h"
#include "content/content_protected.h"
#include "css/css.h"
#include "css/utils.h"
#include "desktop/gui.h"
@ -1589,31 +1589,35 @@ bool html_redraw_background(int x, int y, struct box *box, float scale,
}
/* handle background-repeat */
switch (css_computed_background_repeat(background->style)) {
case CSS_BACKGROUND_REPEAT_REPEAT:
repeat_x = repeat_y = true;
/* optimisation: only plot the colour if
* bitmap is not opaque */
if (background->background->bitmap)
plot_colour = !bitmap_get_opaque(
background->background->bitmap);
break;
case CSS_BACKGROUND_REPEAT_REPEAT_X:
repeat_x = true;
break;
case CSS_BACKGROUND_REPEAT_REPEAT_Y:
repeat_y = true;
break;
case CSS_BACKGROUND_REPEAT_NO_REPEAT:
break;
default:
break;
case CSS_BACKGROUND_REPEAT_REPEAT:
{
struct bitmap *bmp = content_get_bitmap(
background->background);
repeat_x = repeat_y = true;
/* optimisation: only plot the colour if
* bitmap is not opaque */
if (bmp != NULL)
plot_colour = !bitmap_get_opaque(bmp);
}
break;
case CSS_BACKGROUND_REPEAT_REPEAT_X:
repeat_x = true;
break;
case CSS_BACKGROUND_REPEAT_REPEAT_Y:
repeat_y = true;
break;
case CSS_BACKGROUND_REPEAT_NO_REPEAT:
break;
default:
break;
}
/* handle background-position */
css_computed_background_position(background->style,
&hpos, &hunit, &vpos, &vunit);
if (hunit == CSS_UNIT_PCT) {
x += (width - background->background->width) *
x += (width -
content_get_width(background->background)) *
scale * FIXTOFLT(hpos) / 100.;
} else {
x += (int) (FIXTOFLT(nscss_len2px(hpos, hunit,
@ -1621,7 +1625,8 @@ bool html_redraw_background(int x, int y, struct box *box, float scale,
}
if (vunit == CSS_UNIT_PCT) {
y += (height - background->background->height) *
y += (height -
content_get_height(background->background)) *
scale * FIXTOFLT(vpos) / 100.;
} else {
y += (int) (FIXTOFLT(nscss_len2px(vpos, vunit,
@ -1651,6 +1656,8 @@ bool html_redraw_background(int x, int y, struct box *box, float scale,
for (; clip_box; clip_box = clip_box->next) {
/* clip to child boxes if needed */
if (clip_to_children) {
struct bitmap *bmp = NULL;
assert(clip_box->type == BOX_TABLE_CELL);
/* update clip_* to the child cell */
@ -1668,15 +1675,15 @@ bool html_redraw_background(int x, int y, struct box *box, float scale,
if (clip_x1 > px1) clip_x1 = px1;
if (clip_y1 > py1) clip_y1 = py1;
if (clip_box->background != NULL)
bmp = content_get_bitmap(clip_box->background);
/* <td> attributes override <tr> */
if ((clip_x0 >= clip_x1) || (clip_y0 >= clip_y1) ||
(css_computed_background_color(
clip_box->style, &bgcol) !=
CSS_BACKGROUND_COLOR_TRANSPARENT) ||
(clip_box->background &&
clip_box->background->bitmap &&
bitmap_get_opaque(
clip_box->background->bitmap)))
(bmp != NULL && bitmap_get_opaque(bmp)))
continue;
}
@ -1693,35 +1700,30 @@ bool html_redraw_background(int x, int y, struct box *box, float scale,
}
/* and plot the image */
if (plot_content) {
width = content_get_width(background->background);
height = content_get_height(background->background);
if (!repeat_x) {
if (clip_x0 < x)
clip_x0 = x;
if (clip_x1 > x +
background->background->width *
scale)
clip_x1 = x + background->background->
width * scale;
if (clip_x1 > x + width * scale)
clip_x1 = x + width * scale;
}
if (!repeat_y) {
if (clip_y0 < y)
clip_y0 = y;
if (clip_y1 > y +
background->background->height *
scale)
clip_y1 = y + background->background->
height * scale;
if (clip_y1 > y + height * scale)
clip_y1 = y + height * scale;
}
/* valid clipping rectangles only */
if ((clip_x0 < clip_x1) && (clip_y0 < clip_y1)) {
if (!plot.clip(clip_x0, clip_y0,
clip_x1, clip_y1))
return false;
if (!content_redraw_tiled(background->
background, x, y,
ceilf(background->background->
width * scale),
ceilf(background->background->
height * scale),
if (!content_redraw_tiled(
background->background, x, y,
ceilf(width * scale),
ceilf(height * scale),
clip_x0, clip_y0,
clip_x1, clip_y1,
scale, *background_colour,
@ -1784,32 +1786,35 @@ bool html_redraw_inline_background(int x, int y, struct box *box, float scale,
if (plot_content) {
/* handle background-repeat */
switch (css_computed_background_repeat(box->style)) {
case CSS_BACKGROUND_REPEAT_REPEAT:
repeat_x = repeat_y = true;
/* optimisation: only plot the colour if
* bitmap is not opaque */
if (box->background->bitmap)
plot_colour = !bitmap_get_opaque(
box->background->bitmap);
break;
case CSS_BACKGROUND_REPEAT_REPEAT_X:
repeat_x = true;
break;
case CSS_BACKGROUND_REPEAT_REPEAT_Y:
repeat_y = true;
break;
case CSS_BACKGROUND_REPEAT_NO_REPEAT:
break;
default:
break;
case CSS_BACKGROUND_REPEAT_REPEAT:
{
struct bitmap *bmp =
content_get_bitmap(box->background);
repeat_x = repeat_y = true;
/* optimisation: only plot the colour if
* bitmap is not opaque */
if (bmp != NULL)
plot_colour = !bitmap_get_opaque(bmp);
}
break;
case CSS_BACKGROUND_REPEAT_REPEAT_X:
repeat_x = true;
break;
case CSS_BACKGROUND_REPEAT_REPEAT_Y:
repeat_y = true;
break;
case CSS_BACKGROUND_REPEAT_NO_REPEAT:
break;
default:
break;
}
/* handle background-position */
css_computed_background_position(box->style,
&hpos, &hunit, &vpos, &vunit);
if (hunit == CSS_UNIT_PCT) {
x += (px1 - px0 - box->background->width * scale) *
FIXTOFLT(hpos) / 100.;
x += (px1 - px0 - content_get_width(box->background) *
scale) * FIXTOFLT(hpos) / 100.;
if (!repeat_x && ((hpos < 2 && !first) ||
(hpos > 98 && !last))){
@ -1821,8 +1826,8 @@ bool html_redraw_inline_background(int x, int y, struct box *box, float scale,
}
if (vunit == CSS_UNIT_PCT) {
y += (py1 - py0 - box->background->height * scale) *
FIXTOFLT(vpos) / 100.;
y += (py1 - py0 - content_get_height(box->background) *
scale) * FIXTOFLT(vpos) / 100.;
} else {
y += (int) (FIXTOFLT(nscss_len2px(vpos, vunit,
box->style)) * scale);
@ -1843,35 +1848,29 @@ bool html_redraw_inline_background(int x, int y, struct box *box, float scale,
}
/* and plot the image */
if (plot_content) {
int width = content_get_width(box->background);
int height = content_get_height(box->background);
if (!repeat_x) {
if (clip_x0 < x)
clip_x0 = x;
if (clip_x1 > x +
box->background->width *
scale)
clip_x1 = x + box->background->
width * scale;
if (clip_x1 > x + width * scale)
clip_x1 = x + width * scale;
}
if (!repeat_y) {
if (clip_y0 < y)
clip_y0 = y;
if (clip_y1 > y +
box->background->height *
scale)
clip_y1 = y + box->background->
height * scale;
if (clip_y1 > y + height * scale)
clip_y1 = y + height * scale;
}
/* valid clipping rectangles only */
if ((clip_x0 < clip_x1) && (clip_y0 < clip_y1)) {
if (!plot.clip(clip_x0, clip_y0,
clip_x1, clip_y1))
return false;
if (!content_redraw_tiled(box->
background, x, y,
ceilf(box->background->
width * scale),
ceilf(box->background->
height * scale),
if (!content_redraw_tiled(box->background, x, y,
ceilf(width * scale),
ceilf(height * scale),
clip_x0, clip_y0,
clip_x1, clip_y1,
scale, *background_colour,

View File

@ -24,7 +24,8 @@
#include <stdbool.h>
#include <string.h>
#include <strings.h>
#include "content/content.h"
#include "content/content_protected.h"
#include "content/hlcache.h"
#include "render/box.h"
#include "render/imagemap.h"
#include "utils/log.h"
@ -626,20 +627,21 @@ void imagemap_freelist(struct mapentry *list)
/**
* Retrieve url associated with imagemap entry
*
* \param c The containing content
* \param key The map name to search for
* \param x The left edge of the containing box
* \param y The top edge of the containing box
* \param click_x The horizontal location of the click
* \param click_y The vertical location of the click
* \param target Pointer to location to receive target pointer (if any)
* \param h The containing content
* \param key The map name to search for
* \param x The left edge of the containing box
* \param y The top edge of the containing box
* \param click_x The horizontal location of the click
* \param click_y The vertical location of the click
* \param target Pointer to location to receive target pointer (if any)
* \return The url associated with this area, or NULL if not found
*/
const char *imagemap_get(struct content *c, const char *key,
const char *imagemap_get(hlcache_handle *h, const char *key,
unsigned long x, unsigned long y,
unsigned long click_x, unsigned long click_y,
const char **target)
{
struct content *c = hlcache_handle_get_content(h);
unsigned int slot = 0;
struct imagemap *map;
struct mapentry *entry;

View File

@ -22,11 +22,13 @@
#include <libxml/HTMLtree.h>
struct content;
struct hlcache_handle;
void imagemap_destroy(struct content *c);
void imagemap_dump(struct content *c);
bool imagemap_extract(xmlNode *node, struct content *c);
const char *imagemap_get(struct content *c, const char *key,
const char *imagemap_get(struct hlcache_handle *h, const char *key,
unsigned long x, unsigned long y,
unsigned long click_x, unsigned long click_y,
const char **target);

View File

@ -41,7 +41,7 @@
#include <math.h>
#include "css/css.h"
#include "css/utils.h"
#include "content/content.h"
#include "content/content_protected.h"
#include "desktop/gui.h"
#include "desktop/options.h"
#include "desktop/scroll.h"
@ -256,12 +256,14 @@ bool layout_block_context(struct box *block, int viewport_height,
if (!layout_block_object(block))
return false;
if (block->height == AUTO) {
if (block->object->width)
block->height = block->object->height *
(float) block->width /
block->object->width;
if (content_get_width(block->object))
block->height =
content_get_height(block->object) *
(float) block->width /
content_get_width(block->object);
else
block->height = block->object->height;
block->height =
content_get_height(block->object);
}
return true;
}
@ -691,13 +693,13 @@ void layout_minmax_block(struct box *block,
}
if (block->object) {
if (block->object->type == CONTENT_HTML) {
layout_minmax_block(block->object->data.html.layout,
if (content_get_type(block->object) == CONTENT_HTML) {
layout_minmax_block(html_get_box_tree(block->object),
font_func);
min = block->object->data.html.layout->min_width;
max = block->object->data.html.layout->max_width;
min = html_get_box_tree(block->object)->min_width;
max = html_get_box_tree(block->object)->max_width;
} else {
min = max = block->object->width;
min = max = content_get_width(block->object);
}
} else {
/* recurse through children */
@ -795,9 +797,9 @@ bool layout_block_object(struct box *block)
LOG(("block %p, object %s, width %i", block, block->object->url,
block->width));
if (block->object->type == CONTENT_HTML) {
if (content_get_type(block->object) == CONTENT_HTML) {
content_reformat(block->object, block->width, 1);
block->height = block->object->height;
block->height = content_get_height(block->object);
} else {
/* this case handled already in
* layout_block_find_dimensions() */
@ -837,25 +839,25 @@ void layout_block_find_dimensions(int available_width, int viewport_height,
&width, &height, &max_width, &min_width,
margin, padding, border);
if (box->object && box->object->type != CONTENT_HTML) {
if (box->object && content_get_type(box->object) != CONTENT_HTML) {
/* block-level replaced element, see 10.3.4 and 10.6.2 */
if (width == AUTO && height == AUTO) {
width = box->object->width;
height = box->object->height;
width = content_get_width(box->object);
height = content_get_height(box->object);
} else if (width == AUTO) {
if (box->object->height)
width = box->object->width *
if (content_get_height(box->object))
width = content_get_width(box->object) *
(float) height /
box->object->height;
content_get_height(box->object);
else
width = box->object->width;
width = content_get_width(box->object);
} else if (height == AUTO) {
if (box->object->width)
height = box->object->height *
if (content_get_width(box->object))
height = content_get_height(box->object) *
(float) width /
box->object->width;
content_get_width(box->object);
else
height = box->object->height;
height = content_get_height(box->object);
}
}
@ -1168,18 +1170,20 @@ void layout_float_find_dimensions(int available_width,
padding[RIGHT] += scrollbar_width;
padding[BOTTOM] += scrollbar_width;
if (box->object && box->object->type != CONTENT_HTML) {
if (box->object && content_get_type(box->object) != CONTENT_HTML) {
/* Floating replaced element, with intrinsic width or height.
* See 10.3.6 and 10.6.2 */
if (width == AUTO && height == AUTO) {
width = box->object->width;
height = box->object->height;
width = content_get_width(box->object);
height = content_get_height(box->object);
} else if (width == AUTO)
width = box->object->width * (float) height /
box->object->height;
width = content_get_width(box->object) *
(float) height /
content_get_height(box->object);
else if (height == AUTO)
height = box->object->height * (float) width /
box->object->width;
height = content_get_height(box->object) *
(float) width /
content_get_width(box->object);
} else if (box->gadget && (box->gadget->type == GADGET_TEXTBOX ||
box->gadget->type == GADGET_PASSWORD ||
box->gadget->type == GADGET_FILE ||
@ -2079,22 +2083,25 @@ bool layout_line(struct box *first, int *width, int *y,
if (b->object) {
if (b->width == AUTO && b->height == AUTO) {
b->width = b->object->width;
b->height = b->object->height;
b->width = content_get_width(b->object);
b->height = content_get_height(b->object);
} else if (b->width == AUTO) {
if (b->object->height)
b->width = b->object->width *
(float) b->height /
b->object->height;
if (content_get_height(b->object))
b->width =
content_get_width(b->object) *
(float) b->height /
content_get_height(b->object);
else
b->width = b->object->width;
b->width = content_get_width(b->object);
} else if (b->height == AUTO) {
if (b->object->width)
b->height = b->object->height *
(float) b->width /
b->object->width;
if (content_get_width(b->object))
b->height =
content_get_height(b->object) *
(float) b->width /
content_get_width(b->object);
else
b->height = b->object->height;
b->height =
content_get_height(b->object);
}
} else {
/* form control with no object */
@ -2106,14 +2113,15 @@ bool layout_line(struct box *first, int *width, int *y,
CSS_UNIT_EM, b->style));
}
if (b->object && b->object->type == CONTENT_HTML &&
b->width != b->object->available_width) {
if (b->object && content_get_type(b->object) == CONTENT_HTML &&
b->width !=
content_get_available_width(b->object)) {
htype = css_computed_height(b->style, &value, &unit);
content_reformat(b->object, b->width, b->height);
if (htype == CSS_HEIGHT_AUTO)
b->height = b->object->height;
b->height = content_get_height(b->object);
}
if (height < b->height)
@ -2745,14 +2753,14 @@ struct box *layout_minmax_line(struct box *first,
if (b->object) {
if (width == AUTO && height == AUTO) {
width = b->object->width;
width = content_get_width(b->object);
} else if (width == AUTO) {
if (b->object->height)
width = b->object->width *
(float) height /
b->object->height;
if (content_get_height(b->object))
width = content_get_width(b->object) *
(float) height /
content_get_height(b->object);
else
width = b->object->width;
width = content_get_width(b->object);
}
fixed = frac = 0;
calculate_mbp_width(b->style, LEFT, true, true, true,
@ -3709,9 +3717,11 @@ void layout_lists(struct box *box,
if (child->list_marker) {
marker = child->list_marker;
if (marker->object) {
marker->width = marker->object->width;
marker->width =
content_get_width(marker->object);
marker->x = -marker->width;
marker->height = marker->object->height;
marker->height =
content_get_height(marker->object);
marker->y = (line_height(marker->style) -
marker->height) / 2;
} else if (marker->text) {

View File

@ -28,7 +28,8 @@
#include <strings.h>
#include <math.h>
#include <iconv.h>
#include "content/content.h"
#include "content/content_protected.h"
#include "content/hlcache.h"
#include "css/css.h"
#include "css/utils.h"
#include "desktop/gui.h"
@ -39,6 +40,7 @@
#include "render/box.h"
#include "render/font.h"
#include "render/textplain.h"
#include "utils/http.h"
#include "utils/log.h"
#include "utils/messages.h"
#include "utils/talloc.h"
@ -72,14 +74,13 @@ static float textplain_line_height(void);
* Create a CONTENT_TEXTPLAIN.
*/
bool textplain_create(struct content *c, struct content *parent,
const char *params[])
bool textplain_create(struct content *c, const http_parameter *params)
{
unsigned int i;
char *utf8_data;
const char *encoding = "iso-8859-1";
const char *encoding;
iconv_t iconv_cd;
union content_msg_data msg_data;
nserror error;
textplain_style.size = (option_font_size * FONT_SIZE_SCALE) / 10;
@ -87,13 +88,9 @@ bool textplain_create(struct content *c, struct content *parent,
if (!utf8_data)
goto no_memory;
for (i = 0; params[i]; i += 2) {
if (strcasecmp(params[i], "charset") == 0) {
encoding = talloc_strdup(c, params[i + 1]);
if (!encoding)
goto no_memory;
break;
}
error = http_parameter_list_find_item(params, "charset", &encoding);
if (error != NSERROR_OK) {
encoding = "Windows-1252";
}
iconv_cd = iconv_open("utf-8", encoding);
@ -141,18 +138,22 @@ bool textplain_process_data(struct content *c, char *data, unsigned int size)
iconv_t iconv_cd = c->data.textplain.iconv_cd;
size_t count;
union content_msg_data msg_data;
const char *source_data;
unsigned long source_size;
source_data = content__get_source_data(c, &source_size);
do {
char *inbuf = c->source_data + c->data.textplain.converted;
size_t inbytesleft = c->source_size -
char *inbuf = (char *) source_data +
c->data.textplain.converted;
size_t inbytesleft = source_size - c->data.textplain.converted;
char *outbuf = c->data.textplain.utf8_data +
c->data.textplain.utf8_data_size;
size_t outbytesleft = c->data.textplain.utf8_data_allocated -
c->data.textplain.utf8_data_size;
count = iconv(iconv_cd, &inbuf, &inbytesleft,
&outbuf, &outbytesleft);
c->data.textplain.converted = inbuf - c->source_data;
c->data.textplain.converted = inbuf - source_data;
c->data.textplain.utf8_data_size = c->data.textplain.
utf8_data_allocated - outbytesleft;
@ -180,7 +181,7 @@ bool textplain_process_data(struct content *c, char *data, unsigned int size)
}
gui_multitask();
} while (!(c->data.textplain.converted == c->source_size ||
} while (!(c->data.textplain.converted == source_size ||
(count == (size_t)(-1) && errno == EINVAL)));
return true;
@ -466,6 +467,35 @@ bool textplain_redraw(struct content *c, int x, int y,
return true;
}
/**
* Retrieve number of lines in content
*
* \param h Content to retrieve line count from
* \return Number of lines
*/
unsigned long textplain_line_count(hlcache_handle *h)
{
struct content *c = hlcache_handle_get_content(h);
assert(c != NULL);
return c->data.textplain.physical_line_count;
}
/**
* Retrieve the size (in bytes) of text data
*
* \param h Content to retrieve size of
* \return Size, in bytes, of data
*/
size_t textplain_size(hlcache_handle *h)
{
struct content *c = hlcache_handle_get_content(h);
assert(c != NULL);
return c->data.textplain.utf8_data_size;
}
/**
* Return byte offset within UTF8 textplain content, given the co-ordinates
@ -473,15 +503,16 @@ bool textplain_redraw(struct content *c, int x, int y,
* which to search (-1 = above-left, +1 = below-right) if the co-ordinates are not
* contained within a line.
*
* \param c content of type CONTENT_TEXTPLAIN
* \param h content of type CONTENT_TEXTPLAIN
* \param x x ordinate of point
* \param y y ordinate of point
* \param dir direction of search if not within line
* \return byte offset of character containing (or nearest to) point
*/
size_t textplain_offset_from_coords(struct content *c, int x, int y, int dir)
size_t textplain_offset_from_coords(hlcache_handle *h, int x, int y, int dir)
{
struct content *c = hlcache_handle_get_content(h);
float line_height = textplain_line_height();
struct textplain_line *line;
const char *text;
@ -489,6 +520,7 @@ size_t textplain_offset_from_coords(struct content *c, int x, int y, int dir)
size_t length;
int idx;
assert(c != NULL);
assert(c->type == CONTENT_TEXTPLAIN);
y = (int)((float)(y - MARGIN) / line_height);
@ -552,19 +584,24 @@ size_t textplain_offset_from_coords(struct content *c, int x, int y, int dir)
* Given a byte offset within the text, return the line number
* of the line containing that offset (or -1 if offset invalid)
*
* \param c content of type CONTENT_TEXTPLAIN
* \param h content of type CONTENT_TEXTPLAIN
* \param offset byte offset within textual representation
* \return line number, or -1 if offset invalid (larger than size)
*/
int textplain_find_line(struct content *c, unsigned offset)
int textplain_find_line(hlcache_handle *h, unsigned offset)
{
struct textplain_line *line = c->data.textplain.physical_line;
int nlines = c->data.textplain.physical_line_count;
struct content *c = hlcache_handle_get_content(h);
struct textplain_line *line;
int nlines;
int lineno = 0;
assert(c != NULL);
assert(c->type == CONTENT_TEXTPLAIN);
line = c->data.textplain.physical_line;
nlines = c->data.textplain.physical_line_count;
if (offset > c->data.textplain.utf8_data_size)
return -1;
@ -622,30 +659,33 @@ int textplain_coord_from_offset(const char *text, size_t offset, size_t length)
* Given a range of byte offsets within a UTF8 textplain content,
* return a box that fully encloses the text
*
* \param c content of type CONTENT_TEXTPLAIN
* \param h content of type CONTENT_TEXTPLAIN
* \param start byte offset of start of text range
* \param end byte offset of end
* \param r rectangle to be completed
*/
void textplain_coords_from_range(struct content *c, unsigned start, unsigned end,
struct rect *r)
void textplain_coords_from_range(hlcache_handle *h, unsigned start,
unsigned end, struct rect *r)
{
struct content *c = hlcache_handle_get_content(h);
float line_height = textplain_line_height();
char *utf8_data = c->data.textplain.utf8_data;
char *utf8_data;
struct textplain_line *line;
unsigned lineno = 0;
unsigned nlines;
assert(c != NULL);
assert(c->type == CONTENT_TEXTPLAIN);
assert(start <= end);
assert(end <= c->data.textplain.utf8_data_size);
utf8_data = c->data.textplain.utf8_data;
nlines = c->data.textplain.physical_line_count;
line = c->data.textplain.physical_line;
/* find start */
lineno = textplain_find_line(c, start);
lineno = textplain_find_line(h, start);
r->y0 = (int)(MARGIN + lineno * line_height);
@ -654,7 +694,7 @@ void textplain_coords_from_range(struct content *c, unsigned start, unsigned end
forwards most of the time */
/* find end */
lineno = textplain_find_line(c, end);
lineno = textplain_find_line(h, end);
r->x0 = 0;
r->x1 = c->data.textplain.formatted_width;
@ -677,18 +717,20 @@ void textplain_coords_from_range(struct content *c, unsigned start, unsigned end
/**
* Return a pointer to the requested line of text.
*
* \param c content of type CONTENT_TEXTPLAIN
* \param h content of type CONTENT_TEXTPLAIN
* \param lineno line number
* \param poffset receives byte offset of line start within text
* \param plen receives length of returned line
* \return pointer to text, or NULL if invalid line number
*/
char *textplain_get_line(struct content *c, unsigned lineno,
char *textplain_get_line(hlcache_handle *h, unsigned lineno,
size_t *poffset, size_t *plen)
{
struct content *c = hlcache_handle_get_content(h);
struct textplain_line *line;
assert(c != NULL);
assert(c->type == CONTENT_TEXTPLAIN);
if (lineno >= c->data.textplain.physical_line_count)
@ -706,20 +748,24 @@ char *textplain_get_line(struct content *c, unsigned lineno,
* text to fit the window width. Thus only hard newlines are preserved
* in the saved/copied text of a selection.
*
* \param c content of type CONTENT_TEXTPLAIN
* \param h content of type CONTENT_TEXTPLAIN
* \param start starting byte offset within UTF-8 text
* \param end ending byte offset
* \param plen receives validated length
* \return pointer to text, or NULL if no text
*/
char *textplain_get_raw_data(struct content *c, unsigned start, unsigned end,
char *textplain_get_raw_data(hlcache_handle *h, unsigned start, unsigned end,
size_t *plen)
{
size_t utf8_size = c->data.textplain.utf8_data_size;
struct content *c = hlcache_handle_get_content(h);
size_t utf8_size;
assert(c != NULL);
assert(c->type == CONTENT_TEXTPLAIN);
utf8_size = c->data.textplain.utf8_data_size;
/* any text at all? */
if (!utf8_size) return NULL;

View File

@ -28,6 +28,8 @@
#include <iconv.h>
struct content;
struct hlcache_handle;
struct http_parameter;
struct textplain_line {
size_t start;
@ -46,8 +48,7 @@ struct content_textplain_data {
int formatted_width;
};
bool textplain_create(struct content *c, struct content *parent,
const char *params[]);
bool textplain_create(struct content *c, const struct http_parameter *params);
bool textplain_process_data(struct content *c, char *data, unsigned int size);
bool textplain_convert(struct content *c, int width, int height);
void textplain_reformat(struct content *c, int width, int height);
@ -58,16 +59,17 @@ bool textplain_redraw(struct content *c, int x, int y,
float scale, colour background_colour);
/* access to lines for text selection and searching */
#define textplain_line_count(c) ((c)->data.textplain.physical_line_count)
#define textplain_size(c) ((c)->data.textplain.utf8_data_size)
unsigned long textplain_line_count(struct hlcache_handle *h);
size_t textplain_size(struct hlcache_handle *h);
size_t textplain_offset_from_coords(struct content *c, int x, int y, int dir);
void textplain_coords_from_range(struct content *c,
size_t textplain_offset_from_coords(struct hlcache_handle *h, int x, int y,
int dir);
void textplain_coords_from_range(struct hlcache_handle *h,
unsigned start, unsigned end, struct rect *r);
char *textplain_get_line(struct content *c, unsigned lineno,
char *textplain_get_line(struct hlcache_handle *h, unsigned lineno,
size_t *poffset, size_t *plen);
int textplain_find_line(struct content *c, unsigned offset);
char *textplain_get_raw_data(struct content *c,
int textplain_find_line(struct hlcache_handle *h, unsigned offset);
char *textplain_get_raw_data(struct hlcache_handle *h,
unsigned start, unsigned end, size_t *plen);
#endif

View File

@ -279,7 +279,15 @@ static void *myrealloc(void *ptr, size_t len, void *pw)
int main(int argc, char** argv)
{
setbuf(stderr, NULL);
return netsurf_main(argc, argv);
/* initialise netsurf */
netsurf_init(argc, argv);
netsurf_main_loop();
netsurf_exit();
return 0;
}
/**

View File

@ -1396,12 +1396,10 @@ bool gui_window_frame_resize_start(struct gui_window *g)
* \param g gui_window containing the content
* \param c the content to save
*/
void gui_window_save_as_link(struct gui_window *g, struct content *c)
void gui_window_save_link(struct gui_window *g, const char *url,
const char *title)
{
if (!c)
return;
ro_gui_save_prepare(GUI_SAVE_LINK_URL, NULL, NULL, c->url, c->title);
ro_gui_save_prepare(GUI_SAVE_LINK_URL, NULL, NULL, url, title);
ro_gui_dialog_open_persistent(g->window, dialog_saveas, true);
}

19
test/Makefile Normal file
View File

@ -0,0 +1,19 @@
CFLAGS := -std=c99 -g -O0 -D_BSD_SOURCE -D_POSIX_C_SOURCE -I.. \
`pkg-config --cflags libxml-2.0 libcurl libparserutils`
LDFLAGS := `pkg-config --libs libxml-2.0 libcurl libparserutils`
llcache_SRCS := content/fetch.c content/fetchers/fetch_curl.c \
content/fetchers/fetch_data.c content/llcache.c \
content/urldb.c desktop/options.c desktop/version.c \
utils/base64.c utils/hashtable.c utils/messages.c \
utils/url.c utils/useragent.c utils/utf8.c utils/utils.c \
test/llcache.c
llcache: $(addprefix ../,$(llcache_SRCS))
$(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS)
.PHONY: clean
clean:
$(RM) llcache

282
test/llcache.c Normal file
View File

@ -0,0 +1,282 @@
#include <stdio.h>
#include <stdlib.h>
#include "content/fetch.h"
#include "content/llcache.h"
#include "utils/ring.h"
#include "utils/url.h"
/******************************************************************************
* Things that we'd reasonably expect to have to implement *
******************************************************************************/
/* desktop/netsurf.h */
bool verbose_log;
/* utils/utils.h */
void die(const char * const error)
{
fprintf(stderr, "%s\n", error);
exit(1);
}
/* utils/utils.h */
void warn_user(const char *warning, const char *detail)
{
fprintf(stderr, "%s %s\n", warning, detail);
}
/* content/fetch.h */
const char *fetch_filetype(const char *unix_path)
{
return NULL;
}
/* content/fetch.h */
char *fetch_mimetype(const char *ro_path)
{
return NULL;
}
/******************************************************************************
* Things that are absolutely not reasonable, and should disappear *
******************************************************************************/
#include "desktop/cookies.h"
#include "desktop/tree.h"
/* desktop/cookies.h -- used by urldb
*
* URLdb should have a cookies update event + handler registration
*/
bool cookies_update(const char *domain, const struct cookie_data *data)
{
return true;
}
/* image/bitmap.h -- used by urldb
*
* URLdb shouldn't care about bitmaps.
* This is because the legacy RO thumbnail stuff was hacked in and must die.
*/
void bitmap_destroy(void *bitmap)
{
}
/* desktop/tree.h -- used by options.c
*
* Why on earth is tree loading and saving in options.c?
*/
void tree_initialise(struct tree *tree)
{
}
/* desktop/tree.h */
struct node *tree_create_folder_node(struct node *parent, const char *title)
{
return NULL;
}
/* desktop/tree.h */
struct node *tree_create_URL_node(struct node *parent, const char *url,
const struct url_data *data, const char *title)
{
return NULL;
}
/* desktop/tree.h */
struct node_element *tree_find_element(struct node *node, node_element_data d)
{
return NULL;
}
/******************************************************************************
* test: protocol handler *
******************************************************************************/
typedef struct test_context {
struct fetch *parent;
bool aborted;
bool locked;
struct test_context *r_prev;
struct test_context *r_next;
} test_context;
static test_context *ring;
bool test_initialise(const char *scheme)
{
/* Nothing to do */
return true;
}
void test_finalise(const char *scheme)
{
/* Nothing to do */
}
void *test_setup_fetch(struct fetch *parent, const char *url, bool only_2xx,
const char *post_urlenc,
struct fetch_multipart_data *post_multipart,
const char **headers)
{
test_context *ctx = calloc(1, sizeof(test_context));
if (ctx == NULL)
return NULL;
ctx->parent = parent;
RING_INSERT(ring, ctx);
return ctx;
}
bool test_start_fetch(void *handle)
{
/* Nothing to do */
return true;
}
void test_abort_fetch(void *handle)
{
test_context *ctx = handle;
ctx->aborted = true;
}
void test_free_fetch(void *handle)
{
test_context *ctx = handle;
RING_REMOVE(ring, ctx);
free(ctx);
}
void test_process(test_context *ctx)
{
/** \todo Implement */
}
void test_poll(const char *scheme)
{
test_context *ctx, *next;
if (ring == NULL)
return;
ctx = ring;
do {
next = ctx->r_next;
if (ctx->locked)
continue;
if (ctx->aborted == false) {
test_process(ctx);
}
fetch_remove_from_queues(ctx->parent);
fetch_free(ctx->parent);
} while ((ctx = next) != ring && ring != NULL);
}
/******************************************************************************
* The actual test code *
******************************************************************************/
nserror query_handler(const llcache_query *query, void *pw,
llcache_query_response cb, void *cbpw)
{
/* I'm too lazy to actually implement this. It should queue the query,
* then deliver the response from main(). */
return NSERROR_OK;
}
nserror event_handler(const llcache_handle *handle,
const llcache_event *event, void *pw)
{
static char *event_names[] = {
"HAD_HEADERS", "HAD_DATA", "DONE", "ERROR", "PROGRESS"
};
bool *done = pw;
if (event->type != LLCACHE_EVENT_PROGRESS)
fprintf(stdout, "%p : %s\n", handle, event_names[event->type]);
/* Inform main() that the fetch completed */
if (event->type == LLCACHE_EVENT_DONE)
*done = true;
return NSERROR_OK;
}
int main(int argc, char **argv)
{
nserror error;
llcache_handle *handle;
llcache_handle *handle2;
bool done = false;
/* Initialise subsystems */
url_init();
fetch_init();
fetch_add_fetcher("test", test_initialise, test_setup_fetch,
test_start_fetch, test_abort_fetch, test_free_fetch,
test_poll, test_finalise);
/* Initialise low-level cache */
error = llcache_initialise(query_handler, NULL);
if (error != NSERROR_OK) {
fprintf(stderr, "llcache_initialise: %d\n", error);
return 1;
}
/* Retrieve an URL from the low-level cache (may trigger fetch) */
error = llcache_handle_retrieve("http://www.netsurf-browser.org/",
LLCACHE_RETRIEVE_VERIFIABLE, NULL, NULL,
event_handler, &done, &handle);
if (error != NSERROR_OK) {
fprintf(stderr, "llcache_handle_retrieve: %d\n", error);
return 1;
}
/* Poll relevant components */
while (done == false) {
fetch_poll();
llcache_poll();
}
done = false;
error = llcache_handle_retrieve("http://www.netsurf-browser.org/",
LLCACHE_RETRIEVE_VERIFIABLE, NULL, NULL,
event_handler, &done, &handle2);
if (error != NSERROR_OK) {
fprintf(stderr, "llcache_handle_retrieve: %d\n", error);
return 1;
}
while (done == false) {
fetch_poll();
llcache_poll();
}
fprintf(stdout, "%p -> %p\n", handle,
llcache_object_from_handle(handle));
fprintf(stdout, "%p -> %p\n", handle2,
llcache_object_from_handle(handle2));
/* Cleanup */
llcache_handle_release(handle2);
llcache_handle_release(handle);
fetch_quit();
return 0;
}

40
utils/errors.h Normal file
View File

@ -0,0 +1,40 @@
/*
* Copyright 2009 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/** \file
* Error codes
*/
#ifndef NETSURF_UTILS_ERRORS_H_
#define NETSURF_UTILS_ERRORS_H_
/**
* Enumeration of error codes
*/
typedef enum {
NSERROR_OK, /**< No error */
NSERROR_NOMEM, /**< Memory exhaustion */
NSERROR_NO_FETCH_HANDLER, /**< No fetch handler for URL scheme */
NSERROR_NOT_FOUND, /**< Requested item not found */
} nserror;
#endif

390
utils/http.c Normal file
View File

@ -0,0 +1,390 @@
/*
* Copyright 2010 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/** \file
* HTTP header parsing functions
*/
#include <inttypes.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "utils/http.h"
/**
* Representation of an HTTP parameter
*/
struct http_parameter {
struct http_parameter *next; /**< Next parameter in list, or NULL */
char *name; /**< Parameter name */
char *value; /**< Parameter value */
};
/**
* Determine if a character is valid for an HTTP token
*
* \param c Character to consider
* \return True if character is valid, false otherwise
*/
static bool http_is_token_char(uint8_t c)
{
/* [ 32 - 126 ] except ()<>@,;:\"/[]?={} SP HT */
if (c <= ' ' || 126 < c)
return false;
return (strchr("()<>@,;:\\\"/[]?={}", c) == NULL);
}
/**
* Parse an HTTP token
*
* \param input Pointer to current input byte. Updated on exit.
* \param value Pointer to location to receive on-heap token value.
* \return NSERROR_OK on success,
* NSERROR_NOMEM on memory exhaustion
*
* The returned value is owned by the caller
*/
static nserror http_parse_token(const char **input, char **value)
{
const uint8_t *start = (const uint8_t *) *input;
const uint8_t *end;
char *token;
end = start;
while (http_is_token_char(*end))
end++;
token = malloc(end - start + 1);
if (token == NULL)
return NSERROR_NOMEM;
memcpy(token, start, end - start);
token[end - start] = '\0';
*value = token;
*input = (const char *) end;
return NSERROR_OK;
}
/**
* Parse an HTTP quoted-string
*
* \param input Pointer to current input byte. Updated on exit.
* \param value Pointer to location to receive on-heap string value.
* \return NSERROR_OK on success,
* NSERROR_NOMEM on memory exhaustion
*
* The returned value is owned by the caller
*/
static nserror http_parse_quoted_string(const char **input, char **value)
{
const uint8_t *start = (const uint8_t *) *input;
const uint8_t *end;
uint8_t c;
char *string_value;
/* <"> *( qdtext | quoted-pair ) <">
* qdtext = any TEXT except <">
* quoted-pair = "\" CHAR
* TEXT = [ HT, CR, LF, 32-126, 128-255 ]
* CHAR = [ 0 - 127 ]
*
* \todo TEXT may contain non 8859-1 chars encoded per RFC 2047
* \todo Support quoted-pairs
*/
if (*start == '"') {
end = start = start + 1;
c = *end;
while (c == '\t' || c == '\r' || c == '\n' ||
c == ' ' || c == '!' ||
('#' <= c && c <= 126) || c > 127) {
end++;
c = *end;
}
if (*end != '"') {
start--;
end = start;
}
}
string_value = malloc(end - start + 1);
if (string_value == NULL)
return NSERROR_NOMEM;
memcpy(string_value, start, end - start);
string_value[end - start] = '\0';
*value = string_value;
if (end != start)
*input = (const char *) end + 1;
return NSERROR_OK;
}
/**
* Parse an HTTP parameter
*
* \param input Pointer to current input byte. Updated on exit.
* \param parameter Pointer to location to receive on-heap parameter.
* \return NSERROR_OK on success,
* NSERROR_NOMEM on memory exhaustion
*
* The returned parameter is owned by the caller.
*/
static nserror http_parse_parameter(const char **input,
http_parameter **parameter)
{
const char *pos = *input;
char *name;
char *value;
http_parameter *param;
nserror error;
/* token "=" ( token | quoted-string ) */
error = http_parse_token(&pos, &name);
if (error != NSERROR_OK)
return error;
while (*pos == ' ' || *pos == '\t')
pos++;
if (*pos != '=') {
value = strdup("");
if (value == NULL) {
free(name);
return NSERROR_NOMEM;
}
} else {
pos++;
while (*pos == ' ' || *pos == '\t')
pos++;
if (*pos == '"')
error = http_parse_quoted_string(&pos, &value);
else
error = http_parse_token(&pos, &value);
if (error != NSERROR_OK) {
free(name);
return error;
}
}
param = malloc(sizeof(*param));
if (param == NULL) {
free(value);
free(name);
return NSERROR_NOMEM;
}
param->next = NULL;
param->name = name;
param->value = value;
*parameter = param;
*input = pos;
return NSERROR_OK;
}
/**
* Parse an HTTP parameter list
*
* \param input Pointer to current input byte. Updated on exit.
* \param parameters Pointer to location to receive on-heap parameter list.
* \return NSERROR_OK on success,
* NSERROR_NOMEM on memory exhaustion
*
* The returned parameter list is owned by the caller
*/
static nserror http_parse_parameter_list(const char **input,
http_parameter **parameters)
{
const char *pos = *input;
http_parameter *param;
http_parameter *list = NULL;
nserror error;
/* 1*( ";" parameter ) */
while (*pos == ';') {
pos++;
while (*pos == ' ' || *pos == '\t')
pos++;
error = http_parse_parameter(&pos, &param);
if (error != NSERROR_OK) {
while (list != NULL) {
param = list;
list = param->next;
free(param->name);
free(param->value);
free(param);
}
return error;
}
if (list != NULL)
param->next = list;
list = param;
while (*pos == ' ' || *pos == '\t')
pos++;
}
*parameters = list;
*input = pos;
return NSERROR_OK;
}
/* See http.h for documentation */
nserror http_parse_content_type(const char *header_value, char **media_type,
http_parameter **parameters)
{
const char *pos = header_value;
char *type;
char *subtype = NULL;
http_parameter *params = NULL;
char *mime;
size_t mime_len;
nserror error;
/* type "/" subtype *( ";" parameter ) */
while (*pos == ' ' || *pos == '\t')
pos++;
error = http_parse_token(&pos, &type);
if (error != NSERROR_OK)
return error;
while (*pos == ' ' || *pos == '\t')
pos++;
if (*pos == '/') {
pos++;
while (*pos == ' ' || *pos == '\t')
pos++;
error = http_parse_token(&pos, &subtype);
if (error != NSERROR_OK) {
free(type);
return error;
}
while (*pos == ' ' || *pos == '\t')
pos++;
if (*pos == ';') {
pos++;
while (*pos == ' ' || *pos == '\t')
pos++;
error = http_parse_parameter_list(&pos, &params);
if (error != NSERROR_OK) {
free(subtype);
free(type);
return error;
}
}
}
/* <type> + <subtype> + '/' */
mime_len = strlen(type) + (subtype != NULL ? strlen(subtype) : 0) + 1;
mime = malloc(mime_len + 1);
if (mime == NULL) {
http_parameter_list_destroy(params);
free(subtype);
free(type);
return NSERROR_OK;
}
sprintf(mime, "%s/%s", type, subtype != NULL ? subtype : "");
free(subtype);
free(type);
*media_type = mime;
*parameters = params;
return NSERROR_OK;
}
/* See http.h for documentation */
nserror http_parameter_list_find_item(const http_parameter *list,
const char *name, const char **value)
{
while (list != NULL && strcasecmp(name, list->name) != 0)
list = list->next;
if (list == NULL)
return NSERROR_NOT_FOUND;
*value = list->value;
return NSERROR_OK;
}
/* See http.h for documentation */
const http_parameter *http_parameter_list_iterate(const http_parameter *cur,
const char **name, const char **value)
{
if (cur == NULL)
return NULL;
*name = cur->name;
*value = cur->value;
return cur->next;
}
/* See http.h for documentation */
void http_parameter_list_destroy(http_parameter *list)
{
while (list != NULL) {
http_parameter *victim = list;
list = victim->next;
free(victim->name);
free(victim->value);
free(victim);
}
}

Some files were not shown because too many files have changed in this diff Show More