/contrib/network/netsurf/libdom/bindings/hubbub/Makefile |
---|
0,0 → 1,8 |
# Sources |
OBJS := parser.o |
OUTFILE = libo.o |
CFLAGS += -I ./ -I ../../include/ -I ../../src/ -I ../../../libhubbub/include/ -I ../../../libwapcaplet/include/ |
include $(MENUETDEV)/makefiles/Makefile_for_o_lib |
/contrib/network/netsurf/libdom/bindings/hubbub/parser.c |
---|
0,0 → 1,963 |
/* |
* This file is part of libdom. |
* Licensed under the MIT License, |
* http://www.opensource.org/licenses/mit-license.php |
* Copyright 2007 John-Mark Bell <jmb@netsurf-browser.org> |
* Copyright 2009 Bo Yang <struggleyb.nku@gmail.com> |
* Copyright 2012 Daniel Silverstone <dsilvers@netsurf-browser.org> |
*/ |
#include <stdio.h> |
#include <string.h> |
#include "/home/sourcerer/kos_src/newenginek/kolibri/include/hubbub/errors.h" |
#include "/home/sourcerer/kos_src/newenginek/kolibri/include/hubbub/hubbub.h" |
#include "/home/sourcerer/kos_src/newenginek/kolibri/include/hubbub/parser.h" |
#include <dom/dom.h> |
//#include "errors.h" |
#include "parser.h" |
#include "utils.h" |
#include "core/document.h" |
#include "core/string.h" |
#include "core/node.h" |
#include "html/html_document.h" |
#include "html/html_button_element.h" |
#include "html/html_input_element.h" |
#include "html/html_select_element.h" |
#include "html/html_text_area_element.h" |
#include <libwapcaplet/libwapcaplet.h> |
/** |
* libdom Hubbub parser context |
*/ |
struct dom_hubbub_parser { |
hubbub_parser *parser; /**< Hubbub parser instance */ |
hubbub_tree_handler tree_handler; |
/**< Hubbub parser tree handler */ |
struct dom_document *doc; /**< DOM Document we're building */ |
dom_hubbub_encoding_source encoding_source; |
/**< The document's encoding source */ |
const char *encoding; /**< The document's encoding */ |
bool complete; /**< Indicate stream completion */ |
dom_msg msg; /**< Informational messaging function */ |
dom_script script; /**< Script callback function */ |
void *mctx; /**< Pointer to client data */ |
}; |
/* Forward declaration to break reference loop */ |
static hubbub_error add_attributes(void *parser, void *node, const hubbub_attribute *attributes, uint32_t n_attributes); |
/*--------------------- The callbacks definitions --------------------*/ |
static hubbub_error create_comment(void *parser, const hubbub_string *data, |
void **result) |
{ |
dom_hubbub_parser *dom_parser = (dom_hubbub_parser *) parser; |
dom_exception err; |
dom_string *str; |
struct dom_comment *comment; |
*result = NULL; |
err = dom_string_create(data->ptr, data->len, &str); |
if (err != DOM_NO_ERR) { |
dom_parser->msg(DOM_MSG_CRITICAL, dom_parser->mctx, |
"Can't create comment node text"); |
return HUBBUB_UNKNOWN; |
} |
err = dom_document_create_comment(dom_parser->doc, str, &comment); |
if (err != DOM_NO_ERR) { |
dom_string_unref(str); |
dom_parser->msg(DOM_MSG_CRITICAL, dom_parser->mctx, |
"Can't create comment node with text '%.*s'", |
data->len, data->ptr); |
return HUBBUB_UNKNOWN; |
} |
*result = comment; |
dom_string_unref(str); |
return HUBBUB_OK; |
} |
static char *parser_strndup(const char *s, size_t n) |
{ |
size_t len; |
char *s2; |
for (len = 0; len != n && s[len] != '\0'; len++) |
continue; |
s2 = malloc(len + 1); |
if (s2 == NULL) |
return NULL; |
memcpy(s2, s, len); |
s2[len] = '\0'; |
return s2; |
} |
static hubbub_error create_doctype(void *parser, const hubbub_doctype *doctype, |
void **result) |
{ |
dom_hubbub_parser *dom_parser = (dom_hubbub_parser *) parser; |
dom_exception err; |
char *qname, *public_id = NULL, *system_id = NULL; |
struct dom_document_type *dtype; |
*result = NULL; |
qname = parser_strndup((const char *) doctype->name.ptr, |
(size_t) doctype->name.len); |
if (qname == NULL) { |
dom_parser->msg(DOM_MSG_CRITICAL, dom_parser->mctx, |
"Can't create doctype name"); |
goto fail; |
} |
if (doctype->public_missing == false) { |
public_id = parser_strndup( |
(const char *) doctype->public_id.ptr, |
(size_t) doctype->public_id.len); |
} else { |
public_id = strdup(""); |
} |
if (public_id == NULL) { |
dom_parser->msg(DOM_MSG_CRITICAL, dom_parser->mctx, |
"Can't create doctype public id"); |
goto clean1; |
} |
if (doctype->system_missing == false) { |
system_id = parser_strndup( |
(const char *) doctype->system_id.ptr, |
(size_t) doctype->system_id.len); |
} else { |
system_id = strdup(""); |
} |
if (system_id == NULL) { |
dom_parser->msg(DOM_MSG_CRITICAL, dom_parser->mctx, |
"Can't create doctype system id"); |
goto clean2; |
} |
err = dom_implementation_create_document_type(qname, |
public_id, system_id, &dtype); |
if (err != DOM_NO_ERR) { |
dom_parser->msg(DOM_MSG_CRITICAL, dom_parser->mctx, |
"Can't create the document type"); |
goto clean3; |
} |
*result = dtype; |
clean3: |
free(system_id); |
clean2: |
free(public_id); |
clean1: |
free(qname); |
fail: |
if (*result == NULL) |
return HUBBUB_UNKNOWN; |
else |
return HUBBUB_OK; |
} |
static hubbub_error create_element(void *parser, const hubbub_tag *tag, |
void **result) |
{ |
dom_hubbub_parser *dom_parser = (dom_hubbub_parser *) parser; |
dom_exception err; |
dom_string *name; |
struct dom_element *element = NULL; |
hubbub_error herr; |
*result = NULL; |
err = dom_string_create_interned(tag->name.ptr, tag->name.len, &name); |
if (err != DOM_NO_ERR) { |
dom_parser->msg(DOM_MSG_CRITICAL, dom_parser->mctx, |
"Can't create element name"); |
goto fail; |
} |
if (tag->ns == HUBBUB_NS_NULL) { |
err = dom_document_create_element(dom_parser->doc, name, |
&element); |
if (err != DOM_NO_ERR) { |
dom_parser->msg(DOM_MSG_CRITICAL, dom_parser->mctx, |
"Can't create the DOM element"); |
goto clean1; |
} |
} else { |
err = dom_document_create_element_ns(dom_parser->doc, |
dom_namespaces[tag->ns], name, &element); |
if (err != DOM_NO_ERR) { |
dom_parser->msg(DOM_MSG_CRITICAL, dom_parser->mctx, |
"Can't create the DOM element"); |
goto clean1; |
} |
} |
if (element != NULL && tag->n_attributes > 0) { |
herr = add_attributes(parser, element, tag->attributes, |
tag->n_attributes); |
if (herr != HUBBUB_OK) |
goto clean1; |
} |
*result = element; |
clean1: |
dom_string_unref(name); |
fail: |
if (*result == NULL) |
return HUBBUB_UNKNOWN; |
else |
return HUBBUB_OK; |
} |
static hubbub_error create_text(void *parser, const hubbub_string *data, |
void **result) |
{ |
dom_hubbub_parser *dom_parser = (dom_hubbub_parser *) parser; |
dom_exception err; |
dom_string *str; |
struct dom_text *text = NULL; |
*result = NULL; |
err = dom_string_create(data->ptr, data->len, &str); |
if (err != DOM_NO_ERR) { |
dom_parser->msg(DOM_MSG_CRITICAL, dom_parser->mctx, |
"Can't create text '%.*s'", data->len, |
data->ptr); |
goto fail; |
} |
err = dom_document_create_text_node(dom_parser->doc, str, &text); |
if (err != DOM_NO_ERR) { |
dom_parser->msg(DOM_MSG_CRITICAL, dom_parser->mctx, |
"Can't create the DOM text node"); |
goto clean1; |
} |
*result = text; |
clean1: |
dom_string_unref(str); |
fail: |
if (*result == NULL) |
return HUBBUB_UNKNOWN; |
else |
return HUBBUB_OK; |
} |
static hubbub_error ref_node(void *parser, void *node) |
{ |
struct dom_node *dnode = (struct dom_node *) node; |
UNUSED(parser); |
dom_node_ref(dnode); |
return HUBBUB_OK; |
} |
static hubbub_error unref_node(void *parser, void *node) |
{ |
struct dom_node *dnode = (struct dom_node *) node; |
UNUSED(parser); |
dom_node_unref(dnode); |
return HUBBUB_OK; |
} |
static hubbub_error append_child(void *parser, void *parent, void *child, |
void **result) |
{ |
dom_hubbub_parser *dom_parser = (dom_hubbub_parser *) parser; |
dom_exception err; |
err = dom_node_append_child((struct dom_node *) parent, |
(struct dom_node *) child, |
(struct dom_node **) result); |
if (err != DOM_NO_ERR) { |
dom_parser->msg(DOM_MSG_CRITICAL, dom_parser->mctx, |
"Can't append child '%p' for parent '%p'", |
child, parent); |
return HUBBUB_UNKNOWN; |
} |
return HUBBUB_OK; |
} |
static hubbub_error insert_before(void *parser, void *parent, void *child, |
void *ref_child, void **result) |
{ |
dom_hubbub_parser *dom_parser = (dom_hubbub_parser *) parser; |
dom_exception err; |
err = dom_node_insert_before((struct dom_node *) parent, |
(struct dom_node *) child, |
(struct dom_node *) ref_child, |
(struct dom_node **) result); |
if (err != DOM_NO_ERR) { |
dom_parser->msg(DOM_MSG_CRITICAL, dom_parser->mctx, |
"Can't insert node '%p' before node '%p'", |
child, ref_child); |
return HUBBUB_UNKNOWN; |
} |
return HUBBUB_OK; |
} |
static hubbub_error remove_child(void *parser, void *parent, void *child, |
void **result) |
{ |
dom_hubbub_parser *dom_parser = (dom_hubbub_parser *) parser; |
dom_exception err; |
err = dom_node_remove_child((struct dom_node *) parent, |
(struct dom_node *) child, |
(struct dom_node **) result); |
if (err != DOM_NO_ERR) { |
dom_parser->msg(DOM_MSG_CRITICAL, dom_parser->mctx, |
"Can't remove child '%p'", child); |
return HUBBUB_UNKNOWN; |
} |
return HUBBUB_OK; |
} |
static hubbub_error clone_node(void *parser, void *node, bool deep, |
void **result) |
{ |
dom_hubbub_parser *dom_parser = (dom_hubbub_parser *) parser; |
dom_exception err; |
err = dom_node_clone_node((struct dom_node *) node, deep, |
(struct dom_node **) result); |
if (err != DOM_NO_ERR) { |
dom_parser->msg(DOM_MSG_CRITICAL, dom_parser->mctx, |
"Can't clone node '%p'", node); |
return HUBBUB_UNKNOWN; |
} |
return HUBBUB_OK; |
} |
static hubbub_error reparent_children(void *parser, void *node, |
void *new_parent) |
{ |
dom_hubbub_parser *dom_parser = (dom_hubbub_parser *) parser; |
dom_exception err; |
struct dom_node *child, *result; |
while(true) { |
err = dom_node_get_first_child((struct dom_node *) node, |
&child); |
if (err != DOM_NO_ERR) { |
dom_parser->msg(DOM_MSG_CRITICAL, dom_parser->mctx, |
"Error in dom_note_get_first_child"); |
return HUBBUB_UNKNOWN; |
} |
if (child == NULL) |
break; |
err = dom_node_remove_child(node, (struct dom_node *) child, |
&result); |
if (err != DOM_NO_ERR) { |
dom_parser->msg(DOM_MSG_CRITICAL, dom_parser->mctx, |
"Error in dom_node_remove_child"); |
goto fail; |
} |
dom_node_unref(result); |
err = dom_node_append_child((struct dom_node *) new_parent, |
(struct dom_node *) child, &result); |
if (err != DOM_NO_ERR) { |
dom_parser->msg(DOM_MSG_CRITICAL, dom_parser->mctx, |
"Error in dom_node_append_child"); |
goto fail; |
} |
dom_node_unref(result); |
dom_node_unref(child); |
} |
return HUBBUB_OK; |
fail: |
dom_node_unref(child); |
return HUBBUB_UNKNOWN; |
} |
static hubbub_error get_parent(void *parser, void *node, bool element_only, |
void **result) |
{ |
dom_hubbub_parser *dom_parser = (dom_hubbub_parser *) parser; |
dom_exception err; |
struct dom_node *parent; |
dom_node_type type = DOM_NODE_TYPE_COUNT; |
err = dom_node_get_parent_node((struct dom_node *) node, |
&parent); |
if (err != DOM_NO_ERR) { |
dom_parser->msg(DOM_MSG_CRITICAL, dom_parser->mctx, |
"Error in dom_node_get_parent"); |
return HUBBUB_UNKNOWN; |
} |
if (element_only == false) { |
*result = parent; |
return HUBBUB_OK; |
} |
err = dom_node_get_node_type(parent, &type); |
if (err != DOM_NO_ERR) { |
dom_parser->msg(DOM_MSG_CRITICAL, dom_parser->mctx, |
"Error in dom_node_get_type"); |
goto fail; |
} |
if (type == DOM_ELEMENT_NODE) { |
*result = parent; |
return HUBBUB_OK; |
} else { |
*result = NULL; |
dom_node_unref(parent); |
return HUBBUB_OK; |
} |
return HUBBUB_OK; |
fail: |
dom_node_unref(parent); |
return HUBBUB_UNKNOWN; |
} |
static hubbub_error has_children(void *parser, void *node, bool *result) |
{ |
dom_hubbub_parser *dom_parser = (dom_hubbub_parser *) parser; |
dom_exception err; |
err = dom_node_has_child_nodes((struct dom_node *) node, result); |
if (err != DOM_NO_ERR) { |
dom_parser->msg(DOM_MSG_CRITICAL, dom_parser->mctx, |
"Error in dom_node_has_child_nodes"); |
return HUBBUB_UNKNOWN; |
} |
return HUBBUB_OK; |
} |
static hubbub_error form_associate(void *parser, void *form, void *node) |
{ |
dom_hubbub_parser *dom_parser = (dom_hubbub_parser *) parser; |
dom_html_form_element *form_ele = form; |
dom_node_internal *ele = node; |
dom_html_document *doc = (dom_html_document *)ele->owner; |
dom_exception err = DOM_NO_ERR; |
/* Determine the kind of the node we have here. */ |
if (dom_string_caseless_isequal(ele->name, |
doc->memoised[hds_BUTTON])) { |
err = _dom_html_button_element_set_form( |
(dom_html_button_element *)node, form_ele); |
if (err != DOM_NO_ERR) { |
dom_parser->msg(DOM_MSG_CRITICAL, dom_parser->mctx, |
"Error in form_associate"); |
return HUBBUB_UNKNOWN; |
} |
} else if (dom_string_caseless_isequal(ele->name, |
doc->memoised[hds_INPUT])) { |
err = _dom_html_input_element_set_form( |
(dom_html_input_element *)node, form_ele); |
if (err != DOM_NO_ERR) { |
dom_parser->msg(DOM_MSG_CRITICAL, dom_parser->mctx, |
"Error in form_associate"); |
return HUBBUB_UNKNOWN; |
} |
} else if (dom_string_caseless_isequal(ele->name, |
doc->memoised[hds_SELECT])) { |
err = _dom_html_select_element_set_form( |
(dom_html_select_element *)node, form_ele); |
if (err != DOM_NO_ERR) { |
dom_parser->msg(DOM_MSG_CRITICAL, dom_parser->mctx, |
"Error in form_associate"); |
return HUBBUB_UNKNOWN; |
} |
} else if (dom_string_caseless_isequal(ele->name, |
doc->memoised[hds_TEXTAREA])) { |
err = _dom_html_text_area_element_set_form( |
(dom_html_text_area_element *)node, form_ele); |
if (err != DOM_NO_ERR) { |
dom_parser->msg(DOM_MSG_CRITICAL, dom_parser->mctx, |
"Error in form_associate"); |
return HUBBUB_UNKNOWN; |
} |
} |
return HUBBUB_OK; |
} |
static hubbub_error add_attributes(void *parser, void *node, |
const hubbub_attribute *attributes, uint32_t n_attributes) |
{ |
dom_hubbub_parser *dom_parser = (dom_hubbub_parser *) parser; |
dom_exception err; |
uint32_t i; |
for (i = 0; i < n_attributes; i++) { |
dom_string *name, *value; |
err = dom_string_create_interned(attributes[i].name.ptr, |
attributes[i].name.len, &name); |
if (err != DOM_NO_ERR) { |
dom_parser->msg(DOM_MSG_CRITICAL, dom_parser->mctx, |
"Can't create attribute name"); |
goto fail; |
} |
err = dom_string_create(attributes[i].value.ptr, |
attributes[i].value.len, &value); |
if (err != DOM_NO_ERR) { |
dom_parser->msg(DOM_MSG_CRITICAL, dom_parser->mctx, |
"Can't create attribute value"); |
dom_string_unref(name); |
goto fail; |
} |
if (attributes[i].ns == HUBBUB_NS_NULL) { |
err = dom_element_set_attribute( |
(struct dom_element *) node, name, |
value); |
dom_string_unref(name); |
dom_string_unref(value); |
if (err != DOM_NO_ERR) { |
dom_parser->msg(DOM_MSG_CRITICAL, |
dom_parser->mctx, |
"Can't add attribute"); |
} |
} else { |
err = dom_element_set_attribute_ns( |
(struct dom_element *) node, |
dom_namespaces[attributes[i].ns], name, |
value); |
dom_string_unref(name); |
dom_string_unref(value); |
if (err != DOM_NO_ERR) { |
dom_parser->msg(DOM_MSG_CRITICAL, |
dom_parser->mctx, |
"Can't add attribute ns"); |
} |
} |
} |
return HUBBUB_OK; |
fail: |
return HUBBUB_UNKNOWN; |
} |
static hubbub_error set_quirks_mode(void *parser, hubbub_quirks_mode mode) |
{ |
dom_hubbub_parser *dom_parser = (dom_hubbub_parser *) parser; |
switch (mode) { |
case HUBBUB_QUIRKS_MODE_NONE: |
dom_document_set_quirks_mode(dom_parser->doc, |
DOM_DOCUMENT_QUIRKS_MODE_NONE); |
break; |
case HUBBUB_QUIRKS_MODE_LIMITED: |
dom_document_set_quirks_mode(dom_parser->doc, |
DOM_DOCUMENT_QUIRKS_MODE_LIMITED); |
break; |
case HUBBUB_QUIRKS_MODE_FULL: |
dom_document_set_quirks_mode(dom_parser->doc, |
DOM_DOCUMENT_QUIRKS_MODE_FULL); |
break; |
} |
return HUBBUB_OK; |
} |
static hubbub_error change_encoding(void *parser, const char *charset) |
{ |
dom_hubbub_parser *dom_parser = (dom_hubbub_parser *) parser; |
uint32_t source; |
const char *name; |
/* If we have an encoding here, it means we are *certain* */ |
if (dom_parser->encoding != NULL) { |
return HUBBUB_OK; |
} |
/* Find the confidence otherwise (can only be from a BOM) */ |
name = hubbub_parser_read_charset(dom_parser->parser, &source); |
if (source == HUBBUB_CHARSET_CONFIDENT) { |
dom_parser->encoding_source = DOM_HUBBUB_ENCODING_SOURCE_DETECTED; |
dom_parser->encoding = 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 */ |
dom_parser->encoding = charset; |
dom_parser->encoding_source = DOM_HUBBUB_ENCODING_SOURCE_META; |
/* Equal encodings will have the same string pointers */ |
return (charset == name) ? HUBBUB_OK : HUBBUB_ENCODINGCHANGE; |
} |
static hubbub_error complete_script(void *parser, void *script) |
{ |
dom_hubbub_parser *dom_parser = (dom_hubbub_parser *) parser; |
dom_hubbub_error err; |
err = dom_parser->script(dom_parser->mctx, (struct dom_node *)script); |
if (err == DOM_HUBBUB_OK) { |
return HUBBUB_OK; |
} |
if ((err & DOM_HUBBUB_HUBBUB_ERR) != 0) { |
return err & (~DOM_HUBBUB_HUBBUB_ERR); |
} |
return HUBBUB_UNKNOWN; |
} |
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, |
complete_script, |
NULL |
}; |
/** |
* Memory allocator |
*/ |
static void *dom_hubbub_alloc(void *ptr, size_t len, void *pw) |
{ |
UNUSED(pw); |
if (ptr == NULL) |
return len > 0 ? malloc(len) : NULL; |
if (len == 0) { |
free(ptr); |
return NULL; |
} |
return realloc(ptr, len); |
} |
/** |
* Default message callback |
*/ |
static void dom_hubbub_parser_default_msg(uint32_t severity, void *ctx, |
const char *msg, ...) |
{ |
UNUSED(severity); |
UNUSED(ctx); |
UNUSED(msg); |
} |
/** |
* Default script callback. |
*/ |
static dom_hubbub_error |
dom_hubbub_parser_default_script(void *ctx, struct dom_node *node) |
{ |
UNUSED(ctx); |
UNUSED(node); |
return DOM_HUBBUB_OK; |
} |
/** |
* Create a Hubbub parser instance |
* |
* \param params The binding creation parameters |
* \param parser Pointer to location to recive instance. |
* \param document Pointer to location to receive document. |
* \return Error code |
*/ |
dom_hubbub_error |
dom_hubbub_parser_create(dom_hubbub_parser_params *params, |
dom_hubbub_parser **parser, |
dom_document **document) |
{ |
dom_hubbub_parser *binding; |
hubbub_parser_optparams optparams; |
hubbub_error error; |
dom_exception err; |
dom_string *idname = NULL; |
/* check result parameters */ |
if (document == NULL) { |
return DOM_HUBBUB_BADPARM; |
} |
if (parser == NULL) { |
return DOM_HUBBUB_BADPARM; |
} |
/* setup binding parser context */ |
binding = malloc(sizeof(dom_hubbub_parser)); |
if (binding == NULL) { |
return DOM_HUBBUB_NOMEM; |
} |
binding->parser = NULL; |
binding->doc = NULL; |
binding->encoding = params->enc; |
if (params->enc != NULL) { |
binding->encoding_source = DOM_HUBBUB_ENCODING_SOURCE_HEADER; |
} else { |
binding->encoding_source = DOM_HUBBUB_ENCODING_SOURCE_DETECTED; |
} |
binding->complete = false; |
if (params->msg == NULL) { |
binding->msg = dom_hubbub_parser_default_msg; |
} else { |
binding->msg = params->msg; |
} |
binding->mctx = params->ctx; |
/* ensure script function is valid or use the default */ |
if (params->script == NULL) { |
binding->script = dom_hubbub_parser_default_script; |
} else { |
binding->script = params->script; |
} |
/* create hubbub parser */ |
error = hubbub_parser_create(binding->encoding, |
params->fix_enc, |
dom_hubbub_alloc, |
NULL, |
&binding->parser); |
if (error != HUBBUB_OK) { |
free(binding); |
return (DOM_HUBBUB_HUBBUB_ERR | error); |
} |
/* create DOM document */ |
err = dom_implementation_create_document(DOM_IMPLEMENTATION_HTML, |
NULL, |
NULL, |
NULL, |
params->daf, |
params->ctx, |
&binding->doc); |
if (err != DOM_NO_ERR) { |
hubbub_parser_destroy(binding->parser); |
free(binding); |
return DOM_HUBBUB_DOM; |
} |
binding->tree_handler = tree_handler; |
binding->tree_handler.ctx = (void *)binding; |
/* set tree handler on parser */ |
optparams.tree_handler = &binding->tree_handler; |
hubbub_parser_setopt(binding->parser, |
HUBBUB_PARSER_TREE_HANDLER, |
&optparams); |
/* set document node*/ |
optparams.document_node = dom_node_ref((struct dom_node *)binding->doc); |
hubbub_parser_setopt(binding->parser, |
HUBBUB_PARSER_DOCUMENT_NODE, |
&optparams); |
/* set scripting state */ |
optparams.enable_scripting = params->enable_script; |
hubbub_parser_setopt(binding->parser, |
HUBBUB_PARSER_ENABLE_SCRIPTING, |
&optparams); |
/* set the document id parameter before the parse so searches |
* based on id succeed. |
*/ |
err = dom_string_create_interned((const uint8_t *) "id", |
SLEN("id"), |
&idname); |
if (err != DOM_NO_ERR) { |
binding->msg(DOM_MSG_ERROR, binding->mctx, "Can't set DOM document id name"); |
hubbub_parser_destroy(binding->parser); |
free(binding); |
return DOM_HUBBUB_DOM; |
} |
_dom_document_set_id_name(binding->doc, idname); |
dom_string_unref(idname); |
/* set return parameters */ |
*document = (dom_document *)dom_node_ref(binding->doc); |
*parser = binding; |
return DOM_HUBBUB_OK; |
} |
dom_hubbub_error |
dom_hubbub_parser_insert_chunk(dom_hubbub_parser *parser, |
const uint8_t *data, |
size_t length) |
{ |
hubbub_parser_insert_chunk(parser->parser, data, length); |
return DOM_HUBBUB_OK; |
} |
/** |
* Destroy a Hubbub parser instance |
* |
* \param parser The Hubbub parser object |
*/ |
void dom_hubbub_parser_destroy(dom_hubbub_parser *parser) |
{ |
hubbub_parser_destroy(parser->parser); |
parser->parser = NULL; |
if (parser->doc != NULL) { |
dom_node_unref((struct dom_node *) parser->doc); |
parser->doc = NULL; |
} |
free(parser); |
} |
/** |
* Parse data with Hubbub parser |
* |
* \param parser The parser object |
* \param data The data to be parsed |
* \param len The length of the data to be parsed |
* \return DOM_HUBBUB_OK on success, |
* DOM_HUBBUB_HUBBUB_ERR | <hubbub_error> on failure |
*/ |
dom_hubbub_error dom_hubbub_parser_parse_chunk(dom_hubbub_parser *parser, |
const uint8_t *data, size_t len) |
{ |
hubbub_error err; |
err = hubbub_parser_parse_chunk(parser->parser, data, len); |
if (err != HUBBUB_OK) |
return DOM_HUBBUB_HUBBUB_ERR | err; |
return DOM_HUBBUB_OK; |
} |
/** |
* Notify the parser to complete parsing |
* |
* \param parser The parser object |
* \return DOM_HUBBUB_OK on success, |
* DOM_HUBBUB_HUBBUB_ERR | <hubbub_error> on underlaying parser failure |
* DOMHUBBUB_UNKNOWN | <lwc_error> on libwapcaplet failure |
*/ |
dom_hubbub_error dom_hubbub_parser_completed(dom_hubbub_parser *parser) |
{ |
hubbub_error err; |
err = hubbub_parser_completed(parser->parser); |
if (err != HUBBUB_OK) { |
parser->msg(DOM_MSG_ERROR, parser->mctx, |
"hubbub_parser_completed failed: %d", err); |
return DOM_HUBBUB_HUBBUB_ERR | err; |
} |
parser->complete = true; |
return DOM_HUBBUB_OK; |
} |
/** |
* Retrieve the encoding |
* |
* \param parser The parser object |
* \param source The encoding_source |
* \return the encoding name |
*/ |
const char *dom_hubbub_parser_get_encoding(dom_hubbub_parser *parser, |
dom_hubbub_encoding_source *source) |
{ |
*source = parser->encoding_source; |
return parser->encoding != NULL ? parser->encoding |
: "Windows-1252"; |
} |
/** |
* Set the Parse pause state. |
* |
* \param parser The parser object |
* \param pause The pause state to set. |
* \return DOM_HUBBUB_OK on success, |
* DOM_HUBBUB_HUBBUB_ERR | <hubbub_error> on failure |
*/ |
dom_hubbub_error dom_hubbub_parser_pause(dom_hubbub_parser *parser, bool pause) |
{ |
hubbub_error err; |
hubbub_parser_optparams params; |
params.pause_parse = pause; |
err = hubbub_parser_setopt(parser->parser, HUBBUB_PARSER_PAUSE, ¶ms); |
if (err != HUBBUB_OK) |
return DOM_HUBBUB_HUBBUB_ERR | err; |
return DOM_HUBBUB_OK; |
} |
/contrib/network/netsurf/libdom/bindings/hubbub/README |
---|
0,0 → 1,8 |
Hubbub binding for libdom |
========================= |
This is a wrapper around hubbub's parser API, to facilitate |
construction of a libdom DOM tree. The basic premise is that the wrapper |
intercepts the SAX-like events emitted by hubbub's tokeniser then builds |
a libdom DOM tree from them. |
/contrib/network/netsurf/libdom/bindings/hubbub/errors.h |
---|
0,0 → 1,44 |
/* |
* This file is part of libdom. |
* Licensed under the MIT License, |
* http://www.opensource.org/licenses/mit-license.php |
* Copyright 2007 John-Mark Bell <jmb@netsurf-browser.org> |
*/ |
#ifndef dom_hubbub_errors_h_ |
#define dom_hubbub_errors_h_ |
#include <hubbub/errors.h> |
typedef enum { |
DOM_HUBBUB_OK = 0, |
DOM_HUBBUB_NOMEM = 1, |
DOM_HUBBUB_BADPARM = 2, /**< Bad input parameter */ |
DOM_HUBBUB_DOM = 3, /**< DOM operation failed */ |
DOM_HUBBUB_HUBBUB_ERR = (1<<16), |
DOM_HUBBUB_HUBBUB_ERR_PAUSED = (DOM_HUBBUB_HUBBUB_ERR | HUBBUB_PAUSED), |
DOM_HUBBUB_HUBBUB_ERR_ENCODINGCHANGE = (DOM_HUBBUB_HUBBUB_ERR | HUBBUB_ENCODINGCHANGE), |
DOM_HUBBUB_HUBBUB_ERR_NOMEM = (DOM_HUBBUB_HUBBUB_ERR | HUBBUB_NOMEM), |
DOM_HUBBUB_HUBBUB_ERR_BADPARM = (DOM_HUBBUB_HUBBUB_ERR | HUBBUB_BADPARM), |
DOM_HUBBUB_HUBBUB_ERR_INVALID = (DOM_HUBBUB_HUBBUB_ERR | HUBBUB_INVALID), |
DOM_HUBBUB_HUBBUB_ERR_FILENOTFOUND = (DOM_HUBBUB_HUBBUB_ERR | HUBBUB_FILENOTFOUND), |
DOM_HUBBUB_HUBBUB_ERR_NEEDDATA = (DOM_HUBBUB_HUBBUB_ERR | HUBBUB_NEEDDATA), |
DOM_HUBBUB_HUBBUB_ERR_BADENCODING = (DOM_HUBBUB_HUBBUB_ERR | HUBBUB_BADENCODING), |
DOM_HUBBUB_HUBBUB_ERR_UNKNOWN = (DOM_HUBBUB_HUBBUB_ERR | HUBBUB_UNKNOWN), |
} dom_hubbub_error; |
#endif |
/contrib/network/netsurf/libdom/bindings/hubbub/parser.h |
---|
0,0 → 1,101 |
/* |
* This file is part of libdom. |
* Licensed under the MIT License, |
* http://www.opensource.org/licenses/mit-license.php |
* Copyright 2007 John-Mark Bell <jmb@netsurf-browser.org> |
*/ |
#ifndef dom_hubbub_parser_h_ |
#define dom_hubbub_parser_h_ |
#include <stddef.h> |
#include <inttypes.h> |
#include <hubbub/errors.h> |
#include <dom/dom.h> |
#include "errors.h" |
/** |
* Type of script completion function |
*/ |
typedef dom_hubbub_error (*dom_script)(void *ctx, struct dom_node *node); |
typedef struct dom_hubbub_parser dom_hubbub_parser; |
/* The encoding source of the document */ |
typedef enum dom_hubbub_encoding_source { |
DOM_HUBBUB_ENCODING_SOURCE_HEADER, |
DOM_HUBBUB_ENCODING_SOURCE_DETECTED, |
DOM_HUBBUB_ENCODING_SOURCE_META |
} dom_hubbub_encoding_source; |
/* The recommended way to use the parser is: |
* |
* dom_hubbub_parser_create(...); |
* dom_hubbub_parser_parse_chunk(...); |
* call _parse_chunk for all chunks of data |
* |
* After you have parsed the data, |
* |
* dom_hubbub_parser_completed(...); |
* dom_hubbub_parser_destroy(...); |
* |
* Clients must ensure that these function calls above are called in |
* the order shown. dom_hubbub_parser_create() will pass the ownership |
* of the document to the client. After that, the parser should be destroyed. |
* The client must not call any method of this parser after destruction. |
*/ |
/** |
* Parameter block for dom_hubbub_parser_create |
*/ |
typedef struct dom_hubbub_parser_params { |
const char *enc; /**< Source charset, or NULL */ |
bool fix_enc; /**< Whether fix the encoding */ |
bool enable_script; /**< Whether scripting should be enabled. */ |
dom_script script; /**< Script callback function */ |
dom_msg msg; /**< Informational message function */ |
void *ctx; /**< Pointer to client-specific private data */ |
/** default action fetcher function */ |
dom_events_default_action_fetcher daf; |
} dom_hubbub_parser_params; |
/* Create a Hubbub parser instance */ |
dom_hubbub_error dom_hubbub_parser_create(dom_hubbub_parser_params *params, |
dom_hubbub_parser **parser, |
dom_document **document); |
/* Destroy a Hubbub parser instance */ |
void dom_hubbub_parser_destroy(dom_hubbub_parser *parser); |
/* Parse a chunk of data */ |
dom_hubbub_error dom_hubbub_parser_parse_chunk(dom_hubbub_parser *parser, |
const uint8_t *data, size_t len); |
/* insert data into the parse stream but do not parse it */ |
dom_hubbub_error dom_hubbub_parser_insert_chunk(dom_hubbub_parser *parser, |
const uint8_t *data, size_t length); |
/* Notify parser that datastream is empty */ |
dom_hubbub_error dom_hubbub_parser_completed(dom_hubbub_parser *parser); |
/* Retrieve the document's encoding */ |
const char *dom_hubbub_parser_get_encoding(dom_hubbub_parser *parser, |
dom_hubbub_encoding_source *source); |
/** |
* Set the Parse pause state. |
* |
* \param parser The parser object |
* \param pause The pause state to set. |
* \return DOM_HUBBUB_OK on success, |
* DOM_HUBBUB_HUBBUB_ERR | <hubbub_error> on failure |
*/ |
dom_hubbub_error dom_hubbub_parser_pause(dom_hubbub_parser *parser, bool pause); |
#endif |
/contrib/network/netsurf/libdom/bindings/hubbub/utils.h |
---|
0,0 → 1,28 |
/* |
* This file is part of libdom. |
* Licensed under the MIT License, |
* http://www.opensource.org/licenses/mit-license.php |
* Copyright 2007 John-Mark Bell <jmb@netsurf-browser.org> |
*/ |
#ifndef dom_hubbub_utils_h_ |
#define dom_hubbub_utils_h_ |
#ifndef max |
#define max(a,b) ((a)>(b)?(a):(b)) |
#endif |
#ifndef min |
#define min(a,b) ((a)<(b)?(a):(b)) |
#endif |
#ifndef SLEN |
/* Calculate length of a string constant */ |
#define SLEN(s) (sizeof((s)) - 1) /* -1 for '\0' */ |
#endif |
#ifndef UNUSED |
#define UNUSED(x) ((x)=(x)) |
#endif |
#endif |
/contrib/network/netsurf/libdom/bindings/Makefile |
---|
0,0 → 1,3 |
# Bindings |
include $(NSBUILD)/Makefile.subdir |
/contrib/network/netsurf/libdom/bindings/xml/Makefile |
---|
0,0 → 1,33 |
ifeq ($(WITH_LIBXML_BINDING),yes) |
DIR_SOURCES := libxml_xmlparser.c |
# LibXML2 |
ifneq ($(PKGCONFIG),) |
CFLAGS := $(CFLAGS) $(shell $(PKGCONFIG) libxml-2.0 --cflags) |
LDFLAGS := $(LDFLAGS) $(shell $(PKGCONFIG) libxml-2.0 --libs) |
else |
CFLAGS := $(CFLAGS) -I$(PREFIX)/include/libxml2 |
LDFLAGS := $(LDFLAGS) -lxml2 |
endif |
# LibXML 2.6.26 has a bug in its headers that expects _POSIX_C_SOURCE to be |
# defined. Define it here, even though we don't need it. |
CFLAGS := $(CFLAGS) -D_POSIX_C_SOURCE |
DO_XML_INSTALL := yes |
endif |
ifeq ($(WITH_EXPAT_BINDING),yes) |
DIR_SOURCES := expat_xmlparser.c |
LDFLAGS := $(LDFLAGS) -lexpat |
DO_XML_INSTALL := yes |
endif |
ifeq ($(DO_XML_INSTALL),yes) |
DIR_INSTALL_ITEMS := /include/dom/bindings/xml:xmlerror.h;xmlparser.h |
endif |
include $(NSBUILD)/Makefile.subdir |
/contrib/network/netsurf/libdom/bindings/xml/README |
---|
0,0 → 1,14 |
LibXML binding for libdom |
========================= |
This is a wrapper around libxml's push parser API, to facilitate |
construction of a libdom DOM tree. The basic premise is that the wrapper |
intercepts the SAX events emitted by libxml's tokeniser then invokes |
libxml's own SAX handlers, wrapping the results up in libdom-specific |
data structures. |
The tree created is thus a tree of libdom nodes, each of which is linked |
to the libxml node that backs it. This allows the binding to process the |
DOM tree using libxml api, should it need to (e.g. for normalization |
purposes). |
/contrib/network/netsurf/libdom/bindings/xml/expat_xmlparser.c |
---|
0,0 → 1,589 |
/* |
* This file is part of libdom. |
* Licensed under the MIT License, |
* http://www.opensource.org/licenses/mit-license.php |
* Copyright 2012 Daniel Silverstone <dsilvers@netsurf-browser.org> |
*/ |
#include <stdbool.h> |
#include <string.h> |
#include <assert.h> |
#include <stdlib.h> |
#include <stdio.h> |
#include <dom/dom.h> |
#include "xmlparser.h" |
#include "utils.h" |
#include <expat.h> |
/** |
* expat XML parser object |
*/ |
struct dom_xml_parser { |
dom_msg msg; /**< Informational message function */ |
void *mctx; /**< Pointer to client data */ |
XML_Parser parser; /**< expat parser context */ |
struct dom_document *doc; /**< DOM Document we're building */ |
struct dom_node *current; /**< DOM node we're currently building */ |
bool is_cdata; /**< If the character data is cdata or text */ |
}; |
/* Binding functions */ |
static void |
expat_xmlparser_start_element_handler(void *_parser, |
const XML_Char *name, |
const XML_Char **atts) |
{ |
dom_xml_parser *parser = _parser; |
dom_exception err; |
dom_element *elem, *ins_elem; |
dom_string *tag_name; |
dom_string *namespace = NULL; |
const XML_Char *ns_sep = strchr(name, '\n'); |
if (ns_sep != NULL) { |
err = dom_string_create_interned((const uint8_t *)name, |
ns_sep - name, |
&namespace); |
if (err != DOM_NO_ERR) { |
parser->msg(DOM_MSG_CRITICAL, parser->mctx, |
"No memory for namespace name"); |
return; |
} |
name = ns_sep + 1; |
} |
err = dom_string_create_interned((const uint8_t *)name, |
strlen(name), |
&tag_name); |
if (err != DOM_NO_ERR) { |
parser->msg(DOM_MSG_CRITICAL, parser->mctx, |
"No memory for tag name"); |
if (namespace != NULL) |
dom_string_unref(namespace); |
return; |
} |
if (namespace == NULL) |
err = dom_document_create_element(parser->doc, |
tag_name, &elem); |
else |
err = dom_document_create_element_ns(parser->doc, namespace, |
tag_name, &elem); |
if (err != DOM_NO_ERR) { |
if (namespace != NULL) |
dom_string_unref(namespace); |
dom_string_unref(tag_name); |
parser->msg(DOM_MSG_CRITICAL, parser->mctx, |
"Failed to create element '%s'", name); |
return; |
} |
dom_string_unref(tag_name); |
if (namespace != NULL) |
dom_string_unref(namespace); |
/* Add attributes to the element */ |
while (*atts) { |
dom_string *key, *value; |
ns_sep = strchr(*atts, '\n'); |
if (ns_sep != NULL) { |
err = dom_string_create_interned((const uint8_t *)(*atts), |
ns_sep - (*atts), |
&namespace); |
if (err != DOM_NO_ERR) { |
parser->msg(DOM_MSG_CRITICAL, parser->mctx, |
"No memory for attr namespace"); |
dom_node_unref(elem); |
return; |
} |
} else |
namespace = NULL; |
if (ns_sep == NULL) |
err = dom_string_create_interned((const uint8_t *)(*atts), |
strlen(*atts), &key); |
else |
err = dom_string_create_interned((const uint8_t *)(ns_sep + 1), |
strlen(ns_sep + 1), |
&key); |
if (err != DOM_NO_ERR) { |
parser->msg(DOM_MSG_CRITICAL, parser->mctx, |
"No memory for attribute name"); |
if (namespace != NULL) |
dom_string_unref(namespace); |
dom_node_unref(elem); |
return; |
} |
atts++; |
err = dom_string_create((const uint8_t *)(*atts), |
strlen(*atts), &value); |
if (err != DOM_NO_ERR) { |
dom_node_unref(elem); |
if (namespace != NULL) |
dom_string_unref(namespace); |
dom_string_unref(key); |
parser->msg(DOM_MSG_CRITICAL, parser->mctx, |
"No memory for attribute value"); |
return; |
} |
atts++; |
if (namespace == NULL) |
err = dom_element_set_attribute(elem, key, value); |
else |
err = dom_element_set_attribute_ns(elem, namespace, |
key, value); |
if (namespace != NULL) |
dom_string_unref(namespace); |
dom_string_unref(key); |
dom_string_unref(value); |
if (err != DOM_NO_ERR) { |
dom_node_unref(elem); |
parser->msg(DOM_MSG_CRITICAL, parser->mctx, |
"No memory for setting attribute"); |
return; |
} |
} |
err = dom_node_append_child(parser->current, (struct dom_node *) elem, |
(struct dom_node **) (void *) &ins_elem); |
if (err != DOM_NO_ERR) { |
dom_node_unref(elem); |
parser->msg(DOM_MSG_CRITICAL, parser->mctx, |
"No memory for appending child node"); |
return; |
} |
dom_node_unref(ins_elem); |
dom_node_unref(parser->current); |
parser->current = (struct dom_node *)elem; /* Steal initial ref */ |
} |
static void |
expat_xmlparser_end_element_handler(void *_parser, |
const XML_Char *name) |
{ |
dom_xml_parser *parser = _parser; |
dom_exception err; |
dom_node *parent; |
UNUSED(name); |
err = dom_node_get_parent_node(parser->current, &parent); |
if (err != DOM_NO_ERR) { |
parser->msg(DOM_MSG_CRITICAL, parser->mctx, |
"Unable to find a parent while closing element."); |
return; |
} |
dom_node_unref(parser->current); |
parser->current = parent; /* Takes the ref given by get_parent_node */ |
} |
static void |
expat_xmlparser_start_cdata_handler(void *_parser) |
{ |
dom_xml_parser *parser = _parser; |
parser->is_cdata = true; |
} |
static void |
expat_xmlparser_end_cdata_handler(void *_parser) |
{ |
dom_xml_parser *parser = _parser; |
parser->is_cdata = false; |
} |
static void |
expat_xmlparser_cdata_handler(void *_parser, |
const XML_Char *s, |
int len) |
{ |
dom_xml_parser *parser = _parser; |
dom_string *data; |
dom_exception err; |
struct dom_node *cdata, *ins_cdata, *lastchild = NULL; |
dom_node_type ntype = 0; |
err = dom_string_create((const uint8_t *)s, len, &data); |
if (err != DOM_NO_ERR) { |
parser->msg(DOM_MSG_CRITICAL, parser->mctx, |
"No memory for cdata section contents"); |
return; |
} |
err = dom_node_get_last_child(parser->current, &lastchild); |
if (err == DOM_NO_ERR && lastchild != NULL) { |
err = dom_node_get_node_type(lastchild, &ntype); |
} |
if (err != DOM_NO_ERR) { |
dom_string_unref(data); |
if (lastchild != NULL) |
dom_node_unref(lastchild); |
parser->msg(DOM_MSG_CRITICAL, parser->mctx, |
"No memory for cdata section"); |
return; |
} |
if (ntype == DOM_TEXT_NODE && parser->is_cdata == false) { |
/* We can append this text instead */ |
err = dom_characterdata_append_data( |
(dom_characterdata *)lastchild, data); |
dom_string_unref(data); |
if (lastchild != NULL) |
dom_node_unref(lastchild); |
if (err != DOM_NO_ERR) { |
parser->msg(DOM_MSG_CRITICAL, parser->mctx, |
"No memory for cdata section"); |
} |
return; |
} |
if (lastchild != NULL) |
dom_node_unref(lastchild); |
/* We can't append directly, so make a new node */ |
err = parser->is_cdata ? |
dom_document_create_cdata_section(parser->doc, data, |
(dom_cdata_section **) (void *) &cdata) : |
dom_document_create_text_node(parser->doc, data, |
(dom_text **) (void *) &cdata); |
if (err != DOM_NO_ERR) { |
dom_string_unref(data); |
parser->msg(DOM_MSG_CRITICAL, parser->mctx, |
"No memory for cdata section"); |
return; |
} |
/* No longer need data */ |
dom_string_unref(data); |
/* Append cdata section to parent */ |
err = dom_node_append_child(parser->current, cdata, &ins_cdata); |
if (err != DOM_NO_ERR) { |
dom_node_unref((struct dom_node *) cdata); |
parser->msg(DOM_MSG_ERROR, parser->mctx, |
"Failed attaching cdata section"); |
return; |
} |
/* We're not interested in the inserted cdata section */ |
if (ins_cdata != NULL) |
dom_node_unref(ins_cdata); |
/* No longer interested in cdata section */ |
dom_node_unref(cdata); |
} |
static int |
expat_xmlparser_external_entity_ref_handler(XML_Parser parser, |
const XML_Char *context, |
const XML_Char *base, |
const XML_Char *system_id, |
const XML_Char *public_id) |
{ |
FILE *fh; |
XML_Parser subparser; |
unsigned char data[1024]; |
size_t len; |
enum XML_Status status; |
UNUSED(base); |
UNUSED(public_id); |
if (system_id == NULL) |
return XML_STATUS_OK; |
fh = fopen(system_id, "r"); |
if (fh == NULL) |
return XML_STATUS_OK; |
subparser = XML_ExternalEntityParserCreate(parser, |
context, |
NULL); |
if (subparser == NULL) { |
fclose(fh); |
return XML_STATUS_OK; |
} |
/* Parse the file bit by bit */ |
while ((len = fread(data, 1, 1024, fh)) > 0) { |
status = XML_Parse(subparser, (const char *)data, len, 0); |
if (status != XML_STATUS_OK) { |
XML_ParserFree(subparser); |
fclose(fh); |
return XML_STATUS_OK; |
} |
} |
XML_Parse(subparser, "", 0, 1); |
XML_ParserFree(subparser); |
fclose(fh); |
return XML_STATUS_OK; |
} |
static void |
expat_xmlparser_comment_handler(void *_parser, |
const XML_Char *_comment) |
{ |
dom_xml_parser *parser = _parser; |
struct dom_comment *comment, *ins_comment = NULL; |
dom_string *data; |
dom_exception err; |
/* Create DOM string data for comment */ |
err = dom_string_create((const uint8_t *)_comment, |
strlen((const char *) _comment), &data); |
if (err != DOM_NO_ERR) { |
parser->msg(DOM_MSG_CRITICAL, parser->mctx, |
"No memory for comment data"); |
return; |
} |
/* Create comment */ |
err = dom_document_create_comment(parser->doc, data, &comment); |
if (err != DOM_NO_ERR) { |
dom_string_unref(data); |
parser->msg(DOM_MSG_CRITICAL, parser->mctx, |
"No memory for comment node"); |
return; |
} |
/* No longer need data */ |
dom_string_unref(data); |
/* Append comment to parent */ |
err = dom_node_append_child(parser->current, (struct dom_node *) comment, |
(struct dom_node **) (void *) &ins_comment); |
if (err != DOM_NO_ERR) { |
dom_node_unref((struct dom_node *) comment); |
parser->msg(DOM_MSG_CRITICAL, parser->mctx, |
"Failed attaching comment node"); |
return; |
} |
/* We're not interested in the inserted comment */ |
if (ins_comment != NULL) |
dom_node_unref((struct dom_node *) ins_comment); |
/* No longer interested in comment */ |
dom_node_unref((struct dom_node *) comment); |
} |
static void |
expat_xmlparser_start_doctype_decl_handler(void *_parser, |
const XML_Char *doctype_name, |
const XML_Char *system_id, |
const XML_Char *public_id, |
int has_internal_subset) |
{ |
dom_xml_parser *parser = _parser; |
struct dom_document_type *doctype, *ins_doctype = NULL; |
dom_exception err; |
UNUSED(has_internal_subset); |
err = dom_implementation_create_document_type( |
doctype_name, system_id ? system_id : "", |
public_id ? public_id : "", |
&doctype); |
if (err != DOM_NO_ERR) { |
parser->msg(DOM_MSG_CRITICAL, parser->mctx, |
"Failed to create document type"); |
return; |
} |
/* Add doctype to document */ |
err = dom_node_append_child(parser->doc, (struct dom_node *) doctype, |
(struct dom_node **) (void *) &ins_doctype); |
if (err != DOM_NO_ERR) { |
dom_node_unref((struct dom_node *) doctype); |
parser->msg(DOM_MSG_CRITICAL, parser->mctx, |
"Failed attaching doctype"); |
return; |
} |
/* Not interested in inserted node */ |
if (ins_doctype != NULL) |
dom_node_unref((struct dom_node *) ins_doctype); |
/* No longer interested in doctype */ |
dom_node_unref((struct dom_node *) doctype); |
} |
static void |
expat_xmlparser_unknown_data_handler(void *_parser, |
const XML_Char *s, |
int len) |
{ |
UNUSED(_parser); |
UNUSED(s); |
UNUSED(len); |
} |
/** |
* Create an XML parser instance |
* |
* \param enc Source charset, or NULL |
* \param int_enc Desired charset of document buffer (UTF-8 or UTF-16) |
* \param msg Informational message function |
* \param mctx Pointer to client-specific private data |
* \return Pointer to instance, or NULL on memory exhaustion |
* |
* int_enc is ignored due to it being made of bees. |
*/ |
dom_xml_parser * |
dom_xml_parser_create(const char *enc, const char *int_enc, |
dom_msg msg, void *mctx, dom_document **document) |
{ |
dom_xml_parser *parser; |
dom_exception err; |
UNUSED(int_enc); |
parser = calloc(sizeof(*parser), 1); |
if (parser == NULL) { |
msg(DOM_MSG_CRITICAL, mctx, "No memory for parser"); |
return NULL; |
} |
parser->msg = msg; |
parser->mctx = mctx; |
parser->parser = XML_ParserCreateNS(enc, '\n'); |
if (parser->parser == NULL) { |
free(parser); |
msg(DOM_MSG_CRITICAL, mctx, "No memory for parser"); |
return NULL; |
} |
parser->doc = NULL; |
err = dom_implementation_create_document( |
DOM_IMPLEMENTATION_XML, |
/* namespace */ NULL, |
/* qname */ NULL, |
/* doctype */ NULL, |
NULL, |
NULL, |
document); |
if (err != DOM_NO_ERR) { |
parser->msg(DOM_MSG_CRITICAL, parser->mctx, |
"Failed creating document"); |
XML_ParserFree(parser->parser); |
free(parser); |
return NULL; |
} |
parser->doc = (dom_document *) dom_node_ref(*document); |
XML_SetUserData(parser->parser, parser); |
XML_SetElementHandler(parser->parser, |
expat_xmlparser_start_element_handler, |
expat_xmlparser_end_element_handler); |
XML_SetCdataSectionHandler(parser->parser, |
expat_xmlparser_start_cdata_handler, |
expat_xmlparser_end_cdata_handler); |
XML_SetCharacterDataHandler(parser->parser, |
expat_xmlparser_cdata_handler); |
XML_SetParamEntityParsing(parser->parser, |
XML_PARAM_ENTITY_PARSING_ALWAYS); |
XML_SetExternalEntityRefHandler(parser->parser, |
expat_xmlparser_external_entity_ref_handler); |
XML_SetCommentHandler(parser->parser, |
expat_xmlparser_comment_handler); |
XML_SetStartDoctypeDeclHandler(parser->parser, |
expat_xmlparser_start_doctype_decl_handler); |
XML_SetDefaultHandlerExpand(parser->parser, |
expat_xmlparser_unknown_data_handler); |
parser->current = dom_node_ref(parser->doc); |
parser->is_cdata = false; |
return parser; |
} |
/** |
* Destroy an XML parser instance |
* |
* \param parser The parser instance to destroy |
*/ |
void |
dom_xml_parser_destroy(dom_xml_parser *parser) |
{ |
XML_ParserFree(parser->parser); |
if (parser->current != NULL) |
dom_node_unref(parser->current); |
dom_node_unref(parser->doc); |
free(parser); |
} |
/** |
* Parse a chunk of data |
* |
* \param parser The XML parser instance to use for parsing |
* \param data Pointer to data chunk |
* \param len Byte length of data chunk |
* \return DOM_XML_OK on success, DOM_XML_EXTERNAL_ERR | <expat error> on failure |
*/ |
dom_xml_error |
dom_xml_parser_parse_chunk(dom_xml_parser *parser, uint8_t *data, size_t len) |
{ |
enum XML_Status status; |
status = XML_Parse(parser->parser, (const char *)data, len, 0); |
if (status != XML_STATUS_OK) { |
parser->msg(DOM_MSG_ERROR, parser->mctx, |
"XML_Parse failed: %d", status); |
return DOM_XML_EXTERNAL_ERR | status; |
} |
return DOM_XML_OK; |
} |
/** |
* Notify parser that datastream is empty |
* |
* \param parser The XML parser instance to notify |
* \return DOM_XML_OK on success, DOM_XML_EXTERNAL_ERR | <expat error> on failure |
* |
* This will force any remaining data through the parser |
*/ |
dom_xml_error |
dom_xml_parser_completed(dom_xml_parser *parser) |
{ |
enum XML_Status status; |
status = XML_Parse(parser->parser, "", 0, 1); |
if (status != XML_STATUS_OK) { |
parser->msg(DOM_MSG_ERROR, parser->mctx, |
"XML_Parse failed: %d", status); |
return DOM_XML_EXTERNAL_ERR | status; |
} |
return DOM_XML_OK; |
} |
/contrib/network/netsurf/libdom/bindings/xml/libxml_xmlparser.c |
---|
0,0 → 1,1335 |
/* |
* This file is part of libdom. |
* Licensed under the MIT License, |
* http://www.opensource.org/licenses/mit-license.php |
* Copyright 2007 John-Mark Bell <jmb@netsurf-browser.org> |
*/ |
#include <stdbool.h> |
#include <string.h> |
#include <assert.h> |
#include <libxml/parser.h> |
#include <libxml/SAX2.h> |
#include <libxml/xmlerror.h> |
#include <dom/dom.h> |
#include <libwapcaplet/libwapcaplet.h> |
#include "xmlerror.h" |
#include "xmlparser.h" |
#include "utils.h" |
#include "core/document.h" |
static void xml_parser_start_document(void *ctx); |
static void xml_parser_end_document(void *ctx); |
static void xml_parser_start_element_ns(void *ctx, const xmlChar *localname, |
const xmlChar *prefix, const xmlChar *URI, |
int nb_namespaces, const xmlChar **namespaces, |
int nb_attributes, int nb_defaulted, |
const xmlChar **attributes); |
static void xml_parser_end_element_ns(void *ctx, const xmlChar *localname, |
const xmlChar *prefix, const xmlChar *URI); |
static dom_exception xml_parser_link_nodes(dom_xml_parser *parser, |
struct dom_node *dom, xmlNodePtr xml); |
static void xml_parser_add_node(dom_xml_parser *parser, struct dom_node *parent, |
xmlNodePtr child); |
static void xml_parser_add_element_node(dom_xml_parser *parser, |
struct dom_node *parent, xmlNodePtr child); |
static void xml_parser_add_text_node(dom_xml_parser *parser, |
struct dom_node *parent, xmlNodePtr child); |
static void xml_parser_add_cdata_section(dom_xml_parser *parser, |
struct dom_node *parent, xmlNodePtr child); |
static void xml_parser_add_entity_reference(dom_xml_parser *parser, |
struct dom_node *parent, xmlNodePtr child); |
static void xml_parser_add_entity(dom_xml_parser *parser, |
struct dom_node *parent, xmlNodePtr child); |
static void xml_parser_add_comment(dom_xml_parser *parser, |
struct dom_node *parent, xmlNodePtr child); |
static void xml_parser_add_document_type(dom_xml_parser *parser, |
struct dom_node *parent, xmlNodePtr child); |
static void xml_parser_internal_subset(void *ctx, const xmlChar *name, |
const xmlChar *ExternalID, const xmlChar *SystemID); |
static int xml_parser_is_standalone(void *ctx); |
static int xml_parser_has_internal_subset(void *ctx); |
static int xml_parser_has_external_subset(void *ctx); |
static xmlParserInputPtr xml_parser_resolve_entity(void *ctx, |
const xmlChar *publicId, const xmlChar *systemId); |
static xmlEntityPtr xml_parser_get_entity(void *ctx, const xmlChar *name); |
static void xml_parser_entity_decl(void *ctx, const xmlChar *name, |
int type, const xmlChar *publicId, const xmlChar *systemId, |
xmlChar *content); |
static void xml_parser_notation_decl(void *ctx, const xmlChar *name, |
const xmlChar *publicId, const xmlChar *systemId); |
static void xml_parser_attribute_decl(void *ctx, const xmlChar *elem, |
const xmlChar *fullname, int type, int def, |
const xmlChar *defaultValue, xmlEnumerationPtr tree); |
static void xml_parser_element_decl(void *ctx, const xmlChar *name, |
int type, xmlElementContentPtr content); |
static void xml_parser_unparsed_entity_decl(void *ctx, const xmlChar *name, |
const xmlChar *publicId, const xmlChar *systemId, |
const xmlChar *notationName); |
static void xml_parser_set_document_locator(void *ctx, xmlSAXLocatorPtr loc); |
static void xml_parser_reference(void *ctx, const xmlChar *name); |
static void xml_parser_characters(void *ctx, const xmlChar *ch, int len); |
static void xml_parser_comment(void *ctx, const xmlChar *value); |
static xmlEntityPtr xml_parser_get_parameter_entity(void *ctx, |
const xmlChar *name); |
static void xml_parser_cdata_block(void *ctx, const xmlChar *value, int len); |
static void xml_parser_external_subset(void *ctx, const xmlChar *name, |
const xmlChar *ExternalID, const xmlChar *SystemID); |
/** |
* libdom XML parser object |
*/ |
struct dom_xml_parser { |
xmlParserCtxtPtr xml_ctx; /**< libxml parser context */ |
struct dom_document *doc; /**< DOM Document we're building */ |
dom_string *udkey; /**< Key for DOM node user data */ |
dom_msg msg; /**< Informational message function */ |
void *mctx; /**< Pointer to client data */ |
}; |
/** |
* SAX callback dispatch table |
*/ |
static xmlSAXHandler sax_handler = { |
.internalSubset = xml_parser_internal_subset, |
.isStandalone = xml_parser_is_standalone, |
.hasInternalSubset = xml_parser_has_internal_subset, |
.hasExternalSubset = xml_parser_has_external_subset, |
.resolveEntity = xml_parser_resolve_entity, |
.getEntity = xml_parser_get_entity, |
.entityDecl = xml_parser_entity_decl, |
.notationDecl = xml_parser_notation_decl, |
.attributeDecl = xml_parser_attribute_decl, |
.elementDecl = xml_parser_element_decl, |
.unparsedEntityDecl = xml_parser_unparsed_entity_decl, |
.setDocumentLocator = xml_parser_set_document_locator, |
.startDocument = xml_parser_start_document, |
.endDocument = xml_parser_end_document, |
.startElement = NULL, |
.endElement = NULL, |
.reference = xml_parser_reference, |
.characters = xml_parser_characters, |
.ignorableWhitespace = xml_parser_characters, |
.processingInstruction = NULL, |
.comment = xml_parser_comment, |
.warning = NULL, |
.error = NULL, |
.fatalError = NULL, |
.getParameterEntity = xml_parser_get_parameter_entity, |
.cdataBlock = xml_parser_cdata_block, |
.externalSubset = xml_parser_external_subset, |
.initialized = XML_SAX2_MAGIC, |
._private = NULL, |
.startElementNs = xml_parser_start_element_ns, |
.endElementNs = xml_parser_end_element_ns, |
.serror = NULL |
}; |
static void *dom_xml_alloc(void *ptr, size_t len, void *pw) |
{ |
UNUSED(pw); |
if (ptr == NULL) |
return len > 0 ? malloc(len) : NULL; |
if (len == 0) { |
free(ptr); |
return NULL; |
} |
return realloc(ptr, len); |
} |
/** |
* Create an XML parser instance |
* |
* \param enc Source charset, or NULL |
* \param int_enc Desired charset of document buffer (UTF-8 or UTF-16) |
* \param msg Informational message function |
* \param mctx Pointer to client-specific private data |
* \return Pointer to instance, or NULL on memory exhaustion |
* |
* Neither ::enc nor ::int_enc are used here. |
* libxml only supports a UTF-8 document buffer and forcibly setting the |
* parser encoding is not yet implemented |
*/ |
dom_xml_parser *dom_xml_parser_create(const char *enc, const char *int_enc, |
dom_msg msg, void *mctx, dom_document **document) |
{ |
dom_xml_parser *parser; |
dom_exception err; |
int ret; |
UNUSED(enc); |
UNUSED(int_enc); |
parser = dom_xml_alloc(NULL, sizeof(dom_xml_parser), NULL); |
if (parser == NULL) { |
msg(DOM_MSG_CRITICAL, mctx, "No memory for parser"); |
return NULL; |
} |
parser->xml_ctx = |
xmlCreatePushParserCtxt(&sax_handler, parser, "", 0, NULL); |
if (parser->xml_ctx == NULL) { |
dom_xml_alloc(parser, 0, NULL); |
msg(DOM_MSG_CRITICAL, mctx, "Failed to create XML parser"); |
return NULL; |
} |
/* Set options of parsing context */ |
ret = xmlCtxtUseOptions(parser->xml_ctx, XML_PARSE_DTDATTR | |
XML_PARSE_DTDLOAD); |
if (ret != 0) { |
xmlFreeParserCtxt(parser->xml_ctx); |
dom_xml_alloc(parser, 0, NULL); |
msg(DOM_MSG_CRITICAL, mctx, "Failed setting parser options"); |
return NULL; |
} |
/* Create key for user data registration */ |
err = dom_string_create((const uint8_t *) "__xmlnode", |
SLEN("__xmlnode"), &parser->udkey); |
if (err != DOM_NO_ERR) { |
xmlFreeParserCtxt(parser->xml_ctx); |
dom_xml_alloc(parser, 0, NULL); |
msg(DOM_MSG_CRITICAL, mctx, "No memory for userdata key"); |
return NULL; |
} |
err = dom_implementation_create_document( |
DOM_IMPLEMENTATION_XML, |
/* namespace */ NULL, |
/* qname */ NULL, |
/* doctype */ NULL, |
NULL, |
NULL, |
document); |
if (err != DOM_NO_ERR) { |
xmlFreeParserCtxt(parser->xml_ctx); |
dom_string_unref(parser->udkey); |
dom_xml_alloc(parser, 0, NULL); |
parser->msg(DOM_MSG_CRITICAL, parser->mctx, |
"Failed creating document"); |
return NULL; |
} |
parser->doc = (dom_document *) dom_node_ref(*document); |
parser->msg = msg; |
parser->mctx = mctx; |
return parser; |
} |
/** |
* Destroy an XML parser instance |
* |
* \param parser The parser instance to destroy |
*/ |
void dom_xml_parser_destroy(dom_xml_parser *parser) |
{ |
dom_string_unref(parser->udkey); |
dom_node_unref(parser->doc); |
xmlFreeDoc(parser->xml_ctx->myDoc); |
xmlFreeParserCtxt(parser->xml_ctx); |
dom_xml_alloc(parser, 0, NULL); |
} |
/** |
* Parse a chunk of data |
* |
* \param parser The XML parser instance to use for parsing |
* \param data Pointer to data chunk |
* \param len Byte length of data chunk |
* \return DOM_XML_OK on success, DOM_XML_EXTERNAL_ERR | <libxml error> on failure |
*/ |
dom_xml_error dom_xml_parser_parse_chunk(dom_xml_parser *parser, |
uint8_t *data, size_t len) |
{ |
xmlParserErrors err; |
err = xmlParseChunk(parser->xml_ctx, (char *) data, len, 0); |
if (err != XML_ERR_OK) { |
parser->msg(DOM_MSG_ERROR, parser->mctx, |
"xmlParseChunk failed: %d", err); |
return DOM_XML_EXTERNAL_ERR | err; |
} |
return DOM_XML_OK; |
} |
/** |
* Notify parser that datastream is empty |
* |
* \param parser The XML parser instance to notify |
* \return DOM_XML_OK on success, DOM_XML_EXTERNAL_ERR | <libxml error> on failure |
* |
* This will force any remaining data through the parser |
*/ |
dom_xml_error dom_xml_parser_completed(dom_xml_parser *parser) |
{ |
xmlParserErrors err; |
err = xmlParseChunk(parser->xml_ctx, "", 0, 1); |
if (err != XML_ERR_OK) { |
parser->msg(DOM_MSG_ERROR, parser->mctx, |
"xmlParseChunk failed: %d", err); |
return DOM_XML_EXTERNAL_ERR | err; |
} |
return DOM_XML_OK; |
} |
/** |
* Handle a document start SAX event |
* |
* \param ctx The callback context |
*/ |
void xml_parser_start_document(void *ctx) |
{ |
dom_xml_parser *parser = (dom_xml_parser *) ctx; |
dom_exception err; |
/* Invoke libxml2's default behaviour */ |
xmlSAX2StartDocument(parser->xml_ctx); |
/* Link nodes together */ |
err = xml_parser_link_nodes(parser, (struct dom_node *) parser->doc, |
(xmlNodePtr) parser->xml_ctx->myDoc); |
if (err != DOM_NO_ERR) { |
parser->msg(DOM_MSG_WARNING, parser->mctx, |
"Not able to link document nodes"); |
} |
} |
/** |
* Handle a document end SAX event |
* |
* \param ctx The callback context |
*/ |
void xml_parser_end_document(void *ctx) |
{ |
dom_xml_parser *parser = (dom_xml_parser *) ctx; |
xmlNodePtr node; |
xmlNodePtr n; |
dom_exception err; |
/* Invoke libxml2's default behaviour */ |
xmlSAX2EndDocument(parser->xml_ctx); |
/* If there is no document, we can't do anything */ |
if (parser->doc == NULL) { |
parser->msg(DOM_MSG_WARNING, parser->mctx, |
"No document in end_document"); |
return; |
} |
/* We need to mirror any child nodes at the end of the list of |
* children which occur after the last Element node in the list */ |
/* Get XML node */ |
err = dom_node_get_user_data((struct dom_node *) parser->doc, |
parser->udkey, (void **) (void *) &node); |
if (err != DOM_NO_ERR) { |
parser->msg(DOM_MSG_WARNING, parser->mctx, |
"Failed finding XML node"); |
return; |
} |
/* Find last Element node, if any */ |
for (n = node->last; n != NULL; n = n->prev) { |
if (n->type == XML_ELEMENT_NODE) |
break; |
} |
if (n == NULL) { |
/* No Element node found; entire list needs mirroring */ |
n = node->children; |
} else { |
/* Found last Element; skip over it */ |
n = n->next; |
} |
/* Now, mirror nodes in the DOM */ |
for (; n != NULL; n = n->next) { |
xml_parser_add_node(parser, |
(struct dom_node *) node->_private, n); |
} |
} |
/** |
* Handle an element open SAX event |
* |
* \param ctx The callback context |
* \param localname The local name of the element |
* \param prefix The element namespace prefix |
* \param URI The element namespace URI |
* \param nb_namespaces The number of namespace definitions |
* \param namespaces Array of nb_namespaces prefix/URI pairs |
* \param nb_attributes The total number of attributes |
* \param nb_defaulted The number of defaulted attributes |
* \param attributes Array of nb_attributes attribute values |
* |
* The number of non-defaulted attributes is ::nb_attributes - ::nb_defaulted |
* The defaulted attributes are at the end of the array ::attributes. |
*/ |
void xml_parser_start_element_ns(void *ctx, const xmlChar *localname, |
const xmlChar *prefix, const xmlChar *URI, |
int nb_namespaces, const xmlChar **namespaces, |
int nb_attributes, int nb_defaulted, |
const xmlChar **attributes) |
{ |
dom_xml_parser *parser = (dom_xml_parser *) ctx; |
xmlNodePtr parent = parser->xml_ctx->node; |
/* Invoke libxml2's default behaviour */ |
xmlSAX2StartElementNs(parser->xml_ctx, localname, prefix, URI, |
nb_namespaces, namespaces, nb_attributes, |
nb_defaulted, attributes); |
/* If there is no document, we can't do anything */ |
if (parser->doc == NULL) { |
parser->msg(DOM_MSG_WARNING, parser->mctx, |
"No document in start_element_ns"); |
return; |
} |
if (parent == NULL) { |
/* No parent; use document */ |
parent = (xmlNodePtr) parser->xml_ctx->myDoc; |
} |
if (parent->type == XML_DOCUMENT_NODE || |
parent->type == XML_ELEMENT_NODE) { |
/* Mirror in the DOM all children of the parent node |
* between the previous Element child (or the start, |
* whichever is encountered first) and the Element |
* just created */ |
xmlNodePtr n; |
/* Find previous element node, if any */ |
for (n = parser->xml_ctx->node->prev; n != NULL; |
n = n->prev) { |
if (n->type == XML_ELEMENT_NODE) |
break; |
} |
if (n == NULL) { |
/* No previous Element; use parent's children */ |
n = parent->children; |
} else { |
/* Previous Element; skip over it */ |
n = n->next; |
} |
/* Now, mirror nodes in the DOM */ |
for (; n != parser->xml_ctx->node; n = n->next) { |
xml_parser_add_node(parser, |
(struct dom_node *) parent->_private, |
n); |
} |
} |
/* Mirror the created node and its attributes in the DOM */ |
xml_parser_add_node(parser, (struct dom_node *) parent->_private, |
parser->xml_ctx->node); |
} |
/** |
* Handle an element close SAX event |
* |
* \param ctx The callback context |
* \param localname The local name of the element |
* \param prefix The element namespace prefix |
* \param URI The element namespace URI |
*/ |
void xml_parser_end_element_ns(void *ctx, const xmlChar *localname, |
const xmlChar *prefix, const xmlChar *URI) |
{ |
dom_xml_parser *parser = (dom_xml_parser *) ctx; |
xmlNodePtr node = parser->xml_ctx->node; |
xmlNodePtr n; |
/* Invoke libxml2's default behaviour */ |
xmlSAX2EndElementNs(parser->xml_ctx, localname, prefix, URI); |
/* If there is no document, we can't do anything */ |
if (parser->doc == NULL) { |
parser->msg(DOM_MSG_WARNING, parser->mctx, |
"No document in end_element_ns"); |
return; |
} |
/* If node wasn't linked, we can't do anything */ |
if (node->_private == NULL) { |
parser->msg(DOM_MSG_WARNING, parser->mctx, |
"Node '%s' not linked", node->name); |
return; |
} |
/* We need to mirror any child nodes at the end of the list of |
* children which occur after the last Element node in the list */ |
/* Find last Element node, if any */ |
for (n = node->last; n != NULL; n = n->prev) { |
if (n->type == XML_ELEMENT_NODE) |
break; |
} |
if (n == NULL) { |
/* No Element node found; entire list needs mirroring */ |
n = node->children; |
} else { |
/* Found last Element; skip over it */ |
n = n->next; |
} |
/* Now, mirror nodes in the DOM */ |
for (; n != NULL; n = n->next) { |
xml_parser_add_node(parser, |
(struct dom_node *) node->_private, n); |
} |
} |
/** |
* Link a DOM and XML node together |
* |
* \param parser The parser context |
* \param dom The DOM node |
* \param xml The XML node |
* \return DOM_NO_ERR on success, appropriate error otherwise |
*/ |
dom_exception xml_parser_link_nodes(dom_xml_parser *parser, |
struct dom_node *dom, xmlNodePtr xml) |
{ |
void *prev_data; |
dom_exception err; |
/* Register XML node as user data for DOM node */ |
err = dom_node_set_user_data(dom, parser->udkey, xml, NULL, |
&prev_data); |
if (err != DOM_NO_ERR) { |
parser->msg(DOM_MSG_ERROR, parser->mctx, |
"Failed setting user data: %d", err); |
return err; |
} |
/* Register DOM node with the XML node */ |
xml->_private = dom; |
return DOM_NO_ERR; |
} |
/** |
* Add a node to the DOM |
* |
* \param parser The parser context |
* \param parent The parent DOM node |
* \param child The xmlNode to mirror in the DOM as a child of parent |
*/ |
void xml_parser_add_node(dom_xml_parser *parser, struct dom_node *parent, |
xmlNodePtr child) |
{ |
static const char *node_types[] = { |
"THIS_IS_NOT_A_NODE", |
"XML_ELEMENT_NODE", |
"XML_ATTRIBUTE_NODE", |
"XML_TEXT_NODE", |
"XML_CDATA_SECTION_NODE", |
"XML_ENTITY_REF_NODE", |
"XML_ENTITY_NODE", |
"XML_PI_NODE", |
"XML_COMMENT_NODE", |
"XML_DOCUMENT_NODE", |
"XML_DOCUMENT_TYPE_NODE", |
"XML_DOCUMENT_FRAG_NODE", |
"XML_NOTATION_NODE", |
"XML_HTML_DOCUMENT_NODE", |
"XML_DTD_NODE", |
"XML_ELEMENT_DECL", |
"XML_ATTRIBUTE_DECL", |
"XML_ENTITY_DECL", |
"XML_NAMESPACE_DECL", |
"XML_XINCLUDE_START", |
"XML_XINCLUDE_END", |
"XML_DOCB_DOCUMENT_NODE" |
}; |
switch (child->type) { |
case XML_ELEMENT_NODE: |
xml_parser_add_element_node(parser, parent, child); |
break; |
case XML_TEXT_NODE: |
xml_parser_add_text_node(parser, parent, child); |
break; |
case XML_CDATA_SECTION_NODE: |
xml_parser_add_cdata_section(parser, parent, child); |
break; |
case XML_ENTITY_REF_NODE: |
xml_parser_add_entity_reference(parser, parent, child); |
break; |
case XML_COMMENT_NODE: |
xml_parser_add_comment(parser, parent, child); |
break; |
case XML_DTD_NODE: |
xml_parser_add_document_type(parser, parent, child); |
break; |
case XML_ENTITY_DECL: |
xml_parser_add_entity(parser, parent, child); |
break; |
default: |
parser->msg(DOM_MSG_NOTICE, parser->mctx, |
"Unsupported node type: %s", |
node_types[child->type]); |
} |
} |
/** |
* Add an element node to the DOM |
* |
* \param parser The parser context |
* \param parent The parent DOM node |
* \param child The xmlNode to mirror in the DOM as a child of parent |
*/ |
void xml_parser_add_element_node(dom_xml_parser *parser, |
struct dom_node *parent, xmlNodePtr child) |
{ |
struct dom_element *el, *ins_el = NULL; |
xmlAttrPtr a; |
dom_exception err; |
/* Create the element node */ |
if (child->ns == NULL) { |
/* No namespace */ |
dom_string *tag_name; |
/* Create tag name DOM string */ |
err = dom_string_create(child->name, |
strlen((const char *) child->name), &tag_name); |
if (err != DOM_NO_ERR) { |
parser->msg(DOM_MSG_CRITICAL, parser->mctx, |
"No memory for tag name"); |
return; |
} |
/* Create element node */ |
err = dom_document_create_element(parser->doc, |
tag_name, &el); |
if (err != DOM_NO_ERR) { |
dom_string_unref(tag_name); |
parser->msg(DOM_MSG_CRITICAL, parser->mctx, |
"Failed creating element '%s'", |
child->name); |
return; |
} |
/* No longer need tag name */ |
dom_string_unref(tag_name); |
} else { |
/* Namespace */ |
dom_string *namespace; |
dom_string *qname; |
size_t qnamelen = (child->ns->prefix != NULL ? |
strlen((const char *) child->ns->prefix) : 0) + |
(child->ns->prefix != NULL ? 1 : 0) /* ':' */ + |
strlen((const char *) child->name); |
uint8_t qnamebuf[qnamelen + 1 /* '\0' */]; |
/* Create namespace DOM string */ |
err = dom_string_create( |
child->ns->href, |
strlen((const char *) child->ns->href), |
&namespace); |
if (err != DOM_NO_ERR) { |
parser->msg(DOM_MSG_CRITICAL, parser->mctx, |
"No memory for namespace"); |
return; |
} |
/* QName is "prefix:localname", |
* or "localname" if there is no prefix */ |
sprintf((char *) qnamebuf, "%s%s%s", |
child->ns->prefix != NULL ? |
(const char *) child->ns->prefix : "", |
child->ns->prefix != NULL ? ":" : "", |
(const char *) child->name); |
/* Create qname DOM string */ |
err = dom_string_create( |
qnamebuf, |
qnamelen, |
&qname); |
if (err != DOM_NO_ERR) { |
dom_string_unref(namespace); |
parser->msg(DOM_MSG_CRITICAL, parser->mctx, |
"No memory for qname"); |
return; |
} |
/* Create element node */ |
err = dom_document_create_element_ns(parser->doc, |
namespace, qname, &el); |
if (err != DOM_NO_ERR) { |
dom_string_unref(namespace); |
dom_string_unref(qname); |
parser->msg(DOM_MSG_CRITICAL, parser->mctx, |
"Failed creating element '%s'", |
qnamebuf); |
return; |
} |
/* No longer need namespace / qname */ |
dom_string_unref(namespace); |
dom_string_unref(qname); |
} |
/* Add attributes to created element */ |
for (a = child->properties; a != NULL; a = a->next) { |
struct dom_attr *attr, *prev_attr; |
xmlNodePtr c; |
/* Create attribute node */ |
if (a->ns == NULL) { |
/* Attribute has no namespace */ |
dom_string *name; |
/* Create attribute name DOM string */ |
err = dom_string_create( |
a->name, |
strlen((const char *) a->name), |
&name); |
if (err != DOM_NO_ERR) { |
parser->msg(DOM_MSG_CRITICAL, parser->mctx, |
"No memory for attribute name"); |
goto cleanup; |
} |
/* Create attribute */ |
err = dom_document_create_attribute(parser->doc, |
name, &attr); |
if (err != DOM_NO_ERR) { |
dom_string_unref(name); |
parser->msg(DOM_MSG_CRITICAL, parser->mctx, |
"Failed creating attribute \ |
'%s'", a->name); |
goto cleanup; |
} |
/* No longer need attribute name */ |
dom_string_unref(name); |
} else { |
/* Attribute has namespace */ |
dom_string *namespace; |
dom_string *qname; |
size_t qnamelen = (a->ns->prefix != NULL ? |
strlen((const char *) a->ns->prefix) : 0) + |
(a->ns->prefix != NULL ? 1 : 0) /* ':' */ + |
strlen((const char *) a->name); |
uint8_t qnamebuf[qnamelen + 1 /* '\0' */]; |
/* Create namespace DOM string */ |
err = dom_string_create( |
a->ns->href, |
strlen((const char *) a->ns->href), |
&namespace); |
if (err != DOM_NO_ERR) { |
parser->msg(DOM_MSG_CRITICAL, parser->mctx, |
"No memory for namespace"); |
return; |
} |
/* QName is "prefix:localname", |
* or "localname" if there is no prefix */ |
sprintf((char *) qnamebuf, "%s%s%s", |
a->ns->prefix != NULL ? |
(const char *) a->ns->prefix : "", |
a->ns->prefix != NULL ? ":" : "", |
(const char *) a->name); |
/* Create qname DOM string */ |
err = dom_string_create( |
qnamebuf, |
qnamelen, |
&qname); |
if (err != DOM_NO_ERR) { |
dom_string_unref(namespace); |
parser->msg(DOM_MSG_CRITICAL, parser->mctx, |
"No memory for qname"); |
return; |
} |
/* Create attribute */ |
err = dom_document_create_attribute_ns(parser->doc, |
namespace, qname, &attr); |
if (err != DOM_NO_ERR) { |
dom_string_unref(namespace); |
dom_string_unref(qname); |
parser->msg(DOM_MSG_CRITICAL, parser->mctx, |
"Failed creating attribute \ |
'%s'", qnamebuf); |
return; |
} |
/* No longer need namespace / qname */ |
dom_string_unref(namespace); |
dom_string_unref(qname); |
} |
/* Clone subtree (attribute value) */ |
for (c = a->children; c != NULL; c = c->next) { |
xml_parser_add_node(parser, |
(struct dom_node *) attr, c); |
} |
/* Link nodes together */ |
err = xml_parser_link_nodes(parser, |
(struct dom_node *) attr, (xmlNodePtr) a); |
if (err != DOM_NO_ERR) { |
dom_node_unref((struct dom_node *) attr); |
goto cleanup; |
} |
if (a->ns == NULL) { |
/* And add attribute to the element */ |
err = dom_element_set_attribute_node(el, attr, |
&prev_attr); |
if (err != DOM_NO_ERR) { |
dom_node_unref((struct dom_node *) attr); |
parser->msg(DOM_MSG_ERROR, parser->mctx, |
"Failed attaching attribute \ |
'%s'", a->name); |
goto cleanup; |
} |
} else { |
err = dom_element_set_attribute_node_ns(el, attr, |
&prev_attr); |
if (err != DOM_NO_ERR) { |
dom_node_unref((struct dom_node *) attr); |
parser->msg(DOM_MSG_ERROR, parser->mctx, |
"Failed attaching attribute \ |
'%s'", a->name); |
goto cleanup; |
} |
} |
/* We're not interested in the previous attribute (if any) */ |
if (prev_attr != NULL && prev_attr != attr) |
dom_node_unref((struct dom_node *) prev_attr); |
/* We're no longer interested in the attribute node */ |
dom_node_unref((struct dom_node *) attr); |
} |
/* Append element to parent */ |
err = dom_node_append_child(parent, (struct dom_node *) el, |
(struct dom_node **) (void *) &ins_el); |
if (err != DOM_NO_ERR) { |
parser->msg(DOM_MSG_ERROR, parser->mctx, |
"Failed attaching element '%s'", |
child->name); |
goto cleanup; |
} |
/* We're not interested in the inserted element */ |
if (ins_el != NULL) |
dom_node_unref((struct dom_node *) ins_el); |
/* Link nodes together */ |
err = xml_parser_link_nodes(parser, (struct dom_node *) el, |
child); |
if (err != DOM_NO_ERR) { |
goto cleanup; |
} |
/* No longer interested in element node */ |
dom_node_unref((struct dom_node *) el); |
return; |
cleanup: |
/* No longer want node (any attributes attached to it |
* will be cleaned up with it) */ |
dom_node_unref((struct dom_node *) el); |
return; |
} |
/** |
* Add a text node to the DOM |
* |
* \param parser The parser context |
* \param parent The parent DOM node |
* \param child The xmlNode to mirror in the DOM as a child of parent |
*/ |
void xml_parser_add_text_node(dom_xml_parser *parser, struct dom_node *parent, |
xmlNodePtr child) |
{ |
struct dom_text *text, *ins_text = NULL; |
dom_string *data; |
dom_exception err; |
/* Create DOM string data for text node */ |
err = dom_string_create(child->content, |
strlen((const char *) child->content), &data); |
if (err != DOM_NO_ERR) { |
parser->msg(DOM_MSG_CRITICAL, parser->mctx, |
"No memory for text node contents "); |
return; |
} |
/* Create text node */ |
err = dom_document_create_text_node(parser->doc, data, &text); |
if (err != DOM_NO_ERR) { |
dom_string_unref(data); |
parser->msg(DOM_MSG_CRITICAL, parser->mctx, |
"No memory for text node"); |
return; |
} |
/* No longer need data */ |
dom_string_unref(data); |
/* Append text node to parent */ |
err = dom_node_append_child(parent, (struct dom_node *) text, |
(struct dom_node **) (void *) &ins_text); |
if (err != DOM_NO_ERR) { |
dom_node_unref((struct dom_node *) text); |
parser->msg(DOM_MSG_ERROR, parser->mctx, |
"Failed attaching text node"); |
return; |
} |
/* We're not interested in the inserted text node */ |
if (ins_text != NULL) |
dom_node_unref((struct dom_node *) ins_text); |
/* Link nodes together */ |
err = xml_parser_link_nodes(parser, (struct dom_node *) text, |
child); |
if (err != DOM_NO_ERR) { |
dom_node_unref((struct dom_node *) text); |
return; |
} |
/* No longer interested in text node */ |
dom_node_unref((struct dom_node *) text); |
} |
/** |
* Add a cdata section to the DOM |
* |
* \param parser The parser context |
* \param parent The parent DOM node |
* \param child The xmlNode to mirror in the DOM as a child of parent |
*/ |
void xml_parser_add_cdata_section(dom_xml_parser *parser, |
struct dom_node *parent, xmlNodePtr child) |
{ |
struct dom_cdata_section *cdata, *ins_cdata = NULL; |
dom_string *data; |
dom_exception err; |
/* Create DOM string data for cdata section */ |
err = dom_string_create(child->content, |
strlen((const char *) child->content), &data); |
if (err != DOM_NO_ERR) { |
parser->msg(DOM_MSG_CRITICAL, parser->mctx, |
"No memory for cdata section contents"); |
return; |
} |
/* Create cdata section */ |
err = dom_document_create_cdata_section(parser->doc, data, &cdata); |
if (err != DOM_NO_ERR) { |
dom_string_unref(data); |
parser->msg(DOM_MSG_CRITICAL, parser->mctx, |
"No memory for cdata section"); |
return; |
} |
/* No longer need data */ |
dom_string_unref(data); |
/* Append cdata section to parent */ |
err = dom_node_append_child(parent, (struct dom_node *) cdata, |
(struct dom_node **) (void *) &ins_cdata); |
if (err != DOM_NO_ERR) { |
dom_node_unref((struct dom_node *) cdata); |
parser->msg(DOM_MSG_ERROR, parser->mctx, |
"Failed attaching cdata section"); |
return; |
} |
/* We're not interested in the inserted cdata section */ |
if (ins_cdata != NULL) |
dom_node_unref((struct dom_node *) ins_cdata); |
/* Link nodes together */ |
err = xml_parser_link_nodes(parser, (struct dom_node *) cdata, |
child); |
if (err != DOM_NO_ERR) { |
dom_node_unref((struct dom_node *) cdata); |
return; |
} |
/* No longer interested in cdata section */ |
dom_node_unref((struct dom_node *) cdata); |
} |
/** |
* Add an entity reference to the DOM |
* |
* \param parser The parser context |
* \param parent The parent DOM node |
* \param child The xmlNode to mirror in the DOM as a child of parent |
*/ |
void xml_parser_add_entity_reference(dom_xml_parser *parser, |
struct dom_node *parent, xmlNodePtr child) |
{ |
struct dom_entity_reference *entity, *ins_entity = NULL; |
dom_string *name; |
xmlNodePtr c; |
dom_exception err; |
/* Create name of entity reference */ |
err = dom_string_create(child->name, |
strlen((const char *) child->name), &name); |
if (err != DOM_NO_ERR) { |
parser->msg(DOM_MSG_CRITICAL, parser->mctx, |
"No memory for entity reference name"); |
return; |
} |
/* Create text node */ |
err = dom_document_create_entity_reference(parser->doc, name, |
&entity); |
if (err != DOM_NO_ERR) { |
dom_string_unref(name); |
parser->msg(DOM_MSG_CRITICAL, parser->mctx, |
"No memory for entity reference"); |
return; |
} |
/* No longer need name */ |
dom_string_unref(name); |
/* Mirror subtree (reference value) */ |
for (c = child->children; c != NULL; c = c->next) { |
xml_parser_add_node(parser, (struct dom_node *) entity, c); |
} |
/* Append entity reference to parent */ |
err = dom_node_append_child(parent, (struct dom_node *) entity, |
(struct dom_node **) (void *) &ins_entity); |
if (err != DOM_NO_ERR) { |
dom_node_unref((struct dom_node *) entity); |
parser->msg(DOM_MSG_ERROR, parser->mctx, |
"Failed attaching entity reference"); |
return; |
} |
/* We're not interested in the inserted entity reference */ |
if (ins_entity != NULL) |
dom_node_unref((struct dom_node *) ins_entity); |
/* Link nodes together */ |
err = xml_parser_link_nodes(parser, (struct dom_node *) entity, |
child); |
if (err != DOM_NO_ERR) { |
dom_node_unref((struct dom_node *) entity); |
return; |
} |
/* No longer interested in entity reference */ |
dom_node_unref((struct dom_node *) entity); |
} |
static void xml_parser_add_entity(dom_xml_parser *parser, |
struct dom_node *parent, xmlNodePtr child) |
{ |
UNUSED(parser); |
UNUSED(parent); |
UNUSED(child); |
} |
/** |
* Add a comment to the DOM |
* |
* \param parser The parser context |
* \param parent The parent DOM node |
* \param child The xmlNode to mirror in the DOM as a child of parent |
*/ |
void xml_parser_add_comment(dom_xml_parser *parser, struct dom_node *parent, |
xmlNodePtr child) |
{ |
struct dom_comment *comment, *ins_comment = NULL; |
dom_string *data; |
dom_exception err; |
/* Create DOM string data for comment */ |
err = dom_string_create(child->content, |
strlen((const char *) child->content), &data); |
if (err != DOM_NO_ERR) { |
parser->msg(DOM_MSG_CRITICAL, parser->mctx, |
"No memory for comment data"); |
return; |
} |
/* Create comment */ |
err = dom_document_create_comment(parser->doc, data, &comment); |
if (err != DOM_NO_ERR) { |
dom_string_unref(data); |
parser->msg(DOM_MSG_CRITICAL, parser->mctx, |
"No memory for comment node"); |
return; |
} |
/* No longer need data */ |
dom_string_unref(data); |
/* Append comment to parent */ |
err = dom_node_append_child(parent, (struct dom_node *) comment, |
(struct dom_node **) (void *) &ins_comment); |
if (err != DOM_NO_ERR) { |
dom_node_unref((struct dom_node *) comment); |
parser->msg(DOM_MSG_CRITICAL, parser->mctx, |
"Failed attaching comment node"); |
return; |
} |
/* We're not interested in the inserted comment */ |
if (ins_comment != NULL) |
dom_node_unref((struct dom_node *) ins_comment); |
/* Link nodes together */ |
err = xml_parser_link_nodes(parser, (struct dom_node *) comment, |
child); |
if (err != DOM_NO_ERR) { |
dom_node_unref((struct dom_node *) comment); |
return; |
} |
/* No longer interested in comment */ |
dom_node_unref((struct dom_node *) comment); |
} |
/** |
* Add a document type to the DOM |
* |
* \param parser The parser context |
* \param parent The parent DOM node |
* \param child The xmlNode to mirror in the DOM as a child of parent |
*/ |
void xml_parser_add_document_type(dom_xml_parser *parser, |
struct dom_node *parent, xmlNodePtr child) |
{ |
xmlDtdPtr dtd = (xmlDtdPtr) child; |
struct dom_document_type *doctype, *ins_doctype = NULL; |
const char *qname, *public_id, *system_id; |
dom_exception err; |
/* Create qname for doctype */ |
qname = (const char *) dtd->name; |
/* Create public ID for doctype */ |
public_id = dtd->ExternalID != NULL ? |
(const char *) dtd->ExternalID : ""; |
/* Create system ID for doctype */ |
system_id = dtd->SystemID != NULL ? |
(const char *) dtd->SystemID : ""; |
/* Create doctype */ |
err = dom_implementation_create_document_type( |
qname, public_id, system_id, |
&doctype); |
if (err != DOM_NO_ERR) { |
parser->msg(DOM_MSG_CRITICAL, parser->mctx, |
"Failed to create document type"); |
return; |
} |
/* Add doctype to document */ |
err = dom_node_append_child(parent, (struct dom_node *) doctype, |
(struct dom_node **) (void *) &ins_doctype); |
if (err != DOM_NO_ERR) { |
dom_node_unref((struct dom_node *) doctype); |
parser->msg(DOM_MSG_CRITICAL, parser->mctx, |
"Failed attaching doctype"); |
return; |
} |
/* Not interested in inserted node */ |
if (ins_doctype != NULL) |
dom_node_unref((struct dom_node *) ins_doctype); |
/* Link nodes together */ |
err = xml_parser_link_nodes(parser, (struct dom_node *) doctype, |
child); |
if (err != DOM_NO_ERR) { |
dom_node_unref((struct dom_node *) doctype); |
return; |
} |
/* No longer interested in doctype */ |
dom_node_unref((struct dom_node *) doctype); |
} |
/* ------------------------------------------------------------------------*/ |
void xml_parser_internal_subset(void *ctx, const xmlChar *name, |
const xmlChar *ExternalID, const xmlChar *SystemID) |
{ |
dom_xml_parser *parser = (dom_xml_parser *) ctx; |
xmlSAX2InternalSubset(parser->xml_ctx, name, ExternalID, SystemID); |
} |
int xml_parser_is_standalone(void *ctx) |
{ |
dom_xml_parser *parser = (dom_xml_parser *) ctx; |
return xmlSAX2IsStandalone(parser->xml_ctx); |
} |
int xml_parser_has_internal_subset(void *ctx) |
{ |
dom_xml_parser *parser = (dom_xml_parser *) ctx; |
return xmlSAX2HasInternalSubset(parser->xml_ctx); |
} |
int xml_parser_has_external_subset(void *ctx) |
{ |
dom_xml_parser *parser = (dom_xml_parser *) ctx; |
return xmlSAX2HasExternalSubset(parser->xml_ctx); |
} |
xmlParserInputPtr xml_parser_resolve_entity(void *ctx, |
const xmlChar *publicId, const xmlChar *systemId) |
{ |
dom_xml_parser *parser = (dom_xml_parser *) ctx; |
return xmlSAX2ResolveEntity(parser->xml_ctx, publicId, systemId); |
} |
xmlEntityPtr xml_parser_get_entity(void *ctx, const xmlChar *name) |
{ |
dom_xml_parser *parser = (dom_xml_parser *) ctx; |
return xmlSAX2GetEntity(parser->xml_ctx, name); |
} |
void xml_parser_entity_decl(void *ctx, const xmlChar *name, |
int type, const xmlChar *publicId, const xmlChar *systemId, |
xmlChar *content) |
{ |
dom_xml_parser *parser = (dom_xml_parser *) ctx; |
xmlSAX2EntityDecl(parser->xml_ctx, name, type, publicId, systemId, |
content); |
} |
void xml_parser_notation_decl(void *ctx, const xmlChar *name, |
const xmlChar *publicId, const xmlChar *systemId) |
{ |
dom_xml_parser *parser = (dom_xml_parser *) ctx; |
xmlSAX2NotationDecl(parser->xml_ctx, name, publicId, systemId); |
} |
void xml_parser_attribute_decl(void *ctx, const xmlChar *elem, |
const xmlChar *fullname, int type, int def, |
const xmlChar *defaultValue, xmlEnumerationPtr tree) |
{ |
dom_xml_parser *parser = (dom_xml_parser *) ctx; |
xmlSAX2AttributeDecl(parser->xml_ctx, elem, fullname, type, def, |
defaultValue, tree); |
} |
void xml_parser_element_decl(void *ctx, const xmlChar *name, |
int type, xmlElementContentPtr content) |
{ |
dom_xml_parser *parser = (dom_xml_parser *) ctx; |
xmlSAX2ElementDecl(parser->xml_ctx, name, type, content); |
} |
void xml_parser_unparsed_entity_decl(void *ctx, const xmlChar *name, |
const xmlChar *publicId, const xmlChar *systemId, |
const xmlChar *notationName) |
{ |
dom_xml_parser *parser = (dom_xml_parser *) ctx; |
xmlSAX2UnparsedEntityDecl(parser->xml_ctx, name, publicId, |
systemId, notationName); |
} |
void xml_parser_set_document_locator(void *ctx, xmlSAXLocatorPtr loc) |
{ |
dom_xml_parser *parser = (dom_xml_parser *) ctx; |
xmlSAX2SetDocumentLocator(parser->xml_ctx, loc); |
} |
void xml_parser_reference(void *ctx, const xmlChar *name) |
{ |
dom_xml_parser *parser = (dom_xml_parser *) ctx; |
xmlSAX2Reference(parser->xml_ctx, name); |
} |
void xml_parser_characters(void *ctx, const xmlChar *ch, int len) |
{ |
dom_xml_parser *parser = (dom_xml_parser *) ctx; |
xmlSAX2Characters(parser->xml_ctx, ch, len); |
} |
void xml_parser_comment(void *ctx, const xmlChar *value) |
{ |
dom_xml_parser *parser = (dom_xml_parser *) ctx; |
xmlSAX2Comment(parser->xml_ctx, value); |
} |
xmlEntityPtr xml_parser_get_parameter_entity(void *ctx, const xmlChar *name) |
{ |
dom_xml_parser *parser = (dom_xml_parser *) ctx; |
return xmlSAX2GetParameterEntity(parser->xml_ctx, name); |
} |
void xml_parser_cdata_block(void *ctx, const xmlChar *value, int len) |
{ |
dom_xml_parser *parser = (dom_xml_parser *) ctx; |
xmlSAX2CDataBlock(parser->xml_ctx, value, len); |
} |
void xml_parser_external_subset(void *ctx, const xmlChar *name, |
const xmlChar *ExternalID, const xmlChar *SystemID) |
{ |
dom_xml_parser *parser = (dom_xml_parser *) ctx; |
xmlSAX2ExternalSubset(parser->xml_ctx, name, ExternalID, SystemID); |
} |
/contrib/network/netsurf/libdom/bindings/xml/utils.h |
---|
0,0 → 1,28 |
/* |
* This file is part of libdom. |
* Licensed under the MIT License, |
* http://www.opensource.org/licenses/mit-license.php |
* Copyright 2007 John-Mark Bell <jmb@netsurf-browser.org> |
*/ |
#ifndef xml_utils_h_ |
#define xml_utils_h_ |
#ifndef max |
#define max(a,b) ((a)>(b)?(a):(b)) |
#endif |
#ifndef min |
#define min(a,b) ((a)<(b)?(a):(b)) |
#endif |
#ifndef SLEN |
/* Calculate length of a string constant */ |
#define SLEN(s) (sizeof((s)) - 1) /* -1 for '\0' */ |
#endif |
#ifndef UNUSED |
#define UNUSED(x) ((x)=(x)) |
#endif |
#endif |
/contrib/network/netsurf/libdom/bindings/xml/xmlerror.h |
---|
0,0 → 1,19 |
/* |
* This file is part of libdom. |
* Licensed under the MIT License, |
* http://www.opensource.org/licenses/mit-license.php |
* Copyright 2007 John-Mark Bell <jmb@netsurf-browser.org> |
*/ |
#ifndef xml_xmlerror_h_ |
#define xml_xmlerror_h_ |
typedef enum { |
DOM_XML_OK = 0, |
DOM_XML_NOMEM = 1, |
DOM_XML_EXTERNAL_ERR = (1<<16), |
} dom_xml_error; |
#endif |
/contrib/network/netsurf/libdom/bindings/xml/xmlparser.h |
---|
0,0 → 1,34 |
/* |
* This file is part of libdom. |
* Licensed under the MIT License, |
* http://www.opensource.org/licenses/mit-license.php |
* Copyright 2007 John-Mark Bell <jmb@netsurf-browser.org> |
*/ |
#ifndef xml_xmlparser_h_ |
#define xml_xmlparser_h_ |
#include <stddef.h> |
#include <inttypes.h> |
#include <dom/dom.h> |
#include "xmlerror.h" |
typedef struct dom_xml_parser dom_xml_parser; |
/* Create an XML parser instance */ |
dom_xml_parser *dom_xml_parser_create(const char *enc, const char *int_enc, |
dom_msg msg, void *mctx, dom_document **document); |
/* Destroy an XML parser instance */ |
void dom_xml_parser_destroy(dom_xml_parser *parser); |
/* Parse a chunk of data */ |
dom_xml_error dom_xml_parser_parse_chunk(dom_xml_parser *parser, |
uint8_t *data, size_t len); |
/* Notify parser that datastream is empty */ |
dom_xml_error dom_xml_parser_completed(dom_xml_parser *parser); |
#endif |