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

📄 mod_roster.c

📁 jabber server jabber server jabber server jabber server
💻 C
📖 第 1 页 / 共 2 页
字号:
 * handle packets sent by the user in the jabber:iq:roster namespace * * @param mapi the mapi instance containing the packet * @return M_PASS if not in the jabber:iq:roster namespace, M_HANDLED otherwise */mreturn mod_roster_out_iq(mapi m) {    xmlnode roster, cur, pres, item;    int newflag;    jid id;    if (!NSCHECK(m->packet->iq,NS_ROSTER)) return M_PASS;    roster = mod_roster_get(m->user);    switch(jpacket_subtype(m->packet)) {	case JPACKET__GET:	    log_debug2(ZONE, LOGT_ROSTER, "handling get request");	    xmlnode_put_attrib(m->packet->x,"type","result");	    m->s->roster = 1;	    /* insert the roster into the result */	    xmlnode_hide(m->packet->iq);	    xmlnode_insert_tag_node(m->packet->x, roster);	    jpacket_reset(m->packet);	    /* filter out pending subscribes */	    for(cur = xmlnode_get_firstchild(m->packet->iq); cur != NULL; cur = xmlnode_get_nextsibling(cur)) {		if (xmlnode_get_attrib(cur,"subscribe") != NULL)		    xmlnode_hide_attrib(cur,"subscribe");		if (xmlnode_get_attrib(cur,"hidden") != NULL)		    xmlnode_hide(cur);	    }	    /* send to the user */	    js_session_to(m->s,m->packet);	    /* redeliver those subscribes */	    for(cur = xmlnode_get_firstchild(roster); cur != NULL; cur = xmlnode_get_nextsibling(cur))		if (xmlnode_get_attrib(cur,"subscribe") != NULL) {		    pres = xmlnode_new_tag("presence");		    xmlnode_put_attrib(pres,"type","subscribe");		    xmlnode_put_attrib(pres,"from",xmlnode_get_attrib(cur,"jid"));		    if (strlen(xmlnode_get_attrib(cur,"subscribe")) > 0)			xmlnode_insert_cdata(xmlnode_insert_tag(pres,"status"),xmlnode_get_attrib(cur,"subscribe"),-1);		    js_session_to(m->s,jpacket_new(pres));		}	    break;	case JPACKET__SET:	    log_debug2(ZONE, LOGT_ROSTER, "handling set request");	    /* loop through the incoming items updating or creating */	    for(cur = xmlnode_get_firstchild(m->packet->iq); cur != NULL; cur = xmlnode_get_nextsibling(cur)) {		if (xmlnode_get_type(cur) != NTYPE_TAG || xmlnode_get_attrib(cur,"jid") == NULL)		    continue;		id = jid_new(m->packet->p,xmlnode_get_attrib(cur,"jid"));		if (id == NULL || jid_cmpx(jid_user(m->s->id),id,JID_USER|JID_SERVER) == 0) continue;		/* zoom to find the existing item in the current roster, and hide it */		item = mod_roster_get_item(roster, id, &newflag);		xmlnode_hide(item);		/* drop you sukkah */		if (j_strcmp(xmlnode_get_attrib(cur,"subscription"),"remove") == 0) {		    /* cancel our subscription to them */		    if (j_strcmp(xmlnode_get_attrib(item,"subscription"),"both") == 0 || j_strcmp(xmlnode_get_attrib(item,"subscription"),"to") == 0 || j_strcmp(xmlnode_get_attrib(item,"ask"),"subscribe") == 0) {			jpacket jp = jpacket_new(jutil_presnew(JPACKET__UNSUBSCRIBE,xmlnode_get_attrib(cur,"jid"),NULL));			jp->flag = PACKET_FORCE_SENT_MAGIC; /* force to sent it, as we already remove the subscription state */			js_session_from(m->s, jp);		    }		    /* tell them their subscription to us is toast */		    if (j_strcmp(xmlnode_get_attrib(item,"subscription"),"both") == 0 || j_strcmp(xmlnode_get_attrib(item,"subscription"),"from") == 0) {			jpacket jp = jpacket_new(jutil_presnew(JPACKET__UNSUBSCRIBED,xmlnode_get_attrib(cur,"jid"),NULL));			jp->flag = PACKET_FORCE_SENT_MAGIC; /* force to sent it, as we already remove the subscription state */			js_session_from(m->s, jp);		    }		    /* push this remove out */		    mod_roster_push(m->user,cur);		    continue;		}		/* copy the old stuff into the new one and insert it into the roster */		xmlnode_put_attrib(cur,"subscription",xmlnode_get_attrib(item,"subscription"));		xmlnode_put_attrib(cur,"ask",xmlnode_get_attrib(item,"ask")); /* prolly not here, but just in case */		xmlnode_put_attrib(cur,"subscribe", xmlnode_get_attrib(item, "subscribe"));		xmlnode_insert_tag_node(roster,cur);		/* push the new item */		mod_roster_push(m->user,cur);	    }	    /* send to the user */	    jutil_iqresult(m->packet->x);	    jpacket_reset(m->packet);	    js_session_to(m->s,m->packet);	    /* save the changes */	    log_debug2(ZONE, LOGT_ROSTER, "SROSTER: %s",xmlnode2str(roster));	    /* XXX what do we do if the set fails?  hrmf... */	    xdb_set(m->si->xc, m->user->id, NS_ROSTER, roster);	    break;	default:	    /* JPACKET__RESULT: result from a roster push to the client */	    xmlnode_free(m->packet->x);    }    xmlnode_free(roster);    return M_HANDLED;}/** * handle outgoing packets: check for iq and subscription stanzas * * @param m the mapi instance (containing the packet) * @param arg not used/ignored * @return M_IGNORE if the packet is not an iq or subscription packet, else M_PASS if packet not handled or M_HANDLED if packet handled */mreturn mod_roster_out(mapi m, void *arg){    if (m->packet->type == JPACKET_IQ) return mod_roster_out_iq(m);    if (m->packet->type == JPACKET_S10N) return mod_roster_out_s10n(m);    return M_IGNORE;}/** * register mod_roster_out callback for outgoing stanzas when a new session starts * * @param m the mapi instance * @param arg unused/ignored * @return always M_PASS */mreturn mod_roster_session(mapi m, void *arg){    js_mapi_session(es_OUT,m->s,mod_roster_out,NULL);    return M_PASS;}/** * handles subscription stanzas sent to an user * * @param m the mapi instance * @param arg not used/ignored * @return I_IGNORE if not a subscription stanza, else M_PASS if not handled or M_HANDLED if handled */mreturn mod_roster_s10n(mapi m, void *arg) {    xmlnode roster, item, reply, reply2;    char *status;    session top;    int newflag, drop, to, from, push, p_in, p_out;    push = newflag = drop = to = from = p_in = p_out = 0;    /* check for incoming s10n (subscription) requests */    if (m->packet->type != JPACKET_S10N) return M_IGNORE;    /* the user must exist */    if (m->user == NULL) return M_PASS;    /* don't handle packets sent from the user to himself */    if (jid_cmpx(m->packet->from, m->packet->to, JID_USER|JID_SERVER) == 0) return M_PASS; /* vanity complex */    /* now we can get to work and handle this user's incoming subscription crap */    roster = mod_roster_get(m->user);    item = mod_roster_get_item(roster, m->packet->from, &newflag);    reply2 = reply = NULL;    jid_set(m->packet->to, NULL, JID_RESOURCE); /* make sure we're only dealing w/ the user id */    log_debug2(ZONE, LOGT_ROSTER, "s10n %s request from %s with existing item %s", xmlnode_get_attrib(m->packet->x, "type"), jid_full(m->packet->from), xmlnode2str(item));    /* vars containing the old state of the subscritpion */    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");    }    switch(jpacket_subtype(m->packet)) {	case JPACKET__SUBSCRIBE:	    if (from) {		/* already subscribed, respond automatically */		reply = jutil_presnew(JPACKET__SUBSCRIBED, jid_full(m->packet->from), "Already Subscribed");		jid_set(m->packet->to, NULL, JID_RESOURCE);		xmlnode_put_attrib(reply, "from", jid_full(m->packet->to));		drop = 1;		/* the other person obviously is re-adding them to their roster, and should be told of the current presence */		reply2 = jutil_presnew(JPACKET__PROBE,jid_full(m->packet->to),NULL);		xmlnode_put_attrib(reply2,"from",jid_full(m->packet->from));	    } else if (p_in) {		/* we already know that this contact asked for subscription */		drop = 1;		/* no state change */	    } else {		/* tuck request in the roster */		drop = 0;		status = xmlnode_get_tag_data(m->packet->x,"status");		if (status == NULL)		    xmlnode_put_attrib(item,"subscribe","");		else		    xmlnode_put_attrib(item,"subscribe",status);		if (newflag) /* SPECIAL CASE: special flag so that we can hide these incoming subscribe requests */		    xmlnode_put_attrib(item,"hidden","");	    }	    break;	case JPACKET__SUBSCRIBED:	    if (to || !p_out) {		/* already subscribed, or we don't want to subscribe: drop */		drop = 1;	    } else {		/* cancel any ask, s10n=to */		xmlnode_hide_attrib(item,"ask");		mod_roster_set_s10n(from, 1, item);		push = 1;	    }	    break;	case JPACKET__UNSUBSCRIBE:	    if (from || p_in) {		/* respond automatically */		reply = jutil_presnew(JPACKET__UNSUBSCRIBED,jid_full(m->packet->from),"Autoreply");		jid_set(m->packet->to,NULL,JID_RESOURCE);		xmlnode_put_attrib(reply,"from",jid_full(m->packet->to));		/* update state */		xmlnode_hide_attrib(item,"subscribe");		mod_roster_set_s10n(0, to, item);		if (xmlnode_get_attrib(item,"hidden") != NULL)		    xmlnode_hide(item);		else		    push = 1;	    } else {		if (newflag)		    xmlnode_hide(item);		drop = 1;	    }	    break;	case JPACKET__UNSUBSCRIBED:	    if (to || p_out) {		/* cancel any ask, remove s10n=to */		xmlnode_hide_attrib(item,"ask");		mod_roster_set_s10n(from, 0, item);		push = 1;	    } else {		if (newflag)		    xmlnode_hide(item);		drop = 1;	    }    }    /* XXX what do we do if the set fails?  hrmf... */    xdb_set(m->si->xc, m->user->id, NS_ROSTER, roster);    /* these are delayed until after we check the roster back in, avoid rancid race conditions */    if (reply != NULL)	js_deliver(m->si,jpacket_new(reply));    if (reply2 != NULL)	js_deliver(m->si,jpacket_new(reply2));    /* find primary session */    top = js_session_primary(m->user);    /* if we can, deliver this to that session */    if (!drop && top != NULL && top->roster)	js_session_to(top,m->packet);    else	xmlnode_free(m->packet->x);    if (push)        mod_roster_push(m->user,item);    xmlnode_free(roster);    return M_HANDLED;}/** * init the mod_roster module * * Register the following callbacks: * - mod_roster_session for new sessions * - mod_roster_s10n for stanzas send to a user * * @param si the session manager instance */void mod_roster(jsmi si){    /* we just register for new sessions */    js_mapi_register(si,e_SESSION,mod_roster_session,NULL);    js_mapi_register(si,e_DELIVER,mod_roster_s10n,NULL);}

⌨️ 快捷键说明

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