Browse code

core: relocated some folders from root and utils to misc

- utils keeps only the applications related to kamailio c code
- the other are now in misc/tools
- utils/misc/vim moved to misc/extra/
- obsolete and scripts folders moved to misc/

Daniel-Constantin Mierla authored on 07/12/2016 11:46:38
Showing 1 changed files
1 1
deleted file mode 100644
... ...
@@ -1,546 +0,0 @@
1
-/* offline presence authorization "requests" e.g. storing
2
- * watcher information for offline presentities */
3
-
4
-#include <stdio.h>
5
-#include "../../str.h"
6
-#include "../../dprint.h"
7
-#include "../../mem/mem.h"
8
-#include "dlist.h"
9
-#include "presentity.h"
10
-#include "watcher.h"
11
-#include "pdomain.h"
12
-#include "pa_mod.h"
13
-#include "../../parser/parse_from.h"
14
-
15
-#include <libxml/parser.h>
16
-#include <libxml/xpath.h>
17
-
18
-#include <presence/pidf.h>
19
-#include <cds/logger.h>
20
-#include <time.h>
21
-#include "offline_winfo.h"
22
-
23
-#include "winfo_doc.h"
24
-#include "message.h"
25
-
26
-/* ----- Helper and internal functions ----- */
27
-
28
-#define add_str_len(len,p)	if (p) if (p->s) len += p->len
29
-#define set_member_str(buf,len,dst,src)	if (src) if (src->s) { \
30
-			memcpy(buf + len, src->s, src->len); \
31
-			dst.s = buf + len; \
32
-			dst.len = src->len; \
33
-			len += src->len; \
34
-		}
35
-
36
-#define string_val(v,s)	(v).type = DB_STR; \
37
-	(v).val.str_val=s; \
38
-	(v).nul=(s.len == 0); 
39
-
40
-#define time_val(v,t)	(v).type = DB_DATETIME; \
41
-	(v).val.time_val=t;\
42
-	(v).nul=0; 
43
-
44
-#define get_str_val(rvi,dst)	do{if(!rvi.nul){dst.s=(char*)rvi.val.string_val;dst.len=strlen(dst.s);}}while(0)
45
-#define get_blob_val(rvi,dst)	do{if(!rvi.nul){dst=rvi.val.blob_val;}else dst.len=0;}while(0)
46
-#define get_time_val(rvi,dst)	do{if(!rvi.nul){dst=rvi.val.time_val;}}while(0)
47
-#define get_int_val(rvi,dst)	do{if(!rvi.nul){dst=rvi.val.int_val;}else dst=0;}while(0)
48
-
49
-/* expiration time in secs */
50
-int offline_winfo_expiration = 259200;
51
-
52
-/* status of last subscription */
53
-static watcher_status_t last_subscription_status = WS_PENDING; 
54
-
55
-void set_last_subscription_status(watcher_status_t status)
56
-{
57
-	last_subscription_status = status;
58
-}
59
-
60
-watcher_status_t get_last_subscription_status()
61
-{
62
-	return last_subscription_status;
63
-}
64
-
65
-static offline_winfo_t *create_winfo(str *uid, 
66
-		str *wuri, 
67
-		str *events, 
68
-		str *domain,
69
-		str *status)
70
-{
71
-	int len = 0;
72
-	offline_winfo_t *info;
73
-	
74
-	add_str_len(len, uid);
75
-	add_str_len(len, wuri);
76
-	add_str_len(len, events);
77
-	add_str_len(len, domain);
78
-	add_str_len(len, status);
79
-	len += sizeof(offline_winfo_t);
80
-	
81
-	info = (offline_winfo_t*)mem_alloc(len);
82
-	if (info) {
83
-		memset(info, 0, len);
84
-		len = 0;
85
-		set_member_str(info->buffer, len, info->uid, uid);
86
-		set_member_str(info->buffer, len, info->watcher, wuri);
87
-		set_member_str(info->buffer, len, info->events, events);
88
-		set_member_str(info->buffer, len, info->domain, domain);
89
-		set_member_str(info->buffer, len, info->status, status);
90
-		info->created = time(NULL);
91
-		info->expires = info->created + offline_winfo_expiration;
92
-		info->index = -1;
93
-	}
94
-
95
-	return info;
96
-}
97
-
98
-static inline void free_winfo(offline_winfo_t *info)
99
-{
100
-	if (info) mem_free(info);
101
-}
102
-
103
-static inline void free_winfos(offline_winfo_t *info)
104
-{
105
-	offline_winfo_t *n;
106
-	
107
-	while (info) {
108
-		n = info->next;
109
-		free_winfo(info);
110
-		info = n;
111
-	}
112
-}
113
-
114
-static int db_store_winfo(offline_winfo_t *info)
115
-{
116
-	/* ignore duplicit records (should be stored only once!) */
117
-	db_key_t cols[20];
118
-	db_val_t vals[20];
119
-	int n = -1;
120
-	
121
-	if (!pa_db) {
122
-		ERR("database not initialized: set parameter \'use_offline_winfo\' to 1\n");
123
-		return -1;
124
-	}
125
-	
126
-	if (pa_dbf.use_table(pa_db, offline_winfo_table) < 0) {
127
-		LOG(L_ERR, "db_add_watcher: Error in use_table\n");
128
-		return -1;
129
-	}
130
-	
131
-	cols[++n] = col_uid;
132
-	string_val(vals[n], info->uid);
133
-	
134
-	cols[++n] = col_watcher;
135
-	string_val(vals[n], info->watcher);
136
-	
137
-	cols[++n] = col_events;
138
-	string_val(vals[n], info->events);
139
-	
140
-	cols[++n] = col_domain;
141
-	string_val(vals[n], info->domain);
142
-	
143
-	cols[++n] = col_status;
144
-	string_val(vals[n], info->status);
145
-	
146
-	cols[++n] = col_created_on;
147
-	time_val(vals[n], info->created);
148
-	
149
-	cols[++n] = col_expires_on;
150
-	time_val(vals[n], info->expires);
151
-
152
-	/* index ("dbid") is created automaticaly ! */
153
-	
154
-	/* insert new record into database */
155
-	if (pa_dbf.insert(pa_db, cols, vals, n + 1) < 0) {
156
-		return -1;
157
-	}
158
-
159
-	return 0;
160
-}
161
-
162
-static int get_watcher_uri(struct sip_msg* _m, str* uri)
163
-{
164
-	struct sip_uri puri;
165
-	int res = 0;
166
-	
167
-	uri->s = get_from(_m)->uri.s;
168
-	uri->len = get_from(_m)->uri.len;
169
-
170
-	if (parse_uri(uri->s, uri->len, &puri) < 0) {
171
-		LOG(L_ERR, "Error while parsing URI\n");
172
-		return -1;
173
-	}
174
-#if 0	
175
-	uri->s = puri.user.s;
176
-	if ((!uri->s) || (puri.user.len < 1)) {
177
-		uri->s = puri.host.s;
178
-		uri->len = puri.host.len;
179
-		res = 1; /* it is uri without username ! */
180
-	}
181
-#endif
182
-	uri->len = puri.host.s + puri.host.len - uri->s;
183
-	return res;
184
-}
185
-
186
-static int get_events(struct sip_msg* _m, str* events)
187
-{
188
-	char *c;
189
-	str_clear(events);
190
-	
191
-	if (parse_headers(_m, HDR_EVENT_F, 0) == -1) {
192
-		ERR("Error while parsing headers\n");
193
-		return -1;
194
-	}
195
-	if (_m->event) {
196
-		/* parse_event(_m->event); */
197
-		*events = _m->event->body;
198
-		c = str_strchr(events, ';');
199
-		if (c) events->len = c - events->s;
200
-	}
201
-
202
-	return 0;
203
-}
204
-
205
-int remove_expired_winfos()
206
-{
207
-	db_key_t keys[] = { col_expires_on };
208
-	db_val_t vals[1] = { 
209
-		{ DB_DATETIME, 0, { .time_val = time(NULL) } }
210
-	};
211
-	db_op_t ops[] = { OP_LEQ };
212
-	int res = 0;
213
-
214
-	if (!pa_db) {
215
-		ERR("database not initialized: set parameter \'use_offline_winfo\' to 1\n");
216
-		return -1;
217
-	}
218
-	
219
-	if (pa_dbf.use_table(pa_db, offline_winfo_table) < 0) {
220
-		LOG(L_ERR, "db_add_watcher: Error in use_table\n");
221
-		return -1;
222
-	}
223
-
224
-	res = pa_dbf.delete(pa_db, keys, ops, vals, 1);
225
-	if (res < 0 )
226
-		DBG("ERROR cleaning expired offline winfo\n");
227
-	return res;
228
-}
229
-
230
-int db_remove_winfos(offline_winfo_t *info)
231
-{
232
-	db_key_t keys[] = { col_dbid };
233
-	db_val_t vals[1];
234
-	db_op_t ops[] = { OP_EQ };
235
-	int res = 0;
236
-
237
-	if (!pa_db) {
238
-		ERR("database not initialized: set parameter \'use_offline_winfo\' to 1\n");
239
-		return -1;
240
-	}
241
-	
242
-	if (pa_dbf.use_table(pa_db, offline_winfo_table) < 0) {
243
-		LOG(L_ERR, "Error in use_table\n");
244
-		return -1;
245
-	}
246
-
247
-	while (info) {
248
-		vals[0].type = DB_INT;
249
-		vals[0].nul = 0;
250
-		vals[0].val.int_val = info->index;
251
-
252
-		res = pa_dbf.delete(pa_db, keys, ops, vals, 1);
253
-		if (res < 0 )
254
-			DBG("ERROR cleaning expired offline winfo\n");
255
-
256
-		info = info->next;
257
-	}
258
-	return res;
259
-}
260
-
261
-static void send_winfo_cb(struct cell* t, int type, struct tmcb_params* params)
262
-{
263
-	offline_winfo_t *info = NULL;
264
-
265
-	if (!params) {
266
-		ERR("BUG: empty arg\n");
267
-		return;
268
-	}
269
-
270
-	if (params->param) info = (offline_winfo_t *)*(params->param);
271
-	if (!info) {
272
-		ERR("BUG: empty arg\n");
273
-		return;
274
-	}
275
-
276
-	if ((params->code >= 200) && (params->code < 300)) {
277
-		/* delete infos from DB */
278
-		db_remove_winfos(info);
279
-	}
280
-	else 
281
-		ERR("%d response on winfo NOTIFY\n", params->code);
282
-
283
-	
284
-	/* delete infos from memory */
285
-	free_winfos(info);
286
-}
287
-
288
-static int send_winfo(presentity_t *p, offline_winfo_t *info)
289
-{
290
-	watcher_t *w;
291
-	
292
-	if (!p) {
293
-		ERR("BUG: trying to send offline winfo to empty presentity\n");
294
-		return -1;
295
-	}
296
-	
297
-	w = p->first_winfo_watcher;
298
-	while (w) {
299
-		if (w->status == WS_ACTIVE) {
300
-			if (send_winfo_notify_offline(p, w, info, send_winfo_cb, info) == 0) 
301
-				return 0;
302
-		}
303
-		w = w->next;
304
-	}
305
-	
306
-	return -1; /* impossible to send it */
307
-}
308
-
309
-int db_load_winfo(str *uid, str *events, str *domain, offline_winfo_t **infos)
310
-{
311
-	int i, r = 0;
312
-	db_res_t *res = NULL;
313
-	db_key_t result_cols[] = { 
314
-		col_watcher, col_created_on, col_expires_on, col_dbid, col_status
315
-	};
316
-	db_key_t keys[] = { col_uid, col_events };
317
-	db_op_t ops[] = { OP_EQ, OP_EQ };
318
-	db_val_t k_vals[] = { 
319
-		{ DB_STR, 0, { .str_val = *uid } }
320
-	};
321
-	offline_winfo_t *info = NULL;
322
-	offline_winfo_t *last = NULL;
323
-
324
-	*infos = NULL;
325
-	if (pa_dbf.use_table(pa_db, offline_winfo_table) < 0) {
326
-		ERR("Error in use_table\n");
327
-		return -1;
328
-	}
329
-
330
-	if (pa_dbf.query (pa_db, keys, ops, k_vals,
331
-			result_cols, 1, sizeof(result_cols) / sizeof(db_key_t), 
332
-			0, &res) < 0) {
333
-		ERR("Error while querying stored winfos\n");
334
-		r = -1;
335
-		res = NULL;
336
-	}
337
-	if (res) {
338
-		for (i = 0; i < res->n; i++) {
339
-			db_row_t *row = &res->rows[i];
340
-			db_val_t *row_vals = ROW_VALUES(row);
341
-			str watcher = STR_NULL;
342
-			str status = STR_NULL;
343
-			time_t created_on = 0;
344
-			time_t expires_on = 0;
345
-			int index = 0;
346
-
347
-			get_str_val(row_vals[0], watcher);
348
-			get_time_val(row_vals[1], created_on);
349
-			get_time_val(row_vals[2], expires_on);
350
-			get_int_val(row_vals[3], index);
351
-			get_str_val(row_vals[4], status);
352
-			
353
-			info = create_winfo(uid, &watcher, events, domain, &status);
354
-			if (!info) { 
355
-				r = -1; 
356
-				break; 
357
-			}
358
-			info->created = created_on;
359
-			info->expires = expires_on;
360
-			info->index = index;
361
-			
362
-			if (last) last->next = info;
363
-			else *infos = info;
364
-			last = info;
365
-		}
366
-
367
-		pa_dbf.free_result(pa_db, res);
368
-	}
369
-	if ((*infos) && (r != 0)) {
370
-		free_winfos(*infos);
371
-		*infos = NULL;
372
-	}
373
-	
374
-	return r;
375
-}
376
-
377
-/* ----- Handler functions ----- */
378
-#if 0
379
-/* not used due to problems with lost AVP after sending NOTIFY */
380
-static int get_status(str *dst)
381
-{
382
-	avp_t *avp;
383
-	int_str name, val;
384
-	struct search_state s;
385
-	str avp_subscription_status = STR_STATIC_INIT("subscription_status");
386
-
387
-	/* if (!dst) return -1; */
388
-	
389
-	name.s = avp_subscription_status;
390
-	avp = search_first_avp(AVP_CLASS_USER | 
391
-			AVP_TRACK_FROM | AVP_NAME_STR | AVP_VAL_STR, name, &val, 0);
392
-	if (avp) {
393
-		/* don't use default - use value from AVP */
394
-		TRACE("subscription status = %.*s\n", FMT_STR(val.s));
395
-		*dst = val.s;
396
-		return 0;
397
-	} 
398
-	else {
399
-		/* leave default value!! */
400
-		/* TRACE("left default subscription status\n"); */
401
-		TRACE("subscription status AVP not found\n");
402
-	}
403
-	
404
-	return 1;
405
-}
406
-#endif
407
-
408
-static void get_status_str(str *dst)
409
-{
410
-	str s;
411
-	
412
-	switch(get_last_subscription_status()) {
413
-		case WS_ACTIVE:
414
-			s = watcher_status_names[WS_ACTIVE];
415
-			break;
416
-		case WS_REJECTED:
417
-		case WS_PENDING_TERMINATED:
418
-		case WS_TERMINATED:
419
-			s = watcher_status_names[WS_TERMINATED];
420
-			break;
421
-		case WS_PENDING: 
422
-			s = watcher_status_names[WS_PENDING];
423
-			break;
424
-		default: str_clear(&s); /* throw out gcc complains */
425
-	}
426
-	if (dst) *dst = s;
427
-}
428
-
429
-int store_offline_winfo(struct sip_msg* _m, char* _domain, char* _table)
430
-{
431
-	str uid = STR_NULL;
432
-	str wuri = STR_NULL;
433
-	str events = STR_NULL;
434
-	str domain = STR_NULL;
435
-	str status = STR_NULL;
436
-	int res = -1;
437
-	offline_winfo_t *info;
438
-
439
-	if (get_presentity_uid(&uid, _m) < 0) {
440
-		ERR("Error while extracting presentity UID\n");
441
-		return 0; /* ??? impossible to return -1 or 1 */
442
-	}
443
-	get_watcher_uri(_m, &wuri);
444
-	get_events(_m, &events);
445
-	if (_domain) {
446
-		domain.s = _domain;
447
-		domain.len = strlen(_domain);
448
-	}
449
-
450
-	/* get stored subscription status value */
451
-	get_status_str(&status);
452
-	/* TRACE("subscription status is: %.*s\n", FMT_STR(status)); */
453
-
454
-	info = create_winfo(&uid, &wuri, &events, &domain, &status);
455
-	/* store it into database or use internal data structures too? */
456
-	/* better to use only database because of lower memory usage - this 
457
-	 * information could be stored for very long time ! */
458
-	
459
-	db_store_winfo(info);
460
-	
461
-	free_winfo(info); /* don't hold this information in memory ! */
462
-
463
-	return res;
464
-}
465
-
466
-/* send offline winfo as regular watcher info NOTIFY if possible 
467
- * (for presentity got from get_to) */
468
-int dump_offline_winfo(struct sip_msg* _m, char* _domain, char* _events)
469
-{
470
-	struct pdomain* d;
471
-	struct presentity *p;
472
-	str uid = STR_NULL;
473
-	int res = -1;
474
-	str events;
475
-	offline_winfo_t *info;
476
-
477
-	d = (struct pdomain*)_domain;
478
-
479
-	if (get_presentity_uid(&uid, _m) < 0) {
480
-		ERR("Error while extracting presentity UID\n");
481
-		return -1;
482
-	}
483
-	
484
-	if (_events) {
485
-		events.s = _events;
486
-		events.len = strlen(_events);
487
-	}
488
-
489
-	if (db_load_winfo(&uid, &events, d->name, &info) != 0) {
490
-		return -1;
491
-	}
492
-
493
-	if (!info) {
494
-		return 1; /* nothing to do */
495
-	}
496
-
497
-	lock_pdomain(d);
498
-
499
-	if (find_presentity_uid(d, &uid, &p) == 0) {
500
-		/* presentity found */
501
-		if (send_winfo(p, info) == 0) res = 1;
502
-		else res = -1;
503
-	}
504
-
505
-	unlock_pdomain(d);
506
-
507
-	return res;
508
-}
509
-
510
-void offline_winfo_timer(unsigned int ticks, void* param)
511
-{
512
-	remove_expired_winfos();
513
-}
514
-
515
-int check_subscription_status(struct sip_msg* _m, char* _status, char* _x)
516
-{
517
-	watcher_status_t status = (watcher_status_t)_status;
518
-	if (status == get_last_subscription_status()) return 1;
519
-	else return -1;
520
-}
521
-
522
-/* convert char* parameter to watcher_status_t */
523
-int check_subscription_status_fix(void **param, int param_no)
524
-{
525
-	watcher_status_t status = WS_PENDING;
526
-	char *s;
527
-	str ss;
528
-
529
-	if (param_no == 1) {
530
-		s = (char*)*param;
531
-		if (!s) {
532
-			ERR("status not given!\n");
533
-			return -1;
534
-		}
535
-		
536
-		/* TRACE("status name is %s\n", (char*)*param); */
537
-		
538
-		ss.s = s;
539
-		ss.len = strlen(s);
540
-		
541
-		status = watcher_status_from_string(&ss);
542
-		*param = (void*)status;
543
-	}
544
-	return 0;
545
-}
546
-
Browse code

pa(s): obsoleted

Moved pa to obsolete/ because it does not compile (needs upgrade
to the current DB libs) and it does not have a maintainer.

Andrei Pelinescu-Onciul authored on 09/12/2009 09:53:51
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,546 @@
1
+/* offline presence authorization "requests" e.g. storing
2
+ * watcher information for offline presentities */
3
+
4
+#include <stdio.h>
5
+#include "../../str.h"
6
+#include "../../dprint.h"
7
+#include "../../mem/mem.h"
8
+#include "dlist.h"
9
+#include "presentity.h"
10
+#include "watcher.h"
11
+#include "pdomain.h"
12
+#include "pa_mod.h"
13
+#include "../../parser/parse_from.h"
14
+
15
+#include <libxml/parser.h>
16
+#include <libxml/xpath.h>
17
+
18
+#include <presence/pidf.h>
19
+#include <cds/logger.h>
20
+#include <time.h>
21
+#include "offline_winfo.h"
22
+
23
+#include "winfo_doc.h"
24
+#include "message.h"
25
+
26
+/* ----- Helper and internal functions ----- */
27
+
28
+#define add_str_len(len,p)	if (p) if (p->s) len += p->len
29
+#define set_member_str(buf,len,dst,src)	if (src) if (src->s) { \
30
+			memcpy(buf + len, src->s, src->len); \
31
+			dst.s = buf + len; \
32
+			dst.len = src->len; \
33
+			len += src->len; \
34
+		}
35
+
36
+#define string_val(v,s)	(v).type = DB_STR; \
37
+	(v).val.str_val=s; \
38
+	(v).nul=(s.len == 0); 
39
+
40
+#define time_val(v,t)	(v).type = DB_DATETIME; \
41
+	(v).val.time_val=t;\
42
+	(v).nul=0; 
43
+
44
+#define get_str_val(rvi,dst)	do{if(!rvi.nul){dst.s=(char*)rvi.val.string_val;dst.len=strlen(dst.s);}}while(0)
45
+#define get_blob_val(rvi,dst)	do{if(!rvi.nul){dst=rvi.val.blob_val;}else dst.len=0;}while(0)
46
+#define get_time_val(rvi,dst)	do{if(!rvi.nul){dst=rvi.val.time_val;}}while(0)
47
+#define get_int_val(rvi,dst)	do{if(!rvi.nul){dst=rvi.val.int_val;}else dst=0;}while(0)
48
+
49
+/* expiration time in secs */
50
+int offline_winfo_expiration = 259200;
51
+
52
+/* status of last subscription */
53
+static watcher_status_t last_subscription_status = WS_PENDING; 
54
+
55
+void set_last_subscription_status(watcher_status_t status)
56
+{
57
+	last_subscription_status = status;
58
+}
59
+
60
+watcher_status_t get_last_subscription_status()
61
+{
62
+	return last_subscription_status;
63
+}
64
+
65
+static offline_winfo_t *create_winfo(str *uid, 
66
+		str *wuri, 
67
+		str *events, 
68
+		str *domain,
69
+		str *status)
70
+{
71
+	int len = 0;
72
+	offline_winfo_t *info;
73
+	
74
+	add_str_len(len, uid);
75
+	add_str_len(len, wuri);
76
+	add_str_len(len, events);
77
+	add_str_len(len, domain);
78
+	add_str_len(len, status);
79
+	len += sizeof(offline_winfo_t);
80
+	
81
+	info = (offline_winfo_t*)mem_alloc(len);
82
+	if (info) {
83
+		memset(info, 0, len);
84
+		len = 0;
85
+		set_member_str(info->buffer, len, info->uid, uid);
86
+		set_member_str(info->buffer, len, info->watcher, wuri);
87
+		set_member_str(info->buffer, len, info->events, events);
88
+		set_member_str(info->buffer, len, info->domain, domain);
89
+		set_member_str(info->buffer, len, info->status, status);
90
+		info->created = time(NULL);
91
+		info->expires = info->created + offline_winfo_expiration;
92
+		info->index = -1;
93
+	}
94
+
95
+	return info;
96
+}
97
+
98
+static inline void free_winfo(offline_winfo_t *info)
99
+{
100
+	if (info) mem_free(info);
101
+}
102
+
103
+static inline void free_winfos(offline_winfo_t *info)
104
+{
105
+	offline_winfo_t *n;
106
+	
107
+	while (info) {
108
+		n = info->next;
109
+		free_winfo(info);
110
+		info = n;
111
+	}
112
+}
113
+
114
+static int db_store_winfo(offline_winfo_t *info)
115
+{
116
+	/* ignore duplicit records (should be stored only once!) */
117
+	db_key_t cols[20];
118
+	db_val_t vals[20];
119
+	int n = -1;
120
+	
121
+	if (!pa_db) {
122
+		ERR("database not initialized: set parameter \'use_offline_winfo\' to 1\n");
123
+		return -1;
124
+	}
125
+	
126
+	if (pa_dbf.use_table(pa_db, offline_winfo_table) < 0) {
127
+		LOG(L_ERR, "db_add_watcher: Error in use_table\n");
128
+		return -1;
129
+	}
130
+	
131
+	cols[++n] = col_uid;
132
+	string_val(vals[n], info->uid);
133
+	
134
+	cols[++n] = col_watcher;
135
+	string_val(vals[n], info->watcher);
136
+	
137
+	cols[++n] = col_events;
138
+	string_val(vals[n], info->events);
139
+	
140
+	cols[++n] = col_domain;
141
+	string_val(vals[n], info->domain);
142
+	
143
+	cols[++n] = col_status;
144
+	string_val(vals[n], info->status);
145
+	
146
+	cols[++n] = col_created_on;
147
+	time_val(vals[n], info->created);
148
+	
149
+	cols[++n] = col_expires_on;
150
+	time_val(vals[n], info->expires);
151
+
152
+	/* index ("dbid") is created automaticaly ! */
153
+	
154
+	/* insert new record into database */
155
+	if (pa_dbf.insert(pa_db, cols, vals, n + 1) < 0) {
156
+		return -1;
157
+	}
158
+
159
+	return 0;
160
+}
161
+
162
+static int get_watcher_uri(struct sip_msg* _m, str* uri)
163
+{
164
+	struct sip_uri puri;
165
+	int res = 0;
166
+	
167
+	uri->s = get_from(_m)->uri.s;
168
+	uri->len = get_from(_m)->uri.len;
169
+
170
+	if (parse_uri(uri->s, uri->len, &puri) < 0) {
171
+		LOG(L_ERR, "Error while parsing URI\n");
172
+		return -1;
173
+	}
174
+#if 0	
175
+	uri->s = puri.user.s;
176
+	if ((!uri->s) || (puri.user.len < 1)) {
177
+		uri->s = puri.host.s;
178
+		uri->len = puri.host.len;
179
+		res = 1; /* it is uri without username ! */
180
+	}
181
+#endif
182
+	uri->len = puri.host.s + puri.host.len - uri->s;
183
+	return res;
184
+}
185
+
186
+static int get_events(struct sip_msg* _m, str* events)
187
+{
188
+	char *c;
189
+	str_clear(events);
190
+	
191
+	if (parse_headers(_m, HDR_EVENT_F, 0) == -1) {
192
+		ERR("Error while parsing headers\n");
193
+		return -1;
194
+	}
195
+	if (_m->event) {
196
+		/* parse_event(_m->event); */
197
+		*events = _m->event->body;
198
+		c = str_strchr(events, ';');
199
+		if (c) events->len = c - events->s;
200
+	}
201
+
202
+	return 0;
203
+}
204
+
205
+int remove_expired_winfos()
206
+{
207
+	db_key_t keys[] = { col_expires_on };
208
+	db_val_t vals[1] = { 
209
+		{ DB_DATETIME, 0, { .time_val = time(NULL) } }
210
+	};
211
+	db_op_t ops[] = { OP_LEQ };
212
+	int res = 0;
213
+
214
+	if (!pa_db) {
215
+		ERR("database not initialized: set parameter \'use_offline_winfo\' to 1\n");
216
+		return -1;
217
+	}
218
+	
219
+	if (pa_dbf.use_table(pa_db, offline_winfo_table) < 0) {
220
+		LOG(L_ERR, "db_add_watcher: Error in use_table\n");
221
+		return -1;
222
+	}
223
+
224
+	res = pa_dbf.delete(pa_db, keys, ops, vals, 1);
225
+	if (res < 0 )
226
+		DBG("ERROR cleaning expired offline winfo\n");
227
+	return res;
228
+}
229
+
230
+int db_remove_winfos(offline_winfo_t *info)
231
+{
232
+	db_key_t keys[] = { col_dbid };
233
+	db_val_t vals[1];
234
+	db_op_t ops[] = { OP_EQ };
235
+	int res = 0;
236
+
237
+	if (!pa_db) {
238
+		ERR("database not initialized: set parameter \'use_offline_winfo\' to 1\n");
239
+		return -1;
240
+	}
241
+	
242
+	if (pa_dbf.use_table(pa_db, offline_winfo_table) < 0) {
243
+		LOG(L_ERR, "Error in use_table\n");
244
+		return -1;
245
+	}
246
+
247
+	while (info) {
248
+		vals[0].type = DB_INT;
249
+		vals[0].nul = 0;
250
+		vals[0].val.int_val = info->index;
251
+
252
+		res = pa_dbf.delete(pa_db, keys, ops, vals, 1);
253
+		if (res < 0 )
254
+			DBG("ERROR cleaning expired offline winfo\n");
255
+
256
+		info = info->next;
257
+	}
258
+	return res;
259
+}
260
+
261
+static void send_winfo_cb(struct cell* t, int type, struct tmcb_params* params)
262
+{
263
+	offline_winfo_t *info = NULL;
264
+
265
+	if (!params) {
266
+		ERR("BUG: empty arg\n");
267
+		return;
268
+	}
269
+
270
+	if (params->param) info = (offline_winfo_t *)*(params->param);
271
+	if (!info) {
272
+		ERR("BUG: empty arg\n");
273
+		return;
274
+	}
275
+
276
+	if ((params->code >= 200) && (params->code < 300)) {
277
+		/* delete infos from DB */
278
+		db_remove_winfos(info);
279
+	}
280
+	else 
281
+		ERR("%d response on winfo NOTIFY\n", params->code);
282
+
283
+	
284
+	/* delete infos from memory */
285
+	free_winfos(info);
286
+}
287
+
288
+static int send_winfo(presentity_t *p, offline_winfo_t *info)
289
+{
290
+	watcher_t *w;
291
+	
292
+	if (!p) {
293
+		ERR("BUG: trying to send offline winfo to empty presentity\n");
294
+		return -1;
295
+	}
296
+	
297
+	w = p->first_winfo_watcher;
298
+	while (w) {
299
+		if (w->status == WS_ACTIVE) {
300
+			if (send_winfo_notify_offline(p, w, info, send_winfo_cb, info) == 0) 
301
+				return 0;
302
+		}
303
+		w = w->next;
304
+	}
305
+	
306
+	return -1; /* impossible to send it */
307
+}
308
+
309
+int db_load_winfo(str *uid, str *events, str *domain, offline_winfo_t **infos)
310
+{
311
+	int i, r = 0;
312
+	db_res_t *res = NULL;
313
+	db_key_t result_cols[] = { 
314
+		col_watcher, col_created_on, col_expires_on, col_dbid, col_status
315
+	};
316
+	db_key_t keys[] = { col_uid, col_events };
317
+	db_op_t ops[] = { OP_EQ, OP_EQ };
318
+	db_val_t k_vals[] = { 
319
+		{ DB_STR, 0, { .str_val = *uid } }
320
+	};
321
+	offline_winfo_t *info = NULL;
322
+	offline_winfo_t *last = NULL;
323
+
324
+	*infos = NULL;
325
+	if (pa_dbf.use_table(pa_db, offline_winfo_table) < 0) {
326
+		ERR("Error in use_table\n");
327
+		return -1;
328
+	}
329
+
330
+	if (pa_dbf.query (pa_db, keys, ops, k_vals,
331
+			result_cols, 1, sizeof(result_cols) / sizeof(db_key_t), 
332
+			0, &res) < 0) {
333
+		ERR("Error while querying stored winfos\n");
334
+		r = -1;
335
+		res = NULL;
336
+	}
337
+	if (res) {
338
+		for (i = 0; i < res->n; i++) {
339
+			db_row_t *row = &res->rows[i];
340
+			db_val_t *row_vals = ROW_VALUES(row);
341
+			str watcher = STR_NULL;
342
+			str status = STR_NULL;
343
+			time_t created_on = 0;
344
+			time_t expires_on = 0;
345
+			int index = 0;
346
+
347
+			get_str_val(row_vals[0], watcher);
348
+			get_time_val(row_vals[1], created_on);
349
+			get_time_val(row_vals[2], expires_on);
350
+			get_int_val(row_vals[3], index);
351
+			get_str_val(row_vals[4], status);
352
+			
353
+			info = create_winfo(uid, &watcher, events, domain, &status);
354
+			if (!info) { 
355
+				r = -1; 
356
+				break; 
357
+			}
358
+			info->created = created_on;
359
+			info->e