jabberd2  2.2.17
mod_iq_last.c
Go to the documentation of this file.
1 /*
2  * jabberd - Jabber Open Source Server
3  * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney,
4  * Ryan Eatmon, Robert Norris
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA
19  */
20 
21 #include "sm.h"
22 
30 #define uri_LAST "jabber:iq:last"
31 static int ns_LAST = 0;
32 
34  module_t mod = mi->mod;
35  char uptime[10];
36 
37  /* we only want to play with iq:last gets */
38  if(pkt->type != pkt_IQ || pkt->ns != ns_LAST)
39  return mod_PASS;
40 
41  snprintf(uptime, 10, "%d", (int) (time(NULL) - (time_t) mod->private));
42  nad_set_attr(pkt->nad, 2, -1, "seconds", uptime, 0);
43 
44  /* tell them */
45  nad_set_attr(pkt->nad, 1, -1, "type", "result", 6);
46  pkt_router(pkt_tofrom(pkt));
47 
48  return mod_HANDLED;
49 }
50 
52  char lasttime[10];
53  time_t t;
54  os_t os;
55  os_object_t o;
56  st_ret_t ret;
57 
58  /* we only want to play with iq:last gets */
59  if(pkt->type != pkt_IQ || pkt->ns != ns_LAST)
60  return mod_PASS;
61 
62  /* make sure they're allowed */
63  if(!pres_trust(user, pkt->from))
64  return -stanza_err_FORBIDDEN;
65 
66  /* If the IQ was sent to a JID with a resource, then XMPP-IM 11.1.1
67  * requires we deliver it if that resource is available
68  */
69  if (*pkt->to->resource != '\0')
70  return mod_PASS;
71 
72  /* If they have an available resource, we should return a query element with a
73  * seconds value of 0
74  */
75  if(user->top != NULL)
76  {
77  nad_set_attr(pkt->nad, 2, -1, "seconds", "0", 0);
78  nad_set_attr(pkt->nad, 1, -1, "type", "result", 6);
79  pkt_router(pkt_tofrom(pkt));
80 
81  return mod_HANDLED;
82  }
83 
84  ret = storage_get(user->sm->st, "logout", jid_user(user->jid), NULL, &os);
85  switch(ret) {
86  case st_SUCCESS:
87  t = 0;
88 
89  if(os_iter_first(os)) {
90  o = os_iter_object(os);
91 
92  os_object_get_time(os, o, "time", &t);
93  }
94 
95  os_free(os);
96 
97  snprintf(lasttime, 10, "%d", (int) (time(NULL) - t));
98  nad_set_attr(pkt->nad, 2, -1, "seconds", lasttime, 0);
99 
100  nad_set_attr(pkt->nad, 1, -1, "type", "result", 6);
101  pkt_router(pkt_tofrom(pkt));
102 
103  return mod_HANDLED;
104 
105  case st_FAILED:
107 
108  case st_NOTFOUND:
110 
111  case st_NOTIMPL:
113  }
114 
115  /* we never get here */
117 }
118 
119 static void _iq_last_sess_end(mod_instance_t mi, sess_t sess) {
120  time_t t;
121  os_t os;
122  os_object_t o;
123 
124  /* store their logout time */
125  t = time(NULL);
126 
127  os = os_new();
128  o = os_object_new(os);
129 
130  os_object_put_time(o, "time", &t);
131 
132  storage_replace(sess->user->sm->st, "logout", jid_user(sess->jid), NULL, os);
133 
134  os_free(os);
135 }
136 
138  log_debug(ZONE, "deleting logout time for %s", jid_user(jid));
139 
140  storage_delete(mi->sm->st, "logout", jid_user(jid), NULL);
141 }
142 
143 static void _iq_last_free(module_t mod) {
144  sm_unregister_ns(mod->mm->sm, uri_LAST);
146 }
147 
149  module_t mod = mi->mod;
150 
151  if(mod->init) return 0;
152 
155  mod->pkt_sm = _iq_last_pkt_sm;
157  mod->free = _iq_last_free;
158 
159  /* startup time */
160  mod->private = (void *) time(NULL);
161 
162  ns_LAST = sm_register_ns(mod->mm->sm, uri_LAST);
163  feature_register(mod->mm->sm, uri_LAST);
164 
165  return 0;
166 }