From 1145b231d4b682478bdf052efbade9dbd2df11e8 Mon Sep 17 00:00:00 2001 From: James Bursa Date: Thu, 26 Jun 2003 11:41:26 +0000 Subject: [project @ 2003-06-26 11:41:26 by bursa] Implement HTTP redirects. svn path=/import/netsurf/; revision=187 --- content/content.h | 5 +++-- content/fetch.c | 50 ++++++++++++++++++++++++++++++++++++++++---------- content/fetch.h | 6 ++++-- content/fetchcache.c | 10 +++++++++- content/overview | 4 ++++ css/css.c | 13 ++++++++++++- debug/netsurfd.c | 6 +++++- desktop/browser.c | 10 +++++++++- render/html.c | 22 +++++++++++++++++++++- 9 files changed, 107 insertions(+), 19 deletions(-) diff --git a/content/content.h b/content/content.h index 077b3cc89..571e23ab2 100644 --- a/content/content.h +++ b/content/content.h @@ -1,5 +1,5 @@ /** - * $Id: content.h,v 1.12 2003/06/17 19:24:20 bursa Exp $ + * $Id: content.h,v 1.13 2003/06/26 11:41:26 bursa Exp $ */ #ifndef _NETSURF_DESKTOP_CONTENT_H_ @@ -64,7 +64,8 @@ typedef enum { CONTENT_MSG_READY, /* may be displayed */ CONTENT_MSG_DONE, /* finished */ CONTENT_MSG_ERROR, /* error occurred */ - CONTENT_MSG_STATUS /* new status string */ + CONTENT_MSG_STATUS, /* new status string */ + CONTENT_MSG_REDIRECT /* replacement URL */ } content_msg; struct content_user diff --git a/content/fetch.c b/content/fetch.c index 1e2f4686a..714aff555 100644 --- a/content/fetch.c +++ b/content/fetch.c @@ -1,5 +1,5 @@ /** - * $Id: fetch.c,v 1.11 2003/06/24 23:22:00 bursa Exp $ + * $Id: fetch.c,v 1.12 2003/06/26 11:41:26 bursa Exp $ * * This module handles fetching of data from any url. * @@ -39,6 +39,8 @@ struct fetch void *p; struct curl_slist *headers; char *host; + int status_code; + char *location; struct fetch *queue; struct fetch *prev; struct fetch *next; @@ -50,7 +52,7 @@ static CURLM * curl_multi; 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(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); /** @@ -128,6 +130,7 @@ struct fetch * fetch_start(char *url, char *referer, fetch->host = 0; if (uri->server != 0) fetch->host = xstrdup(uri->server); + fetch->status_code = 0; fetch->queue = 0; fetch->prev = 0; fetch->next = 0; @@ -170,10 +173,10 @@ struct fetch * fetch_start(char *url, char *referer, assert(code == CURLE_OK); code = curl_easy_setopt(fetch->curl_handle, CURLOPT_WRITEDATA, fetch); assert(code == CURLE_OK); -/* code = curl_easy_setopt(fetch->curl_handle, CURLOPT_HEADERFUNCTION, fetch_curl_header); + code = curl_easy_setopt(fetch->curl_handle, CURLOPT_HEADERFUNCTION, fetch_curl_header); assert(code == CURLE_OK); code = curl_easy_setopt(fetch->curl_handle, CURLOPT_WRITEHEADER, fetch); - assert(code == CURLE_OK);*/ + assert(code == CURLE_OK); code = curl_easy_setopt(fetch->curl_handle, CURLOPT_USERAGENT, user_agent); assert(code == CURLE_OK); if (referer != 0) { @@ -279,8 +282,9 @@ void fetch_abort(struct fetch *f) } xfree(f->url); - xfree(f->host); - xfree(f->referer); + free(f->host); + free(f->referer); + free(f->location); xfree(f); } @@ -357,10 +361,23 @@ size_t fetch_curl_data(void * data, size_t size, size_t nmemb, struct fetch *f) LOG(("fetch %p, size %u", f, size * nmemb)); if (!f->had_headers) { - /* find the content type and inform the caller */ + /* find the status code and content type and inform the caller */ + long http_code; const char *type; CURLcode code; + code = curl_easy_getinfo(f->curl_handle, CURLINFO_HTTP_CODE, &http_code); + assert(code == CURLE_OK); + LOG(("HTTP status code %li", http_code)); + + 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 0; + } + code = curl_easy_getinfo(f->curl_handle, CURLINFO_CONTENT_TYPE, &type); assert(code == CURLE_OK); @@ -397,10 +414,23 @@ size_t fetch_curl_data(void * data, size_t size, size_t nmemb, struct fetch *f) * fetch_curl_header -- callback function for headers */ -size_t fetch_curl_header(void *data, size_t size, size_t nmemb, struct fetch *f) +size_t fetch_curl_header(char * data, size_t size, size_t nmemb, struct fetch *f) { - LOG(("header '%*s'", size * nmemb, data)); - return size * nmemb; + int i; + size *= nmemb; + if (12 < size && strncasecmp(data, "Location:", 9) == 0) { + /* extract Location header */ + f->location = xcalloc(size, 1); + for (i = 9; data[i] == ' ' || data[i] == '\t'; i++) + ; + strncpy(f->location, data + i, size - i); + for (i = size - i - 1; f->location[i] == ' ' || + f->location[i] == '\t' || + f->location[i] == '\r' || + f->location[i] == '\n'; i--) + f->location[i] = '\0'; + } + return size; } diff --git a/content/fetch.h b/content/fetch.h index 92c269a02..af1414a77 100644 --- a/content/fetch.h +++ b/content/fetch.h @@ -1,5 +1,5 @@ /** - * $Id: fetch.h,v 1.3 2003/04/17 21:35:02 bursa Exp $ + * $Id: fetch.h,v 1.4 2003/06/26 11:41:26 bursa Exp $ * * This module handles fetching of data from any url. * @@ -16,6 +16,8 @@ * Content-Type header in data, then one or more times with FETCH_DATA with * some data for the url, and finally with FETCH_FINISHED. Alternatively, * FETCH_ERROR indicates an error occurred: data contains an error message. + * FETCH_REDIRECT may replace the FETCH_TYPE, FETCH_DATA, FETCH_FINISHED + * sequence if the server sends a replacement URL. * Some private data can be passed as the last parameter to fetch_start, and * callbacks will contain this. * @@ -28,7 +30,7 @@ #ifndef _NETSURF_DESKTOP_FETCH_H_ #define _NETSURF_DESKTOP_FETCH_H_ -typedef enum {FETCH_TYPE, FETCH_DATA, FETCH_FINISHED, FETCH_ERROR} fetch_msg; +typedef enum {FETCH_TYPE, FETCH_DATA, FETCH_FINISHED, FETCH_ERROR, FETCH_REDIRECT} fetch_msg; struct content; struct fetch; diff --git a/content/fetchcache.c b/content/fetchcache.c index 0755b37c5..da5d65e13 100644 --- a/content/fetchcache.c +++ b/content/fetchcache.c @@ -1,5 +1,5 @@ /** - * $Id: fetchcache.c,v 1.10 2003/06/17 19:24:20 bursa Exp $ + * $Id: fetchcache.c,v 1.11 2003/06/26 11:41:26 bursa Exp $ */ #include @@ -83,6 +83,14 @@ void fetchcache_callback(fetch_msg msg, void *p, char *data, unsigned long size) content_destroy(c); break; + case FETCH_REDIRECT: + LOG(("FETCH_REDIRECT, '%s'", data)); + c->fetch = 0; + content_broadcast(c, CONTENT_MSG_REDIRECT, data); + cache_destroy(c); + content_destroy(c); + break; + default: assert(0); } diff --git a/content/overview b/content/overview index 0a911dc44..f58a995c1 100644 --- a/content/overview +++ b/content/overview @@ -44,6 +44,10 @@ callback function is called when the state changes or at other times as follows: CONTENT_MSG_STATUS -- the content structure's status message has changed. + CONTENT_MSG_REDIRECT -- the server has sent a replacement URL for the content. + This message may only occur in CONTENT_STATUS_TYPE_UNKNOWN. The content + will be destroyed and must not be used. + If at any time the resource is no longer required, call content_remove_user(): content_remove_user(c, callback, p1, p2); diff --git a/css/css.c b/css/css.c index 0f5b61923..41c7d25db 100644 --- a/css/css.c +++ b/css/css.c @@ -1,5 +1,5 @@ /** - * $Id: css.c,v 1.9 2003/06/17 19:24:21 bursa Exp $ + * $Id: css.c,v 1.10 2003/06/26 11:41:26 bursa Exp $ */ #include @@ -336,6 +336,17 @@ void css_atimport_callback(content_msg msg, struct content *css, case CONTENT_MSG_STATUS: break; + case CONTENT_MSG_REDIRECT: + c->active--; + free(c->data.css.import_url[i]); + 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); + if (c->data.css.import_content[i]->status != CONTENT_STATUS_DONE) + c->active++; + break; + default: assert(0); } diff --git a/debug/netsurfd.c b/debug/netsurfd.c index 81a494ff0..dcb2150ab 100644 --- a/debug/netsurfd.c +++ b/debug/netsurfd.c @@ -14,7 +14,11 @@ void callback(content_msg msg, struct content *c, void *p1, if (msg == CONTENT_MSG_DONE || msg == CONTENT_MSG_ERROR) done = 1; else if (msg == CONTENT_MSG_STATUS) - printf("=== STATUS: %s", c->status_message); + printf("=== STATUS: %s\n", c->status_message); + else if (msg == CONTENT_MSG_REDIRECT) { + printf("=== REDIRECT to '%s'\n", error); + done = 1; + } } int main(int argc, char *argv[]) diff --git a/desktop/browser.c b/desktop/browser.c index 13fdd7d36..cc7f651a9 100644 --- a/desktop/browser.c +++ b/desktop/browser.c @@ -1,5 +1,5 @@ /** - * $Id: browser.c,v 1.40 2003/06/17 19:24:21 bursa Exp $ + * $Id: browser.c,v 1.41 2003/06/26 11:41:26 bursa Exp $ */ #include "netsurf/content/cache.h" @@ -238,6 +238,7 @@ void browser_window_open_location(struct browser_window* bw, const char* url0) assert(bw != 0 && url0 != 0); url = url_join(url0, bw->url); browser_window_open_location_historical(bw, url); + /* TODO: move this to somewhere below CONTENT_MSG_READY below */ if (bw->history == NULL) bw->history = history_create(NULL, url); else @@ -318,6 +319,13 @@ void browser_window_callback(content_msg msg, struct content *c, browser_window_set_status(bw, c->status_message); break; + case CONTENT_MSG_REDIRECT: + bw->loading_content = 0; + browser_window_set_status(bw, "Redirecting"); + /* error actually holds the new URL */ + browser_window_open_location(bw, error); + break; + default: assert(0); } diff --git a/render/html.c b/render/html.c index ab6b55560..1517e89a5 100644 --- a/render/html.c +++ b/render/html.c @@ -1,5 +1,5 @@ /** - * $Id: html.c,v 1.19 2003/06/17 19:24:21 bursa Exp $ + * $Id: html.c,v 1.20 2003/06/26 11:41:26 bursa Exp $ */ #include @@ -166,6 +166,15 @@ void html_convert_css_callback(content_msg msg, struct content *css, content_broadcast(c, CONTENT_MSG_STATUS, 0); break; + case CONTENT_MSG_REDIRECT: + c->active--; + c->data.html.stylesheet_content[i] = fetchcache( + error, c->url, html_convert_css_callback, + c, i, css->width, css->height); + if (c->data.html.stylesheet_content[i]->status != CONTENT_STATUS_DONE) + c->active++; + break; + default: assert(0); } @@ -423,6 +432,17 @@ void html_object_callback(content_msg msg, struct content *object, c->active, object->status_message); break; + case CONTENT_MSG_REDIRECT: + c->active--; + free(c->data.html.object[i].url); + 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); + if (c->data.html.object[i].content->status != CONTENT_STATUS_DONE) + c->active++; + break; + default: assert(0); } -- cgit v1.2.3