diff options
Diffstat (limited to 'src/utils')
-rw-r--r-- | src/utils/Makefile | 53 | ||||
-rw-r--r-- | src/utils/namespace.c | 218 | ||||
-rw-r--r-- | src/utils/namespace.h | 33 | ||||
-rw-r--r-- | src/utils/utils.h | 4 |
4 files changed, 306 insertions, 2 deletions
diff --git a/src/utils/Makefile b/src/utils/Makefile new file mode 100644 index 00000000..29369ae5 --- /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 00000000..25b56ee8 --- /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 00000000..0bc50931 --- /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 ae861c71..9ec81765 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)) |