jabberd2
2.2.16
|
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 }