removing out-of-date jabber2d patches
authorerickson <erickson@9efc2488-bf62-4759-914b-345cdb29e865>
Mon, 26 Nov 2007 15:13:01 +0000 (15:13 +0000)
committererickson <erickson@9efc2488-bf62-4759-914b-345cdb29e865>
Mon, 26 Nov 2007 15:13:01 +0000 (15:13 +0000)
git-svn-id: svn://svn.open-ils.org/OpenSRF/trunk@1143 9efc2488-bf62-4759-914b-345cdb29e865

src/patch/README [deleted file]
src/patch/mod_offline.c [deleted file]
src/patch/nad.c [deleted file]

diff --git a/src/patch/README b/src/patch/README
deleted file mode 100644 (file)
index 02972b4..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-Note: Copy the source files found in this directory to the location 
-specified in the 'Location' column within the source tree specified
-
-
-Patch                                          Source                          Location                                                                                Purpose
-------------------------------------------------------------------------------------------------------
-
-mod_offline.c                  jabberd-2.0s4           jabberd-2.0s4/sm/mod_offline.c          Disables offline storage 
-------------------------------------------------------------------------------------------------------
-
-nad.c                                          jabberd-2.0s4           jabberd-2.0s4/util/nad.c                                Fixes segfault in a branch of code that we don't use 
-
diff --git a/src/patch/mod_offline.c b/src/patch/mod_offline.c
deleted file mode 100644 (file)
index 4234cd7..0000000
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * jabberd - Jabber Open Source Server
- * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney,
- *                    Ryan Eatmon, Robert Norris
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA
- */
-
-
-/** ! ! !  Patched version to disable offline storage for jabberd-2.0s4 ! ! ! */
-
-#include "sm.h"
-
-/** @file sm/mod_offline.c
-  * @brief offline storage
-  * @author Robert Norris
-  * $Date$
-  * $Revision$
-  */
-
-typedef struct _mod_offline_st {
-    int dropmessages;
-    int dropsubscriptions;
-} *mod_offline_t;
-
-static mod_ret_t _offline_in_sess(mod_instance_t mi, sess_t sess, pkt_t pkt) {
-    st_ret_t ret;
-    os_t os;
-    os_object_t o;
-    os_type_t ot;
-    nad_t nad;
-    pkt_t queued;
-    int ns, elem, attr;
-    char cttl[15], cstamp[18];
-    time_t ttl, stamp;
-
-    /* if they're becoming available for the first time */
-    if(pkt->type == pkt_PRESENCE && pkt->to == NULL && sess->user->top == NULL) {
-
-        ret = storage_get(pkt->sm->st, "queue", jid_user(sess->jid), NULL, &os);
-        if(ret != st_SUCCESS) {
-            log_debug(ZONE, "storage_get returned %d", ret);
-            return mod_PASS;
-        }
-        
-        if(os_iter_first(os))
-            do {
-                o = os_iter_object(os);
-
-                if(os_object_get(o, "xml", (void **) &nad, &ot)) {
-                    queued = pkt_new(pkt->sm, nad_copy(nad));
-                    if(queued == NULL) {
-                        log_debug(ZONE, "invalid queued packet, not delivering");
-                    } else {
-                        /* check expiry as necessary */
-                        if((ns = nad_find_scoped_namespace(queued->nad, uri_EXPIRE, NULL)) >= 0 &&
-                           (elem = nad_find_elem(queued->nad, 1, ns, "x", 1)) >= 0 &&
-                           (attr = nad_find_attr(queued->nad, elem, -1, "seconds", NULL)) >= 0) {
-                            snprintf(cttl, 15, "%.*s", NAD_AVAL_L(queued->nad, attr), NAD_AVAL(queued->nad, attr));
-                            ttl = atoi(cttl);
-
-                            /* it should have a x:delay stamp, because we stamp everything we store */
-                            if((ns = nad_find_scoped_namespace(queued->nad, uri_DELAY, NULL)) >= 0 &&
-                               (elem = nad_find_elem(queued->nad, 1, ns, "x", 1)) >= 0 &&
-                               (attr = nad_find_attr(queued->nad, elem, -1, "stamp", NULL)) >= 0) {
-                                snprintf(cstamp, 18, "%.*s", NAD_AVAL_L(queued->nad, attr), NAD_AVAL(queued->nad, attr));
-                                stamp = datetime_in(cstamp);
-
-                                if(stamp + ttl <= time(NULL)) {
-                                    log_debug(ZONE, "queued packet has expired, dropping");
-                                    pkt_free(queued);
-                                    continue;
-                                }
-                            }
-                        }
-
-                        log_debug(ZONE, "delivering queued packet to %s", jid_full(sess->jid));
-                        pkt_sess(queued, sess);
-                    }
-                }
-            } while(os_iter_next(os));
-
-        os_free(os);
-
-        /* drop the spool */
-        storage_delete(pkt->sm->st, "queue", jid_user(sess->jid), NULL);
-    }
-
-    /* pass it so that other modules and mod_presence can get it */
-    return mod_PASS;
-}
-
-static mod_ret_t _offline_pkt_user(mod_instance_t mi, user_t user, pkt_t pkt) {
-    mod_offline_t offline = (mod_offline_t) mi->mod->private;
-    int ns, elem, attr;
-    os_t os;
-    os_object_t o;
-    pkt_t event;
-
-    /* send messages and s10ns to the top session */
-    if(user->top != NULL && (pkt->type & pkt_MESSAGE || pkt->type & pkt_S10N)) {
-        pkt_sess(pkt, user->top);
-        return mod_HANDLED;
-    }
-
-    /* save messages and s10ns for later */
-    if((pkt->type & pkt_MESSAGE && !offline->dropmessages) ||
-       (pkt->type & pkt_S10N && !offline->dropsubscriptions)) {
-        log_debug(ZONE, "saving message for later");
-
-        pkt_delay(pkt, time(NULL), user->sm->id);
-
-        /* new object */
-        os = os_new();
-        o = os_object_new(os);
-
-        os_object_put(o, "xml", pkt->nad, os_type_NAD);
-
-        /* store it */
-        switch(storage_put(user->sm->st, "queue", jid_user(user->jid), os)) {
-            case st_FAILED:
-                os_free(os);
-                return -stanza_err_INTERNAL_SERVER_ERROR;
-
-            case st_NOTIMPL:
-                os_free(os);
-                return -stanza_err_SERVICE_UNAVAILABLE;     /* xmpp-im 9.5#4 */
-
-            default:
-                os_free(os);
-
-                /* send offline events if they asked for it */
-                if((ns = nad_find_scoped_namespace(pkt->nad, uri_EVENT, NULL)) >= 0 &&
-                   (elem = nad_find_elem(pkt->nad, 1, ns, "x", 1)) >= 0 &&
-                   nad_find_elem(pkt->nad, elem, ns, "offline", 1) >= 0) {
-
-                    event = pkt_create(user->sm, "message", NULL, jid_full(pkt->from), jid_full(pkt->to));
-
-                    attr = nad_find_attr(pkt->nad, 1, -1, "type", NULL);
-                    if(attr >= 0)
-                        nad_set_attr(event->nad, 1, -1, "type", NAD_AVAL(pkt->nad, attr), NAD_AVAL_L(pkt->nad, attr));
-
-                    ns = nad_add_namespace(event->nad, uri_EVENT, NULL);
-                    nad_append_elem(event->nad, ns, "x", 2);
-                    nad_append_elem(event->nad, ns, "offline", 3);
-
-                    nad_append_elem(event->nad, ns, "id", 3);
-                    attr = nad_find_attr(pkt->nad, 1, -1, "id", NULL);
-                    if(attr >= 0)
-                        nad_append_cdata(event->nad, NAD_AVAL(pkt->nad, attr), NAD_AVAL_L(pkt->nad, attr), 4);
-
-                    pkt_router(event);
-                }
-
-                pkt_free(pkt);
-                return mod_HANDLED;
-        }
-    }
-
-    return mod_PASS;
-}
-
-static void _offline_user_delete(mod_instance_t mi, jid_t jid) {
-    os_t os;
-    os_object_t o;
-    os_type_t ot;
-    nad_t nad;
-    pkt_t queued;
-    int ns, elem, attr;
-    char cttl[15], cstamp[18];
-    time_t ttl, stamp;
-
-    log_debug(ZONE, "deleting queue for %s", jid_user(jid));
-
-    /* bounce the queue */
-    if(storage_get(mi->mod->mm->sm->st, "queue", jid_user(jid), NULL, &os) == st_SUCCESS) {
-        if(os_iter_first(os))
-            do {
-                o = os_iter_object(os);
-
-                if(os_object_get(o, "xml", (void **) &nad, &ot)) {
-                    queued = pkt_new(mi->mod->mm->sm, nad);
-                    if(queued == NULL) {
-                        log_debug(ZONE, "invalid queued packet, not delivering");
-                    } else {
-                        /* check expiry as necessary */
-                        if((ns = nad_find_scoped_namespace(queued->nad, uri_EXPIRE, NULL)) >= 0 &&
-                           (elem = nad_find_elem(queued->nad, 1, ns, "x", 1)) >= 0 &&
-                           (attr = nad_find_attr(queued->nad, elem, -1, "seconds", NULL)) >= 0) {
-                            snprintf(cttl, 15, "%.*s", NAD_AVAL_L(queued->nad, attr), NAD_AVAL(queued->nad, attr));
-                            ttl = atoi(cttl);
-
-                            /* it should have a x:delay stamp, because we stamp everything we store */
-                            if((ns = nad_find_scoped_namespace(queued->nad, uri_DELAY, NULL)) >= 0 &&
-                               (elem = nad_find_elem(queued->nad, 1, ns, "x", 1)) >= 0 &&
-                               (attr = nad_find_attr(queued->nad, elem, -1, "stamp", NULL)) >= 0) {
-                                snprintf(cstamp, 18, "%.*s", NAD_AVAL_L(queued->nad, attr), NAD_AVAL(queued->nad, attr));
-                                stamp = datetime_in(cstamp);
-
-                                if(stamp + ttl <= time(NULL)) {
-                                    log_debug(ZONE, "queued packet has expired, dropping");
-                                    pkt_free(queued);
-                                    continue;
-                                }
-                            }
-                        }
-
-                        log_debug(ZONE, "bouncing queued packet from %s", jid_full(queued->from));
-                        pkt_router(pkt_error(queued, stanza_err_ITEM_NOT_FOUND));
-                    }
-                }
-            } while(os_iter_next(os));
-
-        os_free(os);
-    }
-    
-    storage_delete(mi->sm->st, "queue", jid_user(jid), NULL);
-}
-
-static void _offline_free(module_t mod) {
-    mod_offline_t offline = (mod_offline_t) mod->private;
-
-    free(offline);
-}
-
-int offline_init(mod_instance_t mi, char *arg) {
-    module_t mod = mi->mod;
-    char *configval;
-    mod_offline_t offline;
-    int dropmessages = 0;
-    int dropsubscriptions = 0;
-
-    if(mod->init) return 0;
-
-    configval = config_get_one(mod->mm->sm->config, "offline.dropmessages", 0);
-    if (configval != NULL)
-        dropmessages = 1;
-    configval = config_get_one(mod->mm->sm->config, "offline.dropsubscriptions", 0);
-    if (configval != NULL)
-        dropsubscriptions = 1;
-
-    offline = (mod_offline_t) malloc(sizeof(struct _mod_offline_st));
-    offline->dropmessages = dropmessages;
-    offline->dropsubscriptions = dropsubscriptions;
-
-    mod->private = offline;
-
-    mod->in_sess = _offline_in_sess;
-    mod->pkt_user = _offline_pkt_user;
-    mod->user_delete = _offline_user_delete;
-    mod->free = _offline_free;
-
-    return 0;
-}
diff --git a/src/patch/nad.c b/src/patch/nad.c
deleted file mode 100644 (file)
index d9914c4..0000000
+++ /dev/null
@@ -1,1155 +0,0 @@
-/*
- * jabberd - Jabber Open Source Server
- * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney,
- *                    Ryan Eatmon, Robert Norris
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA
- */
-
-
-/** ! ! ! Patched version to fix segfault issue for jabberd-2.0s4 ! ! ! */
-
-/**
- * !!! Things to do (after 2.0)
- *
- * - make nad_find_scoped_namespace() take an element index, and only search
- *   the scope on that element (currently, it searchs all elements from
- *   end to start, which isn't really correct, though it works in most cases
- *
- * - new functions:
- *     * insert one nad (or part thereof) into another nad
- *     * clear a part of a nad (like xmlnode_hide)
- *
- * - audit use of depth array and parent (see j2 bug #792)
- */
-
-#include "util.h"
-
-#ifdef HAVE_EXPAT
-#include "expat/expat.h"
-#endif
-
-/* define NAD_DEBUG to get pointer tracking - great for weird bugs that you can't reproduce */
-#ifdef NAD_DEBUG
-
-static xht _nad_alloc_tracked = NULL;
-static xht _nad_free_tracked = NULL;
-
-static void _nad_ptr_check(const char *func, nad_t nad) {
-    char loc[24];
-    snprintf(loc, sizeof(loc), "%x", (int) nad);
-
-    if(xhash_get(_nad_alloc_tracked, loc) == NULL) {
-        fprintf(stderr, ">>> NAD OP %s: 0x%x not allocated!\n", func, (int) nad);
-        abort();
-    }
-
-    if(xhash_get(_nad_free_tracked, loc) != NULL) {
-        fprintf(stderr, ">>> NAD OP %s: 0x%x previously freed!\n", func, (int) nad);
-        abort();
-    }
-
-    fprintf(stderr, ">>> NAD OP %s: 0x%x\n", func, (int) nad);
-}
-#else
-#define _nad_ptr_check(func,nad)
-#endif
-
-#define BLOCKSIZE 1024
-
-/** internal: do and return the math and ensure it gets realloc'd */
-int _nad_realloc(void **oblocks, int len)
-{
-    void *nblocks;
-    int nlen;
-
-    /* round up to standard block sizes */
-    nlen = (((len-1)/BLOCKSIZE)+1)*BLOCKSIZE;
-
-    /* keep trying till we get it */
-    while((nblocks = realloc(*oblocks, nlen)) == NULL) sleep(1);
-    *oblocks = nblocks;
-    return nlen;
-}
-
-/** this is the safety check used to make sure there's always enough mem */
-#define NAD_SAFE(blocks, size, len) if((size) > len) len = _nad_realloc((void**)&(blocks),(size));
-
-/** internal: append some cdata and return the index to it */
-int _nad_cdata(nad_t nad, const char *cdata, int len)
-{
-    NAD_SAFE(nad->cdata, nad->ccur + len, nad->clen);
-
-    memcpy(nad->cdata + nad->ccur, cdata, len);
-    nad->ccur += len;
-    return nad->ccur - len;
-}
-
-/** internal: create a new attr on any given elem */
-int _nad_attr(nad_t nad, int elem, int ns, const char *name, const char *val, int vallen)
-{
-    int attr;
-
-    /* make sure there's mem for us */
-    NAD_SAFE(nad->attrs, (nad->acur + 1) * sizeof(struct nad_attr_st), nad->alen);
-
-    attr = nad->acur;
-    nad->acur++;
-    nad->attrs[attr].next = nad->elems[elem].attr;
-    nad->elems[elem].attr = attr;
-    nad->attrs[attr].lname = strlen(name);
-    nad->attrs[attr].iname = _nad_cdata(nad,name,nad->attrs[attr].lname);
-    if(vallen > 0)
-        nad->attrs[attr].lval = vallen;
-    else
-        nad->attrs[attr].lval = strlen(val);
-    nad->attrs[attr].ival = _nad_cdata(nad,val,nad->attrs[attr].lval);    
-    nad->attrs[attr].my_ns = ns;
-
-    return attr;
-}
-
-/** create a new cache, simple pointer to a list of nads */
-nad_cache_t nad_cache_new(void)
-{
-    nad_cache_t cache;
-    while((cache = malloc(sizeof(nad_cache_t))) == NULL) sleep(1);
-    *cache = NULL;
-
-#ifdef NAD_DEBUG
-    if(_nad_alloc_tracked == NULL) _nad_alloc_tracked = xhash_new(501);
-    if(_nad_free_tracked == NULL) _nad_free_tracked = xhash_new(501);
-#endif
-    
-    return cache;
-}
-
-
-/** free the cache and any nads in it */
-void nad_cache_free(nad_cache_t cache)
-{
-    nad_t cur;
-    while((cur = *cache) != NULL)
-    {
-        *cache = cur->next;
-        free(cur->elems);
-        free(cur->attrs);
-        free(cur->nss);
-        free(cur->cdata);
-        free(cur->depths);
-        free(cur);
-    }
-    free(cache);
-}
-
-/** get the next nad from the cache, or create some */
-nad_t nad_new(nad_cache_t cache)
-{
-    nad_t nad;
-
-#ifndef NAD_DEBUG
-    /* If cache==NULL, then this NAD is not in a cache */
-
-    if ((cache!=NULL) && (*cache != NULL))
-    {
-        nad = *cache;
-        *cache = nad->next;
-        nad->ccur = nad->ecur = nad->acur = nad->ncur = 0;
-        nad->scope = -1;
-        nad->cache = cache;
-        nad->next = NULL;
-        return nad;
-    }
-#endif
-
-    while((nad = malloc(sizeof(struct nad_st))) == NULL) sleep(1);
-    memset(nad,0,sizeof(struct nad_st));
-
-    nad->scope = -1;
-    nad->cache = cache;
-
-#ifdef NAD_DEBUG
-    {
-    char loc[24];
-    snprintf(loc, sizeof(loc), "%x", (int) nad);
-    xhash_put(_nad_alloc_tracked, pstrdup(xhash_pool(_nad_alloc_tracked), loc), (void *) 1);
-    }
-    _nad_ptr_check(__func__, nad);
-#endif
-
-    return nad;
-}
-
-nad_t nad_copy(nad_t nad)
-{
-    nad_t copy;
-
-    _nad_ptr_check(__func__, nad);
-
-    if(nad == NULL) return NULL;
-
-    /* create a new nad not participating in a cache */
-    copy = nad_new(NULL);
-
-    /* if it's not large enough, make bigger */
-    NAD_SAFE(copy->elems, nad->elen, copy->elen);
-    NAD_SAFE(copy->attrs, nad->alen, copy->alen);
-    NAD_SAFE(copy->nss, nad->nlen, copy->nlen);
-    NAD_SAFE(copy->cdata, nad->clen, copy->clen);
-
-    /* copy all data */
-    memcpy(copy->elems, nad->elems, nad->elen);
-    memcpy(copy->attrs, nad->attrs, nad->alen);
-    memcpy(copy->nss, nad->nss, nad->nlen);
-    memcpy(copy->cdata, nad->cdata, nad->clen);
-
-    /* sync data */
-    copy->ecur = nad->ecur;
-    copy->acur = nad->acur;
-    copy->ncur = nad->ncur;
-    copy->ccur = nad->ccur;
-
-    copy->scope = nad->scope;
-
-    return copy;
-}
-
-/** free nad, or plug nad back in the cache */
-void nad_free(nad_t nad)
-{
-    if(nad == NULL) return;
-
-#ifdef NAD_DEBUG
-    _nad_ptr_check(__func__, nad);
-    {
-    char loc[24];
-    snprintf(loc, sizeof(loc), "%x", (int) nad);
-    xhash_zap(_nad_alloc_tracked, loc);
-    xhash_put(_nad_free_tracked, pstrdup(xhash_pool(_nad_free_tracked), loc), (void *) nad);
-    }
-#else
-    /* If nad->cache != NULL, then put back into cache, otherwise this nad is not in a cache */
-
-    if (nad->cache != NULL) {
-       nad->next = *(nad->cache);
-       *(nad->cache) = nad;
-       return;
-    } 
-#endif
-
-    /* Free nad */
-    free(nad->elems);
-    free(nad->attrs);
-    free(nad->cdata);
-    free(nad->nss);
-    free(nad->depths);
-}
-
-/** locate the next elem at a given depth with an optional matching name */
-int nad_find_elem(nad_t nad, int elem, int ns, const char *name, int depth)
-{
-    int my_ns;
-    int lname = 0;
-
-    _nad_ptr_check(__func__, nad);
-
-    /* make sure there are valid args */
-    if(elem >= nad->ecur || name == NULL) return -1;
-
-    /* set up args for searching */
-    depth = nad->elems[elem].depth + depth;
-    if(name != NULL) lname = strlen(name);
-
-    /* search */
-    for(elem++;elem < nad->ecur;elem++)
-    {
-        /* if we hit one with a depth less than ours, then we don't have the
-         * same parent anymore, bail */
-        if(nad->elems[elem].depth < depth)
-            return -1;
-
-        if(nad->elems[elem].depth == depth && (lname <= 0 || (lname == nad->elems[elem].lname && strncmp(name,nad->cdata + nad->elems[elem].iname, lname) == 0)) &&
-          (ns < 0 || ((my_ns = nad->elems[elem].my_ns) >= 0 && NAD_NURI_L(nad, ns) == NAD_NURI_L(nad, my_ns) && strncmp(NAD_NURI(nad, ns), NAD_NURI(nad, my_ns), NAD_NURI_L(nad, ns)) == 0)))
-            return elem;
-    }
-
-    return -1;
-}
-
-/** get a matching attr on this elem, both name and optional val */
-int nad_find_attr(nad_t nad, int elem, int ns, const char *name, const char *val)
-{
-    int attr, my_ns;
-    int lname, lval = 0;
-
-    _nad_ptr_check(__func__, nad);
-
-    /* make sure there are valid args */
-    if(elem >= nad->ecur || name == NULL) return -1;
-
-    attr = nad->elems[elem].attr;
-    lname = strlen(name);
-    if(val != NULL) lval = strlen(val);
-
-    while(attr >= 0)
-    {
-        /* hefty, match name and if a val, also match that */
-        if(lname == nad->attrs[attr].lname && strncmp(name,nad->cdata + nad->attrs[attr].iname, lname) == 0 && 
-          (lval <= 0 || (lval == nad->attrs[attr].lval && strncmp(val,nad->cdata + nad->attrs[attr].ival, lval) == 0)) &&
-          (ns < 0 || ((my_ns = nad->attrs[attr].my_ns) >= 0 && NAD_NURI_L(nad, ns) == NAD_NURI_L(nad, my_ns) && strncmp(NAD_NURI(nad, ns), NAD_NURI(nad, my_ns), NAD_NURI_L(nad, ns)) == 0)))
-            return attr;
-        attr = nad->attrs[attr].next;
-    }
-    return -1;
-}
-
-/** get a matching ns on this elem, both uri and optional prefix */
-int nad_find_namespace(nad_t nad, int elem, const char *uri, const char *prefix)
-{
-    int check, ns;
-
-    _nad_ptr_check(__func__, nad);
-
-    if(uri == NULL)
-        return -1;
-
-    /* work backwards through our parents, looking for our namespace on each one.
-     * if we find it, link it. if not, the namespace is undeclared - for now, just drop it */
-    check = elem;
-    while(check >= 0)
-    {
-        ns = nad->elems[check].ns;
-        while(ns >= 0)
-        {
-            if(strlen(uri) == NAD_NURI_L(nad, ns) && strncmp(uri, NAD_NURI(nad, ns), NAD_NURI_L(nad, ns)) == 0 && (prefix == NULL || (nad->nss[ns].iprefix >= 0 && strlen(prefix) == NAD_NPREFIX_L(nad, ns) && strncmp(prefix, NAD_NPREFIX(nad, ns), NAD_NPREFIX_L(nad, ns)) == 0)))
-                return ns;
-            ns = nad->nss[ns].next;
-        }
-        check = nad->elems[check].parent;
-    }
-
-    return -1;
-}
-
-/** find a namespace in scope */
-int nad_find_scoped_namespace(nad_t nad, const char *uri, const char *prefix)
-{
-    int ns;
-
-    _nad_ptr_check(__func__, nad);
-
-    if(uri == NULL)
-        return -1;
-
-    for(ns = 0; ns < nad->ncur; ns++)
-    {
-        if(strlen(uri) == NAD_NURI_L(nad, ns) && strncmp(uri, NAD_NURI(nad, ns), NAD_NURI_L(nad, ns)) == 0 &&
-           (prefix == NULL ||
-             (nad->nss[ns].iprefix >= 0 &&
-              strlen(prefix) == NAD_NPREFIX_L(nad, ns) && strncmp(prefix, NAD_NPREFIX(nad, ns), NAD_NPREFIX_L(nad, ns)) == 0)))
-            return ns;
-    }
-
-    return -1;
-}
-
-/** create, update, or zap any matching attr on this elem */
-void nad_set_attr(nad_t nad, int elem, int ns, const char *name, const char *val, int vallen)
-{
-    int attr;
-
-    _nad_ptr_check(__func__, nad);
-
-    /* find one to replace first */
-    if((attr = nad_find_attr(nad, elem, ns, name, NULL)) < 0)
-    {
-        /* only create new if there's a value to store */
-        if(val != NULL)
-            _nad_attr(nad, elem, ns, name, val, vallen);
-        return;
-    }
-
-    /* got matching, update value or zap */
-    if(val == NULL)
-    {
-        nad->attrs[attr].lval = nad->attrs[attr].lname = 0;
-    }else{
-        if(vallen > 0)
-            nad->attrs[attr].lval = vallen;
-        else
-            nad->attrs[attr].lval = strlen(val);
-        nad->attrs[attr].ival = _nad_cdata(nad,val,nad->attrs[attr].lval);
-    }
-
-}
-
-/** shove in a new child elem after the given one */
-int nad_insert_elem(nad_t nad, int parent, int ns, const char *name, const char *cdata)
-{
-    int elem = parent + 1;
-
-    _nad_ptr_check(__func__, nad);
-
-    NAD_SAFE(nad->elems, (nad->ecur + 1) * sizeof(struct nad_elem_st), nad->elen);
-
-    /* relocate all the rest of the elems (unless we're at the end already) */
-    if(nad->ecur != elem)
-        memmove(&nad->elems[elem + 1], &nad->elems[elem], (nad->ecur - elem) * sizeof(struct nad_elem_st));
-    nad->ecur++;
-
-    /* set up req'd parts of new elem */
-    nad->elems[elem].parent = parent;
-    nad->elems[elem].lname = strlen(name);
-    nad->elems[elem].iname = _nad_cdata(nad,name,nad->elems[elem].lname);
-    nad->elems[elem].attr = -1;
-    nad->elems[elem].ns = nad->scope; nad->scope = -1;
-    nad->elems[elem].itail = nad->elems[elem].ltail = 0;
-    nad->elems[elem].my_ns = ns;
-
-    /* add cdata if given */
-    if(cdata != NULL)
-    {
-        nad->elems[elem].lcdata = strlen(cdata);
-        nad->elems[elem].icdata = _nad_cdata(nad,cdata,nad->elems[elem].lcdata);
-    }else{
-        nad->elems[elem].icdata = nad->elems[elem].lcdata = 0;
-    }
-
-    /* parent/child */
-    nad->elems[elem].depth = nad->elems[parent].depth + 1;
-
-    return elem;
-}
-
-/** wrap an element with another element */
-void nad_wrap_elem(nad_t nad, int elem, int ns, const char *name)
-{
-    int cur;
-
-    _nad_ptr_check(__func__, nad);
-
-    if(elem >= nad->ecur) return;
-
-    NAD_SAFE(nad->elems, (nad->ecur + 1) * sizeof(struct nad_elem_st), nad->elen);
-
-    /* relocate all the rest of the elems after us */
-    memmove(&nad->elems[elem + 1], &nad->elems[elem], (nad->ecur - elem) * sizeof(struct nad_elem_st));
-    nad->ecur++;
-
-    /* set up req'd parts of new elem */
-    nad->elems[elem].lname = strlen(name);
-    nad->elems[elem].iname = _nad_cdata(nad,name,nad->elems[elem].lname);
-    nad->elems[elem].attr = -1;
-    nad->elems[elem].ns = nad->scope; nad->scope = -1;
-    nad->elems[elem].itail = nad->elems[elem].ltail = 0;
-    nad->elems[elem].icdata = nad->elems[elem].lcdata = 0;
-    nad->elems[elem].my_ns = ns;
-
-    /* raise the bar on all the children */
-    nad->elems[elem+1].depth++;
-    for(cur = elem + 2; cur < nad->ecur && nad->elems[cur].depth > nad->elems[elem].depth; cur++) nad->elems[cur].depth++;
-
-    /* relink the parents */
-    nad->elems[elem].parent = nad->elems[elem + 1].parent;
-    nad->elems[elem + 1].parent = elem;
-}
-
-/** create a new elem on the list */
-int nad_append_elem(nad_t nad, int ns, const char *name, int depth)
-{
-    int elem;
-
-    _nad_ptr_check(__func__, nad);
-
-    /* make sure there's mem for us */
-    NAD_SAFE(nad->elems, (nad->ecur + 1) * sizeof(struct nad_elem_st), nad->elen);
-
-    elem = nad->ecur;
-    nad->ecur++;
-    nad->elems[elem].lname = strlen(name);
-    nad->elems[elem].iname = _nad_cdata(nad,name,nad->elems[elem].lname);
-    nad->elems[elem].icdata = nad->elems[elem].lcdata = 0;
-    nad->elems[elem].itail = nad->elems[elem].ltail = 0;
-    nad->elems[elem].attr = -1;
-    nad->elems[elem].ns = nad->scope; nad->scope = -1;
-    nad->elems[elem].depth = depth;
-    nad->elems[elem].my_ns = ns;
-
-    /* make sure there's mem in the depth array, then track us */
-    NAD_SAFE(nad->depths, (depth + 1) * sizeof(int), nad->dlen);
-    nad->depths[depth] = elem;
-
-    /* our parent is the previous guy in the depth array */
-    if(depth <= 0)
-        nad->elems[elem].parent = -1;
-    else
-        nad->elems[elem].parent = nad->depths[depth - 1];
-
-    return elem;
-}
-
-/** attach new attr to the last elem */
-int nad_append_attr(nad_t nad, int ns, const char *name, const char *val)
-{
-    _nad_ptr_check(__func__, nad);
-
-    return _nad_attr(nad, nad->ecur - 1, ns, name, val, 0);
-}
-
-/** append new cdata to the last elem */
-void nad_append_cdata(nad_t nad, const char *cdata, int len, int depth)
-{
-    int elem = nad->ecur - 1;
-
-    _nad_ptr_check(__func__, nad);
-
-    /* make sure this cdata is the child of the last elem to append */
-    if(nad->elems[elem].depth == depth - 1)
-    {
-        if(nad->elems[elem].icdata == 0)
-            nad->elems[elem].icdata = nad->ccur;
-        _nad_cdata(nad,cdata,len);
-        nad->elems[elem].lcdata += len;
-        return;
-    }
-
-    /* otherwise, pin the cdata on the tail of the last element at this depth */
-    elem = nad->depths[depth];
-    if(nad->elems[elem].itail == 0)
-        nad->elems[elem].itail = nad->ccur;
-    _nad_cdata(nad,cdata,len);
-    nad->elems[elem].ltail += len;
-}
-
-/** bring a new namespace into scope */
-int nad_add_namespace(nad_t nad, const char *uri, const char *prefix)
-{
-    int ns;
-
-    _nad_ptr_check(__func__, nad);
-
-    /* only add it if its not already in scope */
-    ns = nad_find_scoped_namespace(nad, uri, NULL);
-    if(ns >= 0)
-        return ns;
-
-    /* make sure there's mem for us */
-    NAD_SAFE(nad->nss, (nad->ncur + 1) * sizeof(struct nad_ns_st), nad->nlen);
-
-    ns = nad->ncur;
-    nad->ncur++;
-    nad->nss[ns].next = nad->scope;
-    nad->scope = ns;
-
-    nad->nss[ns].luri = strlen(uri);
-    nad->nss[ns].iuri = _nad_cdata(nad, uri, nad->nss[ns].luri);
-    if(prefix != NULL)
-    {
-        nad->nss[ns].lprefix = strlen(prefix);
-        nad->nss[ns].iprefix = _nad_cdata(nad, prefix, nad->nss[ns].lprefix);    
-    }
-    else
-        nad->nss[ns].iprefix = -1;
-
-    return ns;
-}
-
-/** declare a namespace on an already-existing element */
-int nad_append_namespace(nad_t nad, int elem, const char *uri, const char *prefix) {
-    int ns;
-
-    _nad_ptr_check(__func__, nad);
-
-    /* see if its already scoped on this element */
-    ns = nad_find_namespace(nad, elem, uri, NULL);
-    if(ns >= 0)
-        return ns;
-
-    /* make some room */
-    NAD_SAFE(nad->nss, (nad->ncur + 1) * sizeof(struct nad_ns_st), nad->nlen);
-
-    ns = nad->ncur;
-    nad->ncur++;
-    nad->nss[ns].next = nad->elems[elem].ns;
-    nad->elems[elem].ns = ns;
-
-    nad->nss[ns].luri = strlen(uri);
-    nad->nss[ns].iuri = _nad_cdata(nad, uri, nad->nss[ns].luri);
-    if(prefix != NULL)
-    {
-        nad->nss[ns].lprefix = strlen(prefix);
-        nad->nss[ns].iprefix = _nad_cdata(nad, prefix, nad->nss[ns].lprefix);    
-    }
-    else
-        nad->nss[ns].iprefix = -1;
-
-    return ns;
-}
-
-void _nad_escape(nad_t nad, int data, int len, int flag)
-{
-    char *c;
-    int ic;
-
-    if(len <= 0) return;
-
-    /* first, if told, find and escape ' */
-    while(flag >= 3 && (c = memchr(nad->cdata + data,'\'',len)) != NULL)
-    {
-        /* get offset */
-        ic = c - nad->cdata;
-
-        /* cute, eh?  handle other data before this normally */
-        _nad_escape(nad, data, ic - data, 2);
-
-        /* ensure enough space, and add our escaped &apos; */
-        NAD_SAFE(nad->cdata, nad->ccur + 6, nad->clen);
-        memcpy(nad->cdata + nad->ccur, "&apos;", 6);
-        nad->ccur += 6;
-
-        /* just update and loop for more */
-        len -= (ic+1) - data;
-        data = ic+1;
-    }
-
-    /* next look for < */
-    while(flag >= 2 && (c = memchr(nad->cdata + data,'<',len)) != NULL)
-    {
-        ic = c - nad->cdata;
-        _nad_escape(nad, data, ic - data, 1);
-
-        /* ensure enough space, and add our escaped &lt; */
-        NAD_SAFE(nad->cdata, nad->ccur + 4, nad->clen);
-        memcpy(nad->cdata + nad->ccur, "&lt;", 4);
-        nad->ccur += 4;
-
-        /* just update and loop for more */
-        len -= (ic+1) - data;
-        data = ic+1;
-    }
-
-    /* check for ]]>, we need to escape the > */
-       /* WE DID THIS  (add the '0' as the first test to the while loop 
-               because the loops dies 3 lines in... (and we don't reall
-               need this)) ...
-        */
-    while( 0 && flag >= 1 && (c = memchr(nad->cdata + data, '>', len)) != NULL)
-    {
-        ic = c - nad->cdata;
-
-        _nad_escape(nad, data, ic - data, 0);
-
-        /* check for the sequence */
-
-        if( c >= nad->cdata + 2 && c[-1] == ']' && c[-2] == ']')
-        {
-            /* ensure enough space, and add our escaped &gt; */
-            NAD_SAFE(nad->cdata, nad->ccur + 4, nad->clen);
-            memcpy(nad->cdata + nad->ccur, "&gt;", 4);
-            nad->ccur += 4;
-        }
-
-        /* otherwise, just plug the > in as-is */
-        else
-        {
-            NAD_SAFE(nad->cdata, nad->ccur + 1, nad->clen);
-            *(nad->cdata + nad->ccur) = '>';
-            nad->ccur++;
-        }
-
-        /* just update and loop for more */
-        len -= (ic+1) - data;
-        data = ic+1;
-    }
-
-    /* if & is found, escape it */
-    while((c = memchr(nad->cdata + data,'&',len)) != NULL)
-    {
-        ic = c - nad->cdata;
-
-        /* ensure enough space */
-        NAD_SAFE(nad->cdata, nad->ccur + 5 + (ic - data), nad->clen);
-
-        /* handle normal data */
-        memcpy(nad->cdata + nad->ccur, nad->cdata + data, (ic - data));
-        nad->ccur += (ic - data);
-
-        /* append escaped &lt; */
-        memcpy(nad->cdata + nad->ccur, "&amp;", 5);
-        nad->ccur += 5;
-
-        /* just update and loop for more */
-        len -= (ic+1) - data;
-        data = ic+1;
-    }
-
-    /* nothing exciting, just append normal cdata */
-    NAD_SAFE(nad->cdata, nad->ccur + len, nad->clen);
-    memcpy(nad->cdata + nad->ccur, nad->cdata + data, len);
-    nad->ccur += len;
-}
-
-/** internal recursive printing function */
-int _nad_lp0(nad_t nad, int elem)
-{
-    int attr;
-    int ndepth;
-    int ns;
-
-    /* there's a lot of code in here, but don't let that scare you, it's just duplication in order to be a bit more efficient cpu-wise */
-
-    /* this whole thing is in a big loop for processing siblings */
-    while(elem != nad->ecur)
-    {
-
-    /* make enough space for the opening element */
-    ns = nad->elems[elem].my_ns;
-    if(ns >= 0 && nad->nss[ns].iprefix >= 0)
-    {
-        NAD_SAFE(nad->cdata, nad->ccur + nad->elems[elem].lname + nad->nss[ns].lprefix + 2, nad->clen);
-    } else {
-        NAD_SAFE(nad->cdata, nad->ccur + nad->elems[elem].lname + 1, nad->clen);
-    }
-
-    /* opening tag */
-    *(nad->cdata + nad->ccur++) = '<';
-
-    /* add the prefix if necessary */
-    if(ns >= 0 && nad->nss[ns].iprefix >= 0)
-    {
-        memcpy(nad->cdata + nad->ccur, nad->cdata + nad->nss[ns].iprefix, nad->nss[ns].lprefix);
-        nad->ccur += nad->nss[ns].lprefix;
-        *(nad->cdata + nad->ccur++) = ':';
-    }
-    
-    /* copy in the name */
-    memcpy(nad->cdata + nad->ccur, nad->cdata + nad->elems[elem].iname, nad->elems[elem].lname);
-    nad->ccur += nad->elems[elem].lname;
-
-    /* add the namespaces */
-    for(ns = nad->elems[elem].ns; ns >= 0; ns = nad->nss[ns].next)
-    {
-        /* never explicitly declare the implicit xml namespace */
-        if(nad->nss[ns].luri == strlen(uri_XML) && strncmp(uri_XML, nad->cdata + nad->nss[ns].iuri, nad->nss[ns].luri) == 0)
-            continue;
-
-        /* make space */
-        if(nad->nss[ns].iprefix >= 0)
-        {
-            NAD_SAFE(nad->cdata, nad->ccur + nad->nss[ns].luri + nad->nss[ns].lprefix + 10, nad->clen);
-        } else {
-            NAD_SAFE(nad->cdata, nad->ccur + nad->nss[ns].luri + 9, nad->clen);
-        }
-
-        /* start */
-        memcpy(nad->cdata + nad->ccur, " xmlns", 6);
-        nad->ccur += 6;
-
-        /* prefix if necessary */
-        if(nad->nss[ns].iprefix >= 0)
-        {
-            *(nad->cdata + nad->ccur++) = ':';
-            memcpy(nad->cdata + nad->ccur, nad->cdata + nad->nss[ns].iprefix, nad->nss[ns].lprefix);
-            nad->ccur += nad->nss[ns].lprefix;
-        }
-
-        *(nad->cdata + nad->ccur++) = '=';
-        *(nad->cdata + nad->ccur++) = '\'';
-
-        /* uri */
-        memcpy(nad->cdata + nad->ccur, nad->cdata + nad->nss[ns].iuri, nad->nss[ns].luri);
-        nad->ccur += nad->nss[ns].luri;
-
-        *(nad->cdata + nad->ccur++) = '\'';
-    }
-
-    for(attr = nad->elems[elem].attr; attr >= 0; attr = nad->attrs[attr].next)
-    {
-        if(nad->attrs[attr].lname <= 0) continue;
-
-        /* make enough space for the wrapper part */
-        ns = nad->attrs[attr].my_ns;
-        if(ns >= 0 && nad->nss[ns].iprefix >= 0)
-        {
-            NAD_SAFE(nad->cdata, nad->ccur + nad->attrs[attr].lname + nad->nss[ns].lprefix + 4, nad->clen);
-        } else {
-            NAD_SAFE(nad->cdata, nad->ccur + nad->attrs[attr].lname + 3, nad->clen);
-        }
-
-        *(nad->cdata + nad->ccur++) = ' ';
-
-        /* add the prefix if necessary */
-        if(ns >= 0 && nad->nss[ns].iprefix >= 0)
-        {
-            memcpy(nad->cdata + nad->ccur, nad->cdata + nad->nss[ns].iprefix, nad->nss[ns].lprefix);
-            nad->ccur += nad->nss[ns].lprefix;
-            *(nad->cdata + nad->ccur++) = ':';
-        }
-    
-        /* copy in the name parts */
-        memcpy(nad->cdata + nad->ccur, nad->cdata + nad->attrs[attr].iname, nad->attrs[attr].lname);
-        nad->ccur += nad->attrs[attr].lname;
-        *(nad->cdata + nad->ccur++) = '=';
-        *(nad->cdata + nad->ccur++) = '\'';
-
-        /* copy in the escaped value */
-        _nad_escape(nad, nad->attrs[attr].ival, nad->attrs[attr].lval, 3);
-
-        /* make enough space for the closing quote and add it */
-        NAD_SAFE(nad->cdata, nad->ccur + 1, nad->clen);
-        *(nad->cdata + nad->ccur++) = '\'';
-    }
-
-    /* figure out what's next */
-    if(elem+1 == nad->ecur)
-        ndepth = -1;
-    else
-        ndepth = nad->elems[elem+1].depth;
-
-    /* handle based on if there are children, update nelem after done */
-    if(ndepth <= nad->elems[elem].depth)
-    {
-        /* make sure there's enough for what we could need */
-        NAD_SAFE(nad->cdata, nad->ccur + 2, nad->clen);
-        if(nad->elems[elem].lcdata == 0)
-        {
-            memcpy(nad->cdata + nad->ccur, "/>", 2);
-            nad->ccur += 2;
-        }else{
-            *(nad->cdata + nad->ccur++) = '>';
-
-            /* copy in escaped cdata */
-            _nad_escape(nad, nad->elems[elem].icdata, nad->elems[elem].lcdata,2);
-
-            /* make room */
-            ns = nad->elems[elem].my_ns;
-            if(ns >= 0 && nad->nss[ns].iprefix >= 0)
-            {
-                NAD_SAFE(nad->cdata, nad->ccur + 4 + nad->elems[elem].lname + nad->nss[ns].lprefix, nad->clen);
-            } else {
-                NAD_SAFE(nad->cdata, nad->ccur + 3 + nad->elems[elem].lname, nad->clen);
-            }
-
-            /* close tag */
-            memcpy(nad->cdata + nad->ccur, "</", 2);
-            nad->ccur += 2;
-    
-            /* add the prefix if necessary */
-            if(ns >= 0 && nad->nss[ns].iprefix >= 0)
-            {
-                memcpy(nad->cdata + nad->ccur, nad->cdata + nad->nss[ns].iprefix, nad->nss[ns].lprefix);
-                nad->ccur += nad->nss[ns].lprefix;
-                *(nad->cdata + nad->ccur++) = ':';
-            }
-    
-            memcpy(nad->cdata + nad->ccur, nad->cdata + nad->elems[elem].iname, nad->elems[elem].lname);
-            nad->ccur += nad->elems[elem].lname;
-            *(nad->cdata + nad->ccur++) = '>';
-        }
-
-        /* always try to append the tail */
-        _nad_escape(nad, nad->elems[elem].itail, nad->elems[elem].ltail,2);
-
-        /* if no siblings either, bail */
-        if(ndepth < nad->elems[elem].depth)
-            return elem+1;
-
-        /* next sibling */
-        elem++;
-    }else{
-        int nelem;
-        /* process any children */
-
-        /* close ourself and append any cdata first */
-        NAD_SAFE(nad->cdata, nad->ccur + 1, nad->clen);
-        *(nad->cdata + nad->ccur++) = '>';
-        _nad_escape(nad, nad->elems[elem].icdata, nad->elems[elem].lcdata,2);
-
-        /* process children */
-        nelem = _nad_lp0(nad,elem+1);
-
-        /* close and tail up */
-        ns = nad->elems[elem].my_ns;
-        if(ns >= 0 && nad->nss[ns].iprefix >= 0)
-        {
-            NAD_SAFE(nad->cdata, nad->ccur + 4 + nad->elems[elem].lname + nad->nss[ns].lprefix, nad->clen);
-        } else {
-            NAD_SAFE(nad->cdata, nad->ccur + 3 + nad->elems[elem].lname, nad->clen);
-        }
-        memcpy(nad->cdata + nad->ccur, "</", 2);
-        nad->ccur += 2;
-        if(ns >= 0 && nad->nss[ns].iprefix >= 0)
-        {
-            memcpy(nad->cdata + nad->ccur, nad->cdata + nad->nss[ns].iprefix, nad->nss[ns].lprefix);
-            nad->ccur += nad->nss[ns].lprefix;
-            *(nad->cdata + nad->ccur++) = ':';
-        }
-        memcpy(nad->cdata + nad->ccur, nad->cdata + nad->elems[elem].iname, nad->elems[elem].lname);
-        nad->ccur += nad->elems[elem].lname;
-        *(nad->cdata + nad->ccur++) = '>';
-        _nad_escape(nad, nad->elems[elem].itail, nad->elems[elem].ltail,2);
-
-        /* if the next element is not our sibling, we're done */
-        if(nelem < nad->ecur && nad->elems[nelem].depth < nad->elems[elem].depth)
-            return nelem;
-
-        /* for next sibling in while loop */
-        elem = nelem;
-    }
-
-    /* here's the end of that big while loop */
-    }
-
-    return elem;
-}
-
-void nad_print(nad_t nad, int elem, char **xml, int *len)
-{
-    int ixml = nad->ccur;
-
-    _nad_ptr_check(__func__, nad);
-
-    _nad_lp0(nad,elem);
-    *len = nad->ccur - ixml;
-    *xml = nad->cdata + ixml;
-}
-
-/**
- * nads serialize to a buffer of this form:
- *
- * [buflen][ecur][acur][ncur][ccur][elems][attrs][nss][cdata]
- *
- * nothing is done with endianness or word length, so the nad must be
- * serialized and deserialized on the same platform
- *
- * buflen is not actually used by deserialize(), but is provided as a
- * convenience to the application so it knows how many bytes to read before
- * passing them in to deserialize()
- *
- * the depths array is not stored, so after deserialization
- * nad_append_elem() and nad_append_cdata() will not work. this is rarely
- * a problem
- */
-
-void nad_serialize(nad_t nad, char **buf, int *len) {
-    char *pos;
-
-    _nad_ptr_check(__func__, nad);
-
-    *len = sizeof(int) * 5 + /* 4 ints in nad_t, plus one for len */
-           sizeof(struct nad_elem_st) * nad->ecur +
-           sizeof(struct nad_attr_st) * nad->acur +
-           sizeof(struct nad_ns_st) * nad->ncur +
-           sizeof(char) * nad->ccur;
-
-    *buf = (char *) malloc(*len);
-    pos = *buf;
-
-    * (int *) pos = *len;       pos += sizeof(int);
-    * (int *) pos = nad->ecur;  pos += sizeof(int);
-    * (int *) pos = nad->acur;  pos += sizeof(int);
-    * (int *) pos = nad->ncur;  pos += sizeof(int);
-    * (int *) pos = nad->ccur;  pos += sizeof(int);
-
-    memcpy(pos, nad->elems, sizeof(struct nad_elem_st) * nad->ecur);    pos += sizeof(struct nad_elem_st) * nad->ecur;
-    memcpy(pos, nad->attrs, sizeof(struct nad_attr_st) * nad->acur);    pos += sizeof(struct nad_attr_st) * nad->acur;
-    memcpy(pos, nad->nss, sizeof(struct nad_ns_st) * nad->ncur);        pos += sizeof(struct nad_ns_st) * nad->ncur;
-    memcpy(pos, nad->cdata, sizeof(char) * nad->ccur);
-}
-
-nad_t nad_deserialize(nad_cache_t cache, const char *buf) {
-    nad_t nad = nad_new(cache);
-    const char *pos = buf + sizeof(int);  /* skip len */
-
-    _nad_ptr_check(__func__, nad);
-
-    nad->ecur = * (int *) pos; pos += sizeof(int);
-    nad->acur = * (int *) pos; pos += sizeof(int);
-    nad->ncur = * (int *) pos; pos += sizeof(int);
-    nad->ccur = * (int *) pos; pos += sizeof(int);
-    nad->elen = nad->ecur;
-    nad->alen = nad->acur;
-    nad->nlen = nad->ncur;
-    nad->clen = nad->ccur;
-
-    if(nad->ecur > 0)
-    {
-        nad->elems = (struct nad_elem_st *) malloc(sizeof(struct nad_elem_st) * nad->ecur);
-        memcpy(nad->elems, pos, sizeof(struct nad_elem_st) * nad->ecur);
-        pos += sizeof(struct nad_elem_st) * nad->ecur;
-    }
-
-    if(nad->acur > 0)
-    {
-        nad->attrs = (struct nad_attr_st *) malloc(sizeof(struct nad_attr_st) * nad->acur);
-        memcpy(nad->attrs, pos, sizeof(struct nad_attr_st) * nad->acur);
-        pos += sizeof(struct nad_attr_st) * nad->acur;
-    }
-
-    if(nad->ncur > 0)
-    {
-        nad->nss = (struct nad_ns_st *) malloc(sizeof(struct nad_ns_st) * nad->ncur);
-        memcpy(nad->nss, pos, sizeof(struct nad_ns_st) * nad->ncur);
-        pos += sizeof(struct nad_ns_st) * nad->ncur;
-    }
-
-    if(nad->ccur > 0)
-    {
-        nad->cdata = (char *) malloc(sizeof(char) * nad->ccur);
-        memcpy(nad->cdata, pos, sizeof(char) * nad->ccur);
-    }
-
-    return nad;
-}
-
-#ifdef HAVE_EXPAT
-
-/** parse a buffer into a nad */
-
-struct build_data {
-    nad_t               nad;
-    int                 depth;
-};
-
-static void _nad_parse_element_start(void *arg, const char *name, const char **atts) {
-    struct build_data *bd = (struct build_data *) arg;
-    char buf[1024];
-    char *uri, *elem, *prefix;
-    const char **attr;
-    int ns;
-
-    /* make a copy */
-    strncpy(buf, name, 1024);
-    buf[1023] = '\0';
-
-    /* expat gives us:
-         prefixed namespaced elem: uri|elem|prefix
-          default namespaced elem: uri|elem
-               un-namespaced elem: elem
-     */
-
-    /* extract all the bits */
-    uri = buf;
-    elem = strchr(uri, '|');
-    if(elem != NULL) {
-        *elem = '\0';
-        elem++;
-        prefix = strchr(elem, '|');
-        if(prefix != NULL) {
-            *prefix = '\0';
-            prefix++;
-        }
-        ns = nad_add_namespace(bd->nad, uri, prefix);
-    } else {
-        /* un-namespaced, just take it as-is */
-        uri = NULL;
-        elem = buf;
-        prefix = NULL;
-        ns = -1;
-    }
-
-    /* add it */
-    nad_append_elem(bd->nad, ns, elem, bd->depth);
-
-    /* now the attributes, one at a time */
-    attr = atts;
-    while(attr[0] != NULL) {
-
-        /* make a copy */
-        strncpy(buf, attr[0], 1024);
-        buf[1023] = '\0';
-
-        /* extract all the bits */
-        uri = buf;
-        elem = strchr(uri, '|');
-        if(elem != NULL) {
-            *elem = '\0';
-            elem++;
-            prefix = strchr(elem, '|');
-            if(prefix != NULL) {
-                *prefix = '\0';
-                prefix++;
-            }
-            ns = nad_add_namespace(bd->nad, uri, prefix);
-        } else {
-            /* un-namespaced, just take it as-is */
-            uri = NULL;
-            elem = buf;
-            prefix = NULL;
-            ns = -1;
-        }
-
-        /* add it */
-        nad_append_attr(bd->nad, ns, elem, (char *) attr[1]);
-
-        attr += 2;
-    }
-
-    bd->depth++;
-}
-
-static void _nad_parse_element_end(void *arg, const char *name) {
-    struct build_data *bd = (struct build_data *) arg;
-
-    bd->depth--;
-}
-
-static void _nad_parse_cdata(void *arg, const char *str, int len) {
-    struct build_data *bd = (struct build_data *) arg;
-
-    /* go */
-    nad_append_cdata(bd->nad, (char *) str, len, bd->depth);
-}
-
-static void _nad_parse_namespace_start(void *arg, const char *prefix, const char *uri) {
-    struct build_data *bd = (struct build_data *) arg;
-
-    nad_add_namespace(bd->nad, (char *) uri, (char *) prefix);
-}
-
-nad_t nad_parse(nad_cache_t cache, const char *buf, int len) {
-    struct build_data bd;
-    XML_Parser p;
-
-    if(len == 0)
-        len = strlen(buf);
-
-    p = XML_ParserCreateNS(NULL, '|');
-    if(p == NULL)
-        return NULL;
-
-    bd.nad = nad_new(cache);
-    bd.depth = 0;
-
-    XML_SetUserData(p, (void *) &bd);
-    XML_SetElementHandler(p, _nad_parse_element_start, _nad_parse_element_end);
-    XML_SetCharacterDataHandler(p, _nad_parse_cdata);
-    XML_SetStartNamespaceDeclHandler(p, _nad_parse_namespace_start);
-
-    if(!XML_Parse(p, buf, len, 1)) {
-        XML_ParserFree(p);
-        nad_free(bd.nad);
-        return NULL;
-    }
-
-    XML_ParserFree(p);
-
-    if(bd.depth != 0)
-        return NULL;
-
-    return bd.nad;
-}
-
-#endif