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

@@ -36,28 +36,91 @@ struct _parser_t {
xmpp_stanza_t *stanza;
};
static void _set_attributes(xmpp_stanza_t *stanza, const xmlChar **attrs)
static void _set_attributes(xmpp_stanza_t *stanza, int nattrs,
const xmlChar **attrs)
{
int i;
int i, len;
char *value;
if (!attrs) return;
for (i = 0; attrs[i]; i += 2) {
xmpp_stanza_set_attribute(stanza, (const char *)attrs[i], (const char *)attrs[i+1]);
/* SAX2 uses array of localname/prefix/uri/value_begin/value_end */
for (i = 0; i < nattrs*5; i += 5) {
len = attrs[i+4] - attrs[i+3];
value = xmpp_alloc(stanza->ctx, len + 1);
if (value) {
memcpy(value, attrs[i+3], len);
value[len] = '\0';
xmpp_stanza_set_attribute(stanza, (const char *)attrs[i], value);
xmpp_free(stanza->ctx, value);
}
}
}
/* SAX2 gives us the attrs in an incredibly inconvenient array,
* convert it to what the start callback is expecting */
static char **_convert_attrs(parser_t *parser, int nattrs,
const xmlChar **attrs)
{
int c, i, o, len;
char *value;
char **ret;
if (!attrs) return NULL;
ret = xmpp_alloc(parser->ctx, (nattrs+1)*2*sizeof(char*));
if (!ret) return NULL;
memset(ret, 0, (nattrs+1)*2*sizeof(char*));
for (c = 0; c < nattrs; c++) {
i = c * 5;
o = c * 2;
len = attrs[i+4] - attrs[i+3];
value = xmpp_alloc(parser->ctx, len + 1);
if (value) {
memcpy(value, attrs[i+3], len);
value[len] = '\0';
ret[o] = xmpp_strdup(parser->ctx, (char*)attrs[i]);
ret[o+1] = value;
}
}
return ret;
}
static void _free_cbattrs(parser_t *parser, char **attrs)
{
int i;
if (!attrs)
return;
for (i = 0; attrs[i]; i += 2) {
if (attrs[i]) xmpp_free(parser->ctx, attrs[i]);
if (attrs[i+1]) xmpp_free(parser->ctx, attrs[i+1]);
}
xmpp_free(parser->ctx, attrs);
}
static void _start_element(void *userdata,
const xmlChar *name, const xmlChar **attrs)
const xmlChar *name, const xmlChar *prefix,
const xmlChar *uri, int nnamespaces,
const xmlChar **namespaces, int nattrs,
int ndefaulted, const xmlChar **attrs)
{
parser_t *parser = (parser_t *)userdata;
xmpp_stanza_t *child;
char **cbattrs;
if (parser->depth == 0) {
/* notify the owner */
if (parser->startcb)
parser->startcb((char *)name, (char **)attrs,
cbattrs = _convert_attrs(parser, nattrs, attrs);
parser->startcb((char *)name, cbattrs,
parser->userdata);
_free_cbattrs(parser, cbattrs);
} else {
/* build stanzas at depth 1 */
if (!parser->stanza && parser->depth != 1) {
@@ -71,7 +134,9 @@ static void _start_element(void *userdata,
/* FIXME: can't allocate, disconnect */
}
xmpp_stanza_set_name(parser->stanza, (char *)name);
_set_attributes(parser->stanza, attrs);
_set_attributes(parser->stanza, nattrs, attrs);
if (uri)
xmpp_stanza_set_ns(parser->stanza, (char *)uri);
} else {
/* starting a child of conn->stanza */
child = xmpp_stanza_new(parser->ctx);
@@ -79,7 +144,9 @@ static void _start_element(void *userdata,
/* FIXME: can't allocate, disconnect */
}
xmpp_stanza_set_name(child, (char *)name);
_set_attributes(child, attrs);
_set_attributes(child, nattrs, attrs);
if (uri)
xmpp_stanza_set_ns(child, (char *)uri);
/* add child to parent */
xmpp_stanza_add_child(parser->stanza, child);
@@ -95,7 +162,8 @@ static void _start_element(void *userdata,
parser->depth++;
}
static void _end_element(void *userdata, const xmlChar *name)
static void _end_element(void *userdata, const xmlChar *name,
const xmlChar *prefix, const xmlChar *uri)
{
parser_t *parser = (parser_t *)userdata;
@@ -153,8 +221,9 @@ parser_t *parser_new(xmpp_ctx_t *ctx,
parser->ctx = ctx;
parser->xmlctx = NULL;
memset(&parser->handlers, 0, sizeof(xmlSAXHandler));
parser->handlers.startElement = _start_element;
parser->handlers.endElement = _end_element;
parser->handlers.initialized = XML_SAX2_MAGIC;
parser->handlers.startElementNs = _start_element;
parser->handlers.endElementNs = _end_element;
parser->handlers.characters = _characters;
parser->startcb = startcb;
parser->endcb = endcb;