jabberd2  2.2.16
sm/mod_iq_last.c
Go to the documentation of this file.
00001 /*
00002  * jabberd - Jabber Open Source Server
00003  * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney,
00004  *                    Ryan Eatmon, Robert Norris
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA
00019  */
00020 
00021 #include "sm.h"
00022 
00030 #define uri_LAST    "jabber:iq:last"
00031 static int ns_LAST = 0;
00032 
00033 static mod_ret_t _iq_last_pkt_sm(mod_instance_t mi, pkt_t pkt) {
00034     module_t mod = mi->mod;
00035     char uptime[10];
00036 
00037     /* we only want to play with iq:last gets */
00038     if(pkt->type != pkt_IQ || pkt->ns != ns_LAST)
00039         return mod_PASS;
00040 
00041     snprintf(uptime, 10, "%d", (int) (time(NULL) - (time_t) mod->private));
00042     nad_set_attr(pkt->nad, 2, -1, "seconds", uptime, 0);
00043 
00044     /* tell them */
00045     nad_set_attr(pkt->nad, 1, -1, "type", "result", 6);
00046     pkt_router(pkt_tofrom(pkt));
00047 
00048     return mod_HANDLED;
00049 }
00050 
00051 static mod_ret_t _iq_last_pkt_user(mod_instance_t mi, user_t user, pkt_t pkt) {
00052     char lasttime[10];
00053     time_t t;
00054     os_t os;
00055     os_object_t o;
00056     st_ret_t ret;
00057 
00058     /* we only want to play with iq:last gets */
00059     if(pkt->type != pkt_IQ || pkt->ns != ns_LAST)
00060         return mod_PASS;
00061 
00062     /* make sure they're allowed */
00063     if(!pres_trust(user, pkt->from))
00064         return -stanza_err_FORBIDDEN;
00065 
00066     /* If the IQ was sent to a JID with a resource, then XMPP-IM 11.1.1
00067      * requires we deliver it if that resource is available
00068      */
00069     if (*pkt->to->resource != '\0')
00070     return mod_PASS;
00071 
00072     /* If they have an available resource, we should return a query element with a
00073      * seconds value of 0
00074      */
00075     if(user->top != NULL)
00076     {
00077     nad_set_attr(pkt->nad, 2, -1, "seconds", "0", 0);
00078     nad_set_attr(pkt->nad, 1, -1, "type", "result", 6);
00079     pkt_router(pkt_tofrom(pkt));
00080 
00081         return mod_HANDLED;
00082     }
00083 
00084     ret = storage_get(user->sm->st, "logout", jid_user(user->jid), NULL, &os);
00085     switch(ret) {
00086         case st_SUCCESS:
00087             t = 0;
00088 
00089             if(os_iter_first(os)) {
00090                 o = os_iter_object(os);
00091 
00092                 os_object_get_time(os, o, "time", &t);
00093             }
00094 
00095             os_free(os);
00096 
00097             snprintf(lasttime, 10, "%d", (int) (time(NULL) - t));
00098             nad_set_attr(pkt->nad, 2, -1, "seconds", lasttime, 0);
00099 
00100             nad_set_attr(pkt->nad, 1, -1, "type", "result", 6);
00101             pkt_router(pkt_tofrom(pkt));
00102 
00103             return mod_HANDLED;
00104 
00105         case st_FAILED:
00106             return -stanza_err_INTERNAL_SERVER_ERROR;
00107 
00108         case st_NOTFOUND:
00109             return -stanza_err_SERVICE_UNAVAILABLE;
00110 
00111         case st_NOTIMPL:
00112             return -stanza_err_FEATURE_NOT_IMPLEMENTED;
00113     }
00114 
00115     /* we never get here */
00116     return -stanza_err_INTERNAL_SERVER_ERROR;
00117 }
00118 
00119 static void _iq_last_sess_end(mod_instance_t mi, sess_t sess) {
00120     time_t t;
00121     os_t os;
00122     os_object_t o;
00123 
00124     /* store their logout time */
00125     t = time(NULL);
00126 
00127     os = os_new();
00128     o = os_object_new(os);
00129 
00130     os_object_put_time(o, "time", &t);
00131 
00132     storage_replace(sess->user->sm->st, "logout", jid_user(sess->jid), NULL, os);
00133 
00134     os_free(os);
00135 }
00136 
00137 static void _iq_last_user_delete(mod_instance_t mi, jid_t jid) {
00138     log_debug(ZONE, "deleting logout time for %s", jid_user(jid));
00139 
00140     storage_delete(mi->sm->st, "logout", jid_user(jid), NULL);
00141 }
00142 
00143 static void _iq_last_free(module_t mod) {
00144     sm_unregister_ns(mod->mm->sm, uri_LAST);
00145     feature_unregister(mod->mm->sm, uri_LAST);
00146 }
00147 
00148 DLLEXPORT int module_init(mod_instance_t mi, char *arg) {
00149     module_t mod = mi->mod;
00150 
00151     if(mod->init) return 0;
00152 
00153     mod->sess_end = _iq_last_sess_end;
00154     mod->pkt_user = _iq_last_pkt_user;
00155     mod->pkt_sm = _iq_last_pkt_sm;
00156     mod->user_delete = _iq_last_user_delete;
00157     mod->free = _iq_last_free;
00158 
00159     /* startup time */
00160     mod->private = (void *) time(NULL);
00161 
00162     ns_LAST = sm_register_ns(mod->mm->sm, uri_LAST);
00163     feature_register(mod->mm->sm, uri_LAST);
00164 
00165     return 0;
00166 }