⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mod_roster.c

📁 这是一个完全开放的
💻 C
📖 第 1 页 / 共 2 页
字号:
    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 + -