Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 4224 → Rev 4364

/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, &params);
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