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

📄 mod_groups.c

📁 AnyQ服务端源代码(2004/10/28)源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* -------------------------------------------------------------------------- * * License * * The contents of this file are subject to the Jabber Open Source License * Version 1.0 (the "License").  You may not copy or use this file, in either * source code or executable form, except in compliance with the License.  You * may obtain a copy of the License at http://www.jabber.com/license/ or at * http://www.opensource.org/.   * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the License * for the specific language governing rights and limitations under the * License. * * Copyrights *  * Portions created by or assigned to Jabber.com, Inc. are  * Copyright (c) 1999-2000 Jabber.com, Inc.  All Rights Reserved.  Contact * information for Jabber.com, Inc. is available at http://www.jabber.com/. * * Portions Copyright (c) 1998-1999 Schuyler Heath. *                    (c) 2001      Philip Anderson. *  * Acknowledgements *  * Special thanks to the Jabber Open Source Contributors for their * suggestions and support of Jabber. *  * --------------------------------------------------------------------------*/#include "jsm.h"#define NS_XGROUPS "jabber:xdb:groups"#define NS_XINFO   "jabber:xdb:groups:info" /* info about the group, name, edit/write perms, etc... */#define GROUP_GET(mi,gid) (gt = (grouptab) xhash_get(mi->groups,gid)) ? gt : mod_groups_tab_add(mi,gid)typedef struct{    pool p;    xdbcache xc;    xht groups;    xht config; /* hash of group specfic config */    char *inst; /* register instructions */} *mod_groups_i, _mod_groups_i;typedef struct{    xht to;    xht from;} *grouptab, _grouptab;xmlnode mod_groups_get_info(mod_groups_i mi, pool p, char *host, char *gid){    xmlnode info, xinfo, cur;    jid id;    if (gid == NULL) return NULL;    log_debug("mod_groups","Getting info %s",gid);    id = jid_new(p,host);    jid_set(id,gid,JID_RESOURCE);    xinfo = xdb_get(mi->xc,id,NS_XINFO);    info = xmlnode_get_tag((xmlnode) xhash_get(mi->config,gid),"info");    if (info != NULL)        info = xmlnode_dup(info);    else        return xinfo;    for (cur = xmlnode_get_firstchild(xinfo); cur != NULL; cur = xmlnode_get_nextsibling(cur))        if (xmlnode_get_tag(info,xmlnode_get_name(cur)) == NULL) /* config overrides */            xmlnode_insert_node(info,cur);    xmlnode_free(xinfo);    return info;}xmlnode mod_groups_get_users(mod_groups_i mi, pool p, char *host, char *gid){    xmlnode group, users;    jid id;    if (gid == NULL) return NULL;    log_debug("mod_groups","getting users %s",gid);    /* check config for specfic group before xdb */    group = (xmlnode) xhash_get(mi->config,gid);    if (group != NULL && (users = xmlnode_get_tag(group,"users")) != NULL)        return xmlnode_dup(users);    log_debug("mod_groups","%d %d",group != NULL,users!= NULL);    id = jid_new(p,host);    jid_set(id,gid,JID_RESOURCE);    return xdb_get(mi->xc,id,NS_XGROUPS);}void mod_groups_top_walk(xht h, const char *gid, void *val, void *arg){    if (strchr(gid,'/') == NULL)    {        xmlnode result = (xmlnode) arg;        xmlnode group, info;        pool p;        p = xmlnode_pool(result);        /* config overrides xdb */        xmlnode_hide(xmlnode_get_tag(result,spools(p,"group?id=",gid,p)));        /* bah, vattrib hack */        info = mod_groups_get_info((mod_groups_i) xmlnode_get_vattrib(result,"mi"),p,xmlnode_get_attrib(result,"host"),(char *) gid);        group = xmlnode_insert_tag(result,"group");        xmlnode_put_attrib(group,"name",xmlnode_get_tag_data(info,"name"));        xmlnode_put_attrib(group,"id",gid);        xmlnode_free(info);    }}/* returns toplevel groups */xmlnode mod_groups_get_top(mod_groups_i  mi, pool p, char *host){    xmlnode result;    result = xdb_get(mi->xc,jid_new(p,host),NS_XGROUPS);    if (result == NULL)        result = xmlnode_new_tag("query");    xmlnode_put_vattrib(result,"mi",(void *) mi);    xmlnode_put_attrib(result,"host",host);    /* insert toplevel groups from config */    xhash_walk(mi->config,mod_groups_top_walk,(void *) result);    xmlnode_hide_attrib(result,"mi");    xmlnode_hide_attrib(result,"host");    return result;}/* inserts required groups into result */void mod_groups_current_walk(xht h, const char *gid, void *val, void *arg){    xmlnode info;    info = xmlnode_get_tag((xmlnode) val,"info");    if (xmlnode_get_tag(info,"require") != NULL)    {        xmlnode result = (xmlnode) arg;        xmlnode group;        pool p;        log_debug("mod_groups","required group %s",gid);        p = xmlnode_pool(result);        group = xmlnode_get_tag(result,spools(p,"?id=",gid,p));        if (group == NULL)        {            group = xmlnode_insert_tag(result,"group");            xmlnode_put_attrib(group,"id",gid);            /* remember the jid attrib is "?jid=<jid>" */            if (xmlnode_get_tag(xmlnode_get_tag(info,"users"),xmlnode_get_attrib(result,"jid")) != NULL)                xmlnode_put_attrib(group,"type","both");        }        else            xmlnode_put_attrib(group,"type","both");      }}/* get the list of groups a user is currently a member of */xmlnode mod_groups_get_current(mod_groups_i mi, jid id){    xmlnode result;    pool p;    id = jid_user(id);    result = xdb_get(mi->xc,id,NS_XGROUPS);    if (result == NULL)        result = xmlnode_new_tag("query");    p = xmlnode_pool(result);    xmlnode_put_attrib(result,"jid",spools(p,"?jid=",jid_full(id),p));    xhash_walk(mi->config,mod_groups_current_walk,(void *) result);    xmlnode_hide_attrib(result,"jid");    return result;}grouptab mod_groups_tab_add(mod_groups_i mi, char *gid){    grouptab gt;    log_debug("mod_groups","new group entry %s",gid);    gt = pmalloco(mi->p,sizeof(_grouptab));    gt->to = xhash_new(509);    gt->from = xhash_new(509);    xhash_put(mi->groups,pstrdup(mi->p,gid),gt);    return gt;}void mod_groups_presence_to_walk(xht h, const char *key, void *val, void *arg){    session from;    from = js_session_primary((udata) val);    if (from != NULL)        js_session_to((session) arg,jpacket_new(xmlnode_dup(from->presence)));}/* send presence to a session from the group members */void mod_groups_presence_to(session s, grouptab gt){    xhash_put(gt->to,jid_full(s->u->id),(void *) s->u); /* we don't care if it replaces the old entry */    xhash_walk(gt->from,mod_groups_presence_to_walk,(void *) s);}void mod_groups_presence_from_walk(xht h, const char *key, void *val, void *arg){    xmlnode x = (xmlnode) arg;    udata u = (udata) val;    session s;    s = xmlnode_get_vattrib(x,"s");    if (s->u != u)    {        xmlnode pres;        log_debug("mod_groups","delivering presence to %s",jid_full(u->id));        pres = xmlnode_dup(x);        xmlnode_put_attrib(pres,"to",jid_full(u->id));        xmlnode_hide_attrib(pres,"s");        js_session_from(s,jpacket_new(pres));    }}/* send presence from a session to online members of a group */void mod_groups_presence_from(session s, grouptab gt, xmlnode pres){    udata u = s->u;    log_debug("mod_groups","brodcasting");    if (xhash_get(gt->from,jid_full(u->id)) == NULL)        xhash_put(gt->from,jid_full(u->id),u);    /* send our presence to online users subscribed to this group */    xmlnode_hide_attrib(pres,"to");    xmlnode_put_vattrib(pres,"s",s);    xhash_walk(gt->to,mod_groups_presence_from_walk,(void *) pres);    xmlnode_hide_attrib(pres,"s");}void mod_groups_roster_insert(udata u, xmlnode roster, xmlnode group, char *gn, int add){    xmlnode item, cur, q;    char *id, *user;    user = jid_full(u->id);    q = xmlnode_get_tag(roster,"query");    /* loop through each item in the group */    for (cur = xmlnode_get_firstchild(group); cur != NULL; cur = xmlnode_get_nextsibling(cur))    {        id = xmlnode_get_attrib(cur,"jid");        if (id == NULL || strcmp(id,user) == 0)  /* don't push ourselves */            continue;        /* add them to the roster */        item = xmlnode_insert_tag(q,"item");        xmlnode_put_attrib(item,"jid",id);        xmlnode_put_attrib(item,"subscription",add ? "to":"remove");        xmlnode_put_attrib(item,"name",xmlnode_get_attrib(cur,"name"));        xmlnode_insert_cdata(xmlnode_insert_tag(item,"group"),gn,-1);    }    xmlnode_free(group);}/* push updated roster to all sessions or a specfic session */void mod_groups_roster_push(session s, xmlnode roster, int all){    session cur;    if (all)    {        /* send a copy to all session that have a roster */        for(cur = s->u->sessions; cur != NULL; cur = cur->next)            if(cur->roster)                js_session_to(cur,jpacket_new(cur->next ? xmlnode_dup(roster):roster));    }    else        js_session_to(s,jpacket_new(roster));}void mod_groups_update_walk(xht h, const char *key, void *val, void *arg){    xmlnode packet = (xmlnode) arg;    udata u = (udata) val;    mod_groups_roster_push(js_session_primary(u),xmlnode_dup(packet),1);}/* updates every members roster with the new user */void mod_groups_update_rosters(grouptab gt, jid uid, char *un, char *gn, int add){    xmlnode packet, item, q;    packet = xmlnode_new_tag("iq");    xmlnode_put_attrib(packet, "type", "set");    q = xmlnode_insert_tag(packet, "query");    xmlnode_put_attrib(q,"xmlns",NS_ROSTER);    item = xmlnode_insert_tag(q,"item");    xmlnode_put_attrib(item,"jid",jid_full(uid));    xmlnode_put_attrib(item,"name",un);    xmlnode_put_attrib(item,"subscription",add ? "to" : "remove");    xmlnode_insert_cdata(xmlnode_insert_tag(item,"group"),gn,-1);    xhash_walk(gt->to,mod_groups_update_walk,(void *) packet);    xmlnode_free(packet);}/* adds a user to the master group list and to their personal list */int mod_groups_xdb_add(mod_groups_i mi, pool p, jid uid, char *un, char *gid, char *gn, int both){    xmlnode groups, user, group;    jid xid;    xid = jid_new(p,uid->server);    jid_set(xid,gid,JID_RESOURCE);    user = xmlnode_new_tag("user");    xmlnode_put_attrib(user,"jid",jid_full(uid));    xmlnode_put_attrib(user,"name",un);    if(both && xdb_act(mi->xc,xid,NS_XGROUPS,"insert",spools(p,"?jid=",jid_full(uid),p),user))    {        log_debug(ZONE,"Failed to insert user");        xmlnode_free(user);        return 1;    }    xmlnode_free(user);    /* get the groups this user is currently part of */    groups = mod_groups_get_current(mi,uid);    if (groups == NULL)    {        groups = xmlnode_new_tag("query");        xmlnode_put_attrib(groups,"xmlns",NS_XGROUPS);    }    /* check if the user already as the group listed */    group = xmlnode_get_tag(groups,spools(p,"?id=",gid,p));    if (group == NULL)    {        group = xmlnode_insert_tag(groups,"group");        xmlnode_put_attrib(group,"id",gid);    }    else if (j_strcmp(xmlnode_get_attrib(group,"type"),"both") == 0 && both)    {        /* the group is already there */        xmlnode_free(groups);        return 0;    }    else if (both == 0)    {        xmlnode_free(groups);        return 0;    }    /* save the new group in the users list groups */    if (both)        xmlnode_put_attrib(group,"type","both");    xdb_set(mi->xc,uid,NS_XGROUPS,groups);    xmlnode_free(groups);    return 0;}/* removes a user from the master group list and from their personal list */int mod_groups_xdb_remove(mod_groups_i mi, pool p, jid uid, char *host, char *gid){    xmlnode groups, group, info;    jid xid;    xid = jid_new(p,uid->server);    jid_set(xid,gid,JID_RESOURCE);    if(xdb_act(mi->xc,xid,NS_XGROUPS,"insert",spools(p,"?jid=",jid_full(uid),p),NULL))    {        log_debug(ZONE,"Failed to remove user");        return 1;    }    info = mod_groups_get_info(mi, p, host, gid);    if (xmlnode_get_tag(info,"require") != NULL)        return 0;    /* get the groups this user is currently part of */    groups = mod_groups_get_current(mi,uid);    if (groups == NULL)    {        groups = xmlnode_new_tag("query");        xmlnode_put_attrib(groups,"xmlns",NS_XGROUPS);    }    /* check if the user already as the group listed */    group = xmlnode_get_tag(groups,spools(p,"?id=",gid,p));    if (group == NULL)    {        /* the group isn't there */        xmlnode_free(groups);        return 0;    }    /* Delete Node */    xmlnode_hide(group);    xdb_set(mi->xc,uid,NS_XGROUPS,groups);    xmlnode_free(groups);    return 0;}void mod_groups_register_set(mod_groups_i mi, mapi m){    jpacket jp = m->packet;    pool p = jp->p;    grouptab gt;    xmlnode info, roster, users;    jid uid;    char *gid, *host, *key, *un, *gn;    int add, both;    /* make sure it's a valid register query */    key = xmlnode_get_tag_data(jp->iq,"key");    gid = strchr(pstrdup(p,jp->to->resource),'/') + 1;    if (gid == NULL || key == NULL || jutil_regkey(key,jid_full(jp->from)) == NULL)    {        js_bounce(m->si,jp->x,TERROR_NOTACCEPTABLE);        return;    }    host = jp->from->server;    info = mod_groups_get_info(mi,p,host,gid);    if (info == NULL)    {        js_bounce(m->si,jp->x,TERROR_NOTFOUND);        return;    }    uid = jid_user(jp->from);    un = xmlnode_get_tag_data(jp->iq,"name");    gn = xmlnode_get_tag_data(info,"name");    add = (xmlnode_get_tag(jp->iq, "remove") == NULL);    both = (xmlnode_get_tag(info,"static") == NULL);    if (add)    {        log_debug("mod_groups","register GID %s",gid);        if (mod_groups_xdb_add(mi,p,uid,un ? un : jid_full(uid),gid,gn,both))        {            js_bounce(m->si,jp->x,TERROR_UNAVAIL);            xmlnode_free(info);            return;        }    }    else    {        log_debug("mod_groups","unregister GID %s",gid);        if (mod_groups_xdb_remove(mi,p,uid,host,gid))        {            js_bounce(m->si,jp->x,TERROR_UNAVAIL);            xmlnode_free(info);            return;        }    }    gt = GROUP_GET(mi,gid);    /* push the group to the user */    if (add || xmlnode_get_tag(info,"require") == NULL)    {        users = mod_groups_get_users(mi,p,host,gid);        if (users != NULL)        {            roster = jutil_iqnew(JPACKET__SET,NS_ROSTER);            mod_groups_roster_insert(m->user,roster,users,gn,add);            mod_groups_roster_push(m->s,roster,add);        }    }    /* push/remove the new user to the other members */    if (both)        mod_groups_update_rosters(gt,uid,un,gn,add);    /* send presnce to everyone */    if (add && both)    {        mod_groups_presence_from(m->s,gt,m->s->presence);

⌨️ 快捷键说明

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