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

📄 mod_roster.c

📁 jabber server jabber server jabber server jabber server
💻 C
📖 第 1 页 / 共 2 页
字号:
/* -------------------------------------------------------------------------- * * License * * The contents of this file are subject to the Jabber Open Source License * Version 1.0 (the "JOSL").  You may not copy or use this file, in either * source code or executable form, except in compliance with the JOSL. You * may obtain a copy of the JOSL at http://www.jabber.org/ or at * http://www.opensource.org/.   * * Software distributed under the JOSL is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the JOSL * for the specific language governing rights and limitations under the * JOSL. * * Copyrights *  * Portions created by or assigned to Jabber.com, Inc. are  * Copyright (c) 1999-2002 Jabber.com, Inc.  All Rights Reserved.  Contact * information for Jabber.com, Inc. is available at http://www.jabber.com/. * * Portions Copyright (c) 1998-1999 Jeremie Miller. *  * Acknowledgements *  * Special thanks to the Jabber Open Source Contributors for their * suggestions and support of Jabber. *  * Alternatively, the contents of this file may be used under the terms of the * GNU General Public License Version 2 or later (the "GPL"), in which case * the provisions of the GPL are applicable instead of those above.  If you * wish to allow use of your version of this file only under the terms of the * GPL and not to allow others to use your version of this file under the JOSL, * indicate your decision by deleting the provisions above and replace them * with the notice and other provisions required by the GPL.  If you do not * delete the provisions above, a recipient may use your version of this file * under either the JOSL or the GPL.  *  *  * --------------------------------------------------------------------------*/#include "jsm.h"/** * @file mod_roster.c * @brief handle subscription state changes and the user's access to his roster * * The protocols implemented in this module are documented in XMPP IM. *//** * get the roster of a user * * @param u for which user we want to get the roster * @return the user's roster */xmlnode mod_roster_get(udata u) {    xmlnode ret;    log_debug2(ZONE, LOGT_ROSTER, "getting %s's roster", u->user);    /* get the existing roster */    ret = xdb_get(u->si->xc, u->id, NS_ROSTER);    if (ret == NULL) {	/* there isn't one, sucky, create a container node and let xdb manage it */        log_debug2(ZONE, LOGT_ROSTER, "creating");        ret = xmlnode_new_tag("query");        xmlnode_put_attrib(ret, "xmlns", NS_ROSTER);    }    return ret;}/** * get a single item from the user's roster * * @param roster the complete roster from which the item should be gotten * @param id which item should be gotten * @param newflag where to store 1 if the item did not exist and has just been created * @return the roster item */xmlnode mod_roster_get_item(xmlnode roster, jid id, int *newflag) {    xmlnode ret;    log_debug2(ZONE, LOGT_ROSTER, "getting item %s", jid_full(id));    ret = jid_nodescan(id, roster);    if (ret == NULL) {	/* there isn't one, brew one up */        log_debug2(ZONE, LOGT_ROSTER, "creating");        ret = xmlnode_insert_tag(roster, "item");        xmlnode_put_attrib(ret, "jid", jid_full(id));        xmlnode_put_attrib(ret, "subscription", "none");        *newflag = 1;    }    return ret;}/** * push a (changed) roster item to all sessions of a user * * @param user the user's data * @param item the (changed) roster item to be pushed */void mod_roster_push(udata user, xmlnode item) {    session cur;    xmlnode packet, query;    log_debug2(ZONE, LOGT_ROSTER, "pushing %s", xmlnode2str(item));    if (xmlnode_get_attrib(item, "hidden") != NULL) return;    /* create a jpacket roster item push */    packet = xmlnode_new_tag("iq");    xmlnode_put_attrib(packet, "type", "set");    query = xmlnode_insert_tag(packet, "query");    xmlnode_put_attrib(query, "xmlns", NS_ROSTER);    xmlnode_insert_tag_node(query, item);    xmlnode_hide_attrib(xmlnode_get_firstchild(query), "subscribe"); /* hide the server tirds */    /* send a copy to all session that have a roster */    for(cur = user->sessions; cur != NULL; cur = cur->next)        if (cur->roster)            js_session_to(cur, jpacket_new(xmlnode_dup(packet)));    xmlnode_free(packet);}/** * helper function to update the subscription state in a roster item * * @param from if the is a subscription from the contact to the user's presence * @param to if the user is subscribed to the contact's presence * @param item the roster item in which the subscription state should be changed */void mod_roster_set_s10n(int from, int to, xmlnode item) {    xmlnode_put_attrib(item, "subscription", from ? (to ? "both" : "from") : (to ? "to" : "none"));}/** * force sending all presences of a user to a contact * * @param u the user's data * @param to to which contact the presence should be sent * @param uflag 1 for forcing offline presence, 0 else */void mod_roster_pforce(udata u, jid to, int uflag){    session s;    xmlnode x;    log_debug2(ZONE, LOGT_ROSTER, "brute forcing presence updates");    /* loop through all the sessions */    for(s = u->sessions; s != NULL; s = s->next) {        if (uflag)            x = jutil_presnew(JPACKET__UNAVAILABLE,NULL,NULL);        else            x = xmlnode_dup(s->presence);        xmlnode_put_attrib(x,"to",jid_full(to));        js_session_from(s,jpacket_new(x));    }}/** * handle subscription packets sent by a user * * @param m the mapi instance containing the packet * @return always M_PASS */mreturn mod_roster_out_s10n(mapi m) {    xmlnode roster, item;    int newflag=0, to=0, from=0, p_in=0, p_out=0, route=0, force_sent=0;    jid curr;    /* the packet needs a destination */    if (m->packet->to == NULL)	return M_PASS;    /* don't handle subscription packets sent to the user itself */    if (jid_cmpx(jid_user(m->s->id), m->packet->to, JID_USER|JID_SERVER) == 0)	return M_PASS; /* vanity complex */    log_debug2(ZONE, LOGT_ROSTER, "handling outgoing s10n");    /* get the roster item */    roster = mod_roster_get(m->user);    item = mod_roster_get_item(roster, m->packet->to, &newflag);    /* vars containing the old subscription state */    if (j_strcmp(xmlnode_get_attrib(item, "subscription"),"to") == 0)        to = 1;    if (j_strcmp(xmlnode_get_attrib(item, "subscription"),"from") == 0)        from = 1;    if (j_strcmp(xmlnode_get_attrib(item, "subscription"),"both") == 0)        to = from = 1;    if (j_strcmp(xmlnode_get_attrib(item, "ask"), "subscribe") == 0)	p_out = 1;    if (xmlnode_get_attrib(item, "subscribe") != NULL)	p_in = 1;    /* ask='unsubscribe' can be in xdb from old data written by jabberd up to version 1.4.3 */    if (j_strcmp(xmlnode_get_attrib(item, "ask"), "unsubscribe") == 0) {	to = 0;	xmlnode_put_attrib(item, "subscription", from ? "from" : "none");    }    /* if the packet is flagged with PACKET_FORCE_SENT_MAGIC we have to sent     * it out without checking the previous subscription state. The packet     * has been generated because a roster item has been removed, so we will     * see a state of subscription "none" but we have to inform the other     * server that the subscription has just been removed. */    force_sent = m->packet->flag == PACKET_FORCE_SENT_MAGIC ? 1 : 0;    switch(jpacket_subtype(m->packet)) {	case JPACKET__SUBSCRIBE:	    /* is the user already subscribed to this contact? */	    if (!to) {		/* no */		xmlnode_put_attrib(item,"ask","subscribe");		mod_roster_push(m->user, item);	    }	    /* always route the packet, the user might have rerequested auth	     * because the contact's server is out of sync */	    route = 1;	    break;	case JPACKET__SUBSCRIBED:	    if (force_sent || (!from && p_in)) {		/* XMPP IM, sect. 9 states "None + Pending In", "None + Pending Out/In", and "To + Pending In" */		route = 1;		mod_roster_set_s10n(1, to, item); /* update subscription */		jid_append(js_trustees(m->user), m->packet->to); /* make them trusted now */		xmlnode_hide_attrib(item, "subscribe"); /* reset "Pending In" */		xmlnode_hide_attrib(item, "hidden"); /* make it visible on the user's roster */		mod_roster_pforce(m->user, m->packet->to, 0); /* they are now subscribed to us, send them our presence */		mod_roster_push(m->user, item); /* new roster to the user's other sessions */	    } else {		/* XMPP IM, sect. 9 other states */		route = 0;		/* no state change */	    }	    break;	case JPACKET__UNSUBSCRIBE:	    if (to) {		/* changed behaviour since after version 1.4.3 ... we now immediatelly change to state "From" or "None"		 * jabberd up to version 1.4.3 only set the flag ask="unsubscribe" and waited for an unsubscribed		 * configirmation from the contact's server		 */		mod_roster_set_s10n(from, 0, item);		xmlnode_hide_attrib(item, "ask"); /* reset Pending Out */		mod_roster_push(m->user, item);	    } else if (newflag) {		/* the contact was not on the roster and should not become a roster item */		xmlnode_hide(item);	    }	    /* always route the packet, the user might have unsubscribed a second time	     * because the contact's server is out of sync */	    route = 1;	    break;	case JPACKET__UNSUBSCRIBED:	    if (!from && !p_in && !force_sent) {		/* XMPP IM, sect. 9 states "None", "None + Pending Out", and "To" */		route = 0;		/* no state change */	    } else {		/* other states */		route = 1;		if (p_in) {		    xmlnode_hide_attrib(item, "subscribe"); /* reset "Pending In" */		}		if (from) {		    mod_roster_set_s10n(0, to, item); /* update subscription */		    mod_roster_pforce(m->user, m->packet->to, 1); /* make us offline */		    mod_roster_push(m->user, item);		} else if (force_sent) {		    mod_roster_pforce(m->user, m->packet->to, 1); /* make us offline */		}	    }	    if ((!route || !from && !p_in && force_sent) && newflag || xmlnode_get_attrib(item, "hidden")) {		/* the contact was not on the roster and should not become a roster item */		xmlnode_hide(item);	    }	    break;    }    /* save the roster */    /* XXX what do we do if the set fails?  hrmf... */    xdb_set(m->si->xc, m->user->id, NS_ROSTER, roster);    /* make sure it's sent from the *user*, not the resource */    xmlnode_put_attrib(m->packet->x,"from",jid_full(jid_user(m->s->id)));    jpacket_reset(m->packet);    /* we don't need the roster anymore */    xmlnode_free(roster);    /* should the packet passed to the contact? */    return route ? M_PASS : M_HANDLED;}/**

⌨️ 快捷键说明

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