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

📄 mod_groups.c

📁 jabber server jabber server jabber server jabber server
💻 C
📖 第 1 页 / 共 3 页
字号:
    /* update the jpacket with the data in jp->x */    jpacket_reset(jp);    /* if we return the result of a specific group (not the list), let the user register the group */    if (gid) {        xmlnode_insert_cdata(xmlnode_insert_tag(jp->iq,"ns"),NS_REGISTER,-1);        xmlnode_free(info);    }    /* send the result to the user */    js_session_to(m->s,jp);}/** * handle roster requests by users * * Send the user all group members of users, that are in the same groups. * * @param mi the mod_groups_i structure containing the module internal data * @param m the mapi_struct containing the request for the roster */void mod_groups_roster(mod_groups_i mi, mapi m) {    xmlnode groups, users, cur, roster;    pool p;    udata u = m->user;    char *gid, *host = m->user->id->server;    /* get group the user is a member of */    if ((groups = mod_groups_get_current(mi,u->id)) == NULL)        return;    p = xmlnode_pool(groups);    roster = jutil_iqnew(JPACKET__SET,NS_ROSTER);    /* push each group */    for (cur = xmlnode_get_firstchild(groups); cur != NULL; cur = xmlnode_get_nextsibling(cur)) {        if (xmlnode_get_type(cur) != NTYPE_TAG) continue;        gid = xmlnode_get_attrib(cur,"id");        users = mod_groups_get_users(mi,p,host,gid);        if (users != NULL) {            xmlnode info;            char *gn;            info = mod_groups_get_info(mi,p,host,gid);            gn = xmlnode_get_tag_data(info,"name");            mod_groups_roster_insert(u,roster,users,gn ? gn : gid,1);            xmlnode_free(info);        } else {            log_debug2(ZONE, LOGT_DELIVER, "Failed to get users for group");	}    }    mod_groups_roster_push(m->s,roster,0);    xmlnode_free(groups);}/** * handle iq stanzas sent to the server address * * Handled iq types are jabber:iq:roster requests, that are passed to mod_groups_roster(), * jabber:iq:browse to browse for groups, and jabber:iq:register to join groups. * * Browsing is delegated to mod_groups_browse_get() for get requests, * and mod_groups_browse_set() for set requests. * * Registeration is delegated to mod_groups_register_get() for get requests, * and mod_groups_register_set() for set requests. * * Requests in other namespaces to a resource that starts with "groups/" or is just * "groups" are rejected with an error. * * @param mi the mod_groups_i structure containing module internal data * @param m the mapi_struct containing the iq query * @return M_HANDLED if the packet has been finally handled, M_PASS if other modules should handle the packet */mreturn mod_groups_iq(mod_groups_i mi, mapi m) {    char *ns, *res;    int type;    ns = xmlnode_get_attrib(m->packet->iq,"xmlns");    /* handle roster gets */    type = jpacket_subtype(m->packet);    if (j_strcmp(ns,NS_ROSTER) == 0) {        if (jpacket_subtype(m->packet) == JPACKET__GET) {            log_debug2(ZONE, LOGT_DELIVER, "Roster request");            mod_groups_roster(mi,m);        }        return M_PASS;    }    /* handle iq's to groups */    res = m->packet->to ? m->packet->to->resource : NULL;    if (res && strncmp(res,"groups",6) == 0 && (strlen(res) == 6 || res[6] == '/')) {        if (j_strcmp(ns,NS_BROWSE) == 0) {            log_debug2(ZONE, LOGT_DELIVER, "Browse request");            if (type == JPACKET__GET)                mod_groups_browse_get(mi,m);            else if (type == JPACKET__SET)                mod_groups_browse_set(mi,m);            else                xmlnode_free(m->packet->x);        } else if (j_strcmp(ns,NS_REGISTER) == 0) {            log_debug2(ZONE, LOGT_DELIVER, "Register request");            if (type == JPACKET__GET)                mod_groups_register_get(mi,m);            else if (type == JPACKET__SET)                mod_groups_register_set(mi,m);            else                xmlnode_free(m->packet->x);        } else {            js_bounce_xmpp(m->si,m->packet->x,XTERROR_NOTALLOWED);	}        return M_HANDLED;    }    return M_PASS;}/** * handle undirected presence stanzas sent by a user * * Check if the user is member of any groups, if yes get the group configuration. * Send presences to all members with "subscription" both and probe all members * of the group for their presence. * * @param mi the mod_groups_i module instance data * @param m the mapi_struct containing the presence stanza */void mod_groups_presence(mod_groups_i mi, mapi m) {    grouptab gt;    session s = m->s;    udata u = m->user;    xmlnode groups, cur;    /* is the user member of any group? If not just ignore the presence */    if ((groups = mod_groups_get_current(mi,u->id)) == NULL)        return;    log_debug2(ZONE, LOGT_DELIVER, "Getting groups for %s",jid_full(u->id));    /* get each group */    for (cur = xmlnode_get_firstchild(groups); cur != NULL; cur = xmlnode_get_nextsibling(cur)) {        char *gid;        if ((gid = xmlnode_get_attrib(cur,"id")) == NULL) continue;	/* get the grouptab for this group or create a new one if it does not yet exist */        gt = GROUP_GET(mi,gid);        if(j_strcmp(xmlnode_get_attrib(cur,"type"),"both") == 0)            mod_groups_presence_from(s,gt,m->packet->x);        /* if we are new or our old priority was less then -128 then "probe" the group members */        if (js_session_primary(m->user) || m->s->priority < -128)            mod_groups_presence_to(s,gt);    }    xmlnode_free(groups);}/** * handle packets a user is sending * * If the user is sending an undirected presence stanza it is passed to mod_groups_presence() for processing * and always M_PASS is returned. * * If the user is sending an iq stanza, it is passed to mod_groups_iq() for processing and the * return value of this function is returned. * * Other stanzas than presence and iq are ignored and M_IGNORE is returned. * * @param m the mapi_struct containing the stanza * @param arg the mod_groups_i module instance data * @return M_IGNORE for other stanzas than presence and iq, M_PASS if other modules should process the packet, M_HANDLED if it is fully processed */mreturn mod_groups_out(mapi m, void *arg) {    mod_groups_i mi = (mod_groups_i) arg;    if (m->packet->type == JPACKET_PRESENCE) {        if (m->packet->to == NULL) mod_groups_presence(mi,m);        return M_PASS;    } else if (m->packet->type == JPACKET_IQ) {        return mod_groups_iq(mi,m);    }    return M_IGNORE;}/** * callback to be notified about ended sessions (users that are going offline) * * @param m the mapi_struct containing the offline event * @param arg mod_groups_i module instance data * @return always M_PASS */mreturn mod_groups_end(mapi m, void *arg) {    mod_groups_i mi = (mod_groups_i) arg;    xmlnode groups, cur;    udata u = m->user;    jid id = u->id;    grouptab gt;    if (js_session_primary(u) != NULL || (groups = mod_groups_get_current(mi,id)) == NULL)        return M_PASS;    log_debug2(ZONE, LOGT_DELIVER, "removing user from table");    for (cur = xmlnode_get_firstchild(groups); cur != NULL; cur = xmlnode_get_nextsibling(cur)) {        gt = (grouptab) xhash_get(mi->groups,xmlnode_get_attrib(cur,"id"));        if (gt == NULL) continue;        if(j_strcmp(xmlnode_get_attrib(cur,"type"),"both") == 0)            xhash_zap(gt->from,jid_full(id));        xhash_zap(gt->to,jid_full(id));    }    xmlnode_free(groups);    return M_PASS;}/** * register session related callbacks if a new session is established * * @param m mapi_struct containing the session establishment request * @param arg pointer to the mod_groups_i structure containing module internal data * @return always M_PASS */mreturn mod_groups_session(mapi m, void *arg) {    js_mapi_session(es_OUT,m->s,mod_groups_out,arg);    js_mapi_session(es_END,m->s,mod_groups_end,arg);    return M_PASS;}/** * xhash_walker() to walk the list of members of a group and send a message to them * * @param h the xht containing the members * @param key unused/ignored * @param val the udata_struct for a single recipient * @param arg xmlnode containing the message */void mod_groups_message_walk(xht h, const char *key, void *val, void *arg) {    xmlnode m = (xmlnode) arg;    udata u = (udata) val;    m = xmlnode_dup(m);    xmlnode_put_attrib(m,"to",jid_full(u->id));    js_deliver(u->si,jpacket_new(m));}/** * broadcast a message to all (online) members of a group * * @param mi the mod_groups_i module instance data * @param msg the message to broadcast * @param gid to which group the message should be broadcasted */void mod_groups_message_online(mod_groups_i mi, xmlnode msg, char *gid) {    grouptab gt;    log_debug2(ZONE, LOGT_DELIVER, "broadcast message to '%s'",gid);    gt = (grouptab) xhash_get(mi->groups,gid);    if (gt != NULL) {	/* the group address becomes the sender of the message */        xmlnode_put_attrib(msg,"from",xmlnode_get_attrib(msg,"to"));	/* existing recipient gets replaced, hide it */        xmlnode_hide_attrib(msg,"to");	/* send a copy to each member of the group */        xhash_walk(gt->from,mod_groups_message_walk,(void *) msg);    }    xmlnode_free(msg);}/** * handle messages sent to the server address * * only messages are handled if they are addressed to a resource of the server, * that starts with "groups/" * * @param m the mapi_struct containing the message * @param arg the mod_groups_i structure containing module configuration * @return M_IGNORE if not a message stanza, M_HANDLED if the packet has been handled, M_PASS else */mreturn mod_groups_message(mapi m, void *arg) {    mod_groups_i mi = (mod_groups_i) arg;    xmlnode info;    jpacket jp = m->packet;    char *gid;    if(jp->type != JPACKET_MESSAGE) return M_IGNORE;    if(jp->to == NULL || j_strncmp(jp->to->resource,"groups/",7) != 0) return M_PASS;    /* circular safety: do not handle messages that contain an x element in the jabber:iq:delay namespace  */    if(xmlnode_get_tag(jp->x,"x?xmlns=" NS_DELAY) != NULL) {        xmlnode_free(jp->x);        return M_HANDLED;    }    /* process the resource, it has the form "groups/" followed by the desired group id */    gid = strchr(jp->to->resource,'/');    if (gid == NULL || *++gid == '\0') {	/* there is no group id: bounce! */        js_bounce_xmpp(m->si,jp->x,XTERROR_NOTACCEPTABLE);        return M_HANDLED;    }    /* get the <info/> element for a group */    info = mod_groups_get_info(mi,jp->p,jp->to->server,gid);    if (info == NULL) {	/* there is no such group available */        js_bounce_xmpp(m->si,jp->x,XTERROR_NOTFOUND);        return M_HANDLED;    }    /* check if this user has write access to the group */    if (xmlnode_get_tag(info,spools(jp->p,"write/user=",jid_full(jp->from),jp->p)) != NULL)        mod_groups_message_online(mi,jp->x,gid);    else        js_bounce_xmpp(m->si,jp->x,XTERROR_NOTALLOWED);    xmlnode_free(info);    return M_HANDLED;}/** * xhash_walker() used to free the content of the to and from xhashes in all grouptabs * * @param h the xht containing all groups * @param key the group that should be freed * @param val the grouptab for this group * @param arg unused/ignored */void mod_groups_destroy(xht h, const char *key, void *val, void *arg) {    grouptab gt = (grouptab) val;    xhash_free(gt->to);    xhash_free(gt->from);}/** * shutdown the module, free all allocated memory * * @param m the mapi_struct for the shutdown event * @param arg pointer to the mod_groups_i module internal data * @return always M_PASS */mreturn mod_groups_shutdown(mapi m, void *arg) {    mod_groups_i mi = (mod_groups_i) arg;    xhash_walk(mi->groups,mod_groups_destroy,NULL);    xhash_free(mi->groups);    xhash_free(mi->config);    pool_free(mi->p);    return M_PASS;}/** * init the module, register callbacks, parse configuration * * @param si the jsmi_struct containing the Jabber session manager instance-internal data */void mod_groups(jsmi si) {    pool p;    mod_groups_i mi;    xmlnode cur, config;    char *gid, *id = si->i->id;    log_debug2(ZONE, LOGT_INIT, "initing");    /* generate our module configuration structure */    p = pool_new();    mi = pmalloco(p,sizeof(_mod_groups_i));    mi->p = p;    mi->groups = xhash_new(67);    mi->xc = si->xc;    /* get the configuration xmlnode */    config = js_config(si,"groups");    mi->inst = xmlnode_get_tag_data(config,"instructions");    if (mi->inst == NULL)        mi->inst = pstrdup(p,"This will add the group to your roster");    if (config != NULL)    {        mi->config = xhash_new(67);        for (cur = xmlnode_get_firstchild(config); cur != NULL; cur = xmlnode_get_nextsibling(cur))        {            if (j_strcmp(xmlnode_get_name(cur),"group") != 0) continue;            gid = xmlnode_get_attrib(cur,"id");            if (gid == NULL)            {                log_error(id,"mod_groups: Error loading, no id attribute on group");                pool_free(p);                return;            }            else if (xhash_get(mi->config,gid) != NULL)            {                log_error(si->i->id,"mod_groups: Error loading, group '%s' configured twice",gid);                pool_free(p);                return;            }            if (xmlnode_get_tag(cur,"info") || xmlnode_get_tag(cur,"users"))                xhash_put(mi->config,pstrdup(p,gid),cur);        }    }    js_mapi_register(si,e_SERVER,mod_groups_message,(void *) mi);    js_mapi_register(si,e_SESSION,mod_groups_session,(void *) mi);    js_mapi_register(si,e_SHUTDOWN,mod_groups_shutdown,(void *) mi);}

⌨️ 快捷键说明

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