/* session thread */ mreturn mod_presence_avails(mapi m, void *arg) { modpres mp = (modpres) arg; if (m->packet->type != JPACKET_PRESENCE) return M_IGNORE; if (m->packet->to == NULL) return M_PASS; log_debug("track presence sent to jids"); /* handle invisibles: put in I and remove from A */ if (jpacket_subtype(m->packet) == JPACKET__INVISIBLE) { if (mp->I == NULL) mp->I = jid_new(m->s->p, jid_full(m->packet->to)); else jid_append(mp->I, m->packet->to); mp->A = _mod_presence_whack(m->packet->to, mp->A); return M_PASS; } /* ensure not invisible from before */ mp->I = _mod_presence_whack(m->packet->to, mp->I); /* avails to A */ if (jpacket_subtype(m->packet) == JPACKET__AVAILABLE) jid_append(mp->A, m->packet->to); /* unavails from A */ if (jpacket_subtype(m->packet) == JPACKET__UNAVAILABLE) mp->A = _mod_presence_whack(m->packet->to, mp->A); return M_PASS; }
/* session thread */ mreturn mod_presence_in(mapi m, void *arg) { modpres mp = (modpres) arg; xmlnode pres; if (m->packet->type != JPACKET_PRESENCE) return M_IGNORE; log_debug("incoming filter for %s", jid_full(m->s->id)); if (jpacket_subtype(m->packet) == JPACKET__PROBE) { /* reply with our presence */ if (m->s->presence == NULL) { log_debug("probe from %s and no presence to return", jid_full(m->packet->from)); } else if (!mp->invisible && js_trust(m->user, m->packet->from) && !_mod_presence_search(m->packet->from, mp->I)) { /* compliment of I in T */ log_debug("got a probe, responding to %s", jid_full(m->packet->from)); pres = xmlnode_dup(m->s->presence); xmlnode_put_attrib(pres, "to", jid_full(m->packet->from)); js_session_from(m->s, jpacket_new(pres)); } else if (mp->invisible && js_trust(m->user, m->packet->from) && _mod_presence_search(m->packet->from, mp->A)) { /* when invisible, intersection of A and T */ log_debug("got a probe when invisible, responding to %s", jid_full(m->packet->from)); pres = jutil_presnew(JPACKET__AVAILABLE, jid_full(m->packet->from), NULL); js_session_from(m->s, jpacket_new(pres)); } else { log_debug("%s attempted to probe by someone not qualified", jid_full(m->packet->from)); } xmlnode_free(m->packet->x); return M_HANDLED; } if (jid_cmp(m->packet->from, m->s->id) == 0) { /* this is our presence, don't send to ourselves */ xmlnode_free(m->packet->x); return M_HANDLED; } /* if a presence packet bounced, remove from the A list */ if (jpacket_subtype(m->packet) == JPACKET__ERROR) mp->A = _mod_presence_whack(m->packet->from, mp->A); /* doh! this is a user, they should see invisibles as unavailables */ if (jpacket_subtype(m->packet) == JPACKET__INVISIBLE) xmlnode_put_attrib(m->packet->x, "type", "unavailable"); return M_PASS; }
mreturn mod_browse_reply(mapi m, void *arg) { xmlnode browse, ns, cur; session s; if (m->packet->type != JPACKET_IQ) return M_IGNORE; if (!NSCHECK(m->packet->iq, NS_BROWSE)) return M_PASS; /* first, is this a valid request? */ switch (jpacket_subtype(m->packet)) { case JPACKET__RESULT: case JPACKET__ERROR: return M_PASS; case JPACKET__SET: js_bounce(m->si, m->packet->x, TERROR_NOTALLOWED); return M_HANDLED; } log_debug("handling query for user %s", m->user->user); /* get this dudes browse info */ browse = mod_browse_get(m, m->packet->to); /* insert the namespaces */ ns = xdb_get(m->si->xc, m->packet->to, NS_XDBNSLIST); for (cur = xmlnode_get_firstchild(ns); cur != NULL; cur = xmlnode_get_nextsibling(cur)) if (xmlnode_get_attrib(cur, "type") == NULL) xmlnode_insert_tag_node(browse, cur); /* only include the generic <ns>foo</ns> */ xmlnode_free(ns); /* include any connected resources if there's a s10n from them */ if (js_trust(m->user, m->packet->from)) { SEM_LOCK(m->user->sem); for (s = m->user->sessions; s != NULL; s = s->next) { /* if(s->priority < 0) continue; *** include all resources I guess */ if (xmlnode_get_tag (browse, spools(m->packet->p, "?jid=", jid_full(s->id), m->packet->p)) != NULL) continue; /* already in the browse result */ cur = xmlnode_insert_tag(browse, "user"); xmlnode_put_attrib(cur, "type", "client"); xmlnode_put_attrib(cur, "jid", jid_full(s->id)); } SEM_UNLOCK(m->user->sem); } /* XXX include iq:filter forwards */ jutil_iqresult(m->packet->x); jpacket_reset(m->packet); xmlnode_insert_tag_node(m->packet->x, browse); js_deliver(m->si, m->packet); xmlnode_free(browse); return M_HANDLED; }
int at_iq_vcard(ati ti, jpacket jp) { xmlnode data; at_session s; s = at_session_find_by_jid(ti, jp->from); if(jpacket_subtype(jp) != JPACKET__GET || (s && ((!s->icq && jp->to->user) || (s->icq && s->icq_vcard_response)))) { at_bounce(ti, jp, TERROR_BAD); return 1; } if(!jp->to->user) { xmlnode_insert_node(jutil_iqresult(jp->x),ti->vcard); at_deliver(ti,jp->x); return 1; } if(!s) return 0; jutil_iqresult(jp->x); jp->iq = data = xmlnode_insert_tag(jp->x,"vCard"); xmlnode_put_attrib(data,"xmlns",NS_VCARD); xmlnode_put_attrib(data,"version","3.0"); xmlnode_put_attrib(data,"prodid","-//HandGen//NONSGML vGen v1.0//EN"); s->icq_vcard_response = jp; aim_icq_getsimpleinfo(s->ass, jp->to->user); return 1; }
int at_iq_disco_items(ati ti, jpacket jp) { xmlnode q; if(jpacket_subtype(jp) != JPACKET__GET) { at_bounce(ti, jp, TERROR_BAD); return 1; } if(xmlnode_get_attrib(xmlnode_get_tag(jp->x, "query"),"node") != NULL) { at_bounce(ti, jp, TERROR_NOTALLOWED); return 1; } jutil_iqresult(jp->x); q = xmlnode_insert_tag(jp->x, "query"); xmlnode_put_attrib(q, "xmlns", NS_DISCO_ITEMS); at_deliver(ti,jp->x); return 1; }
/* thread safe with sem */ mreturn mod_presence_deliver(mapi m, void *arg) { session cur; if (m->packet->type != JPACKET_PRESENCE) return M_IGNORE; log_debug("deliver phase"); /* only if we HAVE a user, and it was sent to ONLY the user@server, and there is at least one session available */ if (m->user != NULL && m->packet->to->resource == NULL && js_session_primary_all_sem(m->user) != NULL) { log_debug("broadcasting to %s", m->user->user); /* broadcast */ for (cur = m->user->sessions; cur != NULL; cur = cur->next) { if (cur->priority < -128) continue; js_session_to(cur, jpacket_new(xmlnode_dup(m->packet->x))); } SEM_UNLOCK(m->user->sem); if (jpacket_subtype(m->packet) != JPACKET__PROBE) { /* probes get handled by the offline thread as well? */ xmlnode_free(m->packet->x); return M_HANDLED; } } return M_PASS; }
int at_iq_version(ati ti, jpacket jp) { xmlnode os, x, q; struct utsname un; if(jpacket_subtype(jp) != JPACKET__GET) { at_bounce(ti, jp, TERROR_BAD); return 1; } x = jutil_iqresult(jp->x); q = xmlnode_insert_tag(x,"query"); xmlnode_put_attrib(q,"xmlns",NS_VERSION); xmlnode_insert_cdata(xmlnode_insert_tag(q,"name"),"AIM Transport",-1); xmlnode_insert_cdata(xmlnode_insert_tag(q,"version"), VERSION,-1); uname(&un); os = xmlnode_insert_tag(q,"os"); xmlnode_insert_cdata(os,un.sysname,-1); xmlnode_insert_cdata(os," ",1); xmlnode_insert_cdata(os,un.release,-1); at_deliver(ti,x); // AGAIN!?! return 1; }
int at_iq_time(ati ti, jpacket jp) { xmlnode x, q; time_t t; char *tstr; if(jpacket_subtype(jp) != JPACKET__GET) { at_bounce(ti, jp, TERROR_BAD); return 1; } x = jutil_iqresult(jp->x); q = xmlnode_insert_tag(x,"query"); xmlnode_put_attrib(q,"xmlns",NS_TIME); xmlnode_insert_cdata(xmlnode_insert_tag(q,"utc"),jutil_timestamp(),-1); xmlnode_insert_cdata(xmlnode_insert_tag(q,"tz"),tzname[0],-1); /* create nice display time */ t = time(NULL); tstr = ctime(&t); tstr[strlen(tstr) - 1] = '\0'; /* cut off newline */ xmlnode_insert_cdata(xmlnode_insert_tag(q,"display"),tstr,-1); at_deliver(ti,x); return 1; }
mreturn mod_roster_auto_in_s10n(mapi m, void *arg) { xmlnode reply, x; log_debug("AUTO ROSTER"); //in not s10n if (m->packet->type != JPACKET_S10N) return M_IGNORE; //if no to if (m->packet->to == NULL) return M_PASS; //if from me if (jid_cmpx(m->s->uid, m->packet->from, JID_USER | JID_SERVER) == 0) return M_PASS; log_debug("handling incoming s10n"); switch (jpacket_subtype(m->packet)) { case JPACKET__SUBSCRIBE: log_debug("SUBSCRIBE"); reply = jutil_presnew(JPACKET__SUBSCRIBED, jid_full(m->packet->from), NULL); js_session_from(m->s, jpacket_new(reply)); reply = jutil_presnew(JPACKET__SUBSCRIBE, jid_full(m->packet->from), NULL); js_session_from(m->s, jpacket_new(reply)); break; case JPACKET__SUBSCRIBED: break; case JPACKET__UNSUBSCRIBE: log_debug("UNSUBSCRIBE"); //reply = jutil_presnew(JPACKET__UNSUBSCRIBED, jid_full(m->packet->from),NULL); //js_session_from(m->s, jpacket_new(reply)); //remove account. reply = jutil_iqnew(JPACKET__SET, NS_ROSTER); x = xmlnode_get_tag(reply, "query"); x = xmlnode_insert_tag(x, "item"); xmlnode_put_attrib(x, "jid", jid_full(jid_user(m->packet->from))); xmlnode_put_attrib(x, "subscription", "remove"); js_session_from(m->s, jpacket_new(reply)); // reply = jutil_iqnewpresnew(JPACKET__UNSUBSCRIBE, jid_full(m->packet->from),NULL); // js_session_from(m->s, jpacket_new(reply)); break; case JPACKET__UNSUBSCRIBED: break; } xmlnode_free(m->packet->x); return M_HANDLED; }
void mt_unknown_process(mti ti, jpacket jp) { switch (jp->type) { case JPACKET_IQ: if (jp->to->user != NULL || (ti->con && j_strcmp(ti->con_id,jp->to->server) == 0)) { jp->aux1 = (void *) ti; mtq_send(NULL,jp->p,&mt_unknown_bounce,(void *) jp); } else { if (j_strcmp(jp->iqns,NS_REGISTER) == 0) { jp->aux1 = (void *) ti; mtq_send(NULL,jp->p,&mt_reg_unknown,(void *) jp); } else mt_iq_server(ti,jp); } break; case JPACKET_MESSAGE: case JPACKET_S10N: /* message and s10n aren't allowed without a valid session */ if (jp->to->user != NULL || jpacket_subtype(jp) != JPACKET__SUBSCRIBED) { jp->aux1 = (void *) ti; mtq_send(NULL,jp->p,&mt_unknown_bounce,(void *) jp); break; } /* fall through here to free the node */ case JPACKET_PRESENCE: if (jpacket_subtype(jp) == JPACKET__AVAILABLE && jp->to->user == NULL) { jp->aux1 = (void *) ti; mtq_send(NULL,jp->p,&mt_presence_unknown,(void *) jp); break; } xmlnode_free(jp->x); } }
int at_iq_gateway(ati ti, jpacket jp) { if(jp->to->user != NULL) { at_bounce(ti, jp, TERROR_NOTALLOWED); return 1; } switch(jpacket_subtype(jp)) { case JPACKET__GET: { xmlnode q; jutil_iqresult(jp->x); q = xmlnode_insert_tag(jp->x,"query"); xmlnode_put_attrib(q,"xmlns",NS_GATEWAY); xmlnode_insert_cdata(xmlnode_insert_tag(q,"desc"),"Enter the user's screenname",-1); xmlnode_insert_tag(q,"prompt"); break; } case JPACKET__SET: { char *user, *id; user = xmlnode_get_tag_data(jp->iq,"prompt"); id = user ? spools(jp->p,at_normalize(user),"@",jp->to->server,jp->p) : NULL; if (id) { xmlnode q; jutil_iqresult(jp->x); q = xmlnode_insert_tag(jp->x,"query"); xmlnode_put_attrib(q,"xmlns",NS_GATEWAY); xmlnode_insert_cdata(xmlnode_insert_tag(q,"prompt"),id,-1); } else jutil_error(jp->x,TERROR_BAD); break; } default: jutil_error(jp->x,TERROR_BAD); break; } at_deliver(ti,jp->x); return 1; }
int at_iq_last(ati ti, jpacket jp) { xmlnode last; xmlnode q; char str[10]; /* XXX I can do last if I track logouts in the XDB... not too hard */ if(jpacket_subtype(jp) != JPACKET__GET) { at_bounce(ti, jp, TERROR_BAD); return 1; } if(jp->to->user != NULL) { at_session s; at_buddy buddy; char *res; s = at_session_find_by_jid(ti, jp->from); if(s == NULL) { at_bounce(ti, jp, TERROR_REGISTER); return 1; } buddy = xhash_get(s->buddies, jp->to->user); if(buddy == NULL) { at_bounce(ti, jp, TERROR_BAD); return 1; } jutil_iqresult(jp->x); last = xmlnode_insert_tag(jp->x, "query"); xmlnode_put_attrib(last,"xmlns",NS_LAST); sprintf(str, "%d", buddy->idle_time); xmlnode_put_attrib(last, "seconds", str); at_deliver(ti,jp->x); return 1; } jutil_iqresult(jp->x); last = xmlnode_insert_tag(jp->x, "query"); xmlnode_put_attrib(last,"xmlns",NS_LAST); sprintf(str, "%d", time(NULL) - ti->start_time); xmlnode_put_attrib(last,"seconds", str); at_deliver(ti,jp->x); return 1; }
void at_bounce(ati ti, jpacket p, terror terr) { char *to, *from; xmlnode err, x = p->x; char code[4]; to = xmlnode_get_attrib(x, "to"); from = xmlnode_get_attrib(x, "from"); xmlnode_put_attrib(x, "from", to); xmlnode_put_attrib(x, "to", from); if(p->type == JPACKET_S10N && jpacket_subtype(p) == JPACKET__SUBSCRIBE) { /* bounce subscriptions only */ xmlnode_put_attrib(x, "type", "unsubscribed"); xmlnode_insert_cdata(xmlnode_insert_tag(x, "status"), terr.msg, -1); at_deliver(ti,x); return; } if(jpacket_subtype(p) == JPACKET__ERROR || p->type == JPACKET_PRESENCE || p->type == JPACKET_S10N) { /* presence/error packets are just dropped */ xmlnode_free(x); return; } xmlnode_put_attrib(x,"type", "error"); err = xmlnode_insert_tag(x, "error"); snprintf(code, 4, "%d", terr.code); xmlnode_put_attrib(err, "code", code); if(terr.msg != NULL) xmlnode_insert_cdata(err, terr.msg, strlen(terr.msg)); at_deliver(ti,x); }
mreturn mod_browse_server(mapi m, void *arg) { xmlnode browse, query, x; if (m->packet->type != JPACKET_IQ) return M_IGNORE; if (jpacket_subtype(m->packet) != JPACKET__GET || !NSCHECK(m->packet->iq, NS_BROWSE) || m->packet->to->resource != NULL) return M_PASS; /* get data from the config file */ if ((browse = js_config(m->si, "browse")) == NULL) return M_PASS; log_debug("handling browse query"); /* build the result IQ */ query = xmlnode_insert_tag(jutil_iqresult(m->packet->x), "service"); xmlnode_put_attrib(query, "xmlns", NS_BROWSE); xmlnode_put_attrib(query, "type", "jabber"); xmlnode_put_attrib(query, "jid", m->packet->to->server); xmlnode_put_attrib(query, "name", xmlnode_get_data(js_config(m->si, "vCard/FN"))); /* pull name from the server vCard */ /* copy in the configured services */ xmlnode_insert_node(query, xmlnode_get_firstchild(browse)); /* list the admin stuff */ if (js_admin_jid(m->si, jid_user(m->packet->from), ADMIN_READ)) { x = xmlnode_insert_tag(query, "item"); xmlnode_put_attrib(x, "jid", spools(xmlnode_pool(x), m->packet->to->server, "/admin", xmlnode_pool(x))); xmlnode_put_attrib(x, "name", "Online Users"); xmlnode_insert_cdata(xmlnode_insert_tag(query, "ns"), NS_ADMIN, -1); } jpacket_reset(m->packet); js_deliver(m->si, m->packet); return M_HANDLED; }
int at_iq_browse(ati ti, jpacket jp) { xmlnode q; if(jpacket_subtype(jp) != JPACKET__GET) { at_bounce(ti, jp, TERROR_BAD); return 1; } if(jp->to->user != NULL) { q = xmlnode_insert_tag(jutil_iqresult(jp->x),"item"); xmlnode_put_attrib(q,"xmlns",NS_BROWSE); xmlnode_put_attrib(q,"category","user"); xmlnode_put_attrib(q,"type","client"); xmlnode_put_attrib(q,"jid",jid_full(jp->to)); xmlnode_put_attrib(q,"name", jp->to->user); at_deliver(ti,jp->x); return 1; } q = xmlnode_insert_tag(jutil_iqresult(jp->x),"item"); xmlnode_put_attrib(q,"xmlns",NS_BROWSE); xmlnode_put_attrib(q,"category","service"); xmlnode_put_attrib(q,"type","aim"); xmlnode_put_attrib(q,"jid",jp->to->server); xmlnode_put_attrib(q,"name",xmlnode_get_tag_data(ti->vcard,"FN")); xmlnode_insert_cdata(xmlnode_insert_tag(q,"ns"),NS_DISCO_INFO,-1); xmlnode_insert_cdata(xmlnode_insert_tag(q,"ns"),NS_DISCO_ITEMS,-1); xmlnode_insert_cdata(xmlnode_insert_tag(q,"ns"),NS_REGISTER,-1); xmlnode_insert_cdata(xmlnode_insert_tag(q,"ns"),NS_GATEWAY,-1); at_deliver(ti,jp->x); // WHY! DAMNIT! WHY? return 1; }
mreturn mod_agents_handler(mapi m, void *arg) { if (m->packet->type != JPACKET_IQ) return M_IGNORE; if (jpacket_subtype(m->packet) != JPACKET__GET) return M_PASS; if (m->s != NULL && (m->packet->to != NULL && j_strcmp(jid_full(m->packet->to), m->packet->from->server) != 0)) return M_PASS; /* for session calls, only answer to=NULL or to=server */ if (NSCHECK(m->packet->iq, NS_AGENT)) return mod_agents_agent(m); if (NSCHECK(m->packet->iq, NS_AGENTS)) return mod_agents_agents(m); return M_PASS; }
result mt_receive(instance i, dpacket d, void *arg) { jpacket jp; mti ti; session s; switch(d->type) { case p_NONE: case p_NORM: jp = jpacket_new(d->x); if (jp->from && jp->from->user && jp->type != JPACKET_UNKNOWN && jpacket_subtype(jp) != JPACKET__ERROR) { mti ti = (mti) arg; session s = mt_session_find(ti,jp->from); lowercase(jp->from->server); lowercase(jp->from->user); if (s != NULL) mt_session_process(s,jp); else mt_unknown_process(ti,jp); } else { log_warn(NULL,"Invalid packet"); xmlnode_free(d->x); } break; default: return r_ERR; } return r_DONE; }
/** Process presence from Jabber */ void it_presence(session s, jpacket jp) { log_debug(ZONE,"Session[%s], handling presence",jid_full(s->id)); switch (jpacket_subtype(jp)) { case JPACKET__PROBE: if (jp->to->user) { UIN_t uin; contact c; uin = it_jid2uin(jp->to); if (j_strcmp(jp->to->server,s->ti->sms_id)==0) { uin = SMS_CONTACT; } if (uin == SMS_CONTACT) c = it_sms_get(s,jp->to->user); else c = it_contact_get(s,uin); if (c != NULL) it_contact_send_presence(c,NULL); else { c = it_unknown_contact_add(s, jp->to->user, uin); if (c != NULL) it_contact_send_presence(c,NULL); } } break; case JPACKET__INVISIBLE: { icqstatus status; char *text; if (jp->to->user) /* presence to groupchat here */ break; /* update users presence */ s->p_db = ppdb_insert(s->p_db,jp->from,jp->x); text = xmlnode_get_tag_data(jp->x,"status"); if (text != NULL) strncpy(s->status_text,text,MAX_STATUS_TEXT); else s->status_text[0] = '\0'; status = ICQ_STATUS_INVISIBLE; if (status != s->status) { s->status = status; /* propagate to C++ backend */ SendStatus(s); } /* echo.... */ /* only when connected */ if (!s->connected) { xmlnode_free(jp->x); return; } xmlnode_put_attrib(jp->x,"from",jid_full(jp->to)); xmlnode_put_attrib(jp->x,"to",jid_full(jid_user(jp->from))); it_deliver(s->ti,jp->x); return; } case JPACKET__AVAILABLE: { icqstatus status; char *text; if (jp->to->user) /* presence to groupchat here */ break; log_debug(ZONE,"presence"); /* update user's presence */ s->p_db = ppdb_insert(s->p_db,jp->from,jp->x); text = xmlnode_get_tag_data(jp->x,"status"); if (text != NULL) { strncpy(s->status_text,text,MAX_STATUS_TEXT); } else s->status_text[0] = '\0'; status = jit_show2status(xmlnode_get_tag_data(jp->x,"show")); if (status != s->status) { s->status = status; /* Always set status regardless of being connected or not */ /* Client class will set this status */ /* after connecting */ SendStatus(s); } /* echo.... */ /* only when connected */ if (!s->connected) { xmlnode_free(jp->x); return; } xmlnode_put_attrib(jp->x,"from",jid_full(jp->to)); xmlnode_put_attrib(jp->x,"to",jid_full(jid_user(jp->from))); it_deliver(s->ti,jp->x); return; } case JPACKET__UNAVAILABLE: if (jp->to->user == NULL) { /* kill the session if there are no available resources left */ s->p_db = ppdb_insert(s->p_db,jp->from,jp->x); if (ppdb_primary(s->p_db,s->id) == NULL){ if (!s->exit_flag) EndClient(s); // will call it_session_end } } default: break; } xmlnode_free(jp->x); }
/** Callback processing incoming Jabber packets. */ result it_receive(instance i, dpacket d, void *arg) { iti ti = (iti) arg; jpacket jp; session s; session_ref alt_s; unsigned char *user; log_debug(ti->i->id,"Packet received: %s\n",xmlnode2str(d->x)); switch(d->type) { case p_ROUTE: { /* ignore */ return r_PASS; } case p_NONE: case p_NORM: jp = jpacket_new(d->x); break; default: return r_ERR; } if (!jp->from ||/* !jp->from->user ||*/ jp->type == JPACKET_UNKNOWN /* || jpacket_subtype(jp) == JPACKET__ERROR */) { /* ignore invalid packets */ xmlnode_free(jp->x); return r_DONE; } /* JID user part should be case insensitive */ /* convert user part of from JID to lower case */ if(jp->from->user != NULL) for(user = jp->from->user; *user != '\0'; user++) if(*user < 128) *user = tolower(*user); /* Mangle "from" JID, save original attribute for XDB conversion */ xmlnode_put_attrib(jp->x, "origfrom", xmlnode_get_attrib(jp->x, "from")); xmlnode_put_attrib(jp->x, "from", jid_full(jp->from)); SEM_LOCK(ti->sessions_sem); s = (session) wpxhash_get(ti->sessions,jid_full(jid_user(jp->from))); alt_s = (session_ref) wpxhash_get(ti->sessions_alt,jp->to->user); if (s != NULL) { if (s->exit_flag) { SEM_UNLOCK(ti->sessions_sem); log_alert("exit flag","message to exiting session"); if (jp->type != JPACKET_PRESENCE){ jutil_error(jp->x,TERROR_NOTFOUND); it_deliver(ti,jp->x); } else xmlnode_free(jp->x); } else if ((alt_s != NULL) && ( (jp->type == JPACKET_MESSAGE) // all messages || ((jp->type == JPACKET_IQ) && (j_strcmp(xmlnode_get_attrib(jp->iq,"xmlns"),NS_VCARD) == -1)) // all IQs except of vCard || (jp->type == JPACKET_PRESENCE) )) { // all presences _targeted_to_specific_user_ // rewriting "to" and "from" and putting packet back on the wire xmlnode_put_attrib(jp->x, "from", jid_full(it_uin2jid(jp->p,s->uin,jp->to->server))); xmlnode_put_attrib(jp->x, "to", jid_full(alt_s->s->orgid)); SEM_UNLOCK(ti->sessions_sem); it_deliver(ti,jp->x); } else { jp->aux1 = (void *) s; mtq_send(s->q,jp->p,it_session_jpacket,(void *) jp); SEM_UNLOCK(ti->sessions_sem); } } else { SEM_UNLOCK(ti->sessions_sem); if(jpacket_subtype(jp)!=JPACKET__ERROR) it_unknown(ti,jp); else xmlnode_free(jp->x); } return r_DONE; }
int at_iq_disco_info(ati ti, jpacket jp) { xmlnode q, info; if(jpacket_subtype(jp) != JPACKET__GET) { at_bounce(ti, jp, TERROR_BAD); return 1; } if(xmlnode_get_attrib(xmlnode_get_tag(jp->x, "query"),"node") != NULL) { at_bounce(ti, jp, TERROR_NOTALLOWED); return 1; } if(jp->to->user != NULL) { q = xmlnode_insert_tag(jutil_iqresult(jp->x),"query"); xmlnode_put_attrib(q,"xmlns",NS_DISCO_INFO); info = xmlnode_insert_tag(q, "identity"); xmlnode_put_attrib(info, "category", "client"); xmlnode_put_attrib(info, "type", "pc"); xmlnode_put_attrib(info, "name", jp->to->user); info = xmlnode_insert_tag(q, "feature"); xmlnode_put_attrib(info, "var", NS_VCARD); info = xmlnode_insert_tag(q, "feature"); xmlnode_put_attrib(info, "var", NS_LAST); info = xmlnode_insert_tag(q, "feature"); xmlnode_put_attrib(info, "var", NS_TIME); info = xmlnode_insert_tag(q, "feature"); xmlnode_put_attrib(info, "var", NS_VERSION); at_deliver(ti,jp->x); return 1; } q = xmlnode_insert_tag(jutil_iqresult(jp->x),"query"); xmlnode_put_attrib(q,"xmlns",NS_DISCO_INFO); info = xmlnode_insert_tag(q, "identity"); xmlnode_put_attrib(info, "category", "gateway"); xmlnode_put_attrib(info, "type", "aim"); xmlnode_put_attrib(info,"name",xmlnode_get_tag_data(ti->vcard,"FN")); info = xmlnode_insert_tag(q, "feature"); xmlnode_put_attrib(info, "var", NS_VCARD); info = xmlnode_insert_tag(q, "feature"); xmlnode_put_attrib(info, "var", NS_LAST); info = xmlnode_insert_tag(q, "feature"); xmlnode_put_attrib(info, "var", NS_TIME); info = xmlnode_insert_tag(q, "feature"); xmlnode_put_attrib(info, "var", NS_VERSION); info = xmlnode_insert_tag(q, "feature"); xmlnode_put_attrib(info, "var", NS_GATEWAY); info = xmlnode_insert_tag(q, "feature"); xmlnode_put_attrib(info, "var", NS_REGISTER); at_deliver(ti,jp->x); return 1; }
/* session thread */ mreturn mod_presence_out(mapi m, void *arg) { xmlnode pnew, delay, pold; modpres mp = (modpres) arg; session cur = NULL; int oldpri, newpri; char *priority; if (m->packet->type != JPACKET_PRESENCE) return M_IGNORE; if (m->packet->to != NULL || jpacket_subtype(m->packet) == JPACKET__PROBE || jpacket_subtype(m->packet) == JPACKET__ERROR) return M_PASS; log_debug("new presence from %s of %s", jid_full(m->s->id), xmlnode2str(m->packet->x)); /* pre-existing conditions (no, we are not an insurance company) */ oldpri = m->s->priority; /* check that the priority is in the valid range */ priority = xmlnode_get_tag_data(m->packet->x, "priority"); if (priority == NULL) { newpri = 0; } else { newpri = j_atoi(priority, 0); if (newpri < -128 || newpri > 127) { log_notice("mod_presence", "got presence with invalid priority value from %s", jid_full(m->s->id)); xmlnode_free(m->packet->x); return M_HANDLED; } } /* invisible mode is special, don't you wish you were special too? */ if (jpacket_subtype(m->packet) == JPACKET__INVISIBLE) { log_debug("handling invisible mode request"); /* if we get this and we're available, it means go unavail first then reprocess this packet, nifty trick :) */ if (oldpri >= -128) { js_session_from(m->s, jpacket_new(jutil_presnew (JPACKET__UNAVAILABLE, NULL, xmlnode_get_tag_data(m->packet->x,"status") ))); js_session_from(m->s, m->packet); return M_HANDLED; } /* now, pretend we come online :) */ /* (this is the handling of the reinjected invisible presence * or an initial invisible presence) */ mp->invisible = 1; mod_presence_roster(m, NULL); /* send out probes to users we are subscribed to */ m->s->priority = newpri; /* store presence in xdb? */ if (mp->conf->pres_to_xdb > 0) mod_presence_store(m); xmlnode_free(m->packet->x); /* we do not broadcast invisible presences without a to attribute */ return M_HANDLED; } /* our new presence */ pnew = xmlnode_dup(m->packet->x); /* store presence in xdb? */ if (mp->conf->pres_to_xdb > 0) mod_presence_store(m); /* stamp the sessions presence */ delay = xmlnode_insert_tag(pnew, "x"); xmlnode_put_attrib(delay, "xmlns", NS_DELAY); xmlnode_put_attrib(delay, "from", jid_full(m->s->id)); xmlnode_put_attrib(delay, "stamp", jutil_timestamp()); /* our old presence */ pold = m->s->presence; m->s->presence = pnew; m->s->priority = jutil_priority(pnew); log_debug("presence oldp %d newp %d", oldpri, m->s->priority); /* if we're going offline now, let everyone know */ if (m->s->priority < -128) { /* jutil_priority returns -129 in case the "type" attribute is missing */ if (!mp->invisible) /* bcc's don't get told if we were invisible */ _mod_presence_broadcast(m->s, mp->conf->bcc, m->packet->x, NULL); _mod_presence_broadcast(m->s, mp->A, m->packet->x, NULL); _mod_presence_broadcast(m->s, mp->I, m->packet->x, NULL); /* reset vars */ mp->invisible = 0; mp->A->next = NULL; mp->I = NULL; xmlnode_free(m->packet->x); xmlnode_free(pold); return M_HANDLED; } /* available presence updates, intersection of A and T */ if (oldpri >= -128 && !mp->invisible) { _mod_presence_broadcast_trusted(m->s, mp->A, m->packet->x); xmlnode_free(m->packet->x); xmlnode_free(pold); return M_HANDLED; } /* at this point we're coming out of the closet */ mp->invisible = 0; /* make sure we get notified for any presence about ourselves */ /* XXX: the following is the original code: it caused existing presences * to be stamped several times and the presence to be sent out twice. pnew = jutil_presnew(JPACKET__PROBE,jid_full(m->s->uid),NULL); xmlnode_put_attrib(pnew,"from",jid_full(m->s->uid)); js_session_from(m->s, jpacket_new(pnew)); */ /* XXX: I think this should be okay as well: */ /* send us all presences of our other resources */ for (cur = m->user->sessions; cur != NULL; cur = cur->next) { pool pool_for_existing_presence = NULL; xmlnode duplicated_presence = NULL; jpacket packet = NULL; /* skip our own session (and sanity check) */ if (cur == m->s || cur->presence == NULL) { continue; } /* send the presence to us: we need a new pool as js_session_to() will free the packet's pool */ pool_for_existing_presence = pool_new(); duplicated_presence = xmlnode_dup_pool(pool_for_existing_presence, cur->presence); xmlnode_put_attrib(duplicated_presence, "to", jid_full(m->user->id)); packet = jpacket_new(duplicated_presence); js_session_to(m->s, packet); } /* probe s10ns and populate A */ mod_presence_roster(m, mp->A); /* we broadcast this baby! */ _mod_presence_broadcast(m->s, mp->conf->bcc, m->packet->x, NULL); _mod_presence_broadcast(m->s, mp->A, m->packet->x, NULL); xmlnode_free(m->packet->x); xmlnode_free(pold); return M_HANDLED; }
mreturn mod_browse_set(mapi m, void *arg) { xmlnode browse, cur; jid id, to; if (m->packet->type != JPACKET_IQ) return M_IGNORE; if (!NSCHECK(m->packet->iq, NS_BROWSE) || jpacket_subtype(m->packet) != JPACKET__SET) return M_PASS; if (m->packet->to != NULL) return M_PASS; /* if its to someone other than ourselves */ log_debug("handling set request %s", xmlnode2str(m->packet->iq)); /* no to implies to ourselves */ if (m->packet->to != NULL) to = m->packet->to; else to = m->user->id; /* if we set to a resource, we need to make sure that resource's browse is in the users browse */ if (to->resource != NULL) { browse = mod_browse_get(m, to); /* get our browse info */ xmlnode_hide_attrib(browse, "xmlns"); /* don't need a ns as a child */ for (cur = xmlnode_get_firstchild(browse); cur != NULL; cur = xmlnode_get_nextsibling(cur)) xmlnode_hide(cur); /* erase all children */ xdb_act(m->si->xc, m->user->id, NS_BROWSE, "insert", spools(m->packet->p, "?jid=", jid_full(to), m->packet->p), browse); /* insert and match replace */ xmlnode_free(browse); } /* get the id of the new browse item */ if ((cur = xmlnode_get_firstchild(m->packet->iq)) == NULL || (id = jid_new(m->packet->p, xmlnode_get_attrib(cur, "jid"))) == NULL) { js_bounce(m->si, m->packet->x, TERROR_NOTACCEPTABLE); return M_HANDLED; } /* insert the new item into the resource it was sent to */ xmlnode_hide_attrib(cur, "xmlns"); /* just in case, to make sure it inserts */ if (xdb_act (m->si->xc, to, NS_BROWSE, "insert", spools(m->packet->p, "?jid=", jid_full(id), m->packet->p), cur)) { js_bounce(m->si, m->packet->x, TERROR_UNAVAIL); return M_HANDLED; } /* if the new data we're inserting is to one of our resources, update that resource's browse */ if (jid_cmpx(m->user->id, id, JID_USER | JID_SERVER) == 0 && id->resource != NULL) { /* get the old */ browse = mod_browse_get(m, id); /* transform the new one into the old one */ xmlnode_put_attrib(cur, "xmlns", NS_BROWSE); xmlnode_insert_node(cur, xmlnode_get_firstchild(browse)); xdb_set(m->si->xc, id, NS_BROWSE, cur); /* replace the resource's browse w/ this one */ xmlnode_free(browse); } /* send response to the user */ jutil_iqresult(m->packet->x); jpacket_reset(m->packet); js_session_to(m->s, m->packet); return M_HANDLED; }
/** Got a subscription request from Jabber */ void it_s10n(session s, jpacket jp) { UIN_t uin; contact c; if (jp->to->user == NULL) { /* ignore s10n to the transport */ xmlnode_free(jp->x); return; } uin = it_jid2uin(jp->to); if (uin == 0 || uin == s->uin) { jutil_error(jp->x,TERROR_BAD); it_deliver(s->ti,jp->x); return; } if (s->connected == 0) { queue_elem queue; /* add to circle queue */ queue = pmalloco(jp->p,sizeof(_queue_elem)); queue->elem = (void *)jp; /* next = NULL */ QUEUE_PUT(s->queue,s->queue_last,queue); return; } /* we're connected, go on */ log_debug(ZONE,"presence packet uin = %d",uin); /* check for SMS_CONTACT */ if (j_strcmp(jp->to->server,s->ti->sms_id)==0) { uin = SMS_CONTACT; } if (uin == SMS_CONTACT) c = it_sms_get(s,jp->to->user); else c = it_contact_get(s,uin); switch (jpacket_subtype(jp)) { case JPACKET__SUBSCRIBE: if (c == NULL) { /* if sms contact */ if (uin == SMS_CONTACT) { /* if not our sms id */ if (j_strcmp(jp->to->server,s->ti->sms_id)) { log_debug(ZONE,"not our sms %s",jp->to->server); xmlnode_free(jp->x); break; } c = it_sms_add(s,jp->to->user); log_debug(ZONE,"sms add"); } else c = it_contact_add(s,uin); } log_debug(ZONE,"subscribe"); it_contact_subscribe(c,NULL); xmlnode_free(jp->x); break; case JPACKET__SUBSCRIBED: /* after asking */ if (c) { it_contact_subscribed(c,jp); log_debug(ZONE,"subscribed"); } xmlnode_free(jp->x); break; case JPACKET__UNSUBSCRIBE: if (c) { /* will remove user from icq contacts inform main jabber roster unsubscribed */ it_contact_unsubscribe(c); log_debug(ZONE,"unsubscribe"); } xmlnode_free(jp->x); break; case JPACKET__UNSUBSCRIBED: /* when icq ask for subscribe we have that contacts in our roster remove contact if exist */ if (c) { it_contact_unsubscribed(c,jp); log_debug(ZONE,"unsubscribed"); } xmlnode_free(jp->x); break; default: xmlnode_free(jp->x); break; } }
mreturn mod_stats_server(mapi m, void *arg) { xmlnode cur; int i; if (m->packet->type != JPACKET_IQ) return M_IGNORE; if (jpacket_subtype(m->packet) != JPACKET__GET) return M_PASS; if (!NSCHECK(m->packet->iq, NS_STATS)) return M_PASS; if (m->packet->to->resource) return M_PASS; /* get data from the config file */ i = 0; if (xmlnode_get_tag(js_config(m->si, "stats"), "allow_all") != NULL) i = 1; log_debug("handling stats get %s", jid_full(m->packet->from)); /* check if admin */ if ((i == 0) && (!js_admin_jid(m->si, jid_user(m->packet->from), ADMIN_READ))) { jutil_error(m->packet->x, TERROR_AUTH); jpacket_reset(m->packet); js_deliver(m->si, m->packet); return M_HANDLED; } /* check if any stat have given iq query */ cur = xmlnode_get_firstchild(m->packet->iq); for (; cur != NULL; cur = xmlnode_get_nextsibling(cur)) { if (xmlnode_get_type(cur) != NTYPE_TAG) continue; break; } if (cur != NULL) cur = xmlnode_get_firstchild(m->packet->iq); jutil_tofrom(m->packet->x); xmlnode_put_attrib(m->packet->x, "type", "result"); /* return available stats */ if (!cur) { for (i = 0; available_stats[i]; i++) { xmlnode_put_attrib(xmlnode_insert_tag (m->packet->iq, "stat"), "name", available_stats[i]); } jpacket_reset(m->packet); js_deliver(m->si, m->packet); return M_HANDLED; } /* return server stats */ /* cur is already first stat */ for (; cur != NULL; cur = xmlnode_get_nextsibling(cur)) { char *name; char buf[31]; int found; if (xmlnode_get_type(cur) != NTYPE_TAG) continue; if (j_strcmp(xmlnode_get_name(cur), "stat") != 0) continue; name = xmlnode_get_attrib(cur, "name"); if (!name) continue; log_debug("get stats for %s", name); found = 0; for (i = 0; available_stats[i]; i++) { if (j_strcmp(available_stats[i], name) != 0) continue; log_debug("stats for %s", name); /* give stats */ found = 1; /* time/uptime */ if (j_strcmp(name, "time/uptime") == 0) { snprintf(buf, 30, "%d", time(NULL) - m->si->stats->started); xmlnode_put_attrib(cur, "value", buf); xmlnode_put_attrib(cur, "units", "seconds"); } /* users/online */ if (j_strcmp(name, "users/online") == 0) { snprintf(buf, 30, "%d", m->si->stats->sessioncount); xmlnode_put_attrib(cur, "value", buf); xmlnode_put_attrib(cur, "units", "users"); } if (j_strcmp(name, "users/max_online_today") == 0) { snprintf(buf, 30, "%d", m->si->stats->session_max_today); xmlnode_put_attrib(cur, "value", buf); xmlnode_put_attrib(cur, "units", "users"); } if (j_strcmp(name, "users/max_online_yesterday") == 0) { snprintf(buf, 30, "%d", m->si->stats-> session_max_yesterday); xmlnode_put_attrib(cur, "value", buf); xmlnode_put_attrib(cur, "units", "users"); } if (j_strcmp(name, "users/registered_today") == 0) { snprintf(buf, 30, "%d", m->si->stats-> users_registered_today); xmlnode_put_attrib(cur, "value", buf); xmlnode_put_attrib(cur, "units", "users"); } if (j_strcmp(name, "users/registered_from_start") == 0) { snprintf(buf, 30, "%d", m->si->stats-> users_registered_from_start); xmlnode_put_attrib(cur, "value", buf); xmlnode_put_attrib(cur, "units", "users"); } if (j_strcmp(name, "bandwidth/packets-in") == 0) { snprintf(buf, 30, "%lu", m->si->stats->packets_in); xmlnode_put_attrib(cur, "value", buf); xmlnode_put_attrib(cur, "units", "packets"); } if (j_strcmp(name, "bandwidth/packets-out") == 0) { snprintf(buf, 30, "%lu", m->si->stats->packets_out); xmlnode_put_attrib(cur, "value", buf); xmlnode_put_attrib(cur, "units", "packets"); } #ifndef WIN32 if (j_strcmp(name, "memory/usage") == 0) { long mem = get_memory_usage(); if (mem > 0) { snprintf(buf, 30, "%lu", mem); xmlnode_put_attrib(cur, "value", buf); xmlnode_put_attrib(cur, "units", "bytes"); } else found = 0; } #endif break; } if (found <= 0) { xmlnode err; err = xmlnode_insert_tag(cur, "error"); xmlnode_put_attrib(err, "code", "404"); xmlnode_insert_cdata(err, "Not Found", -1); } } jpacket_reset(m->packet); js_deliver(m->si, m->packet); return M_HANDLED; }