diff options
author | John Mark Bell <jmb@netsurf-browser.org> | 2009-12-17 23:55:02 +0000 |
---|---|---|
committer | John Mark Bell <jmb@netsurf-browser.org> | 2009-12-17 23:55:02 +0000 |
commit | 355799ce0bbb078237dfc1ae9874bbc5342acbc4 (patch) | |
tree | 7ca980c01c0d4d1d55a3b7b15418c95c5618afae /content | |
parent | 4346b2b62b940182575e6612e46234355afa083c (diff) | |
download | netsurf-355799ce0bbb078237dfc1ae9874bbc5342acbc4.tar.gz netsurf-355799ce0bbb078237dfc1ae9874bbc5342acbc4.tar.bz2 |
Merge branches/MarkieB/gtkmain to trunk.
svn path=/trunk/netsurf/; revision=9729
Diffstat (limited to 'content')
-rw-r--r-- | content/content.c | 3 | ||||
-rw-r--r-- | content/fetch.c | 4 | ||||
-rw-r--r-- | content/fetch.h | 18 | ||||
-rw-r--r-- | content/fetchcache.c | 127 | ||||
-rw-r--r-- | content/fetchers/fetch_curl.c | 50 | ||||
-rw-r--r-- | content/fetchers/fetch_data.c | 28 |
6 files changed, 161 insertions, 69 deletions
diff --git a/content/content.c b/content/content.c index e00f3bcd6..8b6cfd47d 100644 --- a/content/content.c +++ b/content/content.c @@ -155,6 +155,9 @@ static const struct mime_entry mime_map[] = { {"image/svg", CONTENT_SVG}, {"image/svg+xml", CONTENT_SVG}, #endif +#ifdef WITH_BMP + {"image/vnd.microsoft.icon", CONTENT_ICO}, +#endif #ifdef WITH_ARTWORKS {"image/x-artworks", CONTENT_ARTWORKS}, #endif diff --git a/content/fetch.c b/content/fetch.c index a1417fee9..4fdeffb3d 100644 --- a/content/fetch.c +++ b/content/fetch.c @@ -601,11 +601,11 @@ bool fetch_get_verifiable(struct fetch *fetch) void fetch_send_callback(fetch_msg msg, struct fetch *fetch, const void *data, - unsigned long size) + unsigned long size, fetch_error_code errorcode) { /*LOG(("Fetcher sending callback. Fetch %p, fetcher %p data %p size %lu", fetch, fetch->fetcher_handle, data, size)); */ - fetch->callback(msg, fetch->p, data, size); + fetch->callback(msg, fetch->p, data, size, errorcode); } diff --git a/content/fetch.h b/content/fetch.h index 3206acc39..2666b8ffc 100644 --- a/content/fetch.h +++ b/content/fetch.h @@ -40,6 +40,19 @@ typedef enum { FETCH_CERT_ERR, } fetch_msg; +typedef enum { + FETCH_ERROR_NO_ERROR, + FETCH_ERROR_CERT, + FETCH_ERROR_AUTHENTICATION, + FETCH_ERROR_HTTP_NOT2, + FETCH_ERROR_COULDNT_RESOLVE_HOST, + FETCH_ERROR_PARTIAL_FILE, + FETCH_ERROR_MEMORY, + FETCH_ERROR_URL, + FETCH_ERROR_ENCODING, + FETCH_ERROR_MISC +} fetch_error_code; + struct content; struct fetch; struct form_successful_control; @@ -58,7 +71,7 @@ struct ssl_cert_info { extern bool fetch_active; typedef void (*fetch_callback)(fetch_msg msg, void *p, const void *data, - unsigned long size); + unsigned long size, fetch_error_code errorcode); void fetch_init(void); @@ -105,7 +118,8 @@ bool fetch_add_fetcher(const char *scheme, fetcher_finalise finaliser); void fetch_send_callback(fetch_msg msg, struct fetch *fetch, - const void *data, unsigned long size); + const void *data, unsigned long size, + fetch_error_code errorcode); void fetch_remove_from_queues(struct fetch *fetch); void fetch_free(struct fetch *f); void fetch_set_http_code(struct fetch *fetch, long http_code); diff --git a/content/fetchcache.c b/content/fetchcache.c index 8643cc1a2..87732d49e 100644 --- a/content/fetchcache.c +++ b/content/fetchcache.c @@ -38,6 +38,8 @@ #include "content/content.h" #include "content/fetchcache.h" #include "content/fetch.h" +#include "desktop/options.h" +#include "desktop/searchweb.h" #include "content/urldb.h" #include "utils/log.h" #include "utils/messages.h" @@ -49,17 +51,23 @@ static char error_page[1000]; static regex_t re_content_type; static void fetchcache_callback(fetch_msg msg, void *p, const void *data, - unsigned long size); + unsigned long size, fetch_error_code errorcode); static char *fetchcache_parse_type(const char *s, char **params[]); static void fetchcache_parse_header(struct content *c, const char *data, size_t size); -static void fetchcache_error_page(struct content *c, const char *error); +static void fetchcache_error_page(struct content *c, const char *error, + fetch_error_code errorcode); +static void fetchcache_search_redirect(struct content *c, const char *error); static void fetchcache_cache_update(struct content *c); static void fetchcache_cache_clone(struct content *c, const struct cache_data *data); static void fetchcache_notmodified(struct content *c, const void *data); static void fetchcache_redirect(struct content *c, const void *data, unsigned long size); +static void fetchcache_redirect_common(struct content *c, bool verifiable, + const char *url, const char *referer, + struct content *parent); + static void fetchcache_auth(struct content *c, const char *realm); @@ -276,7 +284,8 @@ void fetchcache_go(struct content *content, const char *referer, callback(CONTENT_MSG_ERROR, content, p1, p2, msg_data); } else { - fetchcache_error_page(content, error_message); + fetchcache_error_page(content, error_message, + FETCH_ERROR_NO_ERROR); } return; @@ -366,7 +375,8 @@ void fetchcache_go(struct content *content, const char *referer, content_broadcast(content, CONTENT_MSG_ERROR, msg_data); } else { - fetchcache_error_page(content, error_message); + fetchcache_error_page(content, error_message, + FETCH_ERROR_NO_ERROR); } } @@ -405,7 +415,7 @@ void fetchcache_go(struct content *content, const char *referer, */ void fetchcache_callback(fetch_msg msg, void *p, const void *data, - unsigned long size) + unsigned long size, fetch_error_code errorcode) { bool res; struct content *c = p; @@ -506,7 +516,7 @@ void fetchcache_callback(fetch_msg msg, void *p, const void *data, msg_data); } else { content_reset(c); - fetchcache_error_page(c, data); + fetchcache_error_page(c, data, errorcode); } break; @@ -721,17 +731,29 @@ void fetchcache_parse_header(struct content *c, const char *data, /** - * Generate an error page. - * + * Generate an error page. Optionally redirect to web search provider * \param c empty content to generate the page in * \param error message to display */ -void fetchcache_error_page(struct content *c, const char *error) +void fetchcache_error_page(struct content *c, const char *error, + fetch_error_code errorcode) { const char *params[] = { 0 }; int length; - + char *host; + + if (option_search_url_bar) { + if (url_host(c->url, &host) != URL_FUNC_OK) { + warn_user(messages_get("NoMemory"), 0); + } else if ((strcasecmp(host, search_web_provider_host()) + != 0) && (errorcode == + FETCH_ERROR_COULDNT_RESOLVE_HOST)) { + fetchcache_search_redirect(c, error); + free(host); + return; + } + } if ((length = snprintf(error_page, sizeof(error_page), messages_get("ErrorPage"), error)) < 0) length = 0; @@ -746,6 +768,27 @@ void fetchcache_error_page(struct content *c, const char *error) c->fresh = false; } +void fetchcache_search_redirect(struct content *c, const char *error) +{ + char *redirurl, *temp; + + /* clear http:// plus trailing / from url, it is already escaped */ + temp = strdup(c->url + SLEN("http://")); + if (temp == NULL) { + warn_user(messages_get("NoMemory"), 0); + return; + } + temp[strlen(temp)-1] = '\0'; + redirurl = search_web_get_url(temp); + if (redirurl == NULL) { + warn_user(messages_get("NoMemory"), 0); + return; + } + + fetchcache_redirect_common(c, false, redirurl, NULL, c); + free(redirurl); + return; +} /** * Update a content's cache state @@ -930,7 +973,6 @@ void fetchcache_redirect(struct content *c, const void *data, long http_code; const char *ref; struct content *parent; - bool can_fetch; bool parent_was_verifiable; union content_msg_data msg_data; url_func_result result; @@ -1056,32 +1098,50 @@ void fetchcache_redirect(struct content *c, const void *data, } free(scheme); - - /* Determine if we've got a fetch handler for this url */ - can_fetch = fetch_can_fetch(url); + fetchcache_redirect_common(c, parent_was_verifiable, url, referer, parent); + free(url); + free(referer); +} + +/** + * common logic from fetchcache_redirect() / fetchcache_search_redirect() + * \param c the content param from the original function + * \param verifiable parent_was_verifiable [false for search_redirect] + * \param url the url being considered; caller retains ownership + * \param referer referer [ / NULL particularly for search_redirect] + * \param parent parent content [ / c for search_redirect] + */ +void fetchcache_redirect_common(struct content *c, bool verifiable, + const char *url, const char *referer, struct content *parent) +{ + union content_msg_data msg_data; + bool can_fetch; + /* check there's a fetch handler */ + can_fetch = fetch_can_fetch(url); + /* Process users of this content */ while (c->user_list->next) { intptr_t p1, p2; void (*callback)(content_msg msg, - struct content *c, intptr_t p1, - intptr_t p2, - union content_msg_data data); + struct content *c, intptr_t p1, + intptr_t p2, + union content_msg_data data); struct content *replacement; - + p1 = c->user_list->next->p1; p2 = c->user_list->next->p2; callback = c->user_list->next->callback; - + /* If we can't fetch this url, attempt to launch it */ if (!can_fetch) { msg_data.launch_url = url; callback(CONTENT_MSG_LAUNCH, c, p1, p2, msg_data); } - + /* Remove user */ content_remove_user(c, callback, p1, p2); - + if (can_fetch) { /* Get replacement content -- HTTP GET request */ @@ -1101,37 +1161,29 @@ void fetchcache_redirect(struct content *c, const void *data, */ replacement = fetchcache(url, callback, p1, p2, c->width, c->height, c->no_error_pages, - NULL, NULL, parent_was_verifiable, + NULL, NULL, verifiable, c->download); if (!replacement) { msg_data.error = messages_get("BadRedirect"); content_broadcast(c, CONTENT_MSG_ERROR, msg_data); - - free(url); - free(referer); return; - } - + } /* Set replacement's redirect count to 1 greater * than ours */ replacement->redirect_count = c->redirect_count + 1; - + /* Notify user that content has changed */ msg_data.new_url = url; callback(CONTENT_MSG_NEWPTR, replacement, - p1, p2, msg_data); - + p1, p2, msg_data); + /* Start fetching the replacement content */ fetchcache_go(replacement, referer, callback, p1, p2, - c->width, c->height, NULL, NULL, - parent_was_verifiable, parent); + c->width, c->height, NULL, NULL, + verifiable, parent); } } - - /* Clean up */ - free(url); - free(referer); } /** @@ -1218,7 +1270,8 @@ void fetchcache_auth(struct content *c, const char *realm) msg_data.error = error_message; content_broadcast(c, CONTENT_MSG_ERROR, msg_data); } else { - fetchcache_error_page(c, error_message); + fetchcache_error_page(c, error_message, + FETCH_ERROR_URL); } } diff --git a/content/fetchers/fetch_curl.c b/content/fetchers/fetch_curl.c index 8efe0d726..67b74ef99 100644 --- a/content/fetchers/fetch_curl.c +++ b/content/fetchers/fetch_curl.c @@ -748,6 +748,7 @@ void fetch_curl_done(CURL *curl_handle, CURLcode result) { bool finished = false; bool error = false; + fetch_error_code errorcode = FETCH_ERROR_NO_ERROR; bool cert = false; bool abort_fetch; struct curl_fetch_info *f; @@ -778,8 +779,10 @@ void fetch_curl_done(CURL *curl_handle, CURLcode result) * Content-Length header. */ if (!f->had_headers && fetch_curl_process_headers(f)) ; /* redirect with partial body, or similar */ - else + else { error = true; + errorcode = FETCH_ERROR_PARTIAL_FILE; + } } else if (result == CURLE_WRITE_ERROR && f->stopped) /* CURLE_WRITE_ERROR occurs when fetch_curl_data * returns 0, which we use to abort intentionally */ @@ -790,9 +793,14 @@ void fetch_curl_done(CURL *curl_handle, CURLcode result) memset(f->cert_data, 0, sizeof(f->cert_data)); cert = true; } + else if (result == CURLE_COULDNT_RESOLVE_HOST) { + error = true; + errorcode = FETCH_ERROR_COULDNT_RESOLVE_HOST; + } else { LOG(("Unknown cURL response code %d", result)); error = true; + errorcode = FETCH_ERROR_MISC; } fetch_curl_stop(f); @@ -800,7 +808,7 @@ void fetch_curl_done(CURL *curl_handle, CURLcode result) if (abort_fetch) ; /* fetch was aborted: no callback */ else if (finished) - fetch_send_callback(FETCH_FINISHED, f->fetch_handle, 0, 0); + fetch_send_callback(FETCH_FINISHED, f->fetch_handle, 0, 0, errorcode); else if (cert) { int i; BIO *mem; @@ -877,14 +885,14 @@ void fetch_curl_done(CURL *curl_handle, CURLcode result) if (certs[i].cert->references == 0) X509_free(certs[i].cert); } - + errorcode = FETCH_ERROR_CERT; fetch_send_callback(FETCH_CERT_ERR, f->fetch_handle, - &ssl_certs, i); + &ssl_certs, i, errorcode); } else if (error) fetch_send_callback(FETCH_ERROR, f->fetch_handle, - fetch_error_buffer, 0); + fetch_error_buffer, 0, errorcode); fetch_free(f->fetch_handle); } @@ -910,14 +918,16 @@ int fetch_curl_progress(void *clientp, double dltotal, double dlnow, human_friendly_bytesize(dlnow), human_friendly_bytesize(dltotal)); fetch_send_callback(FETCH_PROGRESS, f->fetch_handle, - fetch_progress_buffer, - (unsigned long) percent); + fetch_progress_buffer, + (unsigned long) percent, + FETCH_ERROR_NO_ERROR); } else { snprintf(fetch_progress_buffer, 255, messages_get("ProgressU"), human_friendly_bytesize(dlnow)); fetch_send_callback(FETCH_PROGRESS, f->fetch_handle, - fetch_progress_buffer, 0); + fetch_progress_buffer, 0, + FETCH_ERROR_NO_ERROR); } return 0; @@ -977,7 +987,8 @@ size_t fetch_curl_data(char *data, size_t size, size_t nmemb, /* send data to the caller */ /*LOG(("FETCH_DATA"));*/ - fetch_send_callback(FETCH_DATA, f->fetch_handle, data, size * nmemb); + fetch_send_callback(FETCH_DATA, f->fetch_handle, data, size * nmemb, + FETCH_ERROR_NO_ERROR); if (f->abort) { f->stopped = true; @@ -1006,7 +1017,8 @@ size_t fetch_curl_header(char *data, size_t size, size_t nmemb, return 0; } - fetch_send_callback(FETCH_HEADER, f->fetch_handle, data, size); + fetch_send_callback(FETCH_HEADER, f->fetch_handle, data, size, + FETCH_ERROR_NO_ERROR); #define SKIP_ST(o) for (i = (o); i < (int) size && (data[i] == ' ' || data[i] == '\t'); i++) @@ -1100,20 +1112,23 @@ bool fetch_curl_process_headers(struct curl_fetch_info *f) if (http_code == 304 && !f->post_urlenc && !f->post_multipart) { /* Not Modified && GET request */ - fetch_send_callback(FETCH_NOTMODIFIED, f->fetch_handle, 0, 0); + fetch_send_callback(FETCH_NOTMODIFIED, f->fetch_handle, 0, 0, + FETCH_ERROR_NO_ERROR); return true; } /* handle HTTP redirects (3xx response codes) */ if (300 <= http_code && http_code < 400 && f->location != 0) { LOG(("FETCH_REDIRECT, '%s'", f->location)); - fetch_send_callback(FETCH_REDIRECT, f->fetch_handle, f->location, 0); + fetch_send_callback(FETCH_REDIRECT, f->fetch_handle, + f->location, 0, FETCH_ERROR_NO_ERROR); return true; } /* 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; } @@ -1121,7 +1136,8 @@ bool fetch_curl_process_headers(struct curl_fetch_info *f) if (f->only_2xx && strncmp(f->url, "http", 4) == 0 && (http_code < 200 || 299 < http_code)) { fetch_send_callback(FETCH_ERROR, f->fetch_handle, - messages_get("Not2xx"), 0); + messages_get("Not2xx"), 0, + FETCH_ERROR_HTTP_NOT2); return true; } @@ -1141,7 +1157,7 @@ bool fetch_curl_process_headers(struct curl_fetch_info *f) "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)); + strlen(etag_buf), FETCH_ERROR_NO_ERROR); /* don't set last modified time so as to ensure that local * files are revalidated at all times. */ @@ -1151,7 +1167,7 @@ bool fetch_curl_process_headers(struct curl_fetch_info *f) f->last_modified > s.st_mtime && f->file_etag == s.st_mtime) { fetch_send_callback(FETCH_NOTMODIFIED, f->fetch_handle, - 0, 0); + 0, 0, FETCH_ERROR_NO_ERROR); curl_free(url_path); return true; } @@ -1167,7 +1183,7 @@ bool fetch_curl_process_headers(struct curl_fetch_info *f) curl_free(url_path); LOG(("FETCH_TYPE, '%s'", type)); - fetch_send_callback(FETCH_TYPE, f->fetch_handle, type, f->content_length); + fetch_send_callback(FETCH_TYPE, f->fetch_handle, type, f->content_length, FETCH_ERROR_NO_ERROR); if (f->abort) return true; diff --git a/content/fetchers/fetch_data.c b/content/fetchers/fetch_data.c index 30274f51e..5b40b4ef6 100644 --- a/content/fetchers/fetch_data.c +++ b/content/fetchers/fetch_data.c @@ -129,10 +129,10 @@ static void fetch_data_abort(void *ctx) static void fetch_data_send_callback(fetch_msg msg, struct fetch_data_context *c, const void *data, - unsigned long size) + unsigned long size, fetch_error_code errorcode) { c->locked = true; - fetch_send_callback(msg, c->parent_fetch, data, size); + fetch_send_callback(msg, c->parent_fetch, data, size, errorcode); c->locked = false; } @@ -154,7 +154,7 @@ static bool fetch_data_process(struct fetch_data_context *c) if (strlen(c->url) < 6) { /* 6 is the minimum possible length (data:,) */ fetch_data_send_callback(FETCH_ERROR, c, - "Malformed data: URL", 0); + "Malformed data: URL", 0, FETCH_ERROR_URL); return false; } @@ -164,7 +164,7 @@ static bool fetch_data_process(struct fetch_data_context *c) /* find the comma */ if ( (comma = strchr(params, ',')) == NULL) { fetch_data_send_callback(FETCH_ERROR, c, - "Malformed data: URL", 0); + "Malformed data: URL", 0, FETCH_ERROR_URL); return false; } @@ -179,7 +179,7 @@ static bool fetch_data_process(struct fetch_data_context *c) if (c->mimetype == NULL) { fetch_data_send_callback(FETCH_ERROR, c, "Unable to allocate memory for mimetype in data: URL", - 0); + 0, FETCH_ERROR_MEMORY); return false; } @@ -198,7 +198,8 @@ static bool fetch_data_process(struct fetch_data_context *c) c->datalen = templen; if (unescaped == NULL) { fetch_data_send_callback(FETCH_ERROR, c, - "Unable to URL decode data: URL", 0); + "Unable to URL decode data: URL", 0, + FETCH_ERROR_ENCODING); return false; } @@ -207,7 +208,8 @@ static bool fetch_data_process(struct fetch_data_context *c) if (base64_decode(unescaped, c->datalen, c->data, &(c->datalen)) == false) { fetch_data_send_callback(FETCH_ERROR, c, - "Unable to Base64 decode data: URL", 0); + "Unable to Base64 decode data: URL", 0, + FETCH_ERROR_ENCODING); curl_free(unescaped); return false; } @@ -215,7 +217,8 @@ static bool fetch_data_process(struct fetch_data_context *c) c->data = malloc(c->datalen); if (c->data == NULL) { fetch_data_send_callback(FETCH_ERROR, c, - "Unable to allocate memory for data: URL", 0); + "Unable to allocate memory for data: URL", 0, + FETCH_ERROR_MEMORY); curl_free(unescaped); return false; } @@ -271,14 +274,17 @@ static void fetch_data_poll(const char *scheme) * call to fetch_data_send_callback(). */ fetch_data_send_callback(FETCH_TYPE, - c, c->mimetype, c->datalen); + c, c->mimetype, c->datalen, + FETCH_ERROR_NO_ERROR); if (!c->aborted) { fetch_data_send_callback(FETCH_DATA, - c, c->data, c->datalen); + c, c->data, c->datalen, + FETCH_ERROR_NO_ERROR); } if (!c->aborted) { fetch_data_send_callback(FETCH_FINISHED, - c, &cachedata, 0); + c, &cachedata, 0, + FETCH_ERROR_NO_ERROR); } } else { LOG(("Processing of %s failed!", c->url)); |