diff -u sm.orig/mod_active.c sm/mod_active.c --- sm.orig/mod_active.c Sat Nov 6 16:58:02 2004 +++ sm/mod_active.c Sat Nov 6 16:55:08 2004 @@ -35,7 +35,7 @@ /* get their active status */ if(storage_get(user->sm->st, "active", jid_user(user->jid), NULL, &os) == st_SUCCESS && os_iter_first(os)) { o = os_iter_object(os); - os_object_get(o, "time", (void **) &user->active, &ot); + os_object_get(os, o, "time", (void **) &user->active, os_type_INTEGER, &ot); os_free(os); } else /* can't load them if they're inactive */ diff -u sm.orig/mod_announce.c sm/mod_announce.c --- sm.orig/mod_announce.c Sat Nov 6 16:58:02 2004 +++ sm/mod_announce.c Sat Nov 6 16:55:08 2004 @@ -59,7 +59,7 @@ if((ret = storage_get(mod->mm->sm->st, "motd-message", mod->mm->sm->id, NULL, &os)) == st_SUCCESS) { os_iter_first(os); o = os_iter_object(os); - if(os_object_get(o, "xml", (void **) &nad, &ot)) { + if(os_object_get(os, o, "xml", (void **) &nad, os_type_NAD, &ot)) { /* Copy the nad, as the original is freed when the os is freed below */ data->nad = nad_copy(nad); if((ns = nad_find_scoped_namespace(data->nad, uri_DELAY, NULL)) >= 0 && @@ -140,7 +140,7 @@ storage_get(sess->user->sm->st, "motd-times", jid_user(sess->jid), NULL, &os) == st_SUCCESS) { os_iter_first(os); o = os_iter_object(os); - os_object_get(o, "time", (void **) &t, &ot); + os_object_get(os, o, "time", (void **) &t, os_type_INTEGER, &ot); sess->user->module_data[mod->index] = (void *) t; os_free(os); } diff -u sm.orig/mod_disco_publish.c sm/mod_disco_publish.c --- sm.orig/mod_disco_publish.c Sat Nov 6 16:58:02 2004 +++ sm/mod_disco_publish.c Sat Nov 6 16:55:08 2004 @@ -273,15 +273,15 @@ do { o = os_iter_object(os); - if(os_object_get(o, "jid", (void **) &str, &ot)) { + if(os_object_get(os, o, "jid", (void **) &str, os_type_STRING, &ot)) { di = (disco_item_t) malloc(sizeof(struct disco_item_st)); memset(di, 0, sizeof(struct disco_item_st)); di->jid = jid_new(mod->mm->sm->pc, str, 0); - if(os_object_get(o, "name", (void **) &str, &ot)) + if(os_object_get(os, o, "name", (void **) &str, os_type_STRING, &ot)) strncpy(di->name, str, 256); - if(os_object_get(o, "node", (void **) &str, &ot)) + if(os_object_get(os, o, "node", (void **) &str, os_type_STRING, &ot)) strncpy(di->node, str, 256); di->next = list; diff -u sm.orig/mod_iq_last.c sm/mod_iq_last.c --- sm.orig/mod_iq_last.c Sat Nov 6 16:58:02 2004 +++ sm/mod_iq_last.c Sat Nov 6 16:55:08 2004 @@ -76,7 +76,7 @@ if(os_iter_first(os)) { o = os_iter_object(os); - os_object_get(o, "time", (void **) &t, &ot); + os_object_get(os, o, "time", (void **) &t, os_type_INTEGER, &ot); } os_free(os); diff -u sm.orig/mod_iq_private.c sm/mod_iq_private.c --- sm.orig/mod_iq_private.c Sat Nov 6 16:58:02 2004 +++ sm/mod_iq_private.c Sat Nov 6 16:55:08 2004 @@ -82,7 +82,7 @@ case st_SUCCESS: if(os_iter_first(os)) { o = os_iter_object(os); - if(os_object_get(o, "xml", (void **) &nad, &ot)) { + if(os_object_get(os, o, "xml", (void **) &nad, os_type_NAD, &ot)) { result = pkt_new(sess->user->sm, nad_copy(nad)); if(result != NULL) { nad_set_attr(result->nad, 1, -1, "type", "result", 6); diff -u sm.orig/mod_iq_vcard.c sm/mod_iq_vcard.c --- sm.orig/mod_iq_vcard.c Sat Nov 6 16:58:02 2004 +++ sm/mod_iq_vcard.c Sat Nov 6 16:55:08 2004 @@ -122,7 +122,7 @@ i += 2; - if(!os_object_get(o, dkey, (void **) &dval, &ot)) + if(!os_object_get(os, o, dkey, (void **) &dval, os_type_STRING, &ot)) continue; vskey = strchr(vkey, '/'); diff -u sm.orig/mod_offline.c sm/mod_offline.c --- sm.orig/mod_offline.c Sat Nov 6 16:58:02 2004 +++ sm/mod_offline.c Sat Nov 6 16:55:08 2004 @@ -51,7 +51,7 @@ do { o = os_iter_object(os); - if(os_object_get(o, "xml", (void **) &nad, &ot)) { + if(os_object_get(os, o, "xml", (void **) &nad, os_type_NAD, &ot)) { queued = pkt_new(pkt->sm, nad_copy(nad)); if(queued == NULL) { log_debug(ZONE, "invalid queued packet, not delivering"); @@ -180,7 +180,7 @@ do { o = os_iter_object(os); - if(os_object_get(o, "xml", (void **) &nad, &ot)) { + if(os_object_get(os, o, "xml", (void **) &nad, os_type_NAD, &ot)) { queued = pkt_new(mi->mod->mm->sm, nad); if(queued == NULL) { log_debug(ZONE, "invalid queued packet, not delivering"); diff -u sm.orig/mod_privacy.c sm/mod_privacy.c --- sm.orig/mod_privacy.c Sat Nov 6 16:58:02 2004 +++ sm/mod_privacy.c Sat Nov 6 16:55:08 2004 @@ -134,7 +134,7 @@ o = os_iter_object(os); /* list name */ - if(!os_object_get(o, "list", (void **) &str, &ot)) { + if(!os_object_get(os, o, "list", (void **) &str, os_type_STRING, &ot)) { log_debug(ZONE, "item with no list field, skipping"); continue; } @@ -161,7 +161,7 @@ zitem = (zebra_item_t) pmalloco(zlist->p, sizeof(struct zebra_item_st)); /* item type */ - if(os_object_get(o, "type", (void **) &str, &ot)) + if(os_object_get(os, o, "type", (void **) &str, os_type_STRING, &ot)) switch(str[0]) { case 'j': zitem->type = zebra_JID; @@ -178,7 +178,7 @@ /* item value, according to type */ if(zitem->type != zebra_NONE) { - if(!os_object_get(o, "value", (void **) &str, &ot)) { + if(!os_object_get(os, o, "value", (void **) &str, os_type_STRING, &ot)) { log_debug(ZONE, "no value on non-fall-through item, dropping this item"); free(zitem); continue; @@ -231,17 +231,17 @@ } /* action */ - os_object_get(o, "deny", (void **) &zitem->deny, &ot); + os_object_get(os, o, "deny", (void **) &zitem->deny, os_type_BOOLEAN, &ot); if(zitem->deny) { log_debug(ZONE, "deny rule"); } else { log_debug(ZONE, "accept rule"); } - os_object_get(o, "order", (void **) &(zitem->order), &ot); + os_object_get(os, o, "order", (void **) &(zitem->order), os_type_INTEGER, &ot); log_debug(ZONE, "order %d", zitem->order); - os_object_get(o, "block", (void **) &(zitem->block), &ot); + os_object_get(os, o, "block", (void **) &(zitem->block), os_type_INTEGER, &ot); log_debug(ZONE, "block 0x%x", zitem->block); /* insert it */ @@ -284,7 +284,7 @@ do { o = os_iter_object(os); - if(os_object_get(o, "default", (void **) &str, &ot)) { + if(os_object_get(os, o, "default", (void **) &str, os_type_STRING, &ot)) { z->def = (zebra_list_t) xhash_get(z->lists, str); if(z->def == NULL) { log_debug(ZONE, "storage says the default list for %s is %s, but it doesn't exist!", jid_user(user->jid), str); diff -u sm.orig/mod_roster.c sm/mod_roster.c --- sm.orig/mod_roster.c Sat Nov 6 16:58:02 2004 +++ sm/mod_roster.c Sat Nov 6 16:55:08 2004 @@ -604,7 +604,7 @@ do { o = os_iter_object(os); - if(os_object_get(o, "jid", (void **) &str, &ot)) { + if(os_object_get(os, o, "jid", (void **) &str, os_type_STRING, &ot)) { /* new one */ item = (item_t) malloc(sizeof(struct item_st)); memset(item, 0, sizeof(struct item_st)); @@ -616,12 +616,12 @@ free(item); } else { - if(os_object_get(o, "name", (void **) &str, &ot)) + if(os_object_get(os, o, "name", (void **) &str, os_type_STRING, &ot)) item->name = strdup(str); - os_object_get(o, "to", (void **) &item->to, &ot); - os_object_get(o, "from", (void **) &item->from, &ot); - os_object_get(o, "ask", (void **) &item->ask, &ot); + os_object_get(os, o, "to", (void **) &item->to, os_type_BOOLEAN, &ot); + os_object_get(os, o, "from", (void **) &item->from, os_type_BOOLEAN, &ot); + os_object_get(os, o, "ask", (void **) &item->ask, os_type_INTEGER, &ot); log_debug(ZONE, "adding %s to roster (to %d from %d ask %d name %s)", jid_full(item->jid), item->to, item->from, item->ask, item->name); @@ -647,10 +647,10 @@ do { o = os_iter_object(os); - if(os_object_get(o, "jid", (void **) &str, &ot)) { + if(os_object_get(os, o, "jid", (void **) &str, os_type_STRING, &ot)) { item = xhash_get(user->roster, str); - if(item != NULL && os_object_get(o, "group", (void **) &str, &ot)) { + if(item != NULL && os_object_get(os, o, "group", (void **) &str, os_type_STRING, &ot)) { item->groups = realloc(item->groups, sizeof(char *) * (item->ngroups + 1)); item->groups[item->ngroups] = strdup(str); item->ngroups++; diff -u sm.orig/mod_vacation.c sm/mod_vacation.c --- sm.orig/mod_vacation.c Sat Nov 6 16:58:02 2004 +++ sm/mod_vacation.c Sat Nov 6 16:55:08 2004 @@ -200,9 +200,9 @@ if(os_iter_first(os)) { o = os_iter_object(os); - if(os_object_get(o, "start", (void **) &v->start, &ot) && - os_object_get(o, "end", (void **) &v->end, &ot) && - os_object_get(o, "message", (void **) &v->msg, &ot)) + if(os_object_get(os, o, "start", (void **) &v->start, os_type_INTEGER, &ot) && + os_object_get(os, o, "end", (void **) &v->end, os_type_INTEGER, &ot) && + os_object_get(os, o, "message", (void **) &v->msg, os_type_STRING, &ot)) v->msg = strdup(v->msg); else { v->start = 0; diff -u sm.orig/object.c sm/object.c --- sm.orig/object.c Sat Nov 6 16:58:02 2004 +++ sm/object.c Sat Nov 6 16:55:08 2004 @@ -150,8 +150,13 @@ xhash_put(o->hash, osf->key, (void *) osf); } -int os_object_get(os_object_t o, const char *key, void **val, os_type_t *type) { +int os_object_get(os_t os, os_object_t o, const char *key, void **val, os_type_t type, os_type_t *ot) { os_field_t osf; + nad_t nad; + + /* Type complexity is to deal with string/NADs. If an object contains xml, it will only be + parsed and returned as a NAD if type == os_type_NAD, otherwise if type == os_type_UNKNOWN + it will be returned as string, unless it's already been converted to a NAD */ osf = (os_field_t) xhash_get(o->hash, key); if(osf == NULL) { @@ -159,24 +164,48 @@ return 0; } - *type = osf->type; + if (ot != NULL) + *ot = osf->type; - switch(osf->type) { + switch(type) { case os_type_BOOLEAN: case os_type_INTEGER: * (int *) val = * (int *) osf->val; break; case os_type_STRING: - case os_type_NAD: *val = osf->val; break; + case os_type_NAD: + /* check to see whether it's already a NAD */ + if (osf->type == os_type_NAD) { + *val = osf->val; + } else { + /* parse the string into a NAD */ + nad = nad_parse(NULL, osf->val + 3, strlen(osf->val) - 3); + if(nad == NULL) { + /* unparseable NAD */ + log_debug(ZONE, "cell returned from storage for key %s has unparseable XML content (%lu bytes)", key, strlen(osf->val)-3); + return 0; + } + + /* replace the string with a NAD */ + osf->val = (void *) nad; + + pool_cleanup(os->p, (pool_cleaner) nad_free, (void *) nad); + + *val = osf->val; + osf->type = os_type_NAD; + + } + break; + default: *val = NULL; } - log_debug(ZONE, "got field %s (val %x type %d) to object", key, *val, *type); + log_debug(ZONE, "got field %s (val %x type %d) to object", key, *val, type); return 1; } diff -u sm.orig/sm.h sm/sm.h --- sm.orig/sm.h Sat Nov 6 16:58:02 2004 +++ sm/sm.h Sat Nov 6 16:55:08 2004 @@ -472,7 +472,8 @@ os_type_BOOLEAN, /**< boolean (0 or 1) */ os_type_INTEGER, /**< integer */ os_type_STRING, /**< string */ - os_type_NAD /**< XML */ + os_type_NAD, /**< XML */ + os_type_UNKNOWN /**< unknown */ } os_type_t; /** a single tuple (value) within an object */ @@ -534,8 +535,8 @@ /** add a field to the object */ void os_object_put(os_object_t o, const char *key, const void *val, os_type_t type); -/** get a field from the object (result in val/type), ret 0 == not found */ -int os_object_get(os_object_t o, const char *key, void **val, os_type_t *type); +/** get a field from the object of type type (result in val), ret 0 == not found */ +int os_object_get(os_t os, os_object_t o, const char *key, void **val, os_type_t type, os_type_t *ot); /** set field iterator to first field (1 = exists, 0 = doesn't exist) */ int os_object_iter_first(os_object_t o); @@ -640,4 +641,4 @@ st_filter_t storage_filter(const char *filter); /** see if the object matches the filter */ -int storage_match(st_filter_t filter, os_object_t o); +int storage_match(st_filter_t filter, os_object_t o, os_t os); diff -u sm.orig/storage.c sm/storage.c --- sm.orig/storage.c Sat Nov 6 16:58:02 2004 +++ sm/storage.c Sat Nov 6 16:55:08 2004 @@ -407,14 +407,14 @@ return f; } -int _storage_match(st_filter_t f, os_object_t o) { +int _storage_match(st_filter_t f, os_object_t o, os_t os) { void *val; os_type_t ot; st_filter_t scan; switch(f->type) { case st_filter_type_PAIR: - if(!os_object_get(o, f->key, &val, &ot)) + if(!os_object_get(os, o, f->key, &val, os_type_UNKNOWN, &ot)) return 0; switch(ot) { @@ -442,18 +442,18 @@ case st_filter_type_AND: for(scan = f->sub; scan != NULL; scan = scan->next) - if(!_storage_match(scan, o)) + if(!_storage_match(scan, o, os)) return 0; return 1; case st_filter_type_OR: for(scan = f->sub; scan != NULL; scan = scan->next) - if(_storage_match(scan, o)) + if(_storage_match(scan, o, os)) return 1; return 0; case st_filter_type_NOT: - if(_storage_match(f->sub, o)) + if(_storage_match(f->sub, o, os)) return 0; return 1; } @@ -461,9 +461,9 @@ return 0; } -int storage_match(st_filter_t filter, os_object_t o) { +int storage_match(st_filter_t filter, os_object_t o, os_t os) { if(filter == NULL) return 1; - return _storage_match(filter, o); + return _storage_match(filter, o, os); } diff -u sm.orig/storage_db.c sm/storage_db.c --- sm.orig/storage_db.c Sat Nov 6 16:58:02 2004 +++ sm/storage_db.c Sat Nov 6 16:57:25 2004 @@ -338,7 +338,7 @@ while(err == 0) { o = _st_db_object_deserialise(drv, *os, val.data, val.size); - if(o != NULL && !storage_match(f, o)) + if(o != NULL && !storage_match(f, o, os)) os_object_free(o); err = c->c_get(c, &key, &val, DB_NEXT_DUP); @@ -396,7 +396,7 @@ while(err == 0) { o = _st_db_object_deserialise(drv, os, val.data, val.size); - if(o != NULL && storage_match(f, o)) + if(o != NULL && storage_match(f, o, os)) err = c->c_del(c, 0); if(err == 0) diff -u sm.orig/storage_fs.c sm/storage_fs.c --- sm.orig/storage_fs.c Sat Nov 6 16:58:02 2004 +++ sm/storage_fs.c Sat Nov 6 16:55:08 2004 @@ -304,7 +304,7 @@ if(os_iter_first(*os)) do { o = os_iter_object(*os); - if(!storage_match(sf, o)) + if(!storage_match(sf, o, os)) os_object_free(o); } while(os_iter_next(*os)); @@ -411,7 +411,7 @@ fclose(f); - if(storage_match(sf, o)) { + if(storage_match(sf, o, os)) { ret = unlink(file); if(ret < 0) { log_write(drv->st->sm->log, LOG_ERR, "fs: couldn't unlink '%s': %s", path, strerror(errno)); diff -u sm.orig/storage_mysql.c sm/storage_mysql.c --- sm.orig/storage_mysql.c Sat Nov 6 16:58:02 2004 +++ sm/storage_mysql.c Sat Nov 6 16:55:08 2004 @@ -406,33 +406,7 @@ break; case os_type_STRING: - if(strlen(val) >= 3 && strncmp(val, "NAD", 3) == 0) { - if(strlen(val) == 3) { - log_write(drv->st->sm->log, LOG_ERR, "mysql: found XML cell with no XML content; table=%s, owner=%s", type, owner); - mysql_free_result(res); - os_free(*os); - return st_FAILED; - } - - nad = nad_parse(drv->st->sm->router->nad_cache, &val[3], strlen(val) - 3); - if(nad == NULL) { - log_write(drv->st->sm->log, LOG_ERR, "mysql: found XML cell with unparseable XML content; table=%s, owner=%s", type, owner); - mysql_free_result(res); - os_free(*os); - return st_FAILED; - } - - os_object_put(o, fields[j].name, nad, os_type_NAD); - - nad_free(nad); - } - - else - os_object_put(o, fields[j].name, val, os_type_STRING); - - break; - - case os_type_NAD: + os_object_put(o, fields[j].name, val, os_type_STRING); break; } } diff -u sm.orig/storage_pgsql.c sm/storage_pgsql.c --- sm.orig/storage_pgsql.c Sat Nov 6 16:58:02 2004 +++ sm/storage_pgsql.c Sat Nov 6 16:55:08 2004 @@ -433,33 +433,7 @@ break; case os_type_STRING: - if(strlen(val) >= 3 && strncmp(val, "NAD", 3) == 0) { - if(strlen(val) == 3) { - log_write(drv->st->sm->log, LOG_ERR, "pgsql: found XML cell with no XML content; table=%s, owner=%s", type, owner); - PQclear(res); - os_free(*os); - return st_FAILED; - } - - nad = nad_parse(drv->st->sm->router->nad_cache, &val[3], strlen(val) - 3); - if(nad == NULL) { - log_write(drv->st->sm->log, LOG_ERR, "pgsql: found XML cell with no XML content; table=%s, owner=%s", type, owner); - PQclear(res); - os_free(*os); - return st_FAILED; - } - - os_object_put(o, fname, nad, os_type_NAD); - - nad_free(nad); - } - - else - os_object_put(o, fname, val, os_type_STRING); - - break; - - case os_type_NAD: + os_object_put(o, fname, val, os_type_STRING); break; } }