jabberd2  2.3.6
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 
148 DLLEXPORT int module_init(mod_instance_t mi, const char *arg) {
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 }
user_t user
user this session belongs to
Definition: sm.h:256
pkt_type_t type
packet type
Definition: sm.h:138
int sm_register_ns(sm_t sm, const char *uri)
register a new global ns
Definition: sm.c:324
jid_t jid
session jid (user@host/res)
Definition: sm.h:258
static mod_ret_t _iq_last_pkt_sm(mod_instance_t mi, pkt_t pkt)
Definition: mod_iq_last.c:33
data structures and prototypes for the session manager
void sm_unregister_ns(sm_t sm, const char *uri)
unregister a global ns
Definition: sm.c:338
const char * jid_user(jid_t jid)
expand and return the user
Definition: jid.c:339
pkt_t pkt_tofrom(pkt_t pkt)
swap a packet's to and from attributes
Definition: pkt.c:57
single instance of a module in a chain
Definition: sm.h:446
int init
number of times the module intialiser has been called
Definition: sm.h:416
void(* sess_end)(mod_instance_t mi, sess_t sess)
sess-end handler
Definition: sm.h:421
#define stanza_err_FEATURE_NOT_IMPLEMENTED
Definition: util.h:369
sm_t sm
sm context
Definition: sm.h:237
#define stanza_err_FORBIDDEN
Definition: util.h:370
char * resource
Definition: jid.h:46
int pres_trust(user_t user, jid_t jid)
see if the jid is trusted (ie in the roster with s10n="from" or "both")
Definition: pres.c:356
mm_t mm
module manager
Definition: sm.h:404
static mod_ret_t _iq_last_pkt_user(mod_instance_t mi, user_t user, pkt_t pkt)
Definition: mod_iq_last.c:51
#define DLLEXPORT
Definition: c2s.h:47
void nad_set_attr(nad_t nad, int elem, int ns, const char *name, const char *val, int vallen)
create, update, or zap any matching attr on this elem
Definition: nad.c:403
sess_t top
top priority session
Definition: sm.h:244
sm_t sm
sm context
Definition: sm.h:366
static void _iq_last_free(module_t mod)
Definition: mod_iq_last.c:143
module_t mod
module that this is an instance of
Definition: sm.h:449
jid_t from
packet addressing (not used for routing)
Definition: sm.h:140
void feature_unregister(sm_t sm, const char *feature)
unregister feature
Definition: feature.c:45
void * private
module private data
Definition: sm.h:418
packet summary data wrapper
Definition: sm.h:129
storage_t st
storage subsystem
Definition: sm.h:211
nad_t nad
nad of the entire packet
Definition: sm.h:146
static int ns_LAST
Definition: mod_iq_last.c:31
DLLEXPORT int module_init(mod_instance_t mi, const char *arg)
Definition: mod_iq_last.c:148
Definition: jid.h:42
mod_ret_t(* pkt_user)(mod_instance_t mi, user_t user, pkt_t pkt)
pkt-user handler
Definition: sm.h:430
void pkt_router(pkt_t pkt)
Definition: pkt.c:379
#define log_debug(...)
Definition: log.h:65
static void _iq_last_sess_end(mod_instance_t mi, sess_t sess)
Definition: mod_iq_last.c:119
void feature_register(sm_t sm, const char *feature)
register a feature
Definition: feature.c:37
info/query (get)
Definition: sm.h:106
packet was unhandled, should be passed to the next module
Definition: sm.h:340
int ns
iq sub-namespace
Definition: sm.h:142
packet was handled (and freed)
Definition: sm.h:339
There is one instance of this struct per user who is logged in to this c2s instance.
Definition: c2s.h:74
void(* user_delete)(mod_instance_t mi, jid_t jid)
user-delete handler
Definition: sm.h:438
mod_ret_t(* pkt_sm)(mod_instance_t mi, pkt_t pkt)
pkt-sm handler
Definition: sm.h:429
jid_t to
Definition: sm.h:140
jid_t jid
user jid (user@host)
Definition: sm.h:239
#define ZONE
Definition: mio_impl.h:76
#define uri_LAST
Definition: mod_iq_last.c:30
void(* free)(module_t mod)
called when module is freed
Definition: sm.h:442
data for a single module
Definition: sm.h:403
static void _iq_last_user_delete(mod_instance_t mi, jid_t jid)
Definition: mod_iq_last.c:137
mod_ret_t
module return values
Definition: sm.h:338
#define stanza_err_SERVICE_UNAVAILABLE
Definition: util.h:384
sm_t sm
sm context
Definition: sm.h:447
#define stanza_err_INTERNAL_SERVER_ERROR
Definition: util.h:372
data for a single user
Definition: sm.h:234