summaryrefslogtreecommitdiff
path: root/content/fetchers/data.c
diff options
context:
space:
mode:
Diffstat (limited to 'content/fetchers/data.c')
-rw-r--r--content/fetchers/data.c132
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)