From 5c310d84dc6153b62e33d5aa28a1f75e2e776ea6 Mon Sep 17 00:00:00 2001 From: James Bursa Date: Fri, 29 Aug 2003 12:57:14 +0000 Subject: [project @ 2003-08-29 12:57:14 by bursa] Better handling of server HTTP errors. svn path=/import/netsurf/; revision=259 --- !NetSurf/Resources/en/Messages | 3 ++ content/fetch.c | 79 +++++++++++++++++++++++++----------------- content/fetch.h | 5 ++- content/fetchcache.c | 5 +-- content/fetchcache.h | 3 +- css/css.c | 6 ++-- debug/netsurfd.c | 3 +- desktop/browser.c | 2 +- render/html.c | 12 +++---- 9 files changed, 71 insertions(+), 47 deletions(-) diff --git a/!NetSurf/Resources/en/Messages b/!NetSurf/Resources/en/Messages index b1764fd95..5635197f5 100644 --- a/!NetSurf/Resources/en/Messages +++ b/!NetSurf/Resources/en/Messages @@ -25,3 +25,6 @@ Reload:Reload this page # Download window Downloaded:Download complete, %lu bytes + +Not2xx:Server returned an error + diff --git a/content/fetch.c b/content/fetch.c index eb79afae3..300b68023 100644 --- a/content/fetch.c +++ b/content/fetch.c @@ -18,27 +18,30 @@ */ #include +#include #include #include #include #include "curl/curl.h" #include "libxml/uri.h" #include "netsurf/content/fetch.h" -#include "netsurf/utils/utils.h" -#include "netsurf/utils/log.h" -#include "netsurf/desktop/options.h" #ifdef riscos #include "netsurf/desktop/gui.h" #endif +#include "netsurf/desktop/options.h" +#include "netsurf/utils/log.h" +#include "netsurf/utils/messages.h" +#include "netsurf/utils/utils.h" struct fetch { time_t start_time; CURL * curl_handle; void (*callback)(fetch_msg msg, void *p, char *data, unsigned long size); - int had_headers : 1; - int in_callback : 1; - int aborting : 1; + bool had_headers; + bool in_callback; + bool aborting; + bool only_2xx; char *url; char *referer; char error_buffer[CURL_ERROR_SIZE]; @@ -60,7 +63,7 @@ static struct fetch *fetch_list = 0; static size_t fetch_curl_data(void * data, size_t size, size_t nmemb, struct fetch *f); static size_t fetch_curl_header(char * data, size_t size, size_t nmemb, struct fetch *f); -static int fetch_process_headers(struct fetch *f); +static bool fetch_process_headers(struct fetch *f); #ifdef riscos extern const char * const NETSURF_DIR; @@ -115,7 +118,8 @@ void fetch_quit(void) */ struct fetch * fetch_start(char *url, char *referer, - void (*callback)(fetch_msg msg, void *p, char *data, unsigned long size), void *p) + void (*callback)(fetch_msg msg, void *p, char *data, unsigned long size), + void *p, bool only_2xx) { struct fetch *fetch = xcalloc(1, sizeof(*fetch)), *host_fetch; CURLcode code; @@ -133,9 +137,10 @@ struct fetch * fetch_start(char *url, char *referer, /* construct a new fetch structure */ fetch->start_time = time(0); fetch->callback = callback; - fetch->had_headers = 0; - fetch->in_callback = 0; - fetch->aborting = 0; + fetch->had_headers = false; + fetch->in_callback = false; + fetch->aborting = false; + fetch->only_2xx = only_2xx; fetch->url = xstrdup(url); fetch->referer = 0; if (referer != 0) @@ -223,10 +228,10 @@ struct fetch * fetch_start(char *url, char *referer, /* use proxy if options dictate this */ if (OPTIONS.http) { - code = curl_easy_setopt(fetch->curl_handle, CURLOPT_PROXY, OPTIONS.http_proxy); - assert(code == CURLE_OK); - code = curl_easy_setopt(fetch->curl_handle, CURLOPT_PROXYPORT, (long)OPTIONS.http_port); - assert(code == CURLE_OK); + code = curl_easy_setopt(fetch->curl_handle, CURLOPT_PROXY, OPTIONS.http_proxy); + assert(code == CURLE_OK); + code = curl_easy_setopt(fetch->curl_handle, CURLOPT_PROXYPORT, (long)OPTIONS.http_port); + assert(code == CURLE_OK); } @@ -251,7 +256,7 @@ void fetch_abort(struct fetch *f) if (f->in_callback) { LOG(("in callback: will abort later")); - f->aborting = 1; + f->aborting = true; return; } @@ -325,7 +330,8 @@ void fetch_poll(void) { CURLcode code; CURLMcode codem; - int running, queue, finished; + int running, queue; + bool finished; CURLMsg * curl_msg; struct fetch *f; void *p; @@ -349,7 +355,7 @@ void fetch_poll(void) LOG(("CURLMSG_DONE, result %i", curl_msg->data.result)); /* inform the caller that the fetch is done */ - finished = 0; + finished = false; callback = f->callback; p = f->p; if (curl_msg->data.result == CURLE_OK) { @@ -357,7 +363,7 @@ void fetch_poll(void) if (!f->had_headers && fetch_process_headers(f)) ; /* redirect with no body or similar */ else - finished = 1; + finished = true; } else if (curl_msg->data.result != CURLE_WRITE_ERROR) { /* CURLE_WRITE_ERROR occurs when fetch_curl_data * returns 0, which we use to abort intentionally */ @@ -387,18 +393,20 @@ void fetch_poll(void) size_t fetch_curl_data(void * data, size_t size, size_t nmemb, struct fetch *f) { - f->in_callback = 1; + f->in_callback = true; LOG(("fetch %p, size %u", f, size * nmemb)); - if (!f->had_headers && fetch_process_headers(f)) + if (!f->had_headers && fetch_process_headers(f)) { + f->in_callback = false; return 0; + } /* send data to the caller */ LOG(("FETCH_DATA")); f->callback(FETCH_DATA, f->p, data, size * nmemb); - f->in_callback = 0; + f->in_callback = false; return size * nmemb; } @@ -435,28 +443,37 @@ size_t fetch_curl_header(char * data, size_t size, size_t nmemb, struct fetch *f /** * Find the status code and content type and inform the caller. + * + * Return true if the fetch is being aborted. */ -int fetch_process_headers(struct fetch *f) +bool fetch_process_headers(struct fetch *f) { long http_code; const char *type; CURLcode code; - f->had_headers = 1; + f->had_headers = true; code = curl_easy_getinfo(f->curl_handle, CURLINFO_HTTP_CODE, &http_code); assert(code == CURLE_OK); LOG(("HTTP status code %li", http_code)); + /* handle HTTP redirects (3xx response codes) */ if (300 <= http_code && http_code < 400 && f->location != 0) { - /* redirect */ LOG(("FETCH_REDIRECT, '%s'", f->location)); f->callback(FETCH_REDIRECT, f->p, f->location, 0); - f->in_callback = 0; - return 1; + return true; } + /* handle HTTP errors (non 2xx response codes) */ + if (f->only_2xx && strncmp(f->url, "http", 4) == 0 && + (http_code < 200 || 299 < http_code)) { + f->callback(FETCH_ERROR, f->p, messages_get("Not2xx"), 0); + 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); @@ -472,12 +489,10 @@ int fetch_process_headers(struct fetch *f) LOG(("FETCH_TYPE, '%s'", type)); f->callback(FETCH_TYPE, f->p, type, f->content_length); - if (f->aborting) { - f->in_callback = 0; - return 1; - } + if (f->aborting) + return true; - return 0; + return false; } diff --git a/content/fetch.h b/content/fetch.h index 7bf144f44..cc52cd414 100644 --- a/content/fetch.h +++ b/content/fetch.h @@ -35,6 +35,8 @@ #ifndef _NETSURF_DESKTOP_FETCH_H_ #define _NETSURF_DESKTOP_FETCH_H_ +#include + typedef enum {FETCH_TYPE, FETCH_DATA, FETCH_FINISHED, FETCH_ERROR, FETCH_REDIRECT} fetch_msg; struct content; @@ -42,7 +44,8 @@ struct fetch; void fetch_init(void); struct fetch * fetch_start(char *url, char *referer, - void (*callback)(fetch_msg msg, void *p, char *data, unsigned long size), void *p); + void (*callback)(fetch_msg msg, void *p, char *data, unsigned long size), + void *p, bool only_2xx); void fetch_abort(struct fetch *f); void fetch_poll(void); void fetch_quit(void); diff --git a/content/fetchcache.c b/content/fetchcache.c index 1c950ba4b..4996edd81 100644 --- a/content/fetchcache.c +++ b/content/fetchcache.c @@ -21,7 +21,8 @@ static void fetchcache_callback(fetch_msg msg, void *p, char *data, unsigned lon struct content * fetchcache(const char *url0, char *referer, void (*callback)(content_msg msg, struct content *c, void *p1, void *p2, const char *error), - void *p1, void *p2, unsigned long width, unsigned long height) + void *p1, void *p2, unsigned long width, unsigned long height, + bool only_2xx) { struct content *c; char *url = xstrdup(url0); @@ -45,7 +46,7 @@ struct content * fetchcache(const char *url0, char *referer, c->fetch_size = 0; c->width = width; c->height = height; - c->fetch = fetch_start(url, referer, fetchcache_callback, c); + c->fetch = fetch_start(url, referer, fetchcache_callback, c, only_2xx); if (c->fetch == 0) { LOG(("warning: fetch_start failed")); cache_destroy(c); diff --git a/content/fetchcache.h b/content/fetchcache.h index ddfc2fa76..6f7a083eb 100644 --- a/content/fetchcache.h +++ b/content/fetchcache.h @@ -13,6 +13,7 @@ struct content * fetchcache(const char *url, char *referer, void (*callback)(content_msg msg, struct content *c, void *p1, void *p2, const char *error), - void *p1, void *p2, unsigned long width, unsigned long height); + void *p1, void *p2, unsigned long width, unsigned long height, + bool only_2xx); #endif diff --git a/css/css.c b/css/css.c index da82cf9d1..91d0a061f 100644 --- a/css/css.c +++ b/css/css.c @@ -146,7 +146,7 @@ void css_revive(struct content *c, unsigned int width, unsigned int height) c->data.css.import_content[i] = fetchcache( c->data.css.import_url[i], c->url, css_atimport_callback, c, i, - c->width, c->height); + c->width, c->height, true); if (c->data.css.import_content[i] == 0) continue; if (c->data.css.import_content[i]->status != CONTENT_STATUS_DONE) @@ -297,7 +297,7 @@ void css_atimport(struct content *c, struct node *node) c->data.css.import_url[i] = url_join(url, c->url); c->data.css.import_content[i] = fetchcache( c->data.css.import_url[i], c->url, css_atimport_callback, - c, i, c->width, c->height); + c, i, c->width, c->height, true); if (c->data.css.import_content[i] && c->data.css.import_content[i]->status != CONTENT_STATUS_DONE) c->active++; @@ -345,7 +345,7 @@ void css_atimport_callback(content_msg msg, struct content *css, c->data.css.import_url[i] = xstrdup(error); c->data.css.import_content[i] = fetchcache( c->data.css.import_url[i], c->url, css_atimport_callback, - c, i, css->width, css->height); + c, i, css->width, css->height, true); if (c->data.css.import_content[i] && c->data.css.import_content[i]->status != CONTENT_STATUS_DONE) c->active++; diff --git a/debug/netsurfd.c b/debug/netsurfd.c index 4d21a5495..d9f14d026 100644 --- a/debug/netsurfd.c +++ b/debug/netsurfd.c @@ -5,6 +5,7 @@ * Copyright 2003 James Bursa */ +#include #include #include "netsurf/content/fetch.h" #include "netsurf/content/cache.h" @@ -41,7 +42,7 @@ int main(int argc, char *argv[]) while (1) { puts("=== URL:"); gets(url); - c = fetchcache(url, 0, callback, 0, 0, 100, 1000); + c = fetchcache(url, 0, callback, 0, 0, 100, 1000, false); if (c) { done = c->status == CONTENT_STATUS_DONE; while (!done) diff --git a/desktop/browser.c b/desktop/browser.c index d296ddaea..454a31085 100644 --- a/desktop/browser.c +++ b/desktop/browser.c @@ -233,7 +233,7 @@ void browser_window_open_location_historical(struct browser_window* bw, const ch browser_window_start_throbber(bw); bw->time0 = clock(); bw->loading_content = fetchcache(url, 0, browser_window_callback, bw, 0, - gui_window_get_width(bw->window), 0); + gui_window_get_width(bw->window), 0, false); if (bw->loading_content == 0) { browser_window_set_status(bw, "Unable to fetch document"); return; diff --git a/render/html.c b/render/html.c index a6e6d9e7d..e41a61633 100644 --- a/render/html.c +++ b/render/html.c @@ -181,7 +181,7 @@ void html_convert_css_callback(content_msg msg, struct content *css, c->active--; c->data.html.stylesheet_content[i] = fetchcache( error, c->url, html_convert_css_callback, - c, i, css->width, css->height); + c, i, css->width, css->height, true); if (c->data.html.stylesheet_content[i] != 0 && c->data.html.stylesheet_content[i]->status != CONTENT_STATUS_DONE) c->active++; @@ -234,7 +234,7 @@ void html_find_stylesheets(struct content *c, xmlNode *head) #endif c->url, html_convert_css_callback, - c, 0, c->width, c->height); + c, 0, c->width, c->height, true); assert(c->data.html.stylesheet_content[0] != 0); if (c->data.html.stylesheet_content[0]->status != CONTENT_STATUS_DONE) c->active++; @@ -285,7 +285,7 @@ void html_find_stylesheets(struct content *c, xmlNode *head) (i + 1) * sizeof(*c->data.html.stylesheet_content)); c->data.html.stylesheet_content[i] = fetchcache(url, c->url, html_convert_css_callback, c, i, - c->width, c->height); + c->width, c->height, true); if (c->data.html.stylesheet_content[i] && c->data.html.stylesheet_content[i]->status != CONTENT_STATUS_DONE) c->active++; @@ -368,7 +368,7 @@ void html_fetch_object(struct content *c, char *url, struct box *box) c->data.html.object[i].content = fetchcache(url, c->url, html_object_callback, c, i, - c->width, c->height); /* we don't know the object's + c->width, c->height, true); /* we don't know the object's dimensions yet; use parent's as an estimate */ if (c->data.html.object[i].content) { @@ -463,7 +463,7 @@ void html_object_callback(content_msg msg, struct content *object, c->data.html.object[i].url = xstrdup(error); c->data.html.object[i].content = fetchcache( error, c->url, html_object_callback, - c, i, 0, 0); + c, i, 0, 0, true); if (c->data.html.object[i].content && c->data.html.object[i].content->status != CONTENT_STATUS_DONE) c->active++; @@ -530,7 +530,7 @@ void html_revive(struct content *c, unsigned int width, unsigned int height) c->data.html.object[i].content = fetchcache( c->data.html.object[i].url, c->url, html_object_callback, - c, i, 0, 0); + c, i, 0, 0, true); if (c->data.html.object[i].content && c->data.html.object[i].content->status != CONTENT_STATUS_DONE) c->active++; -- cgit v1.2.3