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

📄 mod_roster.c

📁 这是一个完全开放的
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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 */#include "sm.h"/** @file sm/mod_roster.c  * @brief roster managment & subscriptions  * @author Robert Norris  * $Date: 2004/11/13 16:08:33 $  * $Revision: 1.50.2.7 $  *//** free a single roster item */static void _roster_free_walker(xht roster, const char *key, void *val, void *arg){    item_t item = (item_t) val;    int i;    jid_free(item->jid);        if(item->name != NULL)        free(item->name);    for(i = 0; i < item->ngroups; i++)        free(item->groups[i]);    free(item->groups);    free(item);}/** free the roster */static void _roster_free(user_t user){    if(user->roster == NULL)        return;    log_debug(ZONE, "freeing roster for %s", jid_user(user->jid));    xhash_walk(user->roster, _roster_free_walker, NULL);    xhash_free(user->roster);    user->roster = NULL;}static void _roster_save_item(user_t user, item_t item) {    os_t os;    os_object_t o;    char filter[4096];    int i;    log_debug(ZONE, "saving roster item %s for %s", jid_full(item->jid), jid_user(user->jid));    os = os_new();    o = os_object_new(os);    os_object_put(o, "jid", jid_full(item->jid), os_type_STRING);    if(item->name != NULL)        os_object_put(o, "name", item->name, os_type_STRING);    os_object_put(o, "to", &item->to, os_type_BOOLEAN);    os_object_put(o, "from", &item->from, os_type_BOOLEAN);    os_object_put(o, "ask", &item->ask, os_type_INTEGER);    snprintf(filter, 4096, "(jid=%i:%s)", strlen(jid_full(item->jid)), jid_full(item->jid));    storage_replace(user->sm->st, "roster-items", jid_user(user->jid), filter, os);    os_free(os);    snprintf(filter, 4096, "(jid=%i:%s)", strlen(jid_full(item->jid)), jid_full(item->jid));    if(item->ngroups == 0) {        storage_delete(user->sm->st, "roster-groups", jid_user(user->jid), filter);        return;    }    os = os_new();        for(i = 0; i < item->ngroups; i++) {        o = os_object_new(os);        os_object_put(o, "jid", jid_full(item->jid), os_type_STRING);        os_object_put(o, "group", item->groups[i], os_type_STRING);    }    storage_replace(user->sm->st, "roster-groups", jid_user(user->jid), filter, os);    os_free(os);}/** insert a roster item into this pkt, starting at elem */static void _roster_insert_item(pkt_t pkt, item_t item, int elem){    int ns, i;    char *sub;    ns = nad_add_namespace(pkt->nad, uri_CLIENT, NULL);    elem = nad_insert_elem(pkt->nad, elem, ns, "item", NULL);    nad_set_attr(pkt->nad, elem, -1, "jid", jid_full(item->jid), 0);    if(item->to && item->from)        sub = "both";    else if(item->to)        sub = "to";    else if(item->from)        sub = "from";    else        sub = "none";    nad_set_attr(pkt->nad, elem, -1, "subscription", sub, 0);    if(item->ask == 1)        nad_set_attr(pkt->nad, elem, -1, "ask", "subscribe", 9);    else if(item->ask == 2)        nad_set_attr(pkt->nad, elem, -1, "ask", "unsubscribe", 11);    if(item->name != NULL)        nad_set_attr(pkt->nad, elem, -1, "name", item->name, 0);    for(i = 0; i < item->ngroups; i++)        nad_insert_elem(pkt->nad, elem, NAD_ENS(pkt->nad, elem), "group", item->groups[i]);}/** push this packet to all sessions except the given one */static void _roster_push(user_t user, pkt_t pkt, int mod_index){    sess_t scan;    pkt_t push;    /* do the push */    for(scan = user->sessions; scan != NULL; scan = scan->next)    {        /* don't push to us or to anyone who hasn't loaded the roster */        if((int) scan->module_data[mod_index] == 0)            continue;        push = pkt_dup(pkt, jid_full(scan->jid), NULL);        pkt_sess(push, scan);    }}static mod_ret_t _roster_in_sess_s10n(mod_instance_t mi, sess_t sess, pkt_t pkt){    module_t mod = mi->mod;    item_t item;    pkt_t push;    int ns, elem;    log_debug(ZONE, "got s10n packet");    /* s10ns have to go to someone */    if(pkt->to == NULL)        return -stanza_err_BAD_REQUEST;    /* add a proper from address (no resource) */    if(pkt->from != NULL)        jid_free(pkt->from);    pkt->from = jid_new(mod->mm->sm->pc, jid_user(sess->jid), 0);    nad_set_attr(pkt->nad, 1, -1, "from", jid_full(pkt->from), 0);    /* see if they're already on the roster */    item = xhash_get(sess->user->roster, jid_full(pkt->to));    if(item == NULL)    {        /* if they're not on the roster, there's no subscription,         * so quietly pass it on */        if(pkt->type == pkt_S10N_UN || pkt->type == pkt_S10N_UNED)            return mod_PASS;        /* make a new one */        item = (item_t) malloc(sizeof(struct item_st));        memset(item, 0, sizeof(struct item_st));        item->jid = jid_dup(pkt->to);        /* remember it */        xhash_put(sess->user->roster, jid_full(item->jid), (void *) item);        log_debug(ZONE, "made new empty roster item for %s", jid_full(item->jid));    }    /* a request */    if(pkt->type == pkt_S10N)        item->ask = 1;    else if(pkt->type == pkt_S10N_UN)        item->ask = 2;    /* changing states */    else if(pkt->type == pkt_S10N_ED)    {        /* they're allowed to see us, send them presence */        item->ask = 0;        item->from = 1;        pres_roster(sess, item);    }    else if(pkt->type == pkt_S10N_UNED)    {        /* they're not allowed to see us anymore */        item->ask = 0;        item->from = 0;        pres_roster(sess, item);    }    /* 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);    /* everyone knows */    pkt_free(push);    /* pass it on */    return mod_PASS;}/** build the iq:roster packet from the hash */static void _roster_get_walker(xht roster, const char *id, void *val, void *arg){    item_t item = (item_t) val;    pkt_t pkt = (pkt_t) arg;    _roster_insert_item(pkt, item, 2);}static void _roster_set_item(pkt_t pkt, int elem, sess_t sess, mod_instance_t mi){    module_t mod = mi->mod;    int attr, ns, i;    jid_t jid;    item_t item;    pkt_t push;    char filter[4096];    /* extract the jid */    attr = nad_find_attr(pkt->nad, elem, -1, "jid", NULL);    jid = jid_new(pkt->sm->pc, NAD_AVAL(pkt->nad, attr), NAD_AVAL_L(pkt->nad, attr));    if(jid == NULL) {        log_debug(ZONE, "jid failed prep check, skipping");        return;    }    /* check for removals */    if(nad_find_attr(pkt->nad, elem, -1, "subscription", "remove") >= 0)    {        /* trash the item */        item = xhash_get(sess->user->roster, jid_full(jid));        if(item != NULL)        {            /* tell them they're unsubscribed */            if(item->from) {                log_debug(ZONE, "telling %s that they're unsubscribed", jid_user(item->jid));                pkt_router(pkt_create(sess->user->sm, "presence", "unsubscribed", jid_user(item->jid), jid_user(sess->jid)));            }            item->from = 0;            /* tell them to unsubscribe us */            if(item->to) {                log_debug(ZONE, "unsubscribing from %s", jid_user(item->jid));                pkt_router(pkt_create(sess->user->sm, "presence", "unsubscribe", jid_user(item->jid), jid_user(sess->jid)));            }            item->to = 0;                    /* send unavailable */            pres_roster(sess, item);            /* kill it */            xhash_zap(sess->user->roster, jid_full(jid));            _roster_free_walker(NULL, (const char *) jid_full(jid), (void *) item, NULL);            snprintf(filter, 4096, "(jid=%i:%s)", strlen(jid_full(jid)), jid_full(jid));            storage_delete(sess->user->sm->st, "roster-items", jid_user(sess->jid), filter);            snprintf(filter, 4096, "(jid=%i:%s)", strlen(jid_full(jid)), jid_full(jid));            storage_delete(sess->user->sm->st, "roster-groups", jid_user(sess->jid), filter);        }        log_debug(ZONE, "removed %s from roster", jid_full(jid));        /* 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);        nad_append_elem(push->nad, ns, "query", 3);        elem = nad_append_elem(push->nad, ns, "item", 4);        nad_set_attr(push->nad, elem, -1, "jid", jid_full(jid), 0);        nad_set_attr(push->nad, elem, -1, "subscription", "remove", 6);        /* tell everyone */        _roster_push(sess->user, push, mod->index);        /* we're done */        pkt_free(push);        jid_free(jid);        return;    }    /* find a pre-existing one */    item = xhash_get(sess->user->roster, jid_full(jid));    if(item == NULL)    {        /* make a new one */        item = (item_t) malloc(sizeof(struct item_st));        memset(item, 0, sizeof(struct item_st));        /* add the jid */        item->jid = jid;        /* add it to the roster */        xhash_put(sess->user->roster, jid_full(item->jid), (void *) item);        log_debug(ZONE, "created new roster item %s", jid_full(item->jid));    }    else        jid_free(jid);    /* free the old name */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -