diff options
Diffstat (limited to 'content/fetchers/data.c')
-rw-r--r-- | content/fetchers/data.c | 132 |
1 files changed, 65 insertions, 67 deletions
diff --git a/content/fetchers/data.c b/content/fetchers/data.c index 5ba021fd3..c7de14c3d 100644 --- a/content/fetchers/data.c +++ b/content/fetchers/data.c @@ -23,6 +23,7 @@ #include <stdbool.h> #include <string.h> +#include <stdarg.h> #include <stdlib.h> #include <libwapcaplet/libwapcaplet.h> #include <nsutils/base64.h> @@ -41,7 +42,7 @@ struct fetch_data_context { struct fetch *parent_fetch; - char *url; + nsurl *url; char *mimetype; char *data; size_t datalen; @@ -74,6 +75,36 @@ static bool fetch_data_can_fetch(const nsurl *url) return true; } +static void fetch_data_send_callback(const fetch_msg *msg, + struct fetch_data_context *c) +{ + c->locked = true; + fetch_send_callback(msg, c->parent_fetch); + c->locked = false; +} + +static void fetch_data_send_header(struct fetch_data_context *ctx, + const char *fmt, ...) +{ + char header[64]; + fetch_msg msg; + va_list ap; + int len; + + va_start(ap, fmt); + len = vsnprintf(header, sizeof(header), fmt, ap); + va_end(ap); + + if (len >= (int)sizeof(header) || len < 0) { + return; + } + + msg.type = FETCH_HEADER; + msg.data.header_or_data.len = len; + msg.data.header_or_data.buf = (const uint8_t *)header; + fetch_data_send_callback(&msg, ctx); +} + static void *fetch_data_setup(struct fetch *parent_fetch, nsurl *url, bool only_2xx, bool downgrade_tls, const char *post_urlenc, const struct fetch_multipart_data *post_multipart, @@ -85,14 +116,7 @@ static void *fetch_data_setup(struct fetch *parent_fetch, nsurl *url, return NULL; ctx->parent_fetch = parent_fetch; - - /* TODO: keep as nsurl to avoid copy */ - ctx->url = malloc(nsurl_length(url) + 1); - if (ctx->url == NULL) { - free(ctx); - return NULL; - } - memcpy(ctx->url, nsurl_access(url), nsurl_length(url) + 1); + ctx->url = nsurl_ref(url); RING_INSERT(ring, ctx); @@ -108,10 +132,9 @@ static void fetch_data_free(void *ctx) { struct fetch_data_context *c = ctx; - free(c->url); + nsurl_unref(c->url); free(c->data); free(c->mimetype); - RING_REMOVE(ring, c); free(ctx); } @@ -126,20 +149,12 @@ static void fetch_data_abort(void *ctx) c->aborted = true; } -static void fetch_data_send_callback(const fetch_msg *msg, - struct fetch_data_context *c) -{ - c->locked = true; - fetch_send_callback(msg, c->parent_fetch); - c->locked = false; -} - static bool fetch_data_process(struct fetch_data_context *c) { nserror res; fetch_msg msg; - char *params; - char *comma; + const char *params; + const char *comma; char *unescaped; size_t unescaped_len; @@ -149,9 +164,9 @@ static bool fetch_data_process(struct fetch_data_context *c) * data must still be there. */ - NSLOG(netsurf, INFO, "url: %.140s", c->url); + NSLOG(netsurf, DEEPDEBUG, "url: %.140s", nsurl_access(c->url)); - if (strlen(c->url) < 6) { + if (nsurl_length(c->url) < 6) { /* 6 is the minimum possible length (data:,) */ msg.type = FETCH_ERROR; msg.data.error = "Malformed data: URL"; @@ -160,7 +175,7 @@ static bool fetch_data_process(struct fetch_data_context *c) } /* skip the data: part */ - params = c->url + SLEN("data:"); + params = nsurl_access(c->url) + SLEN("data:"); /* find the comma */ if ( (comma = strchr(params, ',')) == NULL) { @@ -216,21 +231,12 @@ static bool fetch_data_process(struct fetch_data_context *c) free(unescaped); return false; } + free(unescaped); } else { - c->data = malloc(unescaped_len); - if (c->data == NULL) { - msg.type = FETCH_ERROR; - msg.data.error = - "Unable to allocate memory for data: URL"; - fetch_data_send_callback(&msg, c); - free(unescaped); - return false; - } c->datalen = unescaped_len; - memcpy(c->data, unescaped, unescaped_len); + c->data = unescaped; } - free(unescaped); return true; } @@ -238,13 +244,14 @@ static bool fetch_data_process(struct fetch_data_context *c) static void fetch_data_poll(lwc_string *scheme) { fetch_msg msg; - struct fetch_data_context *c, *next; - - if (ring == NULL) return; + struct fetch_data_context *c, *save_ring = NULL; /* Iterate over ring, processing each pending fetch */ - c = ring; - do { + while (ring != NULL) { + /* Take the first entry from the ring */ + c = ring; + RING_REMOVE(ring, c); + /* Ignore fetches that have been flagged as locked. * This allows safe re-entrant calls to this function. * Re-entrancy can occur if, as a result of a callback, @@ -252,14 +259,12 @@ static void fetch_data_poll(lwc_string *scheme) * again. */ if (c->locked == true) { - next = c->r_next; + RING_INSERT(save_ring, c); continue; } /* Only process non-aborted fetches */ if (c->aborted == false && fetch_data_process(c) == true) { - char header[64]; - fetch_set_http_code(c->parent_fetch, 200); NSLOG(netsurf, INFO, "setting data: MIME type to %s, length to %"PRIsizet, @@ -269,22 +274,18 @@ static void fetch_data_poll(lwc_string *scheme) * Therefore, we _must_ check for this after _every_ * call to fetch_data_send_callback(). */ - snprintf(header, sizeof header, "Content-Type: %s", + fetch_data_send_header(c, "Content-Type: %s", c->mimetype); - msg.type = FETCH_HEADER; - msg.data.header_or_data.buf = (const uint8_t *) header; - msg.data.header_or_data.len = strlen(header); - fetch_data_send_callback(&msg, c); if (c->aborted == false) { - snprintf(header, sizeof header, - "Content-Length: %" PRIsizet, - c->datalen); - msg.type = FETCH_HEADER; - msg.data.header_or_data.buf = - (const uint8_t *) header; - msg.data.header_or_data.len = strlen(header); - fetch_data_send_callback(&msg, c); + fetch_data_send_header(c, "Content-Length: %" + PRIsizet, c->datalen); + } + + if (c->aborted == false) { + /* Set max-age to 1 year. */ + fetch_data_send_header(c, "Cache-Control: " + "max-age=31536000"); } if (c->aborted == false) { @@ -300,8 +301,8 @@ static void fetch_data_poll(lwc_string *scheme) fetch_data_send_callback(&msg, c); } } else { - NSLOG(netsurf, INFO, "Processing of %s failed!", - c->url); + NSLOG(netsurf, INFO, "Processing of %.140s failed!", + nsurl_access(c->url)); /* Ensure that we're unlocked here. If we aren't, * then fetch_data_process() is broken. @@ -309,18 +310,15 @@ static void fetch_data_poll(lwc_string *scheme) assert(c->locked == false); } - /* Compute next fetch item at the last possible moment as - * processing this item may have added to the ring. - */ - next = c->r_next; - + /* And now finish */ fetch_remove_from_queues(c->parent_fetch); fetch_free(c->parent_fetch); + } - /* Advance to next ring entry, exiting if we've reached - * the start of the ring or the ring has become empty - */ - } while ( (c = next) != ring && ring != NULL); + /* Finally, if we saved any fetches which were locked, put them back + * into the ring for next time + */ + ring = save_ring; } nserror fetch_data_register(void) |