summaryrefslogtreecommitdiff
path: root/render
diff options
context:
space:
mode:
Diffstat (limited to 'render')
-rw-r--r--render/box_construct.c4
-rw-r--r--render/box_normalise.c14
-rw-r--r--render/html.c513
-rw-r--r--render/html.h7
-rw-r--r--render/html_internal.h21
-rw-r--r--render/html_script.c339
-rw-r--r--render/hubbub_binding.c1325
-rw-r--r--render/libdom_binding.c126
-rw-r--r--render/parser_binding.h63
9 files changed, 478 insertions, 1934 deletions
diff --git a/render/box_construct.c b/render/box_construct.c
index c09563d89..5f8b092c5 100644
--- a/render/box_construct.c
+++ b/render/box_construct.c
@@ -1426,7 +1426,7 @@ css_select_results *box_get_style(html_content *c,
dom_string_byte_length(s),
c->encoding,
nsurl_access(content_get_url(&c->base)),
- c->quirks != BINDING_QUIRKS_MODE_NONE,
+ c->quirks != DOM_DOCUMENT_QUIRKS_MODE_NONE,
box_style_alloc, NULL);
dom_string_unref(s);
@@ -1437,7 +1437,7 @@ css_select_results *box_get_style(html_content *c,
/* Populate selection context */
ctx.ctx = c->select_ctx;
- ctx.quirks = (c->quirks == BINDING_QUIRKS_MODE_FULL);
+ ctx.quirks = (c->quirks == DOM_DOCUMENT_QUIRKS_MODE_FULL);
ctx.base_url = c->base_url;
ctx.universal = c->universal;
diff --git a/render/box_normalise.c b/render/box_normalise.c
index fb378d3e7..19a1cbc25 100644
--- a/render/box_normalise.c
+++ b/render/box_normalise.c
@@ -152,7 +152,7 @@ bool box_normalise_block(struct box *block, html_content *c)
assert(block->style != NULL);
ctx.ctx = c->select_ctx;
- ctx.quirks = (c->quirks == BINDING_QUIRKS_MODE_FULL);
+ ctx.quirks = (c->quirks == DOM_DOCUMENT_QUIRKS_MODE_FULL);
ctx.base_url = c->base_url;
ctx.universal = c->universal;
@@ -254,7 +254,7 @@ bool box_normalise_table(struct box *table, html_content * c)
assert(table->style != NULL);
ctx.ctx = c->select_ctx;
- ctx.quirks = (c->quirks == BINDING_QUIRKS_MODE_FULL);
+ ctx.quirks = (c->quirks == DOM_DOCUMENT_QUIRKS_MODE_FULL);
ctx.base_url = c->base_url;
ctx.universal = c->universal;
@@ -341,7 +341,7 @@ bool box_normalise_table(struct box *table, html_content * c)
assert(table->style != NULL);
ctx.ctx = c->select_ctx;
- ctx.quirks = (c->quirks == BINDING_QUIRKS_MODE_FULL);
+ ctx.quirks = (c->quirks == DOM_DOCUMENT_QUIRKS_MODE_FULL);
ctx.base_url = c->base_url;
ctx.universal = c->universal;
@@ -477,7 +477,7 @@ bool box_normalise_table_spans(struct box *table, struct span_info *spans,
ctx.ctx = c->select_ctx;
ctx.quirks = (c->quirks ==
- BINDING_QUIRKS_MODE_FULL);
+ DOM_DOCUMENT_QUIRKS_MODE_FULL);
ctx.base_url = c->base_url;
ctx.universal = c->universal;
@@ -587,7 +587,7 @@ bool box_normalise_table_row_group(struct box *row_group,
assert(row_group->style != NULL);
ctx.ctx = c->select_ctx;
- ctx.quirks = (c->quirks == BINDING_QUIRKS_MODE_FULL);
+ ctx.quirks = (c->quirks == DOM_DOCUMENT_QUIRKS_MODE_FULL);
ctx.base_url = c->base_url;
ctx.universal = c->universal;
@@ -662,7 +662,7 @@ bool box_normalise_table_row_group(struct box *row_group,
assert(row_group->style != NULL);
ctx.ctx = c->select_ctx;
- ctx.quirks = (c->quirks == BINDING_QUIRKS_MODE_FULL);
+ ctx.quirks = (c->quirks == DOM_DOCUMENT_QUIRKS_MODE_FULL);
ctx.base_url = c->base_url;
ctx.universal = c->universal;
@@ -732,7 +732,7 @@ bool box_normalise_table_row(struct box *row,
assert(row->style != NULL);
ctx.ctx = c->select_ctx;
- ctx.quirks = (c->quirks == BINDING_QUIRKS_MODE_FULL);
+ ctx.quirks = (c->quirks == DOM_DOCUMENT_QUIRKS_MODE_FULL);
ctx.base_url = c->base_url;
ctx.universal = c->universal;
diff --git a/render/html.c b/render/html.c
index 996bfc3a5..8c11f35b9 100644
--- a/render/html.c
+++ b/render/html.c
@@ -28,8 +28,6 @@
#include <strings.h>
#include <stdlib.h>
-#include <dom/dom.h>
-
#include "utils/config.h"
#include "content/content_protected.h"
#include "content/fetch.h"
@@ -38,7 +36,6 @@
#include "desktop/options.h"
#include "desktop/selection.h"
#include "desktop/scrollbar.h"
-#include "javascript/js.h"
#include "image/bitmap.h"
#include "render/box.h"
#include "render/font.h"
@@ -86,15 +83,15 @@ static dom_string *html_dom_string_head;
static dom_string *html_dom_string_rel;
dom_string *html_dom_string_href;
static dom_string *html_dom_string_hreflang;
-static dom_string *html_dom_string_type;
+dom_string *html_dom_string_type;
static dom_string *html_dom_string_media;
static dom_string *html_dom_string_sizes;
static dom_string *html_dom_string_title;
static dom_string *html_dom_string_base;
static dom_string *html_dom_string_link;
static dom_string *html_dom_string_script;
-static dom_string *html_dom_string_text_javascript;
-static dom_string *html_dom_string_src;
+dom_string *html_dom_string_text_javascript;
+dom_string *html_dom_string_src;
dom_string *html_dom_string_target;
static dom_string *html_dom_string__parent;
static dom_string *html_dom_string__self;
@@ -117,107 +114,6 @@ dom_string *html_dom_string_circle;
dom_string *html_dom_string_poly;
dom_string *html_dom_string_polygon;
-typedef bool (script_handler_t)(struct jscontext *jscontext, const char *data, size_t size) ;
-
-
-static script_handler_t *select_script_handler(content_type ctype)
-{
- if (ctype == CONTENT_JS) {
- return js_exec;
- }
- return NULL;
-}
-
-
-/* attempt to progress script execution
- *
- * execute scripts using algorithm found in:
- * http://www.whatwg.org/specs/web-apps/current-work/multipage/scripting-1.html#the-script-element
- *
- */
-static bool html_scripts_exec(html_content *c)
-{
- unsigned int i;
- struct html_script *s;
- script_handler_t *script_handler;
-
- if (c->jscontext == NULL)
- return false;
-
- for (i = 0, s = c->scripts; i != c->scripts_count; i++, s++) {
- if (s->already_started) {
- continue;
- }
-
- assert((s->type == HTML_SCRIPT_EXTERNAL) ||
- (s->type == HTML_SCRIPT_INTERNAL));
-
- if (s->type == HTML_SCRIPT_EXTERNAL) {
- /* ensure script content is present */
- if (s->data.external == NULL)
- continue;
-
- /* ensure script content fetch status is not an error */
- if (content_get_status(s->data.external) == CONTENT_STATUS_ERROR)
- continue;
-
- /* ensure script handler for content type */
- script_handler = select_script_handler(content_get_type(s->data.external));
- if (script_handler == NULL)
- continue; /* unsupported type */
-
- if (content_get_status(s->data.external) == CONTENT_STATUS_DONE) {
- /* external script is now available */
- const char *data;
- unsigned long size;
- data = content_get_source_data(s->data.external, &size );
- script_handler(c->jscontext, data, size);
-
- s->already_started = true;
-
- } else {
- /* script not yet available */
-
- /* check if deferable or asynchronous */
- if (!s->defer && !s->async) {
- break;
- }
- }
- }
- }
-
- return true;
-}
-
-/* create new html script entry */
-static struct html_script *
-html_process_new_script(html_content *c, enum html_script_type type)
-{
- struct html_script *nscript;
- /* add space for new script entry */
- nscript = realloc(c->scripts,
- sizeof(struct html_script) * (c->scripts_count + 1));
- if (nscript == NULL) {
- return NULL;
- }
-
- c->scripts = nscript;
-
- /* increment script entry count */
- nscript = &c->scripts[c->scripts_count];
- c->scripts_count++;
-
- nscript->already_started = false;
- nscript->parser_inserted = false;
- nscript->force_async = true;
- nscript->ready_exec = false;
- nscript->async = false;
- nscript->defer = false;
-
- nscript->type = type;
-
- return nscript;
-}
static void html_destroy_objects(html_content *html)
{
@@ -293,8 +189,8 @@ static void html_box_convert_done(html_content *c, bool success)
/*imagemap_dump(c);*/
/* Destroy the parser binding */
- binding_destroy_tree(c->parser_binding);
- c->parser_binding = NULL;
+ dom_hubbub_parser_destroy(c->parser);
+ c->parser = NULL;
content_set_ready(&c->base);
@@ -309,7 +205,7 @@ static void html_box_convert_done(html_content *c, bool success)
*
* \param c Content to convert
*/
-static void html_finish_conversion(html_content *c)
+void html_finish_conversion(html_content *c)
{
union content_msg_data msg_data;
dom_exception exc; /* returned by libdom functions */
@@ -400,217 +296,17 @@ static void html_finish_conversion(html_content *c)
}
-/**
- * Callback for fetchcache() for linked stylesheets.
- */
-
-static nserror
-html_convert_script_callback(hlcache_handle *script,
- const hlcache_event *event,
- void *pw)
-{
- html_content *parent = pw;
- unsigned int i;
- struct html_script *s;
-
- /* Find script */
- for (i = 0, s = parent->scripts; i != parent->scripts_count; i++, s++) {
- if (s->type == HTML_SCRIPT_EXTERNAL &&
- s->data.external == script)
- break;
- }
-
- assert(i != parent->scripts_count);
-
- switch (event->type) {
- case CONTENT_MSG_LOADING:
- break;
-
- case CONTENT_MSG_READY:
- break;
-
- case CONTENT_MSG_DONE:
- LOG(("script %d done '%s'", i,
- nsurl_access(hlcache_handle_get_url(script))));
- parent->base.active--;
- LOG(("%d fetches active", parent->base.active));
-
- /* script finished loading so try and continue execution */
- html_scripts_exec(parent);
- break;
-
- case CONTENT_MSG_ERROR:
- LOG(("script %s failed: %s",
- nsurl_access(hlcache_handle_get_url(script)),
- event->data.error));
- hlcache_handle_release(script);
- s->data.external = NULL;
- parent->base.active--;
- LOG(("%d fetches active", parent->base.active));
- content_add_error(&parent->base, "?", 0);
-
- /* script failed loading so try and continue execution */
- html_scripts_exec(parent);
-
- break;
-
- case CONTENT_MSG_STATUS:
- html_set_status(parent, content_get_status_message(script));
- content_broadcast(&parent->base, CONTENT_MSG_STATUS,
- event->data);
- break;
-
- default:
- assert(0);
- }
-
- if (parent->base.active == 0)
- html_finish_conversion(parent);
-
- return NSERROR_OK;
-}
-
-/** process script node
- *
- *
- */
-static dom_hubbub_error
-html_process_script(void *ctx, dom_node *node)
-{
- html_content *c = (html_content *)ctx;
- dom_exception exc; /* returned by libdom functions */
- dom_string *src, *script, *mimetype;
- struct html_script *nscript;
- union content_msg_data msg_data;
-
- /* ensure javascript context is available */
- if (c->jscontext == NULL) {
- union content_msg_data msg_data;
-
- msg_data.jscontext = &c->jscontext;
- content_broadcast(&c->base, CONTENT_MSG_GETCTX, msg_data);
- LOG(("javascript context %p ", c->jscontext));
- if (c->jscontext == NULL) {
- /* no context and it could not be created, abort */
- return DOM_HUBBUB_OK;
- }
- }
-
- LOG(("content %p parser %p node %p",c,c->parser_binding, node));
-
- exc = dom_element_get_attribute(node, html_dom_string_type, &mimetype);
- if (exc != DOM_NO_ERR || mimetype == NULL) {
- mimetype = dom_string_ref(html_dom_string_text_javascript);
- }
-
- exc = dom_element_get_attribute(node, html_dom_string_src, &src);
- if (exc != DOM_NO_ERR || src == NULL) {
- struct lwc_string_s *lwcmimetype;
- script_handler_t *script_handler;
-
- /* does not appear to be a src so script is inline content */
- exc = dom_node_get_text_content(node, &script);
- if ((exc != DOM_NO_ERR) || (script == NULL)) {
- dom_string_unref(mimetype);
- return DOM_HUBBUB_OK; /* no contents, skip */
- }
-
- nscript = html_process_new_script(c, HTML_STYLESHEET_INTERNAL);
- if (nscript == NULL) {
- dom_string_unref(mimetype);
- dom_string_unref(script);
- goto html_process_script_no_memory;
- }
-
- nscript->data.internal = script;
- nscript->mimetype = mimetype;
- nscript->already_started = true;
-
- /* charset (encoding) */
-
- /* ensure script handler for content type */
- dom_string_intern(mimetype, &lwcmimetype);
- script_handler = select_script_handler(content_factory_type_from_mime_type(lwcmimetype));
- lwc_string_unref(lwcmimetype);
-
- if (script_handler != NULL) {
- script_handler(c->jscontext,
- dom_string_data(script),
- dom_string_byte_length(script));
- }
-
-
- } else {
- /* script with a src tag */
- nserror ns_error;
- nsurl *joined;
- hlcache_child_context child;
-
-
- nscript = html_process_new_script(c, HTML_STYLESHEET_EXTERNAL);
- if (nscript == NULL) {
- dom_string_unref(src);
- dom_string_unref(mimetype);
- goto html_process_script_no_memory;
- }
-
- /* charset (encoding) */
-
- ns_error = nsurl_join(c->base_url, dom_string_data(src), &joined);
- dom_string_unref(src);
- if (ns_error != NSERROR_OK) {
- dom_string_unref(mimetype);
- goto html_process_script_no_memory;
- }
-
- nscript->mimetype = mimetype; /* keep reference to mimetype */
-
- LOG(("script %i '%s'", c->scripts_count, nsurl_access(joined)));
-
- child.charset = c->encoding;
- child.quirks = c->base.quirks;
-
- ns_error = hlcache_handle_retrieve(joined,
- 0,
- content_get_url(&c->base),
- NULL,
- html_convert_script_callback,
- c,
- &child,
- CONTENT_SCRIPT,
- &nscript->data.external);
-
- nsurl_unref(joined);
-
- if (ns_error != NSERROR_OK) {
- goto html_process_script_no_memory;
- }
-
- c->base.active++; /* ensure base content knows the fetch is active */
- LOG(("%d fetches active", c->base.active));
-
- }
- html_scripts_exec(c);
-
- return DOM_HUBBUB_OK;
-
-html_process_script_no_memory:
- msg_data.error = messages_get("NoMemory");
- content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
- return DOM_HUBBUB_NOMEM;
-}
static nserror
html_create_html_data(html_content *c, const http_parameter *params)
{
lwc_string *charset;
union content_msg_data msg_data;
- binding_error error;
nserror nerror;
- c->parser_binding = NULL;
+ c->parser = NULL;
c->document = NULL;
- c->quirks = BINDING_QUIRKS_MODE_NONE;
+ c->quirks = DOM_DOCUMENT_QUIRKS_MODE_NONE;
c->encoding = NULL;
c->base_url = nsurl_ref(content_get_url(&c->base));
c->base_target = NULL;
@@ -637,8 +333,10 @@ html_create_html_data(html_content *c, const http_parameter *params)
c->jscontext = NULL;
if (lwc_intern_string("*", SLEN("*"), &c->universal) != lwc_error_ok) {
- error = BINDING_NOMEM;
- goto error;
+ msg_data.error = messages_get("NoMemory");
+ content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
+
+ return NSERROR_NOMEM;
}
selection_prepare(&c->sel, (struct content *)c, true);
@@ -650,60 +348,56 @@ html_create_html_data(html_content *c, const http_parameter *params)
lwc_string_unref(charset);
if (c->encoding == NULL) {
- error = BINDING_NOMEM;
- goto error;
+ lwc_string_unref(c->universal);
+ c->universal = NULL;
+
+ msg_data.error = messages_get("NoMemory");
+ content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
+
+ return NSERROR_NOMEM;
+
}
- c->encoding_source = ENCODING_SOURCE_HEADER;
+ c->encoding_source = DOM_HUBBUB_ENCODING_SOURCE_HEADER;
}
/* Create the parser binding */
- error = binding_create_tree(&c->parser_binding,
- c->encoding,
- nsoption_bool(enable_javascript),
- html_process_script,
- c);
- if (error == BINDING_BADENCODING && c->encoding != NULL) {
+ c->parser = dom_hubbub_parser_create(c->encoding,
+ true,
+ nsoption_bool(enable_javascript),
+ NULL,
+ html_process_script,
+ c);
+ if ((c->parser == NULL) && (c->encoding != NULL)) {
/* Ok, we don't support the declared encoding. Bailing out
* isn't exactly user-friendly, so fall back to autodetect */
talloc_free(c->encoding);
c->encoding = NULL;
- error = binding_create_tree(&c->parser_binding,
- c->encoding,
- nsoption_bool(enable_javascript),
- html_process_script,
- c);
+ c->parser = dom_hubbub_parser_create(c->encoding,
+ true,
+ nsoption_bool(enable_javascript),
+ NULL,
+ html_process_script,
+ c);
- }
-
- if (error != BINDING_OK)
- goto error;
- return NSERROR_OK;
-
-error:
- if (error == BINDING_BADENCODING) {
- LOG(("Bad encoding: %s", c->encoding ? c->encoding : ""));
- msg_data.error = messages_get("ParsingFail");
- nerror = NSERROR_BAD_ENCODING;
- } else {
- msg_data.error = messages_get("NoMemory");
- nerror = NSERROR_NOMEM;
}
- content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
+ if (c->parser == NULL) {
+ nsurl_unref(c->base_url);
+ c->base_url = NULL;
- if (c->universal != NULL) {
lwc_string_unref(c->universal);
c->universal = NULL;
- }
- if (c->base_url != NULL) {
- nsurl_unref(c->base_url);
- c->base_url = NULL;
+ msg_data.error = messages_get("NoMemory");
+ content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
+
+ return NSERROR_NOMEM;
}
- return nerror;
+ return NSERROR_OK;
+
}
/**
@@ -757,14 +451,16 @@ static bool
html_process_data(struct content *c, const char *data, unsigned int size)
{
html_content *html = (html_content *) c;
- binding_error err;
+ dom_hubbub_error error;
const char *encoding;
+ const char *source_data;
+ unsigned long source_size;
- err = binding_parse_chunk(html->parser_binding,
- (const uint8_t *) data, size);
- if (err == BINDING_ENCODINGCHANGE) {
+ error = dom_hubbub_parser_parse_chunk(html->parser, (const uint8_t *) data, size);
+
+ if (error == (DOM_HUBBUB_HUBBUB_ERR | HUBBUB_ENCODINGCHANGE)) {
goto encoding_change;
- } else if (err != BINDING_OK) {
+ } else if (error != DOM_HUBBUB_OK) {
union content_msg_data msg_data;
msg_data.error = messages_get("NoMemory");
@@ -778,9 +474,8 @@ html_process_data(struct content *c, const char *data, unsigned int size)
encoding_change:
/* Retrieve new encoding */
- encoding = binding_get_encoding(
- html->parser_binding,
- &html->encoding_source);
+ encoding = dom_hubbub_parser_get_encoding(html->parser,
+ &html->encoding_source);
if (html->encoding != NULL)
talloc_free(html->encoding);
@@ -795,16 +490,17 @@ encoding_change:
}
/* Destroy binding */
- binding_destroy_tree(html->parser_binding);
- html->parser_binding = NULL;
+ dom_hubbub_parser_destroy(html->parser);
+ html->parser = NULL;
/* Create new binding, using the new encoding */
- err = binding_create_tree(&html->parser_binding,
- html->encoding,
- nsoption_bool(enable_javascript),
- html_process_script,
- html);
- if (err == BINDING_BADENCODING) {
+ html->parser = dom_hubbub_parser_create(html->encoding,
+ true,
+ nsoption_bool(enable_javascript),
+ NULL,
+ html_process_script,
+ html);
+ if (html->parser == NULL) {
/* Ok, we don't support the declared encoding. Bailing out
* isn't exactly user-friendly, so fall back to Windows-1252 */
talloc_free(html->encoding);
@@ -817,37 +513,35 @@ encoding_change:
return false;
}
- err = binding_create_tree(&html->parser_binding,
- html->encoding,
- nsoption_bool(enable_javascript),
- html_process_script,
- html);
- }
+ html->parser = dom_hubbub_parser_create(html->encoding,
+ true,
+ nsoption_bool(enable_javascript),
+ NULL,
+ html_process_script,
+ html);
- if (err != BINDING_OK) {
- union content_msg_data msg_data;
+ if (html->parser == NULL) {
+ union content_msg_data msg_data;
+
+ /** @todo add a message callback function and pass the
+ * parser errors back instead of everything being
+ * OOM
+ */
- if (err == BINDING_BADENCODING) {
- LOG(("Bad encoding: %s", html->encoding
- ? html->encoding : ""));
- msg_data.error = messages_get("ParsingFail");
- } else
msg_data.error = messages_get("NoMemory");
- content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
- return false;
- }
+ content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ return false;
+ }
- {
- const char *source_data;
- unsigned long source_size;
+ }
- source_data = content__get_source_data(c, &source_size);
+ source_data = content__get_source_data(c, &source_size);
- /* Recurse to reprocess all the data. This is safe because
- * the encoding is now specified at parser start which means
- * it cannot be changed again. */
- return html_process_data(c, source_data, source_size);
- }
+ /* Recurse to reprocess all the data. This is safe because
+ * the encoding is now specified at parser start which means
+ * it cannot be changed again. */
+ return html_process_data(c, source_data, source_size);
+
}
@@ -2156,7 +1850,7 @@ static bool html_find_stylesheets(html_content *c, dom_node *html)
c->base.active++;
LOG(("%d fetches active", c->base.active));
- if (c->quirks == BINDING_QUIRKS_MODE_FULL) {
+ if (c->quirks == DOM_DOCUMENT_QUIRKS_MODE_FULL) {
ns_error = hlcache_handle_retrieve(html_quirks_stylesheet_url,
0, content_get_url(&c->base), NULL,
html_convert_css_callback, c, &child,
@@ -2224,7 +1918,7 @@ html_find_stylesheets_no_memory:
static bool html_convert(struct content *c)
{
html_content *htmlc = (html_content *) c;
- binding_error err;
+ dom_hubbub_error err;
dom_node *html, *head;
union content_msg_data msg_data;
unsigned long size;
@@ -2235,18 +1929,18 @@ static bool html_convert(struct content *c)
/* finish parsing */
content__get_source_data(c, &size);
- err = binding_parse_completed(htmlc->parser_binding);
- if (err != BINDING_OK) {
+ err = dom_hubbub_parser_completed(htmlc->parser);
+ if (err != DOM_HUBBUB_OK) {
union content_msg_data msg_data;
+ /** @todo Improve precessing of errors */
msg_data.error = messages_get("NoMemory");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
- htmlc->document = binding_get_document(htmlc->parser_binding,
- &htmlc->quirks);
+ htmlc->document = dom_hubbub_parser_get_document(htmlc->parser);
if (htmlc->document == NULL) {
LOG(("Parsing failed"));
@@ -2255,10 +1949,18 @@ static bool html_convert(struct content *c)
return false;
}
+ exc = dom_document_get_quirks_mode(htmlc->document, &htmlc->quirks);
+ if (exc != DOM_NO_ERR) {
+ LOG(("error retrieving quirks"));
+ }
+
+ LOG(("quirks set to %d", htmlc->quirks));
+
+
if (htmlc->encoding == NULL) {
- const char *encoding = binding_get_encoding(
- htmlc->parser_binding,
- &htmlc->encoding_source);
+ const char *encoding;
+ encoding = dom_hubbub_parser_get_encoding(htmlc->parser,
+ &htmlc->encoding_source);
htmlc->encoding = talloc_strdup(c, encoding);
if (htmlc->encoding == NULL) {
@@ -2667,13 +2369,14 @@ static void html_destroy(struct content *c)
if (html->base_url)
nsurl_unref(html->base_url);
- if (html->parser_binding != NULL) {
- binding_destroy_tree(html->parser_binding);
- html->parser_binding = NULL;
+ if (html->parser != NULL) {
+ dom_hubbub_parser_destroy(html->parser);
+ html->parser = NULL;
}
- if (html->document != NULL)
- binding_destroy_document(html->document);
+ if (html->document != NULL) {
+ dom_node_unref(html->document);
+ }
/* Free base target */
if (html->base_target != NULL) {
@@ -3244,7 +2947,7 @@ const char *html_get_encoding(hlcache_handle *h)
* \param h Content to retrieve charset from
* \return Pointer to charset, or NULL
*/
-binding_encoding_source html_get_encoding_source(hlcache_handle *h)
+dom_hubbub_encoding_source html_get_encoding_source(hlcache_handle *h)
{
html_content *c = (html_content *) hlcache_handle_get_content(h);
diff --git a/render/html.h b/render/html.h
index 5867bcff2..64548f810 100644
--- a/render/html.h
+++ b/render/html.h
@@ -26,11 +26,14 @@
#define _NETSURF_RENDER_HTML_H_
#include <stdbool.h>
+
+#include <dom/dom.h>
+#include <dom/bindings/hubbub/parser.h>
+
#include "content/content_type.h"
#include "css/css.h"
#include "desktop/mouse.h"
#include "desktop/plot_style.h"
-#include "render/parser_binding.h"
#include "desktop/frame_types.h"
struct fetch_multipart_data;
@@ -167,7 +170,7 @@ bool text_redraw(const char *utf8_text, size_t utf8_len,
dom_document *html_get_document(struct hlcache_handle *h);
struct box *html_get_box_tree(struct hlcache_handle *h);
const char *html_get_encoding(struct hlcache_handle *h);
-binding_encoding_source html_get_encoding_source(struct hlcache_handle *h);
+dom_hubbub_encoding_source html_get_encoding_source(struct hlcache_handle *h);
struct content_html_frames *html_get_frameset(struct hlcache_handle *h);
struct content_html_iframe *html_get_iframe(struct hlcache_handle *h);
nsurl *html_get_base_url(struct hlcache_handle *h);
diff --git a/render/html_internal.h b/render/html_internal.h
index d5e1f05f3..ad032f720 100644
--- a/render/html_internal.h
+++ b/render/html_internal.h
@@ -31,17 +31,17 @@
typedef struct html_content {
struct content base;
- /** Parser object handle */
- void *parser_binding;
+ dom_hubbub_parser *parser; /**< Parser object handle */
+
/** Document tree */
dom_document *document;
/** Quirkyness of document */
- binding_quirks_mode quirks;
+ dom_document_quirks_mode quirks;
/** Encoding of source, NULL if unknown. */
char *encoding;
/** Source of encoding information. */
- binding_encoding_source encoding_source;
+ dom_hubbub_encoding_source encoding_source;
/** Base URL (may be a copy of content->url). */
nsurl *base_url;
@@ -127,6 +127,12 @@ void html__redraw_a_box(struct content *c, struct box *box);
struct browser_window *html_get_browser_window(struct content *c);
struct search_context *html_get_search(struct content *c);
void html_set_search(struct content *c, struct search_context *s);
+/**
+ * Complete conversion of an HTML document
+ *
+ * \param c Content to convert
+ */
+void html_finish_conversion(html_content *c);
/* in render/html_redraw.c */
bool html_redraw(struct content *c, struct content_redraw_data *data,
@@ -140,6 +146,10 @@ void html_mouse_action(struct content *c, struct browser_window *bw,
void html_overflow_scroll_callback(void *client_data,
struct scrollbar_msg_data *scrollbar_data);
+
+/* in render/html_script.c */
+dom_hubbub_error html_process_script(void *ctx, dom_node *node);
+
/* in render/html_forms.c */
struct form *html_forms_get_forms(const char *docenc, dom_html_document *doc);
struct form_control *html_forms_get_control_for_node(struct form *forms, dom_node *node);
@@ -163,6 +173,9 @@ extern struct dom_string *html_dom_string_coords;
extern struct dom_string *html_dom_string_circle;
extern struct dom_string *html_dom_string_poly;
extern struct dom_string *html_dom_string_polygon;
+extern struct dom_string *html_dom_string_text_javascript;
+extern struct dom_string *html_dom_string_type;
+extern struct dom_string *html_dom_string_src;
#endif
diff --git a/render/html_script.c b/render/html_script.c
new file mode 100644
index 000000000..631dcca1e
--- /dev/null
+++ b/render/html_script.c
@@ -0,0 +1,339 @@
+/*
+ * Copyright 2012 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Content for text/html scripts (implementation).
+ */
+
+#include <assert.h>
+#include <ctype.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <strings.h>
+#include <stdlib.h>
+
+#include "utils/config.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "javascript/js.h"
+#include "content/content_protected.h"
+#include "content/fetch.h"
+#include "render/html_internal.h"
+
+typedef bool (script_handler_t)(struct jscontext *jscontext, const char *data, size_t size) ;
+
+
+static script_handler_t *select_script_handler(content_type ctype)
+{
+ if (ctype == CONTENT_JS) {
+ return js_exec;
+ }
+ return NULL;
+}
+
+
+/* attempt to progress script execution
+ *
+ * execute scripts using algorithm found in:
+ * http://www.whatwg.org/specs/web-apps/current-work/multipage/scripting-1.html#the-script-element
+ *
+ */
+static bool html_scripts_exec(html_content *c)
+{
+ unsigned int i;
+ struct html_script *s;
+ script_handler_t *script_handler;
+
+ if (c->jscontext == NULL)
+ return false;
+
+ for (i = 0, s = c->scripts; i != c->scripts_count; i++, s++) {
+ if (s->already_started) {
+ continue;
+ }
+
+ assert((s->type == HTML_SCRIPT_EXTERNAL) ||
+ (s->type == HTML_SCRIPT_INTERNAL));
+
+ if (s->type == HTML_SCRIPT_EXTERNAL) {
+ /* ensure script content is present */
+ if (s->data.external == NULL)
+ continue;
+
+ /* ensure script content fetch status is not an error */
+ if (content_get_status(s->data.external) == CONTENT_STATUS_ERROR)
+ continue;
+
+ /* ensure script handler for content type */
+ script_handler = select_script_handler(content_get_type(s->data.external));
+ if (script_handler == NULL)
+ continue; /* unsupported type */
+
+ if (content_get_status(s->data.external) == CONTENT_STATUS_DONE) {
+ /* external script is now available */
+ const char *data;
+ unsigned long size;
+ data = content_get_source_data(s->data.external, &size );
+ script_handler(c->jscontext, data, size);
+
+ s->already_started = true;
+
+ } else {
+ /* script not yet available */
+
+ /* check if deferable or asynchronous */
+ if (!s->defer && !s->async) {
+ break;
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+/* create new html script entry */
+static struct html_script *
+html_process_new_script(html_content *c, enum html_script_type type)
+{
+ struct html_script *nscript;
+ /* add space for new script entry */
+ nscript = realloc(c->scripts,
+ sizeof(struct html_script) * (c->scripts_count + 1));
+ if (nscript == NULL) {
+ return NULL;
+ }
+
+ c->scripts = nscript;
+
+ /* increment script entry count */
+ nscript = &c->scripts[c->scripts_count];
+ c->scripts_count++;
+
+ nscript->already_started = false;
+ nscript->parser_inserted = false;
+ nscript->force_async = true;
+ nscript->ready_exec = false;
+ nscript->async = false;
+ nscript->defer = false;
+
+ nscript->type = type;
+
+ return nscript;
+}
+
+/**
+ * Callback for fetchcache() for linked stylesheets.
+ */
+
+static nserror
+html_convert_script_callback(hlcache_handle *script,
+ const hlcache_event *event,
+ void *pw)
+{
+ html_content *parent = pw;
+ unsigned int i;
+ struct html_script *s;
+
+ /* Find script */
+ for (i = 0, s = parent->scripts; i != parent->scripts_count; i++, s++) {
+ if (s->type == HTML_SCRIPT_EXTERNAL &&
+ s->data.external == script)
+ break;
+ }
+
+ assert(i != parent->scripts_count);
+
+ switch (event->type) {
+ case CONTENT_MSG_LOADING:
+ break;
+
+ case CONTENT_MSG_READY:
+ break;
+
+ case CONTENT_MSG_DONE:
+ LOG(("script %d done '%s'", i,
+ nsurl_access(hlcache_handle_get_url(script))));
+ parent->base.active--;
+ LOG(("%d fetches active", parent->base.active));
+
+ /* script finished loading so try and continue execution */
+ html_scripts_exec(parent);
+ break;
+
+ case CONTENT_MSG_ERROR:
+ LOG(("script %s failed: %s",
+ nsurl_access(hlcache_handle_get_url(script)),
+ event->data.error));
+ hlcache_handle_release(script);
+ s->data.external = NULL;
+ parent->base.active--;
+ LOG(("%d fetches active", parent->base.active));
+ content_add_error(&parent->base, "?", 0);
+
+ /* script failed loading so try and continue execution */
+ html_scripts_exec(parent);
+
+ break;
+
+ case CONTENT_MSG_STATUS:
+ html_set_status(parent, content_get_status_message(script));
+ content_broadcast(&parent->base, CONTENT_MSG_STATUS,
+ event->data);
+ break;
+
+ default:
+ assert(0);
+ }
+
+ if (parent->base.active == 0)
+ html_finish_conversion(parent);
+
+ return NSERROR_OK;
+}
+
+/** process script node
+ *
+ *
+ */
+dom_hubbub_error
+html_process_script(void *ctx, dom_node *node)
+{
+ html_content *c = (html_content *)ctx;
+ dom_exception exc; /* returned by libdom functions */
+ dom_string *src, *script, *mimetype;
+ struct html_script *nscript;
+ union content_msg_data msg_data;
+
+ /* ensure javascript context is available */
+ if (c->jscontext == NULL) {
+ union content_msg_data msg_data;
+
+ msg_data.jscontext = &c->jscontext;
+ content_broadcast(&c->base, CONTENT_MSG_GETCTX, msg_data);
+ LOG(("javascript context %p ", c->jscontext));
+ if (c->jscontext == NULL) {
+ /* no context and it could not be created, abort */
+ return DOM_HUBBUB_OK;
+ }
+ }
+
+ LOG(("content %p parser %p node %p",c,c->parser, node));
+
+ exc = dom_element_get_attribute(node, html_dom_string_type, &mimetype);
+ if (exc != DOM_NO_ERR || mimetype == NULL) {
+ mimetype = dom_string_ref(html_dom_string_text_javascript);
+ }
+
+ exc = dom_element_get_attribute(node, html_dom_string_src, &src);
+ if (exc != DOM_NO_ERR || src == NULL) {
+ struct lwc_string_s *lwcmimetype;
+ script_handler_t *script_handler;
+
+ /* does not appear to be a src so script is inline content */
+ exc = dom_node_get_text_content(node, &script);
+ if ((exc != DOM_NO_ERR) || (script == NULL)) {
+ dom_string_unref(mimetype);
+ return DOM_HUBBUB_OK; /* no contents, skip */
+ }
+
+ nscript = html_process_new_script(c, HTML_STYLESHEET_INTERNAL);
+ if (nscript == NULL) {
+ dom_string_unref(mimetype);
+ dom_string_unref(script);
+ goto html_process_script_no_memory;
+ }
+
+ nscript->data.internal = script;
+ nscript->mimetype = mimetype;
+ nscript->already_started = true;
+
+ /* charset (encoding) */
+
+ /* ensure script handler for content type */
+ dom_string_intern(mimetype, &lwcmimetype);
+ script_handler = select_script_handler(content_factory_type_from_mime_type(lwcmimetype));
+ lwc_string_unref(lwcmimetype);
+
+ if (script_handler != NULL) {
+ script_handler(c->jscontext,
+ dom_string_data(script),
+ dom_string_byte_length(script));
+ }
+
+
+ } else {
+ /* script with a src tag */
+ nserror ns_error;
+ nsurl *joined;
+ hlcache_child_context child;
+
+
+ nscript = html_process_new_script(c, HTML_STYLESHEET_EXTERNAL);
+ if (nscript == NULL) {
+ dom_string_unref(src);
+ dom_string_unref(mimetype);
+ goto html_process_script_no_memory;
+ }
+
+ /* charset (encoding) */
+
+ ns_error = nsurl_join(c->base_url, dom_string_data(src), &joined);
+ dom_string_unref(src);
+ if (ns_error != NSERROR_OK) {
+ dom_string_unref(mimetype);
+ goto html_process_script_no_memory;
+ }
+
+ nscript->mimetype = mimetype; /* keep reference to mimetype */
+
+ LOG(("script %i '%s'", c->scripts_count, nsurl_access(joined)));
+
+ child.charset = c->encoding;
+ child.quirks = c->base.quirks;
+
+ ns_error = hlcache_handle_retrieve(joined,
+ 0,
+ content_get_url(&c->base),
+ NULL,
+ html_convert_script_callback,
+ c,
+ &child,
+ CONTENT_SCRIPT,
+ &nscript->data.external);
+
+ nsurl_unref(joined);
+
+ if (ns_error != NSERROR_OK) {
+ goto html_process_script_no_memory;
+ }
+
+ c->base.active++; /* ensure base content knows the fetch is active */
+ LOG(("%d fetches active", c->base.active));
+
+ }
+ html_scripts_exec(c);
+
+ return DOM_HUBBUB_OK;
+
+html_process_script_no_memory:
+ msg_data.error = messages_get("NoMemory");
+ content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
+ return DOM_HUBBUB_NOMEM;
+}
diff --git a/render/hubbub_binding.c b/render/hubbub_binding.c
deleted file mode 100644
index 2f9899fad..000000000
--- a/render/hubbub_binding.c
+++ /dev/null
@@ -1,1325 +0,0 @@
-/*
- * Copyright 2008 Andrew Sidwell <takkaria@netsurf-browser.org>
- * Copyright 2008 John-Mark Bell <jmb@netsurf-browser.org>
- *
- * This file is part of NetSurf, http://www.netsurf-browser.org/
- *
- * NetSurf is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * NetSurf is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <assert.h>
-#include <stdbool.h>
-#include <string.h>
-
-#include <libxml/HTMLparser.h>
-#include <libxml/HTMLtree.h>
-
-#include <hubbub/parser.h>
-#include <hubbub/tree.h>
-
-#include "render/form.h"
-#include "render/parser_binding.h"
-
-#include "utils/config.h"
-#include "utils/log.h"
-#include "utils/talloc.h"
-#include "utils/utils.h"
-
-/**
- * Private data attached to each DOM node
- */
-typedef struct hubbub_private {
- binding_private base;
-
- uint32_t refcnt;
-} hubbub_private;
-
-typedef struct hubbub_ctx {
- hubbub_parser *parser;
-
- htmlDocPtr document;
- bool owns_doc;
-
- binding_quirks_mode quirks;
-
- const char *encoding;
- binding_encoding_source encoding_source;
-
-#define NUM_NAMESPACES (6)
- xmlNsPtr namespaces[NUM_NAMESPACES];
-#undef NUM_NAMESPACES
-
- hubbub_tree_handler tree_handler;
-
- struct form *forms;
-} hubbub_ctx;
-
-static struct {
- const char *prefix;
- const char *url;
-} namespaces[] = {
- { NULL, NULL },
- { NULL, "http://www.w3.org/1999/xhtml" },
- { "math", "http://www.w3.org/1998/Math/MathML" },
- { "svg", "http://www.w3.org/2000/svg" },
- { "xlink", "http://www.w3.org/1999/xlink" },
- /** \todo Oh dear. LibXML2 refuses to create any namespace with a
- * prefix of "xml". That sucks, royally. */
- { "xml", "http://www.w3.org/XML/1998/namespace" },
- { "xmlns", "http://www.w3.org/2000/xmlns/" }
-};
-
-static hubbub_private *create_private(uint32_t refcnt);
-static hubbub_private *copy_private(const hubbub_private *p, uint32_t refcnt);
-static void destroy_private(hubbub_private *p);
-static inline char *c_string_from_hubbub_string(hubbub_ctx *ctx,
- const hubbub_string *str);
-static void create_namespaces(hubbub_ctx *ctx, xmlNode *root);
-static hubbub_error create_comment(void *ctx, const hubbub_string *data,
- void **result);
-static hubbub_error create_doctype(void *ctx, const hubbub_doctype *doctype,
- void **result);
-static hubbub_error create_element(void *ctx, const hubbub_tag *tag,
- void **result);
-static hubbub_error create_text(void *ctx, const hubbub_string *data,
- void **result);
-static hubbub_error ref_node(void *ctx, void *node);
-static hubbub_error unref_node(void *ctx, void *node);
-static hubbub_error append_child(void *ctx, void *parent, void *child,
- void **result);
-static hubbub_error insert_before(void *ctx, void *parent, void *child,
- void *ref_child, void **result);
-static hubbub_error remove_child(void *ctx, void *parent, void *child,
- void **result);
-static hubbub_error clone_node(void *ctx, void *node, bool deep, void **result);
-static hubbub_error reparent_children(void *ctx, void *node, void *new_parent);
-static hubbub_error get_parent(void *ctx, void *node, bool element_only,
- void **result);
-static hubbub_error has_children(void *ctx, void *node, bool *result);
-static hubbub_error form_associate(void *ctx, void *form, void *node);
-static hubbub_error add_attributes(void *ctx, void *node,
- const hubbub_attribute *attributes, uint32_t n_attributes);
-static hubbub_error set_quirks_mode(void *ctx, hubbub_quirks_mode mode);
-static hubbub_error change_encoding(void *ctx, const char *charset);
-
-static struct form *parse_form_element(xmlNode *node, const char *docenc);
-static struct form_control *parse_input_element(xmlNode *node);
-static struct form_control *parse_button_element(xmlNode *node);
-static struct form_control *parse_select_element(xmlNode *node);
-static struct form_control *parse_textarea_element(xmlNode *node);
-
-static hubbub_tree_handler tree_handler = {
- create_comment,
- create_doctype,
- create_element,
- create_text,
- ref_node,
- unref_node,
- append_child,
- insert_before,
- remove_child,
- clone_node,
- reparent_children,
- get_parent,
- has_children,
- form_associate,
- add_attributes,
- set_quirks_mode,
- change_encoding,
- NULL
-};
-
-static void *ns_talloc_based_realloc(void *ptr, size_t len, void *pw)
-{
- /* talloc_realloc_size(pw, ptr, 0) == talloc_free(ptr) */
- return talloc_realloc_size(pw, ptr, len);
-}
-
-binding_error binding_create_tree(void *arena, const char *charset, void **ctx)
-{
- hubbub_ctx *c;
- hubbub_parser_optparams params;
- uint32_t i;
- hubbub_error error;
-
- c = malloc(sizeof(hubbub_ctx));
- if (c == NULL)
- return BINDING_NOMEM;
-
- c->parser = NULL;
- c->encoding = charset;
- c->encoding_source = charset != NULL ? ENCODING_SOURCE_HEADER
- : ENCODING_SOURCE_DETECTED;
- c->document = NULL;
- c->owns_doc = true;
- c->quirks = BINDING_QUIRKS_MODE_NONE;
- c->forms = NULL;
-
- error = hubbub_parser_create(charset, true, ns_talloc_based_realloc,
- arena, &c->parser);
- if (error != HUBBUB_OK) {
- free(c);
- if (error == HUBBUB_BADENCODING)
- return BINDING_BADENCODING;
- else
- return BINDING_NOMEM; /* Assume OOM */
- }
-
- c->document = htmlNewDocNoDtD(NULL, NULL);
- if (c->document == NULL) {
- hubbub_parser_destroy(c->parser);
- free(c);
- return BINDING_NOMEM;
- }
- c->document->_private = create_private(0);
- if (c->document->_private == NULL) {
- xmlFreeDoc(c->document);
- hubbub_parser_destroy(c->parser);
- free(c);
- return BINDING_NOMEM;
- }
-
- for (i = 0; i < sizeof(c->namespaces) / sizeof(c->namespaces[0]); i++) {
- c->namespaces[i] = NULL;
- }
-
- c->tree_handler = tree_handler;
- c->tree_handler.ctx = (void *) c;
-
- params.tree_handler = &c->tree_handler;
- hubbub_parser_setopt(c->parser, HUBBUB_PARSER_TREE_HANDLER, &params);
-
- ref_node(c, c->document);
- params.document_node = c->document;
- hubbub_parser_setopt(c->parser, HUBBUB_PARSER_DOCUMENT_NODE, &params);
-
- *ctx = (void *) c;
-
- return BINDING_OK;
-}
-
-binding_error binding_destroy_tree(void *ctx)
-{
- hubbub_ctx *c = (hubbub_ctx *) ctx;
-
- if (ctx == NULL)
- return BINDING_OK;
-
- if (c->parser != NULL)
- hubbub_parser_destroy(c->parser);
-
- if (c->owns_doc)
- binding_destroy_document(c->document);
-
- c->parser = NULL;
- c->encoding = NULL;
- c->document = NULL;
-
- free(c);
-
- return BINDING_OK;
-}
-
-binding_error binding_parse_chunk(void *ctx, const uint8_t *data, size_t len)
-{
- hubbub_ctx *c = (hubbub_ctx *) ctx;
- hubbub_error err;
-
- err = hubbub_parser_parse_chunk(c->parser, (uint8_t *) data, len);
- if (err == HUBBUB_ENCODINGCHANGE)
- return BINDING_ENCODINGCHANGE;
-
- return err == HUBBUB_NOMEM ? BINDING_NOMEM : BINDING_OK;
-}
-
-binding_error binding_parse_completed(void *ctx)
-{
- hubbub_ctx *c = (hubbub_ctx *) ctx;
- hubbub_error error;
-
- error = hubbub_parser_completed(c->parser);
-
- return error == HUBBUB_NOMEM ? BINDING_NOMEM : BINDING_OK;
-}
-
-const char *binding_get_encoding(void *ctx, binding_encoding_source *source)
-{
- hubbub_ctx *c = (hubbub_ctx *) ctx;
-
- *source = c->encoding_source;
-
- return c->encoding != NULL ? c->encoding : "Windows-1252";
-}
-
-xmlDocPtr binding_get_document(void *ctx, binding_quirks_mode *quirks)
-{
- hubbub_ctx *c = (hubbub_ctx *) ctx;
- xmlDocPtr doc = c->document;
-
- c->owns_doc = false;
-
- *quirks = c->quirks;
-
- return doc;
-}
-
-struct form *binding_get_forms(void *ctx)
-{
- hubbub_ctx *c = (hubbub_ctx *) ctx;
-
- return c->forms;
-}
-
-struct form_control *binding_get_control_for_node(void *ctx, xmlNodePtr node)
-{
- hubbub_ctx *c = (hubbub_ctx *) ctx;
- struct form *f;
- struct form_control *ctl = NULL;
-
- for (f = c->forms; f != NULL; f = f->prev) {
- for (ctl = f->controls; ctl != NULL; ctl = ctl->next) {
- if (ctl->node == node)
- return ctl;
- }
- }
-
- /* No control found. This implies that it's not associated
- * with any form. In this case, we create a control for it
- * on the fly. */
- if (strcasecmp((const char *) node->name, "input") == 0) {
- ctl = parse_input_element(node);
- } else if (strcasecmp((const char *) node->name, "button") == 0) {
- ctl = parse_button_element(node);
- } else if (strcasecmp((const char *) node->name, "select") == 0) {
- ctl = parse_select_element(node);
- } else if (strcasecmp((const char *) node->name, "textarea") == 0) {
- ctl = parse_textarea_element(node);
- }
-
- return ctl;
-}
-
-void binding_destroy_document(xmlDocPtr doc)
-{
- xmlNode *n = (xmlNode *) doc;
-
- while (n != NULL) {
- destroy_private(n->_private);
-
- if (n->children != NULL) {
- n = n->children;
- } else if (n->next != NULL) {
- n = n->next;
- } else {
- while (n->parent != NULL && n->parent->next == NULL)
- n = n->parent;
-
- if (n->parent != NULL)
- n = n->parent->next;
- else
- n = NULL;
- }
- }
-
- xmlFreeDoc(doc);
-}
-
-/*****************************************************************************/
-
-hubbub_private *create_private(uint32_t refcnt)
-{
- hubbub_private *pvt = calloc(1, sizeof(*pvt));
-
- if (pvt != NULL)
- pvt->refcnt = refcnt;
-
- return pvt;
-}
-
-hubbub_private *copy_private(const hubbub_private *p, uint32_t refcnt)
-{
- hubbub_private *pvt = calloc(1, sizeof(*pvt));
-
- if (pvt != NULL) {
- pvt->refcnt = refcnt;
-
- if (p->base.nclasses > 0) {
- pvt->base.classes =
- malloc(p->base.nclasses * sizeof(lwc_string *));
- if (pvt->base.classes == NULL) {
- free(pvt);
- return NULL;
- }
-
- while (pvt->base.nclasses < p->base.nclasses) {
- pvt->base.classes[pvt->base.nclasses] =
- lwc_string_ref(p->base.classes[
- pvt->base.nclasses]);
- pvt->base.nclasses++;
- }
- }
-
- if (p->base.localname != NULL)
- pvt->base.localname = lwc_string_ref(p->base.localname);
-
- if (p->base.id != NULL)
- pvt->base.id = lwc_string_ref(p->base.id);
- }
-
- return pvt;
-}
-
-void destroy_private(hubbub_private *p)
-{
- if (p->base.localname != NULL)
- lwc_string_unref(p->base.localname);
-
- if (p->base.id != NULL)
- lwc_string_unref(p->base.id);
-
- while (p->base.nclasses > 0)
- lwc_string_unref(p->base.classes[--p->base.nclasses]);
-
- if (p->base.classes != NULL)
- free(p->base.classes);
-
- free(p);
-}
-
-char *c_string_from_hubbub_string(hubbub_ctx *ctx, const hubbub_string *str)
-{
- return strndup((const char *) str->ptr, (int) str->len);
-}
-
-void create_namespaces(hubbub_ctx *ctx, xmlNode *root)
-{
- uint32_t i;
-
- for (i = 1; i < sizeof(namespaces) / sizeof(namespaces[0]); i++) {
- ctx->namespaces[i - 1] = xmlNewNs(root,
- BAD_CAST namespaces[i].url,
- BAD_CAST namespaces[i].prefix);
-
- if (ctx->namespaces[i - 1] == NULL) {
- LOG(("Failed creating namespace %s\n",
- namespaces[i].prefix));
- }
- }
-}
-
-hubbub_error create_comment(void *ctx, const hubbub_string *data, void **result)
-{
- hubbub_ctx *c = (hubbub_ctx *) ctx;
- char *content;
- xmlNodePtr n;
-
- content = c_string_from_hubbub_string(c, data);
- if (content == NULL)
- return HUBBUB_NOMEM;
-
- n = xmlNewDocComment(c->document, BAD_CAST content);
- if (n == NULL) {
- free(content);
- return HUBBUB_NOMEM;
- }
- n->_private = create_private(1);
- if (n->_private == NULL) {
- xmlFreeNode(n);
- free(content);
- return HUBBUB_NOMEM;
- }
-
- free(content);
-
- *result = (void *) n;
-
- return HUBBUB_OK;
-}
-
-hubbub_error create_doctype(void *ctx, const hubbub_doctype *doctype,
- void **result)
-{
- hubbub_ctx *c = (hubbub_ctx *) ctx;
- char *name, *public = NULL, *system = NULL;
- xmlDtdPtr n;
-
- name = c_string_from_hubbub_string(c, &doctype->name);
- if (name == NULL)
- return HUBBUB_NOMEM;
-
- if (!doctype->public_missing) {
- public = c_string_from_hubbub_string(c, &doctype->public_id);
- if (public == NULL) {
- free(name);
- return HUBBUB_NOMEM;
- }
- }
-
- if (!doctype->system_missing) {
- system = c_string_from_hubbub_string(c, &doctype->system_id);
- if (system == NULL) {
- free(public);
- free(name);
- return HUBBUB_NOMEM;
- }
- }
-
- n = xmlNewDtd(c->document, BAD_CAST name,
- BAD_CAST (public ? public : ""),
- BAD_CAST (system ? system : ""));
- if (n == NULL) {
- free(system);
- free(public);
- free(name);
- return HUBBUB_NOMEM;
- }
- n->_private = create_private(1);
- if (n->_private == NULL) {
- xmlFreeDtd(n);
- free(system);
- free(public);
- free(name);
- return HUBBUB_NOMEM;
- }
-
- *result = (void *) n;
-
- free(system);
- free(public);
- free(name);
-
- return HUBBUB_OK;
-}
-
-hubbub_error create_element(void *ctx, const hubbub_tag *tag, void **result)
-{
- hubbub_ctx *c = (hubbub_ctx *) ctx;
- lwc_string *iname;
- xmlNodePtr n;
-
- if (lwc_intern_string((const char *) tag->name.ptr, tag->name.len,
- &iname) != lwc_error_ok) {
- return HUBBUB_NOMEM;
- }
-
- if (c->namespaces[0] != NULL) {
- n = xmlNewDocNode(c->document, c->namespaces[tag->ns - 1],
- BAD_CAST lwc_string_data(iname), NULL);
- } else {
- n = xmlNewDocNode(c->document, NULL,
- BAD_CAST lwc_string_data(iname), NULL);
-
- /* We're creating the root node of the document. Therefore,
- * create the namespaces and set this node's namespace */
- if (n != NULL && c->namespaces[0] == NULL) {
- create_namespaces(c, (void *) n);
-
- xmlSetNs(n, c->namespaces[tag->ns - 1]);
- }
- }
- if (n == NULL) {
- lwc_string_unref(iname);
- return HUBBUB_NOMEM;
- }
- n->_private = create_private(1);
- if (n->_private == NULL) {
- xmlFreeNode(n);
- lwc_string_unref(iname);
- return HUBBUB_NOMEM;
- }
-
- if (tag->n_attributes > 0 && add_attributes(ctx, (void *) n,
- tag->attributes, tag->n_attributes) != HUBBUB_OK) {
- destroy_private(n->_private);
- xmlFreeNode(n);
- lwc_string_unref(iname);
- return HUBBUB_NOMEM;
- }
-
- if (lwc_string_length(iname) == SLEN("form") &&
- strcasecmp(lwc_string_data(iname), "form") == 0) {
- struct form *form = parse_form_element(n, c->encoding);
-
- /* Memory exhaustion */
- if (form == NULL) {
- destroy_private(n->_private);
- xmlFreeNode(n);
- lwc_string_unref(iname);
- return HUBBUB_NOMEM;
- }
-
- /* Insert into list */
- form->prev = c->forms;
- c->forms = form;
- }
-
- ((binding_private *) n->_private)->localname = iname;
-
- *result = (void *) n;
-
- return HUBBUB_OK;
-}
-
-hubbub_error create_text(void *ctx, const hubbub_string *data, void **result)
-{
- hubbub_ctx *c = (hubbub_ctx *) ctx;
- xmlNodePtr n;
-
- n = xmlNewDocTextLen(c->document, BAD_CAST data->ptr, (int) data->len);
- if (n == NULL) {
- return HUBBUB_NOMEM;
- }
- n->_private = create_private(1);
- if (n->_private == NULL) {
- xmlFreeNode(n);
- return HUBBUB_NOMEM;
- }
-
- *result = (void *) n;
-
- return HUBBUB_OK;
-}
-
-hubbub_error ref_node(void *ctx, void *node)
-{
- hubbub_ctx *c = (hubbub_ctx *) ctx;
- hubbub_private *pvt;
-
- if (node == c->document) {
- xmlDoc *n = (xmlDoc *) node;
- pvt = n->_private;
-
- pvt->refcnt++;
- } else {
- xmlNode *n = (xmlNode *) node;
- pvt = n->_private;
-
- pvt->refcnt++;
- }
-
- return HUBBUB_OK;
-}
-
-hubbub_error unref_node(void *ctx, void *node)
-{
- hubbub_ctx *c = (hubbub_ctx *) ctx;
- hubbub_private *pvt;
-
- if (node == c->document) {
- xmlDoc *n = (xmlDoc *) node;
- pvt = n->_private;
-
- assert(pvt->refcnt != 0 && "Node has refcount of zero");
-
- pvt->refcnt--;
- } else {
- xmlNode *n = (xmlNode *) node;
- pvt = n->_private;
-
- assert(pvt->refcnt != 0 && "Node has refcount of zero");
-
- pvt->refcnt--;
-
- if (pvt->refcnt == 0 && n->parent == NULL) {
- destroy_private(pvt);
- xmlFreeNode(n);
- }
- }
-
- return HUBBUB_OK;
-}
-
-hubbub_error append_child(void *ctx, void *parent, void *child, void **result)
-{
- xmlNode *chld = (xmlNode *) child;
- xmlNode *p = (xmlNode *) parent;
-
- /** \todo Text node merging logic as per
- * http://www.whatwg.org/specs/web-apps/current-work/multipage/ \
- * tree-construction.html#insert-a-character
- *
- * Doesn't actually matter for us until we have scripting. Thus,
- * this is something which can wait until libdom.
- */
- if (chld->type == XML_TEXT_NODE && p->last != NULL &&
- p->last->type == XML_TEXT_NODE) {
- /* Need to clone the child, as libxml will free it if it
- * merges the content with a pre-existing text node. */
- chld = xmlCopyNode(chld, 0);
- if (chld == NULL)
- return HUBBUB_NOMEM;
-
- *result = xmlAddChild(p, chld);
-
- assert(*result != (void *) chld);
- } else {
- *result = xmlAddChild(p, chld);
- }
-
- if (*result == NULL)
- return HUBBUB_NOMEM;
-
- ref_node(ctx, *result);
-
- return HUBBUB_OK;
-}
-
-hubbub_error insert_before(void *ctx, void *parent, void *child,
- void *ref_child, void **result)
-{
- xmlNode *chld = (xmlNode *) child;
- xmlNode *ref = (xmlNode *) ref_child;
-
- if (chld->type == XML_TEXT_NODE && ref->prev != NULL &&
- ref->prev->type == XML_TEXT_NODE) {
- /* Clone text node, as it'll be freed by libxml */
- chld = xmlCopyNode(chld, 0);
- if (chld == NULL)
- return HUBBUB_NOMEM;
-
- *result = xmlAddNextSibling(ref->prev, chld);
-
- assert(*result != (void *) chld);
- } else {
- *result = xmlAddPrevSibling(ref, chld);
- }
-
- if (*result == NULL)
- return HUBBUB_NOMEM;
-
- ref_node(ctx, *result);
-
- return HUBBUB_OK;
-}
-
-hubbub_error remove_child(void *ctx, void *parent, void *child, void **result)
-{
- xmlNode *chld = (xmlNode *) child;
-
- xmlUnlinkNode(chld);
-
- *result = child;
-
- ref_node(ctx, *result);
-
- return HUBBUB_OK;
-}
-
-hubbub_error clone_node(void *ctx, void *node, bool deep, void **result)
-{
- xmlNode *n = (xmlNode *) node;
- xmlNode *clonedtree;
-
- /* Shallow clone node */
- clonedtree = xmlCopyNode(n, 2);
- if (clonedtree == NULL)
- return HUBBUB_NOMEM;
-
- clonedtree->_private = copy_private(n->_private, 1);
- if (clonedtree->_private == NULL) {
- xmlFreeNode(clonedtree);
- return HUBBUB_NOMEM;
- }
-
- /* Iteratively clone children too, if required */
- if (deep && n->children != NULL) {
- xmlNode *parent = clonedtree, *copy;
-
- n = n->children;
-
- while (n != node) {
- copy = xmlCopyNode(n, 2);
- if (copy == NULL)
- goto error;
-
- copy->_private = copy_private(n->_private, 0);
- if (copy->_private == NULL) {
- xmlFreeNode(copy);
- goto error;
- }
-
- xmlAddChild(parent, copy);
-
- if (n->children != NULL) {
- parent = copy;
- n = n->children;
- } else if (n->next != NULL) {
- n = n->next;
- } else {
- while (n->parent != node &&
- n->parent->next == NULL) {
- parent = parent->parent;
- n = n->parent;
- }
-
- if (n->parent != node) {
- parent = parent->parent;
- n = n->parent->next;
- } else
- n = node;
- }
- }
- }
-
- *result = clonedtree;
-
- return HUBBUB_OK;
-
-error:
- n = clonedtree;
-
- while (n != NULL) {
- destroy_private(n->_private);
-
- if (n->children != NULL) {
- n = n->children;
- } else if (n->next != NULL) {
- n = n->next;
- } else {
- while (n->parent != NULL && n->parent->next == NULL) {
- n = n->parent;
- }
-
- if (n->parent != NULL)
- n = n->parent->next;
- else
- n = NULL;
- }
- }
-
- xmlFreeNode(clonedtree);
-
- return HUBBUB_NOMEM;
-}
-
-hubbub_error reparent_children(void *ctx, void *node, void *new_parent)
-{
- xmlNode *n = (xmlNode *) node;
- xmlNode *p = (xmlNode *) new_parent;
- xmlNode *child;
-
- for (child = n->children; child != NULL; ) {
- xmlNode *next = child->next;
-
- xmlUnlinkNode(child);
-
- if (xmlAddChild(p, child) == NULL)
- return HUBBUB_NOMEM;
-
- child = next;
- }
-
- return HUBBUB_OK;
-}
-
-hubbub_error get_parent(void *ctx, void *node, bool element_only, void **result)
-{
- xmlNode *n = (xmlNode *) node;
-
- *result = (void *) n->parent;
-
- if (*result != NULL && element_only &&
- ((xmlNode *) *result)->type != XML_ELEMENT_NODE) {
- *result = NULL;
- }
-
- if (*result != NULL)
- ref_node(ctx, *result);
-
- return HUBBUB_OK;
-}
-
-hubbub_error has_children(void *ctx, void *node, bool *result)
-{
- xmlNode *n = (xmlNode *) node;
-
- *result = n->children != NULL;
-
- return HUBBUB_OK;
-}
-
-hubbub_error form_associate(void *ctx, void *form, void *node)
-{
- hubbub_ctx *c = (hubbub_ctx *) ctx;
- xmlNode *n = (xmlNode *) node;
- struct form *f;
- struct form_control *control = NULL;
- xmlChar *id = NULL;
-
- /* Find form object to associate with:
- *
- * 1) If node possesses an @form, use the form with a matching @id
- * 2) Otherwise, use the form provided
- */
- id = xmlGetProp(n, (const xmlChar *) "form");
- for (f = c->forms; f != NULL; f = f->prev) {
- if (id == NULL && f->node == form) {
- break;
- } else if (id != NULL) {
- xmlNode *fn = (xmlNode *) f->node;
- xmlChar *fid = xmlGetProp(fn, (const xmlChar *) "id");
-
- if (fid != NULL && strcmp((char *) id,
- (char *) fid) == 0) {
- xmlFree(fid);
- break;
- } else if (fid != NULL) {
- xmlFree(fid);
- }
- }
- }
- if (id != NULL)
- xmlFree(id);
-
- /* None found -- give up */
- if (f == NULL)
- return HUBBUB_OK;
-
- /* Will be one of: button, fieldset, input, label,
- * output, select, textarea.
- *
- * We ignore fieldset, label and output.
- */
- if (strcasecmp((const char *) n->name, "input") == 0) {
- control = parse_input_element(n);
- } else if (strcasecmp((const char *) n->name, "button") == 0) {
- control = parse_button_element(n);
- } else if (strcasecmp((const char *) n->name, "select") == 0) {
- control = parse_select_element(n);
- } else if (strcasecmp((const char *) n->name, "textarea") == 0) {
- control = parse_textarea_element(n);
- } else
- return HUBBUB_OK;
-
- /* Memory exhaustion */
- if (control == NULL)
- return HUBBUB_NOMEM;
-
- /* Add the control to the form */
- form_add_control(f, control);
-
- return HUBBUB_OK;
-}
-
-static hubbub_error parse_class_attr(lwc_string *value,
- lwc_string ***classes, uint32_t *nclasses)
-{
- const char *pv;
- lwc_string **cls = NULL;
- uint32_t count = 0;
-
- /* Count number of classes */
- for (pv = lwc_string_data(value); *pv != '\0'; ) {
- if (*pv != ' ') {
- while (*pv != ' ' && *pv != '\0')
- pv++;
- count++;
- } else {
- while (*pv == ' ')
- pv++;
- }
- }
-
- /* If there are some, unpack them */
- if (count > 0) {
- cls = malloc(count * sizeof(lwc_string *));
- if (cls == NULL)
- return HUBBUB_NOMEM;
-
- for (pv = lwc_string_data(value), count = 0; *pv != '\0'; ) {
- if (*pv != ' ') {
- const char *s = pv;
- while (*pv != ' ' && *pv != '\0')
- pv++;
- if (lwc_intern_string(s, pv - s,
- &cls[count]) != lwc_error_ok)
- goto error;
- count++;
- } else {
- while (*pv == ' ')
- pv++;
- }
- }
- }
-
- *classes = cls;
- *nclasses = count;
-
- return HUBBUB_OK;
-error:
- while (count > 0)
- lwc_string_unref(cls[--count]);
-
- free(cls);
-
- return HUBBUB_NOMEM;
-}
-
-hubbub_error add_attributes(void *ctx, void *node,
- const hubbub_attribute *attributes, uint32_t n_attributes)
-{
- hubbub_ctx *c = (hubbub_ctx *) ctx;
- xmlNode *n = (xmlNode *) node;
- binding_private *p = n->_private;
- uint32_t attr;
-
- for (attr = 0; attr < n_attributes; attr++) {
- xmlAttr *prop;
- lwc_string *name, *value;
-
- if (lwc_intern_string((const char *) attributes[attr].name.ptr,
- attributes[attr].name.len,
- &name) != lwc_error_ok)
- return HUBBUB_NOMEM;
-
- if (lwc_intern_string((const char *) attributes[attr].value.ptr,
- attributes[attr].value.len,
- &value) != lwc_error_ok) {
- lwc_string_unref(name);
- return HUBBUB_NOMEM;
- }
-
- if (attributes[attr].ns != HUBBUB_NS_NULL &&
- c->namespaces[0] != NULL) {
- prop = xmlNewNsProp(n,
- c->namespaces[attributes[attr].ns - 1],
- BAD_CAST lwc_string_data(name),
- BAD_CAST lwc_string_data(value));
- } else {
- prop = xmlNewProp(n, BAD_CAST lwc_string_data(name),
- BAD_CAST lwc_string_data(value));
- }
-
- /* Handle @id / @class */
- if (p->id == NULL && lwc_string_length(name) == SLEN("id") &&
- strcasecmp(lwc_string_data(name), "id") == 0) {
- p->id = lwc_string_ref(value);
- } else if (p->nclasses == 0 &&
- lwc_string_length(name) == SLEN("class") &&
- strcasecmp(lwc_string_data(name),
- "class") == 0) {
- hubbub_error error;
-
- error = parse_class_attr(value, &p->classes,
- &p->nclasses);
- if (error != HUBBUB_OK) {
- lwc_string_unref(value);
- lwc_string_unref(name);
- return error;
- }
- }
-
- lwc_string_unref(value);
- lwc_string_unref(name);
-
- if (prop == NULL) {
- return HUBBUB_NOMEM;
- }
- }
-
- return HUBBUB_OK;
-}
-
-hubbub_error set_quirks_mode(void *ctx, hubbub_quirks_mode mode)
-{
- hubbub_ctx *c = (hubbub_ctx *) ctx;
-
- switch (mode) {
- case HUBBUB_QUIRKS_MODE_NONE:
- c->quirks = BINDING_QUIRKS_MODE_NONE;
- break;
- case HUBBUB_QUIRKS_MODE_LIMITED:
- c->quirks = BINDING_QUIRKS_MODE_LIMITED;
- break;
- case HUBBUB_QUIRKS_MODE_FULL:
- c->quirks = BINDING_QUIRKS_MODE_FULL;
- break;
- }
-
- return HUBBUB_OK;
-}
-
-hubbub_error change_encoding(void *ctx, const char *charset)
-{
- hubbub_ctx *c = (hubbub_ctx *) ctx;
- uint32_t source;
- const char *name;
-
- /* If we have an encoding here, it means we are *certain* */
- if (c->encoding != NULL) {
- return HUBBUB_OK;
- }
-
- /* Find the confidence otherwise (can only be from a BOM) */
- name = hubbub_parser_read_charset(c->parser, &source);
-
- if (source == HUBBUB_CHARSET_CONFIDENT) {
- c->encoding_source = ENCODING_SOURCE_DETECTED;
- c->encoding = (char *) charset;
- return HUBBUB_OK;
- }
-
- /* So here we have something of confidence tentative... */
- /* http://www.whatwg.org/specs/web-apps/current-work/#change */
-
- /* 2. "If the new encoding is identical or equivalent to the encoding
- * that is already being used to interpret the input stream, then set
- * the confidence to confident and abort these steps." */
-
- /* Whatever happens, the encoding should be set here; either for
- * reprocessing with a different charset, or for confirming that the
- * charset is in fact correct */
- c->encoding = charset;
- c->encoding_source = ENCODING_SOURCE_META;
-
- /* Equal encodings will have the same string pointers */
- return (charset == name) ? HUBBUB_OK : HUBBUB_ENCODINGCHANGE;
-}
-
-struct form *parse_form_element(xmlNode *node, const char *docenc)
-{
- struct form *form;
- form_method method;
- xmlChar *action, *meth, *charset, *target;
-
- action = xmlGetProp(node, (const xmlChar *) "action");
- charset = xmlGetProp(node, (const xmlChar *) "accept-charset");
- target = xmlGetProp(node, (const xmlChar *) "target");
-
- method = method_GET;
- meth = xmlGetProp(node, (const xmlChar *) "method");
- if (meth != NULL) {
- if (strcasecmp((char *) meth, "post") == 0) {
- xmlChar *enctype;
-
- method = method_POST_URLENC;
-
- enctype = xmlGetProp(node, (const xmlChar *) "enctype");
- if (enctype != NULL) {
- if (strcasecmp((char *) enctype,
- "multipart/form-data") == 0)
- method = method_POST_MULTIPART;
-
- xmlFree(enctype);
- }
- }
- xmlFree(meth);
- }
-
- form = form_new(node, (char *) action, (char *) target, method,
- (char *) charset, docenc);
-
- if (target != NULL)
- xmlFree(target);
- if (charset != NULL)
- xmlFree(charset);
- if (action != NULL)
- xmlFree(action);
-
- return form;
-}
-
-struct form_control *parse_input_element(xmlNode *node)
-{
- struct form_control *control = NULL;
- xmlChar *type = xmlGetProp(node, (const xmlChar *) "type");
- xmlChar *name;
-
- if (type != NULL && strcasecmp((char *) type, "password") == 0) {
- control = form_new_control(node, GADGET_PASSWORD);
- } else if (type != NULL && strcasecmp((char *) type, "file") == 0) {
- control = form_new_control(node, GADGET_FILE);
- } else if (type != NULL && strcasecmp((char *) type, "hidden") == 0) {
- control = form_new_control(node, GADGET_HIDDEN);
- } else if (type != NULL && strcasecmp((char *) type, "checkbox") == 0) {
- control = form_new_control(node, GADGET_CHECKBOX);
- } else if (type != NULL && strcasecmp((char *) type, "radio") == 0) {
- control = form_new_control(node, GADGET_RADIO);
- } else if (type != NULL && strcasecmp((char *) type, "submit") == 0) {
- control = form_new_control(node, GADGET_SUBMIT);
- } else if (type != NULL && strcasecmp((char *) type, "reset") == 0) {
- control = form_new_control(node, GADGET_RESET);
- } else if (type != NULL && strcasecmp((char *) type, "button") == 0) {
- control = form_new_control(node, GADGET_BUTTON);
- } else if (type != NULL && strcasecmp((char *) type, "image") == 0) {
- control = form_new_control(node, GADGET_IMAGE);
- } else {
- control = form_new_control(node, GADGET_TEXTBOX);
- }
-
- xmlFree(type);
-
- if (control == NULL)
- return NULL;
-
- if (control->type == GADGET_CHECKBOX || control->type == GADGET_RADIO) {
- control->selected =
- xmlHasProp(node, (const xmlChar *) "checked") != NULL;
- }
-
- if (control->type == GADGET_PASSWORD ||
- control->type == GADGET_TEXTBOX) {
- xmlChar *len = xmlGetProp(node, (const xmlChar *) "maxlength");
- if (len != NULL) {
- if (len[0] != '\0')
- control->maxlength = atoi((char *) len);
- xmlFree(len);
- }
- }
-
- if (control->type != GADGET_FILE && control->type != GADGET_IMAGE) {
- xmlChar *value = xmlGetProp(node, (const xmlChar *) "value");
- if (value != NULL) {
- control->value = strdup((char *) value);
-
- xmlFree(value);
-
- if (control->value == NULL) {
- form_free_control(control);
- return NULL;
- }
-
- control->length = strlen(control->value);
- }
-
- if (control->type == GADGET_TEXTBOX ||
- control->type == GADGET_PASSWORD) {
- if (control->value == NULL) {
- control->value = strdup("");
- if (control->value == NULL) {
- form_free_control(control);
- return NULL;
- }
-
- control->length = 0;
- }
-
- control->initial_value = strdup(control->value);
- if (control->initial_value == NULL) {
- form_free_control(control);
- return NULL;
- }
- }
- }
-
- name = xmlGetProp(node, (const xmlChar *) "name");
- if (name != NULL) {
- control->name = strdup((char *) name);
-
- xmlFree(name);
-
- if (control->name == NULL) {
- form_free_control(control);
- return NULL;
- }
- }
-
- return control;
-}
-
-struct form_control *parse_button_element(xmlNode *node)
-{
- struct form_control *control;
- xmlChar *type = xmlGetProp(node, (const xmlChar *) "type");
- xmlChar *name;
- xmlChar *value;
-
- if (type == NULL || strcasecmp((char *) type, "submit") == 0) {
- control = form_new_control(node, GADGET_SUBMIT);
- } else if (strcasecmp((char *) type, "reset") == 0) {
- control = form_new_control(node, GADGET_RESET);
- } else {
- control = form_new_control(node, GADGET_BUTTON);
- }
-
- xmlFree(type);
-
- if (control == NULL)
- return NULL;
-
- value = xmlGetProp(node, (const xmlChar *) "value");
- if (value != NULL) {
- control->value = strdup((char *) value);
-
- xmlFree(value);
-
- if (control->value == NULL) {
- form_free_control(control);
- return NULL;
- }
- }
-
- name = xmlGetProp(node, (const xmlChar *) "name");
- if (name != NULL) {
- control->name = strdup((char *) name);
-
- xmlFree(name);
-
- if (control->name == NULL) {
- form_free_control(control);
- return NULL;
- }
- }
-
- return control;
-}
-
-struct form_control *parse_select_element(xmlNode *node)
-{
- struct form_control *control = form_new_control(node, GADGET_SELECT);
- xmlChar *name;
-
- if (control == NULL)
- return NULL;
-
- control->data.select.multiple =
- xmlHasProp(node, (const xmlChar *) "multiple") != NULL;
-
- name = xmlGetProp(node, (const xmlChar *) "name");
- if (name != NULL) {
- control->name = strdup((char *) name);
-
- xmlFree(name);
-
- if (control->name == NULL) {
- form_free_control(control);
- return NULL;
- }
- }
-
- return control;
-}
-
-struct form_control *parse_textarea_element(xmlNode *node)
-{
- struct form_control *control = form_new_control(node, GADGET_TEXTAREA);
- xmlChar *name;
-
- if (control == NULL)
- return NULL;
-
- name = xmlGetProp(node, (const xmlChar *) "name");
- if (name != NULL) {
- control->name = strdup((char *) name);
-
- xmlFree(name);
-
- if (control->name == NULL) {
- form_free_control(control);
- return NULL;
- }
- }
-
- return control;
-}
-
diff --git a/render/libdom_binding.c b/render/libdom_binding.c
deleted file mode 100644
index 9ae76469c..000000000
--- a/render/libdom_binding.c
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright 2011 Vincent Sanders <vince@netsurf-browser.org>
- *
- * This file is part of NetSurf, http://www.netsurf-browser.org/
- *
- * NetSurf is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * NetSurf is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <dom/dom.h>
-#include <dom/bindings/hubbub/parser.h>
-
-#include "render/form.h"
-#include "render/parser_binding.h"
-
-#include "utils/log.h"
-
-binding_error binding_create_tree(void **ctx, const char *charset, bool enable_script, dom_script script, void *context)
-{
- dom_hubbub_parser *parser = NULL;
-
- parser = dom_hubbub_parser_create(charset, true, enable_script, NULL, script, context);
- if (parser == NULL) {
- LOG(("Can't create Hubbub Parser\n"));
- return BINDING_NOMEM;
- }
- *ctx = parser;
- return BINDING_OK;
-}
-
-binding_error binding_destroy_tree(void *ctx)
-{
- dom_hubbub_parser_destroy(ctx);
- return BINDING_OK;
-}
-
-binding_error binding_parse_chunk(void *ctx, const uint8_t *data, size_t len)
-{
- dom_hubbub_error error;
- error = dom_hubbub_parser_parse_chunk(ctx, data, len);
- if (error == (DOM_HUBBUB_HUBBUB_ERR | HUBBUB_ENCODINGCHANGE)) {
- return BINDING_ENCODINGCHANGE;
- } else if (error != DOM_HUBBUB_OK) {
- return BINDING_NOMEM;
- }
- return BINDING_OK;
-}
-
-binding_error binding_parse_completed(void *ctx)
-{
- dom_hubbub_error error;
- error = dom_hubbub_parser_completed(ctx);
- if (error != DOM_HUBBUB_OK) {
- return BINDING_NOMEM;
- }
- return BINDING_OK;
-}
-
-const char *binding_get_encoding(void *ctx, binding_encoding_source *source)
-{
- dom_hubbub_encoding_source hubbub_src;
- const char *encoding;
-
- encoding = dom_hubbub_parser_get_encoding(ctx, &hubbub_src);
-
- switch (hubbub_src) {
- case DOM_HUBBUB_ENCODING_SOURCE_HEADER:
- *source = ENCODING_SOURCE_HEADER;
- break;
-
- case DOM_HUBBUB_ENCODING_SOURCE_DETECTED:
- *source = ENCODING_SOURCE_DETECTED;
- break;
-
- case DOM_HUBBUB_ENCODING_SOURCE_META:
- *source = ENCODING_SOURCE_META;
- break;
- }
-
- return encoding;
-}
-
-dom_document *binding_get_document(void *ctx, binding_quirks_mode *quirks)
-{
- return dom_hubbub_parser_get_document(ctx);
-}
-
-struct form *binding_get_forms(void *ctx)
-{
- return NULL;
-}
-
-struct form_control *binding_get_control_for_node(void *ctx, dom_node *node)
-{
- /** \todo implement properly */
- struct form_control *ctl = form_new_control(node, GADGET_HIDDEN);
- if (ctl != NULL) {
- ctl->value = strdup("");
- ctl->initial_value = strdup("");
- ctl->name = strdup("foo");
-
- if (ctl->value == NULL || ctl->initial_value == NULL ||
- ctl->name == NULL) {
- form_free_control(ctl);
- ctl = NULL;
- }
- }
-
- return ctl;
-}
-
-void binding_destroy_document(dom_document *doc)
-{
- dom_node_unref(doc);
-}
-
-
diff --git a/render/parser_binding.h b/render/parser_binding.h
deleted file mode 100644
index cf3497867..000000000
--- a/render/parser_binding.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright 2008 John-Mark Bell <jmb@netsurf-browser.org>
- *
- * This file is part of NetSurf, http://www.netsurf-browser.org/
- *
- * NetSurf is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * NetSurf is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef _NETSURF_RENDER_PARSER_BINDING_H_
-#define _NETSURF_RENDER_PARSER_BINDING_H_
-
-#include <dom/dom.h>
-#include <dom/bindings/hubbub/parser.h>
-
-struct box;
-struct form;
-struct form_control;
-
-typedef enum binding_error {
- BINDING_OK,
- BINDING_NOMEM,
- BINDING_BADENCODING,
- BINDING_ENCODINGCHANGE
-} binding_error;
-
-typedef enum binding_encoding_source {
- ENCODING_SOURCE_HEADER,
- ENCODING_SOURCE_DETECTED,
- ENCODING_SOURCE_META
-} binding_encoding_source;
-
-typedef enum binding_quirks_mode {
- BINDING_QUIRKS_MODE_NONE,
- BINDING_QUIRKS_MODE_LIMITED,
- BINDING_QUIRKS_MODE_FULL
-} binding_quirks_mode;
-
-binding_error binding_create_tree(void **ctx, const char *charset, bool enable_script, dom_script script, void *context);
-binding_error binding_destroy_tree(void *ctx);
-
-binding_error binding_parse_chunk(void *ctx, const uint8_t *data, size_t len);
-binding_error binding_parse_completed(void *ctx);
-
-const char *binding_get_encoding(void *ctx, binding_encoding_source *source);
-dom_document *binding_get_document(void *ctx, binding_quirks_mode *quirks);
-
-struct form *binding_get_forms(void *ctx);
-struct form_control *binding_get_control_for_node(void *ctx, dom_node *node);
-
-void binding_destroy_document(dom_document *doc);
-
-#endif
-