jabberd2  2.3.3
mod_template_roster.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 /* user template - roster */
31 
32 typedef struct _template_roster_st {
34  const char *filename;
35  time_t mtime;
38 
39 /* union for xhash_iter_get to comply with strict-alias rules for gcc3 */
40 union xhashv
41 {
42  void **val;
44 };
45 
47  struct stat st;
48  FILE *f;
49  long size;
50  char *buf;
51  nad_t nad;
52  int nitems, eitem, ajid, as10n, aname, egroup;
53  item_t item;
54 
55  if(stat(tr->filename, &st) < 0) {
56  log_write(tr->sm->log, LOG_ERR, "couldn't stat roster template %s: %s", tr->filename, strerror(errno));
57  return 1;
58  }
59 
60  if(st.st_mtime <= tr->mtime)
61  return 0;
62 
63  tr->mtime = st.st_mtime;
64 
65  if(tr->items != NULL)
66  xhash_free(tr->items);
67 
68  tr->items = xhash_new(101);
69 
70  f = fopen(tr->filename, "r");
71  if(f == NULL) {
72  log_write(tr->sm->log, LOG_ERR, "couldn't open roster template %s: %s", tr->filename, strerror(errno));
73  return 1;
74  }
75 
76  fseek(f, 0, SEEK_END);
77  size = ftell(f);
78  fseek(f, 0, SEEK_SET);
79 
80  buf = (char *) malloc(sizeof(char) * size);
81 
82  if (fread(buf, 1, size, f) != size || ferror(f)) {
83  log_write(tr->sm->log, LOG_ERR, "couldn't read from roster template %s: %s", tr->filename, strerror(errno));
84  free(buf);
85  fclose(f);
86  return 1;
87  }
88 
89  fclose(f);
90 
91  nad = nad_parse(buf, size);
92  if(nad == NULL) {
93  log_write(tr->sm->log, LOG_ERR, "couldn't parse roster template");
94  free(buf);
95  return 1;
96  }
97 
98  free(buf);
99 
100  if(nad->ecur < 2) {
101  log_write(tr->sm->log, LOG_NOTICE, "roster template has no elements");
102  }
103 
104  nitems = 0;
105  eitem = nad_find_elem(nad, 0, NAD_ENS(nad, 0), "item", 1);
106  while(eitem >= 0) {
107  ajid = nad_find_attr(nad, eitem, -1, "jid", NULL);
108  if(ajid < 0) {
109  log_write(tr->sm->log, LOG_ERR, "roster template has item with no jid, skipping");
110  continue;
111  }
112 
113  item = (item_t) pmalloco(xhash_pool(tr->items), sizeof(struct item_st));
114 
115  item->jid = jid_new(NAD_AVAL(nad, ajid), NAD_AVAL_L(nad, ajid));
116  if(item->jid == NULL) {
117  log_write(tr->sm->log, LOG_ERR, "roster template has item with invalid jid, skipping");
118  continue;
119  }
120  pool_cleanup(xhash_pool(tr->items), (void (*)(void *)) jid_free, item->jid);
121 
122  as10n = nad_find_attr(nad, eitem, -1, "subscription", NULL);
123  if(as10n >= 0) {
124  if(NAD_AVAL_L(nad, as10n) == 2 && strncmp("to", NAD_AVAL(nad, as10n), 2) == 0)
125  item->to = 1;
126  else if(NAD_AVAL_L(nad, as10n) == 4 && strncmp("from", NAD_AVAL(nad, as10n), 4) == 0)
127  item->from = 1;
128  else if(NAD_AVAL_L(nad, as10n) == 4 && strncmp("both", NAD_AVAL(nad, as10n), 4) == 0)
129  item->to = item->from = 1;
130  }
131 
132  aname = nad_find_attr(nad, eitem, -1, "name", NULL);
133  if(aname >= 0)
134  item->name = pstrdupx(xhash_pool(tr->items), NAD_AVAL(nad, aname), NAD_AVAL_L(nad, aname));
135 
136  egroup = nad_find_elem(nad, eitem, NAD_ENS(nad, 0), "group", 1);
137  while(egroup >= 0) {
138  if(NAD_CDATA_L(nad, egroup) <= 0) {
139  log_write(tr->sm->log, LOG_ERR, "roster template has zero-length group, skipping");
140  continue;
141  }
142 
143  item->groups = (const char **) realloc(item->groups, sizeof(char *) * (item->ngroups + 1));
144  item->groups[item->ngroups] = pstrdupx(xhash_pool(tr->items), NAD_CDATA(nad, egroup), NAD_CDATA_L(nad, egroup));
145  item->ngroups++;
146 
147  egroup = nad_find_elem(nad, egroup, NAD_ENS(nad, 0), "group", 0);
148  }
149 
150  if(item->groups != NULL)
151  pool_cleanup(xhash_pool(tr->items), free, item->groups);
152 
153  xhash_put(tr->items, jid_full(item->jid), item);
154 
155  log_debug(ZONE, "loaded roster template item %s, %d groups", jid_full(item->jid), item->ngroups);
156 
157  nitems++;
158 
159  eitem = nad_find_elem(nad, eitem, NAD_ENS(nad, 0), "item", 0);
160  }
161 
162  log_write(tr->sm->log, LOG_NOTICE, "loaded %d items from roster template", nitems);
163 
164  return 0;
165 }
166 
169  os_t os;
170  os_object_t o;
171  char filter[4096];
172  int i;
173 
174  log_debug(ZONE, "saving roster item %s for %s", jid_full(item->jid), jid_user(jid));
175 
176  os = os_new();
177  o = os_object_new(os);
178 
179  os_object_put(o, "jid", jid_full(item->jid), os_type_STRING);
180 
181  if(item->name != NULL)
182  os_object_put(o, "name", item->name, os_type_STRING);
183 
184  os_object_put(o, "to", &item->to, os_type_BOOLEAN);
185  os_object_put(o, "from", &item->from, os_type_BOOLEAN);
186  os_object_put(o, "ask", &item->ask, os_type_INTEGER);
187 
188  snprintf(filter, 4096, "(jid=%zu:%s)", strlen(jid_full(item->jid)), jid_full(item->jid));
189 
190  storage_replace(sm->st, "roster-items", jid_user(jid), filter, os);
191 
192  os_free(os);
193 
194  snprintf(filter, 4096, "(jid=%zu:%s)", strlen(jid_full(item->jid)), jid_full(item->jid));
195 
196  if(item->ngroups == 0) {
197  storage_delete(sm->st, "roster-groups", jid_user(jid), filter);
198  return;
199  }
200 
201  os = os_new();
202 
203  for(i = 0; i < item->ngroups; i++) {
204  o = os_object_new(os);
205 
206  os_object_put(o, "jid", jid_full(item->jid), os_type_STRING);
207  os_object_put(o, "group", item->groups[i], os_type_STRING);
208  }
209 
210  storage_replace(sm->st, "roster-groups", jid_user(jid), filter, os);
211 
212  os_free(os);
213 }
214 
217  item_t item;
218  union xhashv xhv;
219 
220  if(_template_roster_reload(tr) != 0)
221  return 0;
222 
223  log_debug(ZONE, "populating roster with items from template");
224 
225  if(xhash_iter_first(tr->items))
226  do {
227  xhv.item_val = &item;
228  xhash_iter_get(tr->items, NULL, NULL, xhv.val);
229 
230  _template_roster_save_item(tr->sm, jid, item);
231  } while(xhash_iter_next(tr->items));
232 
233  return 0;
234 }
235 
236 static void _template_roster_free(module_t mod) {
238 
239  if(tr->items != NULL)
240  xhash_free(tr->items);
241 
242  free(tr);
243 }
244 
245 DLLEXPORT int module_init(mod_instance_t mi, const char *arg) {
246  module_t mod = mi->mod;
247  const char *filename;
249 
250  if(mod->init) return 0;
251 
252  filename = config_get_one(mod->mm->sm->config, "user.template.roster", 0);
253  if(filename == NULL)
254  return 0;
255 
256  tr = (template_roster_t) calloc(1, sizeof(struct _template_roster_st));
257 
258  tr->sm = mod->mm->sm;
259  tr->filename = filename;
260 
261  mod->private = tr;
262 
265 
266  return 0;
267 }
static sm_t sm
Definition: main.c:33
Definition: nad.h:93
data structures and prototypes for the session manager
#define NAD_CDATA_L(N, E)
Definition: nad.h:186
void xhash_free(xht h)
Definition: xhash.c:241
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
jid_t jid_new(const char *id, int len)
make a new jid
Definition: jid.c:81
single instance of a module in a chain
Definition: sm.h:445
log_t log
log context
Definition: sm.h:199
static int _template_roster_user_create(mod_instance_t mi, jid_t jid)
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
config_t config
config context
Definition: sm.h:197
int init
number of times the module intialiser has been called
Definition: sm.h:415
void log_write(log_t log, int level, const char *msgfmt,...)
Definition: log.c:104
DLLEXPORT int module_init(mod_instance_t mi, const char *arg)
int ask
pending subscription (0 == none, 1 == subscribe, 2 == unsubscribe)
Definition: sm.h:161
int xhash_iter_next(xht h)
Definition: xhash.c:320
mm_t mm
module manager
Definition: sm.h:403
static int _template_roster_reload(template_roster_t tr)
#define DLLEXPORT
Definition: c2s.h:47
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
module_t mod
module that this is an instance of
Definition: sm.h:448
void * private
module private data
Definition: sm.h:417
void ** val
Definition: c2s.h:384
void * pmalloco(pool_t p, int size)
easy safety utility (for creating blank mem for structs, etc)
Definition: pool.c:183
nad_t nad_parse(const char *buf, int len)
create a nad from raw xml
Definition: nad.c:1386
char * pstrdupx(pool_t p, const char *src, int len)
use given size
Definition: pool.c:205
storage_t st
storage subsystem
Definition: sm.h:210
session manager global context
Definition: sm.h:167
void jid_free(jid_t jid)
free a jid
Definition: jid.c:286
static void _template_roster_save_item(sm_t sm, jid_t jid, item_t item)
!!! this is a cut & paste of _roster_save_time - break it out
void xhash_put(xht h, const char *key, void *val)
Definition: xhash.c:163
int ngroups
number of groups in groups array
Definition: sm.h:157
Definition: jid.h:42
int ecur
Definition: nad.h:105
int xhash_iter_get(xht h, const char **key, int *keylen, void **val)
Definition: xhash.c:374
const char ** groups
groups this item is in
Definition: sm.h:155
#define NAD_AVAL_L(N, A)
Definition: nad.h:190
#define log_debug(...)
Definition: log.h:65
roster items
Definition: sm.h:150
#define NAD_AVAL(N, A)
Definition: nad.h:189
struct item_st * item_t
roster items
item_t * item_val
int xhash_iter_first(xht h)
iteration
Definition: xhash.c:311
int from
subscription to this item (they get presence FROM us, they send presence TO us)
Definition: sm.h:159
jid_t jid
id of this item
Definition: sm.h:151
int to
Definition: sm.h:159
pool_t xhash_pool(xht h)
get our pool
Definition: xhash.c:305
#define NAD_CDATA(N, E)
Definition: nad.h:185
#define ZONE
Definition: mio_impl.h:76
session packet handling
Definition: c2s.h:382
const char * config_get_one(config_t c, const char *key, int num)
get config value n for this key
Definition: config.c:277
void(* free)(module_t mod)
called when module is freed
Definition: sm.h:441
xht xhash_new(int prime)
Definition: xhash.c:96
data for a single module
Definition: sm.h:402
int nad_find_attr(nad_t nad, int elem, int ns, const char *name, const char *val)
get a matching attr on this elem, both name and optional val
Definition: nad.c:235
struct _template_roster_st * template_roster_t
int(* user_create)(mod_instance_t mi, jid_t jid)
user-create handler
Definition: sm.h:436
static void _template_roster_free(module_t mod)
#define NAD_ENS(N, E)
Definition: nad.h:196
const char * name
display name
Definition: sm.h:153