diff options
author | James Bursa <james@netsurf-browser.org> | 2007-10-02 04:48:30 +0000 |
---|---|---|
committer | James Bursa <james@netsurf-browser.org> | 2007-10-02 04:48:30 +0000 |
commit | db7a0824d343af80cfadf946d5c63365d731b346 (patch) | |
tree | ad7f51afc6c6cae709deeae42ec206be81cf9f64 /render | |
parent | ca50ffb53cd9e93960246a4bde0ee2d7bb68d4df (diff) | |
download | netsurf-db7a0824d343af80cfadf946d5c63365d731b346.tar.gz netsurf-db7a0824d343af80cfadf946d5c63365d731b346.tar.bz2 |
Process inline stylesheets anywhere in document, not just in <head>.
svn path=/trunk/netsurf/; revision=3615
Diffstat (limited to 'render')
-rw-r--r-- | render/html.c | 300 |
1 files changed, 185 insertions, 115 deletions
diff --git a/render/html.c b/render/html.c index 8ed3517e4..1068319e3 100644 --- a/render/html.c +++ b/render/html.c @@ -54,7 +54,10 @@ static void html_convert_css_callback(content_msg msg, struct content *css, intptr_t p1, intptr_t p2, union content_msg_data data); static bool html_meta_refresh(struct content *c, xmlNode *head); static bool html_head(struct content *c, xmlNode *head); -static bool html_find_stylesheets(struct content *c, xmlNode *head); +static bool html_find_stylesheets(struct content *c, xmlNode *html, + xmlNode *head); +static bool html_find_inline_stylesheets(struct content *c, xmlNode *html); +static bool html_process_style_element(struct content *c, xmlNode *style); static void html_object_callback(content_msg msg, struct content *object, intptr_t p1, intptr_t p2, union content_msg_data data); static void html_object_done(struct box *box, struct content *object, @@ -453,7 +456,7 @@ bool html_convert(struct content *c, int width, int height) } /* get stylesheets */ - if (!html_find_stylesheets(c, head)) + if (!html_find_stylesheets(c, html, head)) return false; /* convert xml tree to box tree */ @@ -699,14 +702,16 @@ bool html_meta_refresh(struct content *c, xmlNode *head) * Process inline stylesheets and fetch linked stylesheets. * * \param c content structure + * \param head xml node of html element * \param head xml node of head element, or 0 if none * \return true on success, false if an error occurred */ -bool html_find_stylesheets(struct content *c, xmlNode *head) +bool html_find_stylesheets(struct content *c, xmlNode *html, + xmlNode *head) { - xmlNode *node, *node2; - char *rel, *type, *media, *href, *data, *url; + xmlNode *node; + char *rel, *type, *media, *href, *url; unsigned int i = STYLESHEET_START; unsigned int last_active = 0; union content_msg_data msg_data; @@ -759,132 +764,83 @@ bool html_find_stylesheets(struct content *c, xmlNode *head) if (node->type != XML_ELEMENT_NODE) continue; - if (strcmp(node->name, "link") == 0) { - /* rel=<space separated list, including 'stylesheet'> */ - if ((rel = (char *) xmlGetProp(node, (const xmlChar *) "rel")) == NULL) - continue; - if (strcasestr(rel, "stylesheet") == 0) { - xmlFree(rel); - continue; - } else if (strcasestr(rel, "alternate")) { - /* Ignore alternate stylesheets */ - xmlFree(rel); - continue; - } + if (strcmp(node->name, "link") != 0) + continue; + + /* rel=<space separated list, including 'stylesheet'> */ + if ((rel = (char *) xmlGetProp(node, (const xmlChar *) "rel")) == NULL) + continue; + if (strcasestr(rel, "stylesheet") == 0) { + xmlFree(rel); + continue; + } else if (strcasestr(rel, "alternate")) { + /* Ignore alternate stylesheets */ xmlFree(rel); + continue; + } + xmlFree(rel); - /* type='text/css' or not present */ - if ((type = (char *) xmlGetProp(node, (const xmlChar *) "type")) != NULL) { - if (strcmp(type, "text/css") != 0) { - xmlFree(type); - continue; - } + /* type='text/css' or not present */ + if ((type = (char *) xmlGetProp(node, (const xmlChar *) "type")) != NULL) { + if (strcmp(type, "text/css") != 0) { xmlFree(type); + continue; } + xmlFree(type); + } - /* media contains 'screen' or 'all' or not present */ - if ((media = (char *) xmlGetProp(node, (const xmlChar *) "media")) != NULL) { - if (strcasestr(media, "screen") == 0 && - strcasestr(media, "all") == 0) { - xmlFree(media); - continue; - } + /* media contains 'screen' or 'all' or not present */ + if ((media = (char *) xmlGetProp(node, (const xmlChar *) "media")) != NULL) { + if (strcasestr(media, "screen") == 0 && + strcasestr(media, "all") == 0) { xmlFree(media); - } - - /* href='...' */ - if ((href = (char *) xmlGetProp(node, (const xmlChar *) "href")) == NULL) - continue; - - /* TODO: only the first preferred stylesheets (ie. those with a - * title attribute) should be loaded (see HTML4 14.3) */ - - res = url_join(href, c->data.html.base_url, &url); - xmlFree(href); - if (res != URL_FUNC_OK) continue; + } + xmlFree(media); + } - LOG(("linked stylesheet %i '%s'", i, url)); + /* href='...' */ + if ((href = (char *) xmlGetProp(node, (const xmlChar *) "href")) == NULL) + continue; - /* start fetch */ - stylesheet_content = talloc_realloc(c, - c->data.html.stylesheet_content, - struct content *, i + 1); - if (!stylesheet_content) - goto no_memory; - c->data.html.stylesheet_content = stylesheet_content; - c->data.html.stylesheet_content[i] = fetchcache(url, - html_convert_css_callback, - (intptr_t) c, i, c->width, c->height, - true, 0, 0, false, false); - if (!c->data.html.stylesheet_content[i]) - goto no_memory; - c->active++; - fetchcache_go(c->data.html.stylesheet_content[i], - c->url, - html_convert_css_callback, - (intptr_t) c, i, c->width, c->height, - 0, 0, false, c->url); - free(url); - i++; - - } else if (strcmp(node->name, "style") == 0) { - /* type='text/css', or not present (invalid but common) */ - if ((type = (char *) xmlGetProp(node, (const xmlChar *) "type")) != NULL) { - if (strcmp(type, "text/css") != 0) { - xmlFree(type); - continue; - } - xmlFree(type); - } + /* TODO: only the first preferred stylesheets (ie. those with a + * title attribute) should be loaded (see HTML4 14.3) */ - /* media contains 'screen' or 'all' or not present */ - if ((media = (char *) xmlGetProp(node, (const xmlChar *) "media")) != NULL) { - if (strcasestr(media, "screen") == 0 && - strcasestr(media, "all") == 0) { - xmlFree(media); - continue; - } - xmlFree(media); - } + res = url_join(href, c->data.html.base_url, &url); + xmlFree(href); + if (res != URL_FUNC_OK) + continue; - /* create stylesheet */ - LOG(("style element")); - if (c->data.html.stylesheet_content[STYLESHEET_STYLE] == 0) { - const char *params[] = { 0 }; - c->data.html.stylesheet_content[STYLESHEET_STYLE] = - content_create(c->data.html. - base_url); - if (!c->data.html.stylesheet_content[STYLESHEET_STYLE]) - goto no_memory; - if (!content_set_type(c->data.html. - stylesheet_content[STYLESHEET_STYLE], - CONTENT_CSS, "text/css", - params)) - /** \todo not necessarily caused by - * memory exhaustion */ - goto no_memory; - } + LOG(("linked stylesheet %i '%s'", i, url)); - /* can't just use xmlNodeGetContent(node), because that won't give - * the content of comments which may be used to 'hide' the content */ - for (node2 = node->children; node2 != 0; node2 = node2->next) { - data = xmlNodeGetContent(node2); - if (!content_process_data(c->data.html. - stylesheet_content[STYLESHEET_STYLE], - data, strlen(data))) { - xmlFree(data); - /** \todo not necessarily caused by - * memory exhaustion */ - goto no_memory; - } - xmlFree(data); - } - } + /* start fetch */ + stylesheet_content = talloc_realloc(c, + c->data.html.stylesheet_content, + struct content *, i + 1); + if (!stylesheet_content) + goto no_memory; + c->data.html.stylesheet_content = stylesheet_content; + c->data.html.stylesheet_content[i] = fetchcache(url, + html_convert_css_callback, + (intptr_t) c, i, c->width, c->height, + true, 0, 0, false, false); + if (!c->data.html.stylesheet_content[i]) + goto no_memory; + c->active++; + fetchcache_go(c->data.html.stylesheet_content[i], + c->url, + html_convert_css_callback, + (intptr_t) c, i, c->width, c->height, + 0, 0, false, c->url); + free(url); + i++; } c->data.html.stylesheet_count = i; + if (!html_find_inline_stylesheets(c, html)) + return false; + if (c->data.html.stylesheet_content[STYLESHEET_STYLE] != 0) { if (css_convert(c->data.html.stylesheet_content[STYLESHEET_STYLE], c->width, c->height)) { @@ -952,6 +908,120 @@ no_memory: /** + * Process inline stylesheets in the document. + * + * \param c content structure + * \param head xml node of html element + * \return true on success, false if an error occurred + */ + +bool html_find_inline_stylesheets(struct content *c, xmlNode *html) +{ + xmlNode *node = html; + + /* depth-first search the tree for style elements */ + while (node) { + if (node->children) { /* 1. children */ + node = node->children; + } else if (node->next) { /* 2. siblings */ + node = node->next; + } else { /* 3. ancestor siblings */ + while (node && !node->next) + node = node->parent; + if (!node) + break; + node = node->next; + } + + assert(node); + + if (node->type != XML_ELEMENT_NODE) + continue; + if (strcmp(node->name, "style") != 0) + continue; + + if (!html_process_style_element(c, node)) + return false; + } + + return true; +} + + +/** + * Process an inline stylesheet in the document. + * + * \param c content structure + * \param style xml node of style element + * \return true on success, false if an error occurred + */ + +bool html_process_style_element(struct content *c, xmlNode *style) +{ + xmlNode *child; + char *type, *media, *data; + union content_msg_data msg_data; + + /* type='text/css', or not present (invalid but common) */ + if ((type = (char *) xmlGetProp(style, (const xmlChar *) "type"))) { + if (strcmp(type, "text/css") != 0) { + xmlFree(type); + return true; + } + xmlFree(type); + } + + /* media contains 'screen' or 'all' or not present */ + if ((media = (char *) xmlGetProp(style, (const xmlChar *) "media"))) { + if (strcasestr(media, "screen") == 0 && + strcasestr(media, "all") == 0) { + xmlFree(media); + return true; + } + xmlFree(media); + } + + /* create stylesheet */ + if (c->data.html.stylesheet_content[STYLESHEET_STYLE] == 0) { + const char *params[] = { 0 }; + c->data.html.stylesheet_content[STYLESHEET_STYLE] = + content_create(c->data.html.base_url); + if (!c->data.html.stylesheet_content[STYLESHEET_STYLE]) + goto no_memory; + if (!content_set_type(c->data.html. + stylesheet_content[STYLESHEET_STYLE], + CONTENT_CSS, "text/css", params)) + /** \todo not necessarily caused by + * memory exhaustion */ + goto no_memory; + } + + /* can't just use xmlNodeGetContent(style), because that won't + * give the content of comments which may be used to 'hide' + * the content */ + for (child = style->children; child != 0; child = child->next) { + data = xmlNodeGetContent(child); + if (!content_process_data(c->data.html. + stylesheet_content[STYLESHEET_STYLE], + data, strlen(data))) { + xmlFree(data); + /** \todo not necessarily caused by + * memory exhaustion */ + goto no_memory; + } + xmlFree(data); + } + + return true; + +no_memory: + msg_data.error = messages_get("NoMemory"); + content_broadcast(c, CONTENT_MSG_ERROR, msg_data); + return false; +} + + +/** * Callback for fetchcache() for linked stylesheets. */ |