📄 mod_roster.c
字号:
if(item->name != NULL) { free(item->name); item->name = NULL; } /* extract the name */ attr = nad_find_attr(pkt->nad, elem, -1, "name", NULL); if(attr >= 0) { item->name = (char *) malloc(sizeof(char) * (NAD_AVAL_L(pkt->nad, attr) + 1)); sprintf(item->name, "%.*s", NAD_AVAL_L(pkt->nad, attr), NAD_AVAL(pkt->nad, attr)); } /* free the old groups */ if(item->groups != NULL) { for(i = 0; i < item->ngroups; i++) free(item->groups[i]); free(item->groups); item->ngroups = 0; item->groups = NULL; } /* loop over the groups, adding them to the array */ elem = nad_find_elem(pkt->nad, elem, NAD_ENS(pkt->nad, elem), "group", 1); while(elem >= 0) { /* empty group tags get skipped */ if(NAD_CDATA_L(pkt->nad, elem) >= 0) { /* make room and shove it in */ item->groups = (char **) realloc(item->groups, sizeof(char *) * (item->ngroups + 1)); item->groups[item->ngroups] = (char *) malloc(sizeof(char) * (NAD_CDATA_L(pkt->nad, elem) + 1)); sprintf(item->groups[item->ngroups], "%.*s", NAD_CDATA_L(pkt->nad, elem), NAD_CDATA(pkt->nad, elem)); item->ngroups++; } elem = nad_find_elem(pkt->nad, elem, NAD_ENS(pkt->nad, elem), "group", 0); } log_debug(ZONE, "added %s to roster (to %d from %d ask %d name %s ngroups %d)", jid_full(item->jid), item->to, item->from, item->ask, item->name, item->ngroups); /* save changes */ _roster_save_item(sess->user, item); /* build a new packet to push out to everyone */ push = pkt_create(sess->user->sm, "iq", "set", NULL, NULL); ns = nad_add_namespace(push->nad, uri_ROSTER, NULL); elem = nad_append_elem(push->nad, ns, "query", 3); _roster_insert_item(push, item, elem); /* tell everyone */ _roster_push(sess->user, push, mod->index); /* we're done */ pkt_free(push);}/** our main handler for packets arriving from a session */static mod_ret_t _roster_in_sess(mod_instance_t mi, sess_t sess, pkt_t pkt){ module_t mod = mi->mod; int elem, attr; pkt_t result; /* handle s10ns in a different function */ if(pkt->type & pkt_S10N) return _roster_in_sess_s10n(mi, sess, pkt); /* we only want to play with iq:roster packets */ if(pkt->ns != ns_ROSTER) return mod_PASS; /* quietly drop results, its probably them responding to a push */ if(pkt->type == pkt_IQ_RESULT) { pkt_free(pkt); return mod_HANDLED; } /* need gets or sets */ if(pkt->type != pkt_IQ && pkt->type != pkt_IQ_SET) return mod_PASS; /* get */ if(pkt->type == pkt_IQ) { /* build the packet */ xhash_walk(sess->user->roster, _roster_get_walker, (void *) pkt); nad_set_attr(pkt->nad, 1, -1, "type", "result", 6); pkt_sess(pkt, sess); /* remember that they loaded it, so we know to push updates to them */ sess->module_data[mod->index] = (void *) 1; return mod_HANDLED; } /* set, find the item */ elem = nad_find_elem(pkt->nad, 2, NAD_ENS(pkt->nad, 2), "item", 1); if(elem < 0) /* no item, abort */ return -stanza_err_BAD_REQUEST; /* loop over items and stick them in */ while(elem >= 0) { /* extract the jid */ attr = nad_find_attr(pkt->nad, elem, -1, "jid", NULL); if(attr < 0) { log_debug(ZONE, "no jid on this item, aborting"); /* no jid, abort */ return -stanza_err_BAD_REQUEST; } /* utility */ _roster_set_item(pkt, elem, sess, mi); /* next one */ elem = nad_find_elem(pkt->nad, elem, NAD_ENS(pkt->nad, elem), "item", 0); } /* send the result */ result = pkt_create(sess->user->sm, "iq", "result", NULL, NULL); pkt_id(pkt, result); /* tell them */ pkt_sess(result, sess); /* free the request */ pkt_free(pkt); return mod_HANDLED;}/** handle incoming s10ns */static mod_ret_t _roster_pkt_user(mod_instance_t mi, user_t user, pkt_t pkt){ module_t mod = mi->mod; item_t item; int ns, elem; /* only want s10ns */ if(!(pkt->type & pkt_S10N)) return mod_PASS; /* drop route errors */ if(pkt->rtype & route_ERROR) { pkt_free(pkt); return mod_HANDLED; } /* get the roster item */ item = (item_t) xhash_get(user->roster, jid_full(pkt->from)); if(item == NULL) { /* they're not on the roster, so subs / unsubs go direct */ if(pkt->type == pkt_S10N || pkt->type == pkt_S10N_UN) return mod_PASS; /* we didn't ask for this, so we don't care */ pkt_free(pkt); return mod_HANDLED; } /* trying to subscribe */ if(pkt->type == pkt_S10N) { if(item->from) { /* already subscribed, tell them */ nad_set_attr(pkt->nad, 1, -1, "type", "subscribed", 10); pkt_router(pkt_tofrom(pkt)); /* update their presence from the leading session */ if(user->top != NULL) pres_roster(user->top, item); return mod_HANDLED; } return mod_PASS; } /* trying to unsubscribe */ if(pkt->type == pkt_S10N_UN) { if(!item->from) { /* already unsubscribed, tell them */ nad_set_attr(pkt->nad, 1, -1, "type", "unsubscribed", 12); pkt_router(pkt_tofrom(pkt)); /* update their presence from the leading session */ if(user->top != NULL) pres_roster(user->top, item); return mod_HANDLED; } return mod_PASS; } /* update our s10n */ if(pkt->type == pkt_S10N_ED) item->to = 1; else item->to = 0; item->ask = 0; /* save changes */ _roster_save_item(user, item); /* if there's no sessions, then we're done */ if(user->sessions == NULL) return mod_PASS; /* We have to free old packet - Lemming's memory leak fix */ pkt_free(pkt); /* build a new packet to push out to everyone */ pkt = pkt_create(user->sm, "iq", "set", NULL, NULL); ns = nad_add_namespace(pkt->nad, uri_ROSTER, NULL); elem = nad_append_elem(pkt->nad, ns, "query", 3); _roster_insert_item(pkt, item, elem); /* tell everyone */ _roster_push(user, pkt, mod->index); /* everyone knows */ pkt_free(pkt); return mod_HANDLED;}/** load the roster from the database */static int _roster_user_load(mod_instance_t mi, user_t user) { os_t os; os_object_t o; os_type_t ot; char *str; item_t item, olditem; log_debug(ZONE, "loading roster for %s", jid_user(user->jid)); user->roster = xhash_new(101); /* pull all the items */ if(storage_get(user->sm->st, "roster-items", jid_user(user->jid), NULL, &os) == st_SUCCESS) { if(os_iter_first(os)) do { o = os_iter_object(os); 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)); item->jid = jid_new(mi->mod->mm->sm->pc, str, 0); if(item->jid == NULL) { log_debug(ZONE, "eek! invalid jid %s, skipping it", str); jid_free(item->jid); free(item); } else { if(os_object_get(os, o, "name", (void **) &str, os_type_STRING, &ot)) item->name = strdup(str); 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); olditem = xhash_get(user->roster, jid_full(item->jid)); if(olditem) { log_debug(ZONE, "removing old %s entry first", jid_full(item->jid)); xhash_zap(user->roster, jid_full(item->jid)); _roster_free_walker(user->roster, jid_full(item->jid), (void *) olditem, NULL); } /* its good */ xhash_put(user->roster, jid_full(item->jid), (void *) item); } } } while(os_iter_next(os)); os_free(os); } /* pull the groups and match them up */ if(storage_get(user->sm->st, "roster-groups", jid_user(user->jid), NULL, &os) == st_SUCCESS) { if(os_iter_first(os)) do { o = os_iter_object(os); 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(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++; log_debug(ZONE, "added group %s to item %s", str, jid_full(item->jid)); } } } while(os_iter_next(os)); os_free(os); } pool_cleanup(user->p, (void (*))(void *) _roster_free, user); return 0;}static void _roster_user_delete(mod_instance_t mi, jid_t jid) { log_debug(ZONE, "deleting roster data for %s", jid_user(jid)); storage_delete(mi->sm->st, "roster-items", jid_user(jid), NULL); storage_delete(mi->sm->st, "roster-groups", jid_user(jid), NULL);}int roster_init(mod_instance_t mi, char *arg) { module_t mod = mi->mod; if(mod->init) return 0; mod->in_sess = _roster_in_sess; mod->pkt_user = _roster_pkt_user; mod->user_load = _roster_user_load; mod->user_delete = _roster_user_delete; feature_register(mod->mm->sm, uri_ROSTER); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -