diff options
author | Daniel Silverstone <dsilvers@digital-scurf.org> | 2012-07-07 19:56:40 +0100 |
---|---|---|
committer | Daniel Silverstone <dsilvers@digital-scurf.org> | 2012-07-07 19:56:40 +0100 |
commit | dc9100ba7c08d60e1ad5925bfe463ed5537b5710 (patch) | |
tree | bd1ca685165aac4c93600d62dd8503195dc973b9 /render | |
parent | ea5a8ed771bd8f5dde7632820c7d42a6de435c2a (diff) | |
download | netsurf-dc9100ba7c08d60e1ad5925bfe463ed5537b5710.tar.gz netsurf-dc9100ba7c08d60e1ad5925bfe463ed5537b5710.tar.bz2 |
Binding: Construct forms objects for a document
Diffstat (limited to 'render')
-rw-r--r-- | render/libdom_binding.c | 173 |
1 files changed, 166 insertions, 7 deletions
diff --git a/render/libdom_binding.c b/render/libdom_binding.c index 9ae76469c..57f97cf24 100644 --- a/render/libdom_binding.c +++ b/render/libdom_binding.c @@ -24,29 +24,45 @@ #include "utils/log.h" +typedef struct binding_ctx { + dom_hubbub_parser *parser; + dom_document *extracted; +} binding_ctx; + binding_error binding_create_tree(void **ctx, const char *charset, bool enable_script, dom_script script, void *context) { dom_hubbub_parser *parser = NULL; + binding_ctx *bctx = NULL; + + bctx = calloc(sizeof(*bctx), 1); + if (bctx == NULL) { + LOG(("Can't allocate memory for binding context")); + return BINDING_NOMEM; + } 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; + bctx->parser = parser; + *ctx = bctx; return BINDING_OK; } binding_error binding_destroy_tree(void *ctx) { - dom_hubbub_parser_destroy(ctx); + struct binding_ctx *bctx = ctx; + dom_hubbub_parser_destroy(bctx->parser); + free(bctx); return BINDING_OK; } binding_error binding_parse_chunk(void *ctx, const uint8_t *data, size_t len) { + struct binding_ctx *bctx = ctx; dom_hubbub_error error; - error = dom_hubbub_parser_parse_chunk(ctx, data, len); + error = dom_hubbub_parser_parse_chunk(bctx->parser, data, len); if (error == (DOM_HUBBUB_HUBBUB_ERR | HUBBUB_ENCODINGCHANGE)) { return BINDING_ENCODINGCHANGE; } else if (error != DOM_HUBBUB_OK) { @@ -57,8 +73,9 @@ binding_error binding_parse_chunk(void *ctx, const uint8_t *data, size_t len) binding_error binding_parse_completed(void *ctx) { + struct binding_ctx *bctx = ctx; dom_hubbub_error error; - error = dom_hubbub_parser_completed(ctx); + error = dom_hubbub_parser_completed(bctx->parser); if (error != DOM_HUBBUB_OK) { return BINDING_NOMEM; } @@ -67,10 +84,11 @@ binding_error binding_parse_completed(void *ctx) const char *binding_get_encoding(void *ctx, binding_encoding_source *source) { + struct binding_ctx *bctx = ctx; dom_hubbub_encoding_source hubbub_src; const char *encoding; - encoding = dom_hubbub_parser_get_encoding(ctx, &hubbub_src); + encoding = dom_hubbub_parser_get_encoding(bctx->parser, &hubbub_src); switch (hubbub_src) { case DOM_HUBBUB_ENCODING_SOURCE_HEADER: @@ -91,12 +109,153 @@ const char *binding_get_encoding(void *ctx, binding_encoding_source *source) dom_document *binding_get_document(void *ctx, binding_quirks_mode *quirks) { - return dom_hubbub_parser_get_document(ctx); + struct binding_ctx *bctx = ctx; + if (bctx->extracted == NULL) + bctx->extracted = dom_hubbub_parser_get_document(bctx->parser); + return bctx->extracted; +} + +static struct form * +parse_form_element(dom_hubbub_parser *parser, dom_node *node) +{ + dom_string *ds_action = NULL; + dom_string *ds_charset = NULL; + dom_string *ds_target = NULL; + dom_string *ds_method = NULL; + dom_string *ds_enctype = NULL; + char *action = NULL, *charset = NULL, *target = NULL; + form_method method; + dom_html_form_element *formele = (dom_html_form_element *)(node); + struct form * ret = NULL; + const char *docenc; + + /* Retrieve the attributes from the node */ + if (dom_html_form_element_get_action(formele, &ds_action) != DOM_NO_ERR) + goto out; + + if (dom_html_form_element_get_accept_charset(formele, &ds_charset) != DOM_NO_ERR) + goto out; + + if (dom_html_form_element_get_target(formele, &ds_target) != DOM_NO_ERR) + goto out; + + if (dom_html_form_element_get_method(formele, &ds_method) != DOM_NO_ERR) + goto out; + + if (dom_html_form_element_get_enctype(formele, &ds_enctype) != DOM_NO_ERR) + goto out; + + /* Extract the plain attributes ready for use. We have to do this + * because we cannot guarantee that the dom_strings are NULL terminated + * and thus we copy them. + */ + if (ds_action != NULL) + action = strndup(dom_string_data(ds_action), + dom_string_byte_length(ds_action)); + + if (ds_charset != NULL) + charset = strndup(dom_string_data(ds_charset), + dom_string_byte_length(ds_charset)); + + if (ds_target != NULL) + target = strndup(dom_string_data(ds_target), + dom_string_byte_length(ds_target)); + + /* Determine the method */ + method = method_GET; + if (ds_method != NULL) { + if (strncasecmp("post", dom_string_data(ds_method), + dom_string_byte_length(ds_method)) == 0) { + method = method_POST_URLENC; + if (ds_enctype != NULL) { + if (strncasecmp("multipart/form-data", + dom_string_data(ds_enctype), + dom_string_byte_length(ds_enctype)) == 0) { + method = method_POST_MULTIPART; + } + } + } + } + + /* Retrieve the document encoding */ + { + dom_hubbub_encoding_source hubbub_src; + docenc = dom_hubbub_parser_get_encoding(parser, &hubbub_src); + } + + /* Construct the form object */ + ret = form_new(node, action, target, method, charset, docenc); + +out: + if (ds_action != NULL) + dom_string_unref(ds_action); + if (ds_charset != NULL) + dom_string_unref(ds_charset); + if (ds_target != NULL) + dom_string_unref(ds_target); + if (ds_method != NULL) + dom_string_unref(ds_method); + if (ds_enctype != NULL) + dom_string_unref(ds_enctype); + if (action != NULL) + free(action); + if (charset != NULL) + free(charset); + if (target != NULL) + free(charset); + return ret; } struct form *binding_get_forms(void *ctx) { - return NULL; + binding_ctx *bctx = ctx; + binding_quirks_mode ignored; + dom_html_document *doc = + (dom_html_document *)binding_get_document(ctx, &ignored); + dom_html_collection *forms; + struct form *ret = NULL, *newf; + dom_node *node; + unsigned long nforms, n; + + if (doc == NULL) + return NULL; + + /* Attempt to build a set of all the forms */ + if (dom_html_document_get_forms(doc, &forms) != DOM_NO_ERR) + return NULL; + + /* Count the number of forms so we can iterate */ + if (dom_html_collection_get_length(forms, &nforms) != DOM_NO_ERR) + goto out; + + /* Iterate the forms collection, making form structs for returning */ + for (n = 0; n < nforms; ++n) { + if (dom_html_collection_item(forms, n, &node) != DOM_NO_ERR) { + goto out; + } + newf = parse_form_element(bctx->parser, node); + dom_node_unref(node); + if (newf == NULL) { + goto err; + } + newf->prev = ret; + ret = newf; + } + + /* All went well */ + goto out; +err: + while (ret != NULL) { + struct form *prev = ret->prev; + /* Destroy ret */ + free(ret); + ret = prev; + } +out: + /* Finished with the collection, return it */ + dom_html_collection_unref(forms); + + return ret; } struct form_control *binding_get_control_for_node(void *ctx, dom_node *node) |