📄 mod_roster.c
字号:
roster = mod_roster_get(m->user); switch(jpacket_subtype(m->packet)) { case JPACKET__GET: log_debug("mod_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_debug("mod_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, NULL, &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) js_session_from(m->s,jpacket_new(jutil_presnew(JPACKET__UNSUBSCRIBE,xmlnode_get_attrib(cur,"jid"),NULL))); /* 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) js_session_from(m->s,jpacket_new(jutil_presnew(JPACKET__UNSUBSCRIBED,xmlnode_get_attrib(cur,"jid"),NULL))); /* 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_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_debug(ZONE,"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); break; } xmlnode_free(roster); return M_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;}mreturn mod_roster_session(mapi m, void *arg){ js_mapi_session(es_OUT,m->s,mod_roster_out,NULL); return M_PASS;}mreturn mod_roster_s10n(mapi m, void *arg){ xmlnode roster, item, reply, reply2; char *status; session top; int newflag, drop, to, from, push; push = newflag = drop = to = from = 0; /* check for incoming s10n (subscription) requests */ if(m->packet->type != JPACKET_S10N) return M_IGNORE; if(m->user == NULL) return M_PASS; 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,xmlnode_get_attrib(m->packet->x,"name"),&newflag); reply2 = reply = NULL; jid_set(m->packet->to,NULL,JID_RESOURCE); /* make sure we're only dealing w/ the user id */ log_debug("mod_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 */ 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; 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{ /* tuck request in the roster */ 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) { /* already subscribed, drop */ drop = 1; }else{ /* cancel any ask, s10n=to */ xmlnode_hide_attrib(item,"ask"); mod_roster_set_s10n(S10N_ADD_TO,item); push = 1; } break; case JPACKET__UNSUBSCRIBE: if(from) { /* remove s10n=from */ xmlnode_hide_attrib(item,"subscribe"); mod_roster_set_s10n(S10N_REM_FROM,item); if(xmlnode_get_attrib(item,"hidden") != NULL) xmlnode_hide(item); else push = 1; }else{ if(newflag) xmlnode_hide(item); drop = 1; } /* 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)); break; case JPACKET__UNSUBSCRIBED: if(to || xmlnode_get_attrib(item,"ask") != NULL) { /* cancel any ask, remove s10n=to */ xmlnode_hide_attrib(item,"ask"); mod_roster_set_s10n(S10N_REM_TO,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;}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 + -