#include "jsm.h"
xmlnode mod_browse_get(mapi m, jid id)
{
xmlnode browse, x;
if(id == NULL)
id = m->user->id;
if((browse = xdb_get(m->si->xc, id, NS_BROWSE)) == NULL)
{
if(id->resource == NULL)
{
browse = xmlnode_new_tag("user");
if((x = xdb_get(m->si->xc, m->user->id, NS_VCARD)) != NULL)
xmlnode_put_attrib(browse,"name",xmlnode_get_tag_data(x,"FN"));
else if((x = xdb_get(m->si->xc, m->user->id, NS_REGISTER)) != NULL)
xmlnode_put_attrib(browse,"name",xmlnode_get_tag_data(x,"name"));
xmlnode_free(x);
}else{
browse = xmlnode_new_tag("item");
}
xmlnode_put_attrib(browse,"xmlns",NS_BROWSE);
xmlnode_put_attrib(browse,"jid",jid_full(id));
xdb_set(m->si->xc, id, NS_BROWSE, browse);
}
return browse;
}
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;
log_debug("mod_browse","handling set request %s",xmlnode2str(m->packet->iq));
if(m->packet->to != NULL)
to = m->packet->to;
else
to = m->user->id;
if(to->resource != NULL)
{
browse = mod_browse_get(m, to);
xmlnode_hide_attrib(browse,"xmlns");
for(cur = xmlnode_get_firstchild(browse); cur != NULL; cur = xmlnode_get_nextsibling(cur))
xmlnode_hide(cur);
xdb_act(m->si->xc, m->user->id, NS_BROWSE, "insert", spools(m->packet->p,"?jid=",jid_full(to),m->packet->p), browse);
xmlnode_free(browse);
}
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;
}
xmlnode_hide_attrib(cur,"xmlns");
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(jid_cmpx(m->user->id, id, JID_USER|JID_SERVER) == 0 && id->resource != NULL)
{
browse = mod_browse_get(m, id);
xmlnode_put_attrib(cur, "xmlns", NS_BROWSE);
xmlnode_insert_node(cur, xmlnode_get_firstchild(browse));
xdb_set(m->si->xc, id, NS_BROWSE, cur);
xmlnode_free(browse);
}
jutil_iqresult(m->packet->x);
jpacket_reset(m->packet);
js_session_to(m->s,m->packet);
return M_HANDLED;
}
mreturn mod_browse_session(mapi m, void *arg)
{
js_mapi_session(es_OUT,m->s,mod_browse_set,NULL);
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;
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("mod_browse","handling query for user %s",m->user->user);
browse = mod_browse_get(m, m->packet->to);
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);
xmlnode_free(ns);
if(js_trust(m->user, m->packet->from))
for(s = m->user->sessions; s != NULL; s = s->next)
{
if(xmlnode_get_tag(browse,spools(m->packet->p,"?jid=",jid_full(s->id),m->packet->p)) != NULL) continue;
cur = xmlnode_insert_tag(browse,"user");
xmlnode_put_attrib(cur,"type", "client");
xmlnode_put_attrib(cur,"jid", jid_full(s->id));
}
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;
}
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;
if((browse = js_config(m->si,"browse")) == NULL)
return M_PASS;
log_debug("mod_browse","handling browse query");
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")));
xmlnode_insert_node(query,xmlnode_get_firstchild(browse));
if(js_admin(m->user, 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;
}
void mod_browse(jsmi si)
{
js_mapi_register(si,e_SESSION,mod_browse_session,NULL);
js_mapi_register(si,e_OFFLINE,mod_browse_reply,NULL);
js_mapi_register(si,e_SERVER,mod_browse_server,NULL);
}