From 69f02e926f746b31500f46572d606fdc482ff0cb Mon Sep 17 00:00:00 2001 From: John Mark Bell Date: Sun, 4 Apr 2010 17:17:24 +0000 Subject: Make the high-level cache drop contents of unacceptable type on the floor. svn path=/trunk/netsurf/; revision=10238 --- content/hlcache.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++--- content/hlcache.h | 22 ++++++++------- css/css.c | 4 ++- desktop/browser.c | 3 ++- desktop/searchweb.c | 11 +++++++- render/favicon.c | 33 ++++++++++------------- render/html.c | 11 +++++--- 7 files changed, 123 insertions(+), 39 deletions(-) diff --git a/content/hlcache.c b/content/hlcache.c index 05a416b0b..298fe8151 100644 --- a/content/hlcache.c +++ b/content/hlcache.c @@ -26,7 +26,9 @@ #include "content/content.h" #include "content/hlcache.h" +#include "utils/http.h" #include "utils/log.h" +#include "utils/messages.h" #include "utils/url.h" typedef struct hlcache_entry hlcache_entry; @@ -38,6 +40,8 @@ struct hlcache_retrieval_ctx { hlcache_handle *handle; /**< High-level handle for object */ + const content_type *accepted_types; /**< Accepted types, or NULL */ + hlcache_child_context child; /**< Child context */ }; @@ -62,6 +66,8 @@ static hlcache_entry *hlcache_content_list; static nserror hlcache_llcache_callback(llcache_handle *handle, const llcache_event *event, void *pw); +static bool hlcache_type_is_acceptable(llcache_handle *llcache, + const content_type *accepted_types); 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); @@ -74,7 +80,8 @@ static void hlcache_content_callback(struct content *c, nserror hlcache_handle_retrieve(const char *url, uint32_t flags, const char *referer, llcache_post_data *post, hlcache_handle_callback cb, void *pw, - hlcache_child_context *child, hlcache_handle **result) + hlcache_child_context *child, + const content_type *accepted_types, hlcache_handle **result) { hlcache_retrieval_ctx *ctx; nserror error; @@ -97,6 +104,8 @@ nserror hlcache_handle_retrieve(const char *url, uint32_t flags, ctx->child.quirks = child->quirks; } + ctx->accepted_types = accepted_types; + ctx->handle->cb = cb; ctx->handle->pw = pw; @@ -218,9 +227,26 @@ nserror hlcache_llcache_callback(llcache_handle *handle, switch (event->type) { case LLCACHE_EVENT_HAD_HEADERS: - error = hlcache_find_content(ctx); - if (error != NSERROR_OK) - return error; + if (hlcache_type_is_acceptable(handle, ctx->accepted_types)) { + error = hlcache_find_content(ctx); + if (error != NSERROR_OK) + return error; + } else { + /* Unacceptable type: abort fetch and report error */ + llcache_handle_abort(handle); + llcache_handle_release(handle); + + if (ctx->handle->cb != NULL) { + hlcache_event hlevent; + + hlevent.type = CONTENT_MSG_ERROR; + hlevent.data.error = messages_get("BadType"); + + ctx->handle->cb(ctx->handle, &hlevent, + ctx->handle->pw); + } + } + /* No longer require retrieval context */ free(ctx); break; @@ -246,6 +272,50 @@ nserror hlcache_llcache_callback(llcache_handle *handle, return NSERROR_OK; } +/** + * Determine if the type of a low-level cache object is acceptable + * + * \param llcache Low-level cache object to consider + * \param accepted_types Array of acceptable types, or NULL for any + * \return True if the type is acceptable, false otherwise + */ +bool hlcache_type_is_acceptable(llcache_handle *llcache, + const content_type *accepted_types) +{ + const char *content_type_header; + char *mime_type; + http_parameter *params; + content_type type; + nserror error; + + if (accepted_types == NULL) + return true; + + content_type_header = + llcache_handle_get_header(llcache, "Content-Type"); + if (content_type_header == NULL) + content_type_header = "text/plain"; + + error = http_parse_content_type(content_type_header, &mime_type, + ¶ms); + if (error != NSERROR_OK) + return false; + + type = content_lookup(mime_type); + + free(mime_type); + http_parameter_list_destroy(params); + + while (*accepted_types != CONTENT_UNKNOWN) { + if (*accepted_types == type) + break; + + accepted_types++; + } + + return *accepted_types == type; +} + /** * Find a content for the high-level cache handle * diff --git a/content/hlcache.h b/content/hlcache.h index 5ef42a301..1208b15c4 100644 --- a/content/hlcache.h +++ b/content/hlcache.h @@ -56,20 +56,23 @@ typedef nserror (*hlcache_handle_callback)(hlcache_handle *handle, /** * 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 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 + * \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 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 accepted_types Array of acceptable content types, or NULL for any + * \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. * + * The \a accepted_types array must be terminated with CONTENT_UNKNOWN + * * \todo The above rules should be encoded in the handler_map. * * \todo Is there any way to sensibly reduce the number of parameters here? @@ -77,7 +80,8 @@ typedef nserror (*hlcache_handle_callback)(hlcache_handle *handle, nserror hlcache_handle_retrieve(const char *url, uint32_t flags, const char *referer, llcache_post_data *post, hlcache_handle_callback cb, void *pw, - hlcache_child_context *child, hlcache_handle **result); + hlcache_child_context *child, + const content_type *accepted_types, hlcache_handle **result); /** * Release a high-level cache handle diff --git a/css/css.c b/css/css.c index ef38d76aa..1bbbfe608 100644 --- a/css/css.c +++ b/css/css.c @@ -200,6 +200,7 @@ bool nscss_convert(struct content *c) */ css_error nscss_convert_css_data(struct content_css_data *c) { + static const content_type accept[] = { CONTENT_CSS, CONTENT_UNKNOWN }; const char *referer; uint32_t i = 0; css_error error; @@ -252,7 +253,8 @@ css_error nscss_convert_css_data(struct content_css_data *c) c->imports[c->import_count].media = media; nerror = hlcache_handle_retrieve(lwc_string_data(uri), 0, referer, NULL, nscss_import, c, - &child, &c->imports[c->import_count++].c); + &child, accept, + &c->imports[c->import_count++].c); if (error != NSERROR_OK) { return CSS_NOMEM; } diff --git a/desktop/browser.c b/desktop/browser.c index 70d6b8cf4..e1b071fdb 100644 --- a/desktop/browser.c +++ b/desktop/browser.c @@ -409,7 +409,8 @@ void browser_window_go_post(struct browser_window *bw, const char *url, error = hlcache_handle_retrieve(url2, 0, referer, fetch_is_post ? &post : NULL, browser_window_callback, bw, - parent != NULL ? &child : NULL, &c); + parent != NULL ? &child : NULL, + NULL, &c); if (error == NSERROR_NO_FETCH_HANDLER) { gui_launch_url(url2); free(url2); diff --git a/desktop/searchweb.c b/desktop/searchweb.c index aa993b6a8..89f86ed93 100644 --- a/desktop/searchweb.c +++ b/desktop/searchweb.c @@ -206,6 +206,12 @@ char *search_web_get_url(const char *encsearchterm) void search_web_retrieve_ico(bool localdefault) { + static const content_type accept[] = { +#ifdef WITH_BMP + CONTENT_ICO, +#endif + CONTENT_UNKNOWN + }; char *url; nserror error; @@ -230,7 +236,8 @@ void search_web_retrieve_ico(bool localdefault) } error = hlcache_handle_retrieve(url, 0, NULL, NULL, - search_web_ico_callback, NULL, NULL, &search_ico); + search_web_ico_callback, NULL, NULL, accept, + &search_ico); if (error != NSERROR_OK) search_ico = NULL; @@ -269,6 +276,8 @@ nserror search_web_ico_callback(hlcache_handle *ico, } else #endif { + hlcache_handle_release(ico); + search_ico = NULL; search_web_retrieve_ico(true); } break; diff --git a/render/favicon.c b/render/favicon.c index 06ff0b94f..d1eaaacdd 100644 --- a/render/favicon.c +++ b/render/favicon.c @@ -148,6 +148,18 @@ char *favicon_get_icon_ref(struct content *c, xmlNode *html) bool favicon_get_icon(struct content *c, xmlNode *html) { + static const content_type permitted_types[] = { +#ifdef WITH_BMP + CONTENT_ICO, +#endif +#if defined(WITH_MNG) || defined(WITH_PNG) + CONTENT_PNG, +#endif +#ifdef WITH_GIF + CONTENT_GIF, +#endif + CONTENT_UNKNOWN + }; char *url; nserror error; @@ -157,7 +169,7 @@ bool favicon_get_icon(struct content *c, xmlNode *html) error = hlcache_handle_retrieve(url, LLCACHE_RETRIEVE_NO_ERROR_PAGES, content__get_url(c), NULL, favicon_callback, c, NULL, - &c->data.html.favicon); + permitted_types, &c->data.html.favicon); free(url); @@ -171,29 +183,12 @@ bool favicon_get_icon(struct content *c, xmlNode *html) nserror favicon_callback(hlcache_handle *icon, const hlcache_event *event, void *pw) { - static const content_type permitted_types[] = { -#ifdef WITH_BMP - CONTENT_ICO, -#endif -#if defined(WITH_MNG) || defined(WITH_PNG) - CONTENT_PNG, -#endif -#ifdef WITH_GIF - CONTENT_GIF, -#endif - CONTENT_UNKNOWN - }; struct content *c = pw; - const content_type *type; 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 (content_get_type(icon) == *type) - break; - - if (*type == CONTENT_UNKNOWN) { + if (content_get_type(icon) == CONTENT_UNKNOWN) { union content_msg_data msg_data; LOG(("%s is not a favicon", content_get_url(icon))); diff --git a/render/html.c b/render/html.c index 2ead62fc3..f50146d95 100644 --- a/render/html.c +++ b/render/html.c @@ -783,6 +783,7 @@ bool html_meta_refresh(struct content *c, xmlNode *head) bool html_find_stylesheets(struct content *c, xmlNode *html) { + static const content_type accept[] = { CONTENT_CSS, CONTENT_UNKNOWN }; xmlNode *node; char *rel, *type, *media, *href, *url, *url2; unsigned int i = STYLESHEET_START; @@ -819,7 +820,7 @@ bool html_find_stylesheets(struct content *c, xmlNode *html) ns_error = hlcache_handle_retrieve(default_stylesheet_url, 0, content__get_url(c), NULL, - html_convert_css_callback, c, &child, + html_convert_css_callback, c, &child, accept, &c->data.html.stylesheets[ STYLESHEET_BASE].data.external); if (ns_error != NSERROR_OK) @@ -830,7 +831,7 @@ bool html_find_stylesheets(struct content *c, xmlNode *html) if (c->data.html.quirks == BINDING_QUIRKS_MODE_FULL) { ns_error = hlcache_handle_retrieve(quirks_stylesheet_url, 0, content__get_url(c), NULL, - html_convert_css_callback, c, &child, + html_convert_css_callback, c, &child, accept, &c->data.html.stylesheets[ STYLESHEET_QUIRKS].data.external); if (ns_error != NSERROR_OK) @@ -842,7 +843,7 @@ bool html_find_stylesheets(struct content *c, xmlNode *html) if (option_block_ads) { ns_error = hlcache_handle_retrieve(adblock_stylesheet_url, 0, content__get_url(c), NULL, - html_convert_css_callback, c, &child, + html_convert_css_callback, c, &child, accept, &c->data.html.stylesheets[ STYLESHEET_ADBLOCK].data.external); if (ns_error != NSERROR_OK) @@ -951,6 +952,7 @@ bool html_find_stylesheets(struct content *c, xmlNode *html) ns_error = hlcache_handle_retrieve(url2, 0, content__get_url(c), NULL, html_convert_css_callback, c, &child, + accept, &c->data.html.stylesheets[i]. data.external); @@ -1246,7 +1248,7 @@ bool html_fetch_object(struct content *c, const char *url, struct box *box, } error = hlcache_handle_retrieve(url2, 0, content__get_url(c), NULL, - html_object_callback, c, &child, + html_object_callback, c, &child, permitted_types, &c_fetch); /* No longer need normalized url */ @@ -1313,6 +1315,7 @@ bool html_replace_object(struct content *c, unsigned int i, const char *url) /* initialise fetch */ error = hlcache_handle_retrieve(url2, 0, content__get_url(c), NULL, html_object_callback, c, &child, + c->data.html.object[i].permitted_types, &c_fetch); free(url2); -- cgit v1.2.3