📄 mod_groups.c
字号:
*/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 * * @param mi mod_groups_i struct containing module instance data * @param p memory pool to use * @param uid the user, that should be added * @param un the user's name * @param gid the group id to add the user to * @param gn the group name * @param both subscription type both? * @return 1 on failure, 0 on success */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_debug2(ZONE, LOGT_DELIVER, "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 * * @param mi the mod_groups_i struct containing module instance data * @param p memory pool to use * @param uid which user to remove * @param host host to use * @param gid group id from which the user should be removed * @return 0 on success, 1 on failure */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); /* insert with a match will overwrite the node with NULL and therefore remove it */ if(xdb_act(mi->xc,xid,NS_XGROUPS,"insert",spools(p,"?jid=",jid_full(uid),p),NULL)) { log_debug2(ZONE, LOGT_DELIVER, "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;}/** * handle register set requests (the actual registration with a group) * * @param mi the mod_groups_i struct containing module instance data * @param m the mapi_struct containing module instance data */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_xmpp(m->si,jp->x,XTERROR_NOTACCEPTABLE); return; } host = jp->from->server; /* check if the group exists */ info = mod_groups_get_info(mi,p,host,gid); if (info == NULL) { js_bounce_xmpp(m->si,jp->x,XTERROR_NOTFOUND); return; } uid = jid_user(jp->from); un = xmlnode_get_tag_data(jp->iq,"name"); gn = xmlnode_get_tag_data(info,"name"); /* register or unregister? */ add = (xmlnode_get_tag(jp->iq, "remove") == NULL); both = (xmlnode_get_tag(info,"static") == NULL); if (add) { log_debug2(ZONE, LOGT_DELIVER, "register GID %s",gid); if (mod_groups_xdb_add(mi,p,uid,un ? un : jid_full(uid),gid,gn,both)) { js_bounce_xmpp(m->si,jp->x,XTERROR_UNAVAIL); xmlnode_free(info); return; } } else { log_debug2(ZONE, LOGT_DELIVER, "unregister GID %s",gid); if (mod_groups_xdb_remove(mi,p,uid,host,gid)) { js_bounce_xmpp(m->si,jp->x,XTERROR_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); mod_groups_presence_to(m->s,gt); } jutil_iqresult(jp->x); jpacket_reset(jp); js_session_to(m->s,jp); xmlnode_free(info);}/** * handle a register get request * * Return what is required to register a group * * @param mi the mod_groups_i struct containing module instance data * @param m the mapi_struct containing the register get request */void mod_groups_register_get(mod_groups_i mi, mapi m) { jpacket jp = m->packet; xmlnode q; char *gid, *name = ""; xmlnode members, user; jid uid = m->user->id; gid = strchr(pstrdup(jp->p, jp->to->resource),'/'); /* Check that it is somewhat valid */ if (gid != NULL && *++gid != '\0') { jutil_iqresult(jp->x); q = xmlnode_insert_tag(jp->x,"query"); xmlnode_put_attrib(q,"xmlns",NS_REGISTER); /* Search to see if this users is already registered */ members = mod_groups_get_users(mi,jp->p,jp->from->server,gid); user = xmlnode_get_tag(members,spools(jp->p,"?jid=",uid->full,jp->p)); if (user) { /* if the user is already registered, add the <registered/> element */ name = xmlnode_get_attrib(user, "name"); xmlnode_insert_tag(q,"registered"); } xmlnode_free(members); xmlnode_insert_cdata(xmlnode_insert_tag(q,"name"),name,-1); xmlnode_insert_cdata(xmlnode_insert_tag(q,"key"),jutil_regkey(NULL,jid_full(jp->from)),-1); xmlnode_insert_cdata(xmlnode_insert_tag(q,"instructions"),mi->inst,-1); jpacket_reset(jp); js_session_to(m->s,jp); } else { /* there has been no group id in the request */ js_bounce_xmpp(m->si,jp->x,XTERROR_NOTACCEPTABLE); }}/** * handle browse set requests for groups * * Only users with "edit" rights are allowed to update a group * * @param mi the mod_groups_i struct containing module instance data * @param m the mapi_struct containing the request */void mod_groups_browse_set(mod_groups_i mi, mapi m) { jpacket jp = m->packet; pool p = jp->p; grouptab gt; xmlnode info, user; jid uid; char *gid, *gn, *un, *host, *action; int add; log_debug2(ZONE, LOGT_DELIVER, "Setting"); /* get the group ID ... we only handle the request if there is a specified group */ gid = strchr(jp->to->resource,'/'); if (gid == NULL || *++gid == '\0') { js_bounce_xmpp(m->si,jp->x,XTERROR_NOTACCEPTABLE); return; } user = xmlnode_get_tag(jp->iq,"user"); uid = jid_new(p,xmlnode_get_attrib(user,"jid")); un = xmlnode_get_attrib(user,"name"); action = xmlnode_get_attrib(user, "action"); /* it's an add action if there is no action attribute or its value is NOT remove */ add = ( ( action == NULL ) || j_strcmp(action, "remove") ); if (uid == NULL || un == NULL) { js_bounce_xmpp(m->si,jp->x,XTERROR_NOTACCEPTABLE); return; } /* is the user allowed to edit a group? */ info = mod_groups_get_info(mi,p,jp->to->server,gid); if (info == NULL || xmlnode_get_tag(info,spools(p,"edit/user=",jid_full(jp->from),p)) == NULL) { js_bounce_xmpp(m->si,jp->x,XTERROR_NOTALLOWED); return; } gn = xmlnode_get_tag_data(info,"name"); if (add) { /* adding a user */ log_debug2(ZONE, LOGT_DELIVER, "Adding"); if (mod_groups_xdb_add(mi,p,uid,un,gid,gn,1)) { js_bounce_xmpp(m->si,jp->x,XTERROR_UNAVAIL); xmlnode_free(info); return; } } else { /* removing a user */ log_debug2(ZONE, LOGT_DELIVER, "Removing"); host = jp->from->server; if (mod_groups_xdb_remove(mi,p,uid,host,gid)) { js_bounce_xmpp(m->si,jp->x,XTERROR_UNAVAIL); xmlnode_free(info); return; } } gt = GROUP_GET(mi,gid); /* push the new user to the other members */ mod_groups_update_rosters(gt,uid,un,gn,add); /* XXX how can we push the roster to the new user and send their presence? lookup their session? */ xmlnode_free(info); jutil_iqresult(jp->x); jpacket_reset(jp); js_session_to(m->s,jp);}/** * build a result jpacket for a browse request containing the browse result for a group * * @param p the memory pool to use * @param jp the jpacket where to place the result * @param group the group for which to generate the result * @param host the hostname of the server * @param gn the group name */void mod_groups_browse_result(pool p, jpacket jp, xmlnode group, char *host, char *gn) { xmlnode q, cur, tag; char *id, *name; q = xmlnode_insert_tag(jutil_iqresult(jp->x),"item"); xmlnode_put_attrib(q,"xmlns",NS_BROWSE); xmlnode_put_attrib(q,"jid",jid_full(jp->to)); xmlnode_put_attrib(q,"name",gn ? gn : "Toplevel groups"); for (cur = xmlnode_get_firstchild(group); cur != NULL; cur = xmlnode_get_nextsibling(cur)) { if (xmlnode_get_type(cur) != NTYPE_TAG) continue; name = xmlnode_get_name(cur); if (j_strcmp(name,"group") == 0) { tag = xmlnode_insert_tag(q,"item"); xmlnode_put_attrib(tag,"name",xmlnode_get_attrib(cur,"name")); id = spools(p,host,"/groups/",xmlnode_get_attrib(cur,"id"),p); xmlnode_put_attrib(tag,"jid",id); } else if (j_strcmp(name,"user") == 0) { xmlnode_insert_node(q,cur); } }}/** * handle browse-get requests by a user * * @param mi the mod_groups_i instance data * @param m the mapi_struct containing the browse-get-request */void mod_groups_browse_get(mod_groups_i mi, mapi m) { jpacket jp = m->packet; xmlnode group; pool p = jp->p; xmlnode info = NULL; char *gid, *gn, *host = jp->to->server; log_debug2(ZONE, LOGT_DELIVER, "Browse request"); gid = strchr(jp->to->resource,'/'); if (gid != NULL && *++gid != '\0') { /* there is a group id: get this group's data */ group = mod_groups_get_users(mi,p,host,gid); info = mod_groups_get_info(mi,p,host,gid); gn = xmlnode_get_tag_data(info,"name"); } else { /* there is no group id: get the toplevel groups */ group = mod_groups_get_top(mi,p,host); gn = NULL; } if (group == NULL && gn == NULL) { js_bounce_xmpp(m->si,jp->x,XTERROR_NOTFOUND); return; } if (group != NULL) { /* send (a) group(s) */ mod_groups_browse_result(p,jp,group,host,gn); xmlnode_free(group); } else { /* there is only a name */ xmlnode q; q = xmlnode_insert_tag(jutil_iqresult(jp->x),"item"); xmlnode_put_attrib(q,"xmlns",NS_BROWSE); xmlnode_put_attrib(q,"jid",jid_full(jp->to)); xmlnode_put_attrib(q,"name",gn); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -