#include "jsm.h"
mreturn mod_offline_message(mapi m)
{
session top;
xmlnode cur = NULL, cur2;
char str[10];
if((top = js_session_primary(m->user)) != NULL)
{
js_session_to(top,m->packet);
return M_HANDLED;
}
for(cur = xmlnode_get_firstchild(m->packet->x); cur != NULL; cur = xmlnode_get_nextsibling(cur))
if(NSCHECK(cur,NS_EVENT))
{
if(xmlnode_get_tag(cur,"id") != NULL)
return M_PASS;
if(xmlnode_get_tag(cur,"offline") != NULL)
break;
}
log_debug("mod_offline","handling message for %s",m->user->user);
if((cur2 = xmlnode_get_tag(m->packet->x,"x?xmlns=" NS_EXPIRE)) != NULL)
{
if(j_atoi(xmlnode_get_attrib(cur2, "seconds"),0) == 0)
return M_PASS;
sprintf(str,"%d",(int)time(NULL));
xmlnode_put_attrib(cur2,"stored",str);
}
jutil_delay(m->packet->x,"Offline Storage");
if(xdb_act(m->si->xc, m->user->id, NS_OFFLINE, "insert", NULL, m->packet->x))
return M_PASS;
if(cur != NULL)
{
jutil_tofrom(m->packet->x);
for(cur2 = xmlnode_get_firstchild(m->packet->x); cur2 != NULL; cur2 = xmlnode_get_nextsibling(cur2))
if(cur2 != cur)
xmlnode_hide(cur2);
for(cur2 = xmlnode_get_firstchild(cur); cur2 != NULL; cur2 = xmlnode_get_nextsibling(cur2))
xmlnode_hide(cur2);
xmlnode_insert_tag(cur,"offline");
xmlnode_insert_cdata(xmlnode_insert_tag(cur,"id"),xmlnode_get_attrib(m->packet->x,"id"), -1);
js_deliver(m->si, jpacket_reset(m->packet));
}else{
xmlnode_free(m->packet->x);
}
return M_HANDLED;
}
mreturn mod_offline_handler(mapi m, void *arg)
{
if(m->packet->type == JPACKET_MESSAGE) return mod_offline_message(m);
return M_IGNORE;
}
void mod_offline_out_available(mapi m)
{
xmlnode opts, cur, x;
int now = time(NULL);
int expire, stored, diff;
char str[10];
log_debug("mod_offline","avability established, check for messages");
if((opts = xdb_get(m->si->xc, m->user->id, NS_OFFLINE)) == NULL)
return;
for(cur = xmlnode_get_firstchild(opts); cur != NULL; cur = xmlnode_get_nextsibling(cur))
{
if((x = xmlnode_get_tag(cur,"x?xmlns=" NS_EXPIRE)) != NULL)
{
expire = j_atoi(xmlnode_get_attrib(x,"seconds"),0);
stored = j_atoi(xmlnode_get_attrib(x,"stored"),now);
diff = now - stored;
if(diff >= expire)
{
log_debug(ZONE,"dropping expired message %s",xmlnode2str(cur));
xmlnode_hide(cur);
continue;
}
sprintf(str,"%d",expire - diff);
xmlnode_put_attrib(x,"seconds",str);
xmlnode_hide_attrib(x,"stored");
}
js_session_to(m->s,jpacket_new(xmlnode_dup(cur)));
xmlnode_hide(cur);
}
xdb_set(m->si->xc, m->user->id, NS_OFFLINE, opts);
xmlnode_free(opts);
}
mreturn mod_offline_out(mapi m, void *arg)
{
if(m->packet->type != JPACKET_PRESENCE) return M_IGNORE;
if(js_online(m))
mod_offline_out_available(m);
return M_PASS;
}
mreturn mod_offline_session(mapi m, void *arg)
{
log_debug(ZONE,"session init");
js_mapi_session(es_OUT, m->s, mod_offline_out, NULL);
return M_PASS;
}
void mod_offline(jsmi si)
{
log_debug("mod_offline","init");
js_mapi_register(si,e_OFFLINE, mod_offline_handler, NULL);
js_mapi_register(si,e_SESSION, mod_offline_session, NULL);
}