From ce0d5294d5898b6100269bd39d38c0884d5fd4b4 Mon Sep 17 00:00:00 2001 From: James Bursa Date: Sat, 27 Dec 2003 20:15:23 +0000 Subject: [project @ 2003-12-27 20:15:22 by bursa] Use charset from Content-Type header. svn path=/import/netsurf/; revision=460 --- content/content.c | 12 ++++++--- content/content.h | 3 ++- content/fetchcache.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++----- content/fetchcache.h | 1 + content/other.c | 2 +- content/other.h | 2 +- 6 files changed, 82 insertions(+), 13 deletions(-) (limited to 'content') diff --git a/content/content.c b/content/content.c index 280364b9d..a3ff9f777 100644 --- a/content/content.c +++ b/content/content.c @@ -57,7 +57,7 @@ static const struct mime_entry mime_map[] = { /** An entry in handler_map. */ struct handler_entry { - void (*create)(struct content *c); + void (*create)(struct content *c, const char *params[]); void (*process_data)(struct content *c, char *data, unsigned long size); int (*convert)(struct content *c, unsigned int width, unsigned int height); void (*revive)(struct content *c, unsigned int width, unsigned int height); @@ -169,9 +169,15 @@ struct content * content_create(char *url) * status is changed to CONTENT_STATUS_LOADING. CONTENT_MSG_LOADING is sent to * all users. The create function for the type is called to initialise the type * specific parts of the content structure. + * + * \param c content structure + * \param type content_type to initialise to + * \param mime_type MIME-type string for this content + * \param params array of strings, ordered attribute, value, attribute, ..., 0 */ -void content_set_type(struct content *c, content_type type, char* mime_type) +void content_set_type(struct content *c, content_type type, char* mime_type, + const char *params[]) { assert(c != 0); assert(c->status == CONTENT_STATUS_TYPE_UNKNOWN); @@ -180,7 +186,7 @@ void content_set_type(struct content *c, content_type type, char* mime_type) c->type = type; c->mime_type = xstrdup(mime_type); c->status = CONTENT_STATUS_LOADING; - handler_map[type].create(c); + handler_map[type].create(c, params); content_broadcast(c, CONTENT_MSG_LOADING, 0); /* c may be destroyed at this point as a result of * CONTENT_MSG_LOADING, so must not be accessed */ diff --git a/content/content.h b/content/content.h index 72034b316..2e4a36f31 100644 --- a/content/content.h +++ b/content/content.h @@ -139,7 +139,8 @@ struct browser_window; content_type content_lookup(const char *mime_type); struct content * content_create(char *url); -void content_set_type(struct content *c, content_type type, char *mime_type); +void content_set_type(struct content *c, content_type type, char *mime_type, + const char *params[]); void content_process_data(struct content *c, char *data, unsigned long size); void content_convert(struct content *c, unsigned long width, unsigned long height); void content_revive(struct content *c, unsigned long width, unsigned long height); diff --git a/content/fetchcache.c b/content/fetchcache.c index 9e89f5876..cc755e73c 100644 --- a/content/fetchcache.c +++ b/content/fetchcache.c @@ -15,6 +15,8 @@ #include #include +#include +#include #include "netsurf/content/cache.h" #include "netsurf/content/content.h" #include "netsurf/content/fetchcache.h" @@ -23,7 +25,9 @@ #include "netsurf/utils/utils.h" +static regex_t re_content_type; static void fetchcache_callback(fetch_msg msg, void *p, char *data, unsigned long size); +static char *fetchcache_parse_type(char *s, char **params[]); /** @@ -95,20 +99,21 @@ void fetchcache_callback(fetch_msg msg, void *p, char *data, unsigned long size) { struct content *c = p; content_type type; - char *mime_type; - char *semic; - char *url; + char *mime_type, *url; + char **params; + unsigned int i; switch (msg) { case FETCH_TYPE: c->total_size = size; - mime_type = xstrdup(data); - if ((semic = strchr(mime_type, ';')) != 0) - *semic = 0; /* remove "; charset=..." */ + mime_type = fetchcache_parse_type(data, ¶ms); type = content_lookup(mime_type); LOG(("FETCH_TYPE, type %u", type)); - content_set_type(c, type, mime_type); + content_set_type(c, type, mime_type, params); free(mime_type); + for (i = 0; params[i]; i++) + free(params[i]); + free(params); break; case FETCH_DATA: @@ -172,6 +177,62 @@ void fetchcache_callback(fetch_msg msg, void *p, char *data, unsigned long size) } +/** + * Initialise the fetchcache module. + */ + +void fetchcache_init(void) +{ + regcomp_wrapper(&re_content_type, + "^([-0-9a-zA-Z_.]+/[-0-9a-zA-Z_.]+)[ \t]*" + "(;[ \t]*([-0-9a-zA-Z_.]+)=" + "([-0-9a-zA-Z_.]+|\"([^\"]|[\\].)*\")[ \t]*)*$", + REG_EXTENDED); +} + + +/** + * Parse a Content-Type header. + * + * \param s a Content-Type header + * \param params updated to point to an array of strings, ordered attribute, + * value, attribute, ..., 0 + * \return a new string containing the MIME-type + */ + +#define MAX_ATTRS 10 + +char *fetchcache_parse_type(char *s, char **params[]) +{ + char *type; + unsigned int i; + int r; + regmatch_t pmatch[2 + MAX_ATTRS * 3]; + *params = xcalloc(MAX_ATTRS * 2 + 2, sizeof (*params)[0]); + + r = regexec(&re_content_type, s, 2 + MAX_ATTRS * 3, pmatch, 0); + if (r) { + LOG(("failed to parse content-type '%s'", s)); + return xstrdup(s); + } + + type = strndup(s + pmatch[1].rm_so, pmatch[1].rm_eo - pmatch[1].rm_so); + assert(type); + + /* parameters */ + for (i = 0; i != MAX_ATTRS && pmatch[2 + 3 * i].rm_so != -1; i++) { + (*params)[2 * i] = strndup(s + pmatch[2 + 3 * i + 1].rm_so, + pmatch[2 + 3 * i + 1].rm_eo - pmatch[2 + 3 * i + 1].rm_so); + (*params)[2 * i + 1] = strndup(s + pmatch[2 + 3 * i + 2].rm_so, + pmatch[2 + 3 * i + 2].rm_eo - pmatch[2 + 3 * i + 2].rm_so); + assert((*params)[2 * i] && (*params)[2 * i + 1]); + } + (*params)[2 * i] = 0; + + return type; +} + + #ifdef TEST #include diff --git a/content/fetchcache.h b/content/fetchcache.h index 36d40e098..12326970b 100644 --- a/content/fetchcache.h +++ b/content/fetchcache.h @@ -26,5 +26,6 @@ struct content * fetchcache(const char *url, char *referer, void *p1, void *p2, unsigned long width, unsigned long height, bool only_2xx, char *post_urlenc, struct form_successful_control *post_multipart, bool cookies); +void fetchcache_init(void); #endif diff --git a/content/other.c b/content/other.c index a974bd8ed..a4ef7bec7 100644 --- a/content/other.c +++ b/content/other.c @@ -17,7 +17,7 @@ #include "netsurf/utils/utils.h" -void other_create(struct content *c) +void other_create(struct content *c, char *params[]) { c->data.other.data = xcalloc(0, 1); c->data.other.length = 0; diff --git a/content/other.h b/content/other.h index 96326a159..71fd4aab4 100644 --- a/content/other.h +++ b/content/other.h @@ -24,7 +24,7 @@ struct content_other_data { unsigned long length; /**< Current length of stored data. */ }; -void other_create(struct content *c); +void other_create(struct content *c, char *params[]); void other_process_data(struct content *c, char *data, unsigned long size); int other_convert(struct content *c, unsigned int width, unsigned int height); void other_revive(struct content *c, unsigned int width, unsigned int height); -- cgit v1.2.3