Add XML namespace support.

This commit is contained in:
Codewalker
2014-12-24 11:46:11 -06:00
parent 0fed8a55e4
commit e2f1c1e94a
4 changed files with 146 additions and 19 deletions

View File

@@ -23,6 +23,9 @@
#include "common.h"
#include "parser.h"
/* ASCII FF is invalid UTF-8 and should never be present in well-formed XML */
#define NAMESPACE_SEP ('\xFF')
struct _parser_t {
xmpp_ctx_t *ctx;
XML_Parser expat;
@@ -34,23 +37,71 @@ struct _parser_t {
xmpp_stanza_t *stanza;
};
/* return allocated string with the name from a delimited
* namespace/name string */
static char *_xml_name(xmpp_ctx_t *ctx, const char *nsname)
{
char *result = NULL;
const char *c;
int len;
c = strchr(nsname, NAMESPACE_SEP);
if (c == NULL) return xmpp_strdup(ctx, nsname);
c++;
len = strlen(c);
result = xmpp_alloc(ctx, len + 1);
if (result != NULL) {
memcpy(result, c, len);
result[len] = '\0';
}
return result;
}
/* return allocated string with the namespace from a delimited string */
static char *_xml_namespace(xmpp_ctx_t *ctx, const char *nsname)
{
char *result = NULL;
const char *c;
c = strchr(nsname, NAMESPACE_SEP);
if (c != NULL) {
result = xmpp_alloc(ctx, (c-nsname) + 1);
if (result != NULL) {
memcpy(result, nsname, (c-nsname));
result[c-nsname] = '\0';
}
}
return result;
}
static void _set_attributes(xmpp_stanza_t *stanza, const XML_Char **attrs)
{
char *attr;
int i;
if (!attrs) return;
for (i = 0; attrs[i]; i += 2) {
xmpp_stanza_set_attribute(stanza, attrs[i], attrs[i+1]);
/* namespaced attributes aren't used in xmpp, discard namespace */
attr = _xml_name(stanza->ctx, attrs[i]);
xmpp_stanza_set_attribute(stanza, attr, attrs[i+1]);
xmpp_free(stanza->ctx, attr);
}
}
static void _start_element(void *userdata,
const XML_Char *name,
const XML_Char *nsname,
const XML_Char **attrs)
{
parser_t *parser = (parser_t *)userdata;
xmpp_stanza_t *child;
char *ns, *name;
ns = _xml_namespace(parser->ctx, nsname);
name = _xml_name(parser->ctx, nsname);
if (parser->depth == 0) {
/* notify the owner */
@@ -71,6 +122,8 @@ static void _start_element(void *userdata,
}
xmpp_stanza_set_name(parser->stanza, name);
_set_attributes(parser->stanza, attrs);
if (ns)
xmpp_stanza_set_ns(parser->stanza, ns);
} else {
/* starting a child of parser->stanza */
child = xmpp_stanza_new(parser->ctx);
@@ -79,6 +132,8 @@ static void _start_element(void *userdata,
}
xmpp_stanza_set_name(child, name);
_set_attributes(child, attrs);
if (ns)
xmpp_stanza_set_ns(child, ns);
/* add child to parent */
xmpp_stanza_add_child(parser->stanza, child);
@@ -91,6 +146,9 @@ static void _start_element(void *userdata,
}
}
if (ns) xmpp_free(parser->ctx, ns);
if (name) xmpp_free(parser->ctx, name);
parser->depth++;
}
@@ -180,7 +238,7 @@ int parser_reset(parser_t *parser)
if (parser->stanza)
xmpp_stanza_release(parser->stanza);
parser->expat = XML_ParserCreate(NULL);
parser->expat = XML_ParserCreateNS(NULL, NAMESPACE_SEP);
if (!parser->expat) return 0;
parser->depth = 0;