summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile3
-rw-r--r--src/bootstrap/Makefile2
-rw-r--r--src/bootstrap/init_fini.c47
-rw-r--r--src/core/document.c87
-rw-r--r--src/utils/Makefile53
-rw-r--r--src/utils/namespace.c218
-rw-r--r--src/utils/namespace.h33
-rw-r--r--src/utils/utils.h4
8 files changed, 372 insertions, 75 deletions
diff --git a/src/Makefile b/src/Makefile
index b0f78b2..6c780a4 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -36,16 +36,19 @@ OBJS =
release: $(addprefix Release/, $(addsuffix .o, $(OBJS)))
@${MAKE} -C bootstrap release
@${MAKE} -C core release
+ @${MAKE} -C utils release
@${AR} ${ARFLAGS} $(RELEASE) Release/*
debug: $(addprefix Debug/, $(addsuffix .o, $(OBJS)))
@${MAKE} -C bootstrap debug
@${MAKE} -C core debug
+ @${MAKE} -C utils debug
@${AR} ${ARFLAGS} $(DEBUG) Debug/*
clean:
@${MAKE} -C bootstrap clean
@${MAKE} -C core clean
+ @${MAKE} -C utils clean
ifneq (${OBJS}, )
-@${RM} ${RMFLAGS} $(addprefix Release/, $(addsuffix .o, ${OBJS}))
-@${RM} ${RMFLAGS} $(addprefix Debug/, $(addsuffix .o, ${OBJS}))
diff --git a/src/bootstrap/Makefile b/src/bootstrap/Makefile
index 6c904cc..0eed6c7 100644
--- a/src/bootstrap/Makefile
+++ b/src/bootstrap/Makefile
@@ -22,7 +22,7 @@
CFLAGS += -I$(CURDIR)
# Objects
-OBJS = implregistry
+OBJS = implregistry init_fini
.PHONY: clean debug distclean export release setup test
diff --git a/src/bootstrap/init_fini.c b/src/bootstrap/init_fini.c
new file mode 100644
index 0000000..001eaf9
--- /dev/null
+++ b/src/bootstrap/init_fini.c
@@ -0,0 +1,47 @@
+/*
+ * 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 <dom/bootstrap/implpriv.h>
+
+#include "utils/namespace.h"
+
+/**
+ * Initialise the dom library
+ *
+ * \param alloc Pointer to memory (de)allocation function
+ * \param pw Pointer to client-specific private data
+ * \return DOM_NO_ERR on success.
+ *
+ * This should be invoked by the binding's initialiser and must be
+ * the first DOM library method called.
+ */
+dom_exception dom_initialise(dom_alloc alloc, void *pw)
+{
+ dom_exception err;
+
+ err = _dom_namespace_initialise(alloc, pw);
+
+ return err;
+}
+
+/**
+ * Finalise the dom library
+ *
+ * \return DOM_NO_ERR on success.
+ *
+ * This should be invoked by the binding's finaliser and must be
+ * the last DOM library method called.
+ */
+dom_exception dom_finalise(void)
+{
+ dom_exception err;
+
+ err = _dom_namespace_finalise();
+
+ return err;
+}
+
diff --git a/src/core/document.c b/src/core/document.c
index b456983..5148224 100644
--- a/src/core/document.c
+++ b/src/core/document.c
@@ -25,6 +25,7 @@
#include "core/nodelist.h"
#include "core/pi.h"
#include "core/text.h"
+#include "utils/namespace.h"
#include "utils/utils.h"
struct dom_document_type;
@@ -551,52 +552,23 @@ dom_exception dom_document_create_element_ns(struct dom_document *doc,
struct dom_string *namespace, struct dom_string *qname,
struct dom_element **result)
{
- const uint8_t *qd, *c, *ln;
- size_t qlen;
- size_t local_len;
- size_t prefix_len;
- struct dom_string *prefix = NULL;
- struct dom_string *localname;
+ struct dom_string *prefix, *localname;
dom_exception err;
/** \todo ensure document supports XML feature */
- /** \todo validate qname */
- dom_string_get_data(qname, &qd, &qlen);
-
- /* Divide QName into prefix/localname pair */
- for (c = qd; c != qd + qlen; c++) {
- if (*c == (const uint8_t) ':')
- break;
- }
-
- if (c == qd + qlen) {
- ln = qd;
- local_len = qlen;
- prefix_len = 0;
- } else {
- ln = ++c;
- local_len = qlen - (c - qd);
- prefix_len = (c - qd - 1 /* ':' */);
- }
-
- if (prefix_len > 0) {
- err = dom_string_create_from_ptr(doc, qd, prefix_len, &prefix);
- if (err != DOM_NO_ERR) {
- return err;
- }
+ /* Validate qname */
+ err = _dom_namespace_validate_qname(qname, namespace);
+ if (err != DOM_NO_ERR) {
+ return err;
}
- err = dom_string_create_from_ptr(doc, ln, local_len, &localname);
+ /* Divide QName into prefix/localname pair */
+ err = _dom_namespace_split_qname(qname, doc, &prefix, &localname);
if (err != DOM_NO_ERR) {
- if (prefix != NULL) {
- dom_string_unref(prefix);
- }
return err;
}
- /** \todo validate namespace */
-
/* Attempt to create element */
err = dom_element_create(doc, localname, namespace, prefix, result);
@@ -641,52 +613,23 @@ dom_exception dom_document_create_attribute_ns(struct dom_document *doc,
struct dom_string *namespace, struct dom_string *qname,
struct dom_attr **result)
{
- const uint8_t *qd, *c, *ln;
- size_t qlen;
- size_t local_len;
- size_t prefix_len;
- struct dom_string *prefix = NULL;
- struct dom_string *localname;
+ struct dom_string *prefix, *localname;
dom_exception err;
/** \todo ensure document supports XML feature */
- /** \todo validate qname */
- dom_string_get_data(qname, &qd, &qlen);
-
- /* Divide QName into prefix/localname pair */
- for (c = qd; c != qd + qlen; c++) {
- if (*c == (const uint8_t) ':')
- break;
- }
-
- if (c == qd + qlen) {
- ln = qd;
- local_len = qlen;
- prefix_len = 0;
- } else {
- ln = ++c;
- local_len = qlen - (c - qd);
- prefix_len = (c - qd - 1 /* ':' */);
- }
-
- if (prefix_len > 0) {
- err = dom_string_create_from_ptr(doc, qd, prefix_len, &prefix);
- if (err != DOM_NO_ERR) {
- return err;
- }
+ /* Validate qname */
+ err = _dom_namespace_validate_qname(qname, namespace);
+ if (err != DOM_NO_ERR) {
+ return err;
}
- err = dom_string_create_from_ptr(doc, ln, local_len, &localname);
+ /* Divide QName into prefix/localname pair */
+ err = _dom_namespace_split_qname(qname, doc, &prefix, &localname);
if (err != DOM_NO_ERR) {
- if (prefix != NULL) {
- dom_string_unref(prefix);
- }
return err;
}
- /** \todo validate namespace */
-
/* Attempt to create attribute */
err = dom_attr_create(doc, localname, namespace, prefix, result);
diff --git a/src/utils/Makefile b/src/utils/Makefile
new file mode 100644
index 0000000..29369ae
--- /dev/null
+++ b/src/utils/Makefile
@@ -0,0 +1,53 @@
+# Makefile for libdom
+#
+# Toolchain is exported by top-level makefile
+#
+# Top-level makefile also exports the following variables:
+#
+# COMPONENT Name of component
+# EXPORT Absolute path of export directory
+# TOP Absolute path of source tree root
+#
+# The top-level makefile requires the following targets to exist:
+#
+# clean Clean source tree
+# debug Create a debug binary
+# distclean Fully clean source tree, back to pristine condition
+# export Export distributable components to ${EXPORT}
+# release Create a release binary
+# setup Perform any setup required prior to compilation
+# test Execute any test cases
+
+# Manipulate include paths
+CFLAGS += -I$(CURDIR)
+
+# Objects
+OBJS = namespace
+
+.PHONY: clean debug distclean export release setup test
+
+# Targets
+release: $(addprefix ../Release/, $(addsuffix .o, $(OBJS)))
+
+debug: $(addprefix ../Debug/, $(addsuffix .o, $(OBJS)))
+
+clean:
+ -@${RM} ${RMFLAGS} $(addprefix ../Release/, $(addsuffix .o, ${OBJS}))
+ -@${RM} ${RMFLAGS} $(addprefix ../Debug/, $(addsuffix .o, ${OBJS}))
+
+distclean:
+
+setup:
+
+export:
+
+test:
+
+# Pattern rules
+../Release/%.o: %.c
+ @${ECHO} ${ECHOFLAGS} "==> $<"
+ @${CC} -c ${CFLAGS} -DNDEBUG -o $@ $<
+
+../Debug/%.o: %.c
+ @${ECHO} ${ECHOFLAGS} "==> $<"
+ @${CC} -c -g ${CFLAGS} -o $@ $<
diff --git a/src/utils/namespace.c b/src/utils/namespace.c
new file mode 100644
index 0000000..25b56ee
--- /dev/null
+++ b/src/utils/namespace.c
@@ -0,0 +1,218 @@
+/*
+ * 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 <string.h>
+
+#include <dom/core/string.h>
+
+#include "utils/namespace.h"
+#include "utils/utils.h"
+
+/** XML namespace URI */
+static struct dom_string *xml;
+/** XMLNS namespace URI */
+static struct dom_string *xmlns;
+
+/**
+ * Initialise the namespace component
+ *
+ * \param alloc Pointer to memory (de)allocation function
+ * \param pw Pointer to client-specific private data
+ * \return DOM_NO_ERR on success.
+ */
+dom_exception _dom_namespace_initialise(dom_alloc alloc, void *pw)
+{
+ dom_exception err;
+
+ err = dom_string_create_from_ptr_no_doc(alloc, pw,
+ (const uint8_t *) "http://www.w3.org/XML/1998/namespace",
+ SLEN("http://www.w3.org/XML/1998/namespace"),
+ &xml);
+ if (err != DOM_NO_ERR) {
+ return err;
+ }
+
+ err = dom_string_create_from_ptr_no_doc(alloc, pw,
+ (const uint8_t *) "http://www.w3.org/2000/xmlns",
+ SLEN("http://www.w3.org/2000/xmlns"),
+ &xmlns);
+ if (err != DOM_NO_ERR) {
+ dom_string_unref(xml);
+ return err;
+ }
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Finalise the namespace component
+ *
+ * \return DOM_NO_ERR on success.
+ */
+dom_exception _dom_namespace_finalise(void)
+{
+ dom_string_unref(xmlns);
+ dom_string_unref(xml);
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Ensure a QName is valid
+ *
+ * \param qname The qname to validate
+ * \param namespace The namespace URI associated with the QName, or NULL
+ * \return DOM_NO_ERR if valid,
+ * DOM_INVALID_CHARACTER_ERR if ::qname contains an invalid character,
+ * DOM_NAMESPACE_ERR if ::qname is malformed, or it has a
+ * prefix and ::namespace is NULL, or
+ * ::qname has a prefix "xml" and
+ * ::namespace is not
+ * "http://www.w3.org/XML/1998/namespace",
+ * or ::qname has a prefix "xmlns" and
+ * ::namespace is not
+ * "http://www.w3.org/2000/xmlns", or
+ * ::namespace is
+ * "http://www.w3.org/2000/xmlns" and
+ * ::qname is not (or is not prefixed by)
+ * "xmlns".
+ */
+dom_exception _dom_namespace_validate_qname(struct dom_string *qname,
+ struct dom_string *namespace)
+{
+ const uint8_t *qname_data, *c;
+ size_t qname_len;
+
+ dom_string_get_data(qname, &qname_data, &qname_len);
+
+ /** \todo search qname for invalid characters */
+ /** \todo ensure qname is not malformed */
+
+ /* Find colon */
+ /** \todo assumes ASCII-compatible encoding */
+ for (c = qname_data; c != qname_data + qname_len; c++) {
+ if (*c == (const uint8_t) ':') {
+ break;
+ }
+ }
+
+ if (c == qname_data + qname_len) {
+ /* No prefix */
+ /* If namespace URI is for xmlns, ensure qname == "xmlns" */
+ if (namespace != NULL &&
+ dom_string_cmp(namespace, xmlns) == 0 &&
+ (qname_len != SLEN("xmlns") ||
+ strncmp((const char *) qname_data, "xmlns",
+ SLEN("xmlns")) != 0)) {
+ return DOM_NAMESPACE_ERR;
+ }
+ } else {
+ /* Prefix */
+ /* Ensure there is a namespace URI */
+ if (namespace == NULL) {
+ return DOM_NAMESPACE_ERR;
+ }
+
+ /* Test for invalid XML namespace */
+ if (c - qname_data == SLEN("xml") &&
+ strncmp((const char *) qname_data, "xml",
+ SLEN("xml")) == 0 &&
+ dom_string_cmp(namespace, xml) != 0) {
+ return DOM_NAMESPACE_ERR;
+ }
+
+ /* Test for invalid xmlns namespace */
+ if (c - qname_data == SLEN("xmlns") &&
+ strncmp((const char *) qname_data, "xmlns",
+ SLEN("xmlns")) == 0 &&
+ dom_string_cmp(namespace, xmlns) != 0) {
+ return DOM_NAMESPACE_ERR;
+ }
+
+ /* Test for presence of xmlns namespace with non xmlns prefix */
+ if (dom_string_cmp(namespace, xmlns) == 0 &&
+ (c - qname_data != SLEN("xmlns") ||
+ strncmp((const char *) qname_data, "xmlns",
+ SLEN("xmlns")) != 0)) {
+ return DOM_NAMESPACE_ERR;
+ }
+ }
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Split a QName into a namespace prefix and localname string
+ *
+ * \param qname The qname to split
+ * \param doc The document context to create the prefix/localname in
+ * \param prefix Pointer to location to receive prefix
+ * \param localname Pointer to location to receive localname
+ * \return DOM_NO_ERR on success.
+ *
+ * If there is no prefix present in ::qname, then ::prefix will be NULL.
+ *
+ * ::prefix and ::localname will be referenced. The caller should unreference
+ * them once finished.
+ */
+dom_exception _dom_namespace_split_qname(struct dom_string *qname,
+ struct dom_document *doc, struct dom_string **prefix,
+ struct dom_string **localname)
+{
+ const uint8_t *qname_data, *c, *local_data;
+ size_t qname_len;
+ size_t local_len;
+ size_t prefix_len;
+ struct dom_string *p = NULL;
+ struct dom_string *l;
+ dom_exception err;
+
+ dom_string_get_data(qname, &qname_data, &qname_len);
+
+ /* Find colon, if any */
+ /** \todo assumes ASCII-compatible encoding */
+ for (c = qname_data; c != qname_data + qname_len; c++) {
+ if (*c == (const uint8_t) ':')
+ break;
+ }
+
+ if (c == qname_data + qname_len) {
+ /* None found => no prefix */
+ local_data = qname_data;
+ local_len = qname_len;
+ prefix_len = 0;
+ } else {
+ /* Found one => prefix */
+ local_data = ++c;
+ local_len = qname_len - (c - qname_data);
+ prefix_len = (c - qname_data - 1 /* ':' */);
+ }
+
+ /* Create prefix, if one exists */
+ if (prefix_len > 0) {
+ err = dom_string_create_from_ptr(doc, qname_data,
+ prefix_len, &p);
+ if (err != DOM_NO_ERR) {
+ return err;
+ }
+ }
+
+ /* Create localname */
+ err = dom_string_create_from_ptr(doc, local_data, local_len, &l);
+ if (err != DOM_NO_ERR) {
+ if (p != NULL) {
+ dom_string_unref(p);
+ }
+ return err;
+ }
+
+ *prefix = p;
+ *localname = l;
+
+ return DOM_NO_ERR;
+}
+
diff --git a/src/utils/namespace.h b/src/utils/namespace.h
new file mode 100644
index 0000000..0bc5093
--- /dev/null
+++ b/src/utils/namespace.h
@@ -0,0 +1,33 @@
+/*
+ * 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_utils_namespace_h_
+#define dom_utils_namespace_h_
+
+#include <dom/functypes.h>
+#include <dom/core/exceptions.h>
+
+struct dom_document;
+struct dom_string;
+
+/* Initialise the namespace component */
+dom_exception _dom_namespace_initialise(dom_alloc alloc, void *pw);
+
+/* Finalise the namespace component */
+dom_exception _dom_namespace_finalise(void);
+
+/* Ensure a QName is valid */
+dom_exception _dom_namespace_validate_qname(struct dom_string *qname,
+ struct dom_string *namespace);
+
+/* Split a QName into a namespace prefix and localname string */
+dom_exception _dom_namespace_split_qname(struct dom_string *qname,
+ struct dom_document *doc, struct dom_string **prefix,
+ struct dom_string **localname);
+
+#endif
+
diff --git a/src/utils/utils.h b/src/utils/utils.h
index ae861c7..9ec8176 100644
--- a/src/utils/utils.h
+++ b/src/utils/utils.h
@@ -5,8 +5,8 @@
* Copyright 2007 John-Mark Bell <jmb@netsurf-browser.org>
*/
-#ifndef dom_utils_h_
-#define dom_utils_h_
+#ifndef dom_utils_utils_h_
+#define dom_utils_utils_h_
#ifndef max
#define max(a,b) ((a)>(b)?(a):(b))