jabberd2  2.3.1
mod_vacation.c
Go to the documentation of this file.
1 /*
2  * jabberd - Jabber Open Source Server
3  * Copyright (c) 2002-2003 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_VACATION "http://jabber.org/protocol/vacation"
31 static int ns_VACATION = 0;
32 
33 typedef struct _vacation_st {
34  time_t start;
35  time_t end;
36  char *msg;
37 } *vacation_t;
38 
40  module_t mod = mi->mod;
41  vacation_t v = sess->user->module_data[mod->index];
42  int ns, start, end, msg;
43  char dt[30];
44  pkt_t res;
45  os_t os;
46  os_object_t o;
47 
48  /* we only want to play with vacation iq packets */
49  if((pkt->type != pkt_IQ && pkt->type != pkt_IQ_SET) || pkt->ns != ns_VACATION)
50  return mod_PASS;
51 
52  /* if it has a to, throw it out */
53  if(pkt->to != NULL)
54  return -stanza_err_BAD_REQUEST;
55 
56  /* get */
57  if(pkt->type == pkt_IQ) {
58  if(v->msg == NULL) {
59  res = pkt_create(mod->mm->sm, "iq", "result", NULL, NULL);
60  pkt_id(pkt, res);
61  pkt_free(pkt);
62 
63  pkt_sess(res, sess);
64 
65  return mod_HANDLED;
66  }
67 
68  ns = nad_find_scoped_namespace(pkt->nad, uri_VACATION, NULL);
69 
70  if(v->start != 0) {
71  datetime_out(v->start, dt_DATETIME, dt, 30);
72  nad_insert_elem(pkt->nad, 2, ns, "start", dt);
73  } else
74  nad_insert_elem(pkt->nad, 2, ns, "start", NULL);
75 
76  if(v->end != 0) {
77  datetime_out(v->end, dt_DATETIME, dt, 30);
78  nad_insert_elem(pkt->nad, 2, ns, "end", dt);
79  } else
80  nad_insert_elem(pkt->nad, 2, ns, "end", NULL);
81 
82  nad_insert_elem(pkt->nad, 2, ns, "message", v->msg);
83 
84  pkt_tofrom(pkt);
85  nad_set_attr(pkt->nad, 1, -1, "type", "result", 6);
86 
87  pkt_sess(pkt, sess);
88 
89  return mod_HANDLED;
90  }
91 
92  /* set */
93  ns = nad_find_scoped_namespace(pkt->nad, uri_VACATION, NULL);
94 
95  start = nad_find_elem(pkt->nad, 2, ns, "start", 1);
96  end = nad_find_elem(pkt->nad, 2, ns, "end", 1);
97  msg = nad_find_elem(pkt->nad, 2, ns, "message", 1);
98 
99  if(start < 0 || end < 0 || msg < 0) {
100  /* forget */
101  if(v->msg != NULL) {
102  free(v->msg);
103  v->msg = NULL;
104  }
105  v->start = 0;
106  v->end = 0;
107 
108  storage_delete(mi->sm->st, "vacation-settings", jid_user(sess->jid), NULL);
109 
110  res = pkt_create(mod->mm->sm, "iq", "result", NULL, NULL);
111  pkt_id(pkt, res);
112  pkt_free(pkt);
113 
114  pkt_sess(res, sess);
115 
116  return mod_HANDLED;
117  }
118 
119  if(NAD_CDATA_L(pkt->nad, start) > 0) {
120  strncpy(dt, NAD_CDATA(pkt->nad, start), (30 < NAD_CDATA_L(pkt->nad, start) ? 30 : NAD_CDATA_L(pkt->nad, start)));
121  v->start = datetime_in(dt);
122  } else
123  v->start = 0;
124 
125  if(NAD_CDATA_L(pkt->nad, end) > 0) {
126  strncpy(dt, NAD_CDATA(pkt->nad, end), (30 < NAD_CDATA_L(pkt->nad, end) ? 30 : NAD_CDATA_L(pkt->nad, end)));
127  v->end = datetime_in(dt);
128  } else
129  v->end = 0;
130 
131  v->msg = (char *) malloc(sizeof(char) * (NAD_CDATA_L(pkt->nad, msg) + 1));
132  strncpy(v->msg, NAD_CDATA(pkt->nad, msg), NAD_CDATA_L(pkt->nad, msg));
133  v->msg[NAD_CDATA_L(pkt->nad, msg)] = '\0';
134 
135  os = os_new();
136  o = os_object_new(os);
137  os_object_put(o, "start", &v->start, os_type_INTEGER);
138  os_object_put(o, "end", &v->end, os_type_INTEGER);
139  os_object_put(o, "message", v->msg, os_type_STRING);
140 
141  if(storage_replace(mod->mm->sm->st, "vacation-settings", jid_user(sess->user->jid), NULL, os) != st_SUCCESS) {
142  free(v->msg);
143  v->msg = NULL;
144  v->start = 0;
145  v->end = 0;
147  }
148 
149  res = pkt_create(mod->mm->sm, "iq", "result", NULL, NULL);
150  pkt_id(pkt, res);
151  pkt_free(pkt);
152 
153  pkt_sess(res, sess);
154 
155  return mod_HANDLED;
156 }
157 
159  module_t mod = mi->mod;
160  vacation_t v = user->module_data[mod->index];
161  time_t t;
162  pkt_t res;
163 
164  if(v->msg == NULL)
165  return mod_PASS;
166 
167  /* only want messages, and only if they're offline */
168  if(!(pkt->type & pkt_MESSAGE) || user->top != NULL)
169  return mod_PASS;
170 
171  /* reply only to real, human users - they always have full JIDs in 'from' */
172  jid_expand(pkt->from);
173  if(pkt->from->node[0] == '\0' || pkt->from->resource[0] == '\0') {
174  pkt_free(pkt);
175  return mod_HANDLED;
176  }
177 
178  t = time(NULL);
179 
180  if(v->start < t && (t < v->end || v->end == 0)) {
181  res = pkt_create(mod->mm->sm, "message", NULL, jid_full(pkt->from), user->jid->domain);
182  nad_insert_elem(res->nad, 1, NAD_ENS(res->nad, 1), "subject", "Automated reply");
183  nad_insert_elem(res->nad, 1, NAD_ENS(res->nad, 1), "body", v->msg);
184  pkt_router(res);
185 
186  /* !!! remember that we sent this */
187  }
188 
189  return mod_PASS;
190 }
191 
193  if(v->msg != NULL)
194  free(v->msg);
195  free(v);
196 }
197 
199  module_t mod = mi->mod;
200  vacation_t v;
201  os_t os;
202  os_object_t o;
203 
204  v = (vacation_t) calloc(1, sizeof(struct _vacation_st));
205  user->module_data[mod->index] = v;
206 
207  if(storage_get(mod->mm->sm->st, "vacation-settings", jid_user(user->jid), NULL, &os) == st_SUCCESS) {
208  if(os_iter_first(os)) {
209  o = os_iter_object(os);
210 
211  if(os_object_get_time(os, o, "start", &v->start) &&
212  os_object_get_time(os, o, "end", &v->end) &&
213  os_object_get_str(os, o, "message", &v->msg))
214  v->msg = strdup(v->msg);
215  else {
216  v->start = 0;
217  v->end = 0;
218  v->msg = NULL;
219  }
220  }
221 
222  os_free(os);
223  }
224 
225  pool_cleanup(user->p, (void (*))(void *) _vacation_user_free, v);
226 
227  return 0;
228 }
229 
231  log_debug(ZONE, "deleting vacations settings for %s", jid_user(jid));
232 
233  storage_delete(mi->sm->st, "vacation-settings", jid_user(jid), NULL);
234 }
235 
236 static void _vacation_free(module_t mod) {
239 }
240 
241 DLLEXPORT int module_init(mod_instance_t mi, const char *arg) {
242  module_t mod = mi->mod;
243 
244  if(mod->init) return 0;
245 
246  mod->in_sess = _vacation_in_sess;
250  mod->free = _vacation_free; /* mmm good! :) */
251 
254 
255  return 0;
256 }
static mod_ret_t _vacation_in_sess(mod_instance_t mi, sess_t sess, pkt_t pkt)
Definition: mod_vacation.c:39
user_t user
user this session belongs to
Definition: sm.h:255
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:257
data structures and prototypes for the session manager
struct _vacation_st * vacation_t
int nad_insert_elem(nad_t nad, int parent, int ns, const char *name, const char *cdata)
shove in a new child elem after the given one
Definition: nad.c:405
#define NAD_CDATA_L(N, E)
Definition: nad.h:186
static mod_ret_t _vacation_pkt_user(mod_instance_t mi, user_t user, pkt_t pkt)
Definition: mod_vacation.c:158
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
const char * jid_full(jid_t jid)
expand and return the full
Definition: jid.c:347
pkt_t pkt_tofrom(pkt_t pkt)
swap a packet&#39;s to and from attributes
Definition: pkt.c:57
single instance of a module in a chain
Definition: sm.h:445
int nad_find_elem(nad_t nad, int elem, int ns, const char *name, int depth)
locate the next elem at a given depth with an optional matching name
Definition: nad.c:204
int init
number of times the module intialiser has been called
Definition: sm.h:415
info/query (set)
Definition: sm.h:107
static void _vacation_user_free(vacation_t v)
Definition: mod_vacation.c:192
char * resource
Definition: jid.h:46
int index
module index.
Definition: sm.h:407
void jid_expand(jid_t jid)
build user and full if they&#39;re out of date
Definition: jid.c:299
int(* user_load)(mod_instance_t mi, user_t user)
user-load handler
Definition: sm.h:433
mm_t mm
module manager
Definition: sm.h:403
#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:375
sess_t top
top priority session
Definition: sm.h:243
void pool_cleanup(pool_t p, pool_cleanup_t f, void *arg)
public cleanup utils, insert in a way that they are run FIFO, before mem frees
Definition: pool.c:251
sm_t sm
sm context
Definition: sm.h:365
pool_t p
memory pool this user is allocated off
Definition: sm.h:234
module_t mod
module that this is an instance of
Definition: sm.h:448
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
packet summary data wrapper
Definition: sm.h:129
static int ns_VACATION
Definition: mod_vacation.c:31
storage_t st
storage subsystem
Definition: sm.h:210
nad_t nad
nad of the entire packet
Definition: sm.h:146
void datetime_out(time_t t, datetime_t type, char *date, int datelen)
Definition: datetime.c:114
mod_ret_t(* in_sess)(mod_instance_t mi, sess_t sess, pkt_t pkt)
in-sess handler
Definition: sm.h:422
#define stanza_err_BAD_REQUEST
Definition: util.h:367
char * domain
Definition: jid.h:45
Definition: jid.h:42
void pkt_id(pkt_t src, pkt_t dest)
convenience - copy the packet id from src to dest
Definition: pkt.c:353
static int _vacation_user_load(mod_instance_t mi, user_t user)
Definition: mod_vacation.c:198
void pkt_router(pkt_t pkt)
Definition: pkt.c:379
void pkt_free(pkt_t pkt)
Definition: pkt.c:315
#define log_debug(...)
Definition: log.h:65
DLLEXPORT int module_init(mod_instance_t mi, const char *arg)
Definition: mod_active.c:70
void feature_register(sm_t sm, const char *feature)
register a feature
Definition: feature.c:37
info/query (get)
Definition: sm.h:106
static void _vacation_free(module_t mod)
Definition: mod_vacation.c:236
void(* user_delete)(mod_instance_t mi, jid_t jid)
user-delete handler
Definition: sm.h:437
packet was unhandled, should be passed to the next module
Definition: sm.h:339
int ns
iq sub-namespace
Definition: sm.h:142
packet was handled (and freed)
Definition: sm.h:338
There is one instance of this struct per user who is logged in to this c2s instance.
Definition: c2s.h:74
time_t datetime_in(char *date)
Definition: datetime.c:34
void(* free)(module_t mod)
called when module is freed
Definition: sm.h:441
message
Definition: sm.h:95
jid_t to
Definition: sm.h:140
mod_ret_t(* pkt_user)(mod_instance_t mi, user_t user, pkt_t pkt)
pkt-user handler
Definition: sm.h:429
static void _vacation_user_delete(mod_instance_t mi, jid_t jid)
Definition: mod_vacation.c:230
#define NAD_CDATA(N, E)
Definition: nad.h:185
jid_t jid
user jid (user@host)
Definition: sm.h:238
#define ZONE
Definition: mio_impl.h:76
time_t start
Definition: mod_vacation.c:34
data for a single module
Definition: sm.h:402
void ** module_data
per-user module data
Definition: sm.h:248
#define uri_VACATION
Definition: mod_vacation.c:30
pkt_t pkt_create(sm_t sm, const char *elem, const char *type, const char *to, const char *from)
Definition: pkt.c:328
mod_ret_t
module return values
Definition: sm.h:337
sm_t sm
sm context
Definition: sm.h:446
#define stanza_err_INTERNAL_SERVER_ERROR
Definition: util.h:372
void pkt_sess(pkt_t pkt, sess_t sess)
Definition: pkt.c:459
char * node
Definition: jid.h:44
#define NAD_ENS(N, E)
Definition: nad.h:196
data for a single user
Definition: sm.h:233
int nad_find_scoped_namespace(nad_t nad, const char *uri, const char *prefix)
find a namespace in scope
Definition: nad.c:290