Browse code

- modified presence and presence_xml to allow using external XCAP servers with the possibility to configure the mode of operation through presence_xml module parameter 'integrated_xcap_server'

git-svn-id: https://openser.svn.sourceforge.net/svnroot/openser/trunk@2628 689a6050-402a-0410-94f2-e92a70836424

Anca Vamanu authored on 22/08/2007 13:32:55
Showing 29 changed files
... ...
@@ -44,14 +44,18 @@ Anca-Maria Vamanu
44 44
 
45 45
    2. Developer's Guide
46 46
 
47
-        2.1. bind_presence(event_api_t* api)
48
-        2.2. add_event(ev_t* event)
49
-        2.3. apply_auth_nbody
50
-        2.4. is_watcher_allowed
51
-        2.5. agg_nbody
52
-        2.6. free_body
53
-        2.7. evs_publ_handl
54
-        2.8. evs_subs_handl
47
+        2.1. bind_presence(presence_api_t* api)
48
+        2.2. add_event
49
+        2.3. get_rules_doc
50
+        2.4. get_auth_status
51
+        2.5. apply_auth_nbody
52
+        2.6. agg_nbody
53
+        2.7. free_body
54
+        2.8. evs_publ_handl
55
+        2.9. evs_subs_handl
56
+        2.10. contains_event
57
+        2.11. get_event_list
58
+        2.12. update_watchers_status
55 59
 
56 60
    3. Frequently Asked Questions
57 61
 
... ...
@@ -69,7 +73,7 @@ Anca-Maria Vamanu
69 73
    1-11. Set fallback2db parameter
70 74
    1-12. handle_publish usage
71 75
    1-13. handle_subscribe usage
72
-   2-1. event_api_t structure
76
+   2-1. presence_api_t structure
73 77
      _________________________________________________________
74 78
 
75 79
 Chapter 1. User's Guide
... ...
@@ -246,7 +250,7 @@ modparam("presence", "max_expires", 3600)
246 250
 1.3.10. server_address (str)
247 251
 
248 252
    The presence server address which will become the value of
249
-   Contact header filed for 200OK replyes to Subscribe and
253
+   Contact header filed for 200OK replies to Subscribe and
250 254
    Publish and in Notify messages.
251 255
 
252 256
    Example 1-10. Set server_address parameter
... ...
@@ -294,7 +298,7 @@ modparam("presence", "fallback2db", 1)
294 298
                 if($hdr(Sender)!= NULL)
295 299
                         handle_publish("$hdr(Sender)");
296 300
                 else
297
-                        handle_publish("");
301
+                        handle_publish();
298 302
                 t_release();
299 303
         }
300 304
 ...
... ...
@@ -333,81 +337,116 @@ Chapter 2. Developer's Guide
333 337
    in other OpenSER modules.
334 338
      _________________________________________________________
335 339
 
336
-2.1. bind_presence(event_api_t* api)
340
+2.1. bind_presence(presence_api_t* api)
337 341
 
338 342
    This function binds the presence modules and fills the
339 343
    structure with one exported function -> add_event, which when
340 344
    called adds a new event to be handled by presence.
341 345
 
342
-   Example 2-1. event_api_t structure
346
+   Example 2-1. presence_api_t structure
343 347
 ...
344
-typedef struct event_api {
348
+typedef struct presence_api {
345 349
         add_event_t add_event;
346
-} event_api_t;
350
+        contains_event_t contains_event;
351
+        get_event_list_t get_event_list;
352
+        update_watchers_t update_watchers_status;
353
+}presence_api_t;
347 354
 ...
348 355
      _________________________________________________________
349 356
 
350
-2.2. add_event(ev_t* event)
357
+2.2. add_event
358
+
359
+   Field type:
360
+...
361
+typedef int (*add_event_t)(pres_ev_t* event);
362
+...
351 363
 
352 364
    This function receives as a parameter a structure with event
353
-   specific information and adds it to presence list.
365
+   specific information and adds it to presence event list.
354 366
 
355 367
    The structure received as a parameter:
356 368
 ...
357
-typedef struct ev
369
+typedef struct pres_ev
358 370
 {
359 371
         str name;
360
-        str* param;         // required param
361
-        str stored_name;
372
+        event_t* evp;
362 373
         str content_type;
363
-        int default_expires; /* the package default expires*/
374
+        int default_expires;
364 375
         int type;
365
-/*      it can be: PUBL_TYPE or WINFO_TYPE */
376
+        int etag_not_new;
377
+        /*
378
+         *  0 - the standard mechanism (allocating new etag
379
+                        for each Publish)
380
+         *  1 - allocating an etag only
381
+                        for an initial Publish
382
+        */
366 383
         int req_auth;
367
-/* flag to mark if the event requires authorization*/
384
+        get_rules_doc_t* get_rules_doc;
368 385
         apply_auth_t*  apply_auth_nbody;
369
-        is_allowed_t*  is_watcher_allowed;
370
-
386
+        is_allowed_t*  get_auth_status;
387
+
388
+        /* an agg_body_t function should be registered
389
+         * if the event permits having multiple published
390
+         * states and requires an aggregation of the information
391
+         * otherwise, this field should be NULL and the last
392
+         * published state is taken when constructing Notify msg
393
+         */
371 394
         agg_nbody_t* agg_nbody;
372 395
         publ_handling_t  * evs_publ_handl;
373 396
         subs_handling_t  * evs_subs_handl;
374
-        free_body_t*    free_body;
375
-
376
-/* this two should not be filed when the structure is given as a
377
-        parmeter for add_event function */
378
-        struct ev* wipeer;
379
-        struct ev* next;
397
+        free_body_t* free_body;
398
+        struct pres_ev* wipeer;
399
+        struct pres_ev* next;
380 400
 
381
-}ev_t;
401
+}pres_ev_t;
382 402
 ...
383 403
      _________________________________________________________
384 404
 
385
-2.3. apply_auth_nbody
386
-
387
-   This parameter should be a function to be calledfor an event
388
-   that requires authorization, when constructing final body. It
389
-   is called only if the req_auth field is not 0.
405
+2.3. get_rules_doc
390 406
 
391 407
    Filed type:
392 408
 ...
393
-typedef int (apply_auth_t)(str* , struct subscription*, str* );
394
-..
409
+typedef int (get_rules_doc_t)(str* user, str* domain, str** rules_doc);
410
+...
411
+
412
+   This function returns the authorization rules document that
413
+   will be used in obtaining the status of the subscription and
414
+   processing the notified body. A reference to the document
415
+   should be put in the auth_rules_doc of the subs_t structure
416
+   given as a parameter to the functions described bellow.
395 417
      _________________________________________________________
396 418
 
397
-2.4. is_watcher_allowed
419
+2.4. get_auth_status
398 420
 
399 421
    This filed is a function to be called for a subscription
400 422
    request to return the state for that subscription according to
401
-   authorization rules. It is called only if the req_auth field
402
-   is not 0.
423
+   authorization rules. In the auth_rules_doc field of the subs_t
424
+   structure received as a parameter should contain the rules
425
+   document of the presentity in case, if it exists.
426
+
427
+   It is called only if the req_auth field is not 0.
403 428
 
404 429
    Filed type:
405 430
 ...
406 431
 typedef int (is_allowed_t)(struct subscription* subs);
407
-..
432
+...
433
+     _________________________________________________________
434
+
435
+2.5. apply_auth_nbody
436
+
437
+   This parameter should be a function to be called for an event
438
+   that requires authorization, when constructing final body. The
439
+   authorization document is taken from the auth_rules_doc field
440
+   of the subs_t structure given as a parameter. It is called
441
+   only if the req_auth field is not 0.
442
+
443
+   Filed type:
444
+...
445
+typedef int (apply_auth_t)(str* , struct subscription*, str** );
446
+...
408 447
      _________________________________________________________
409 448
 
410
-2.5. agg_nbody
449
+2.6. agg_nbody
411 450
 
412 451
    If present, this field marks that the events requires
413 452
    aggregation of states. This function receives a body array and
... ...
@@ -418,14 +457,15 @@ typedef int (is_allowed_t)(struct subscription* subs);
418 457
 
419 458
    Filed type:
420 459
 ...
421
-typedef str* (agg_nbody_t)(str** body_array, int n, int off_index);
460
+typedef str* (agg_nbody_t)(str* pres_user, str* pres_domain,
461
+str** body_array, int n, int off_index);
422 462
 ..
423 463
      _________________________________________________________
424 464
 
425
-2.6. free_body
465
+2.7. free_body
426 466
 
427 467
    This field must be field in if subsequent processing is
428
-   performed on the info from database before beeing inserted in
468
+   performed on the info from database before being inserted in
429 469
    Notify message body(if agg_nbody or apply_auth_nbody fields
430 470
    are filled in). It should match the allocation function used
431 471
    when processing the body.
... ...
@@ -436,17 +476,17 @@ typedef void(free_body_t)(char* body);
436 476
 ..
437 477
      _________________________________________________________
438 478
 
439
-2.7. evs_publ_handl
479
+2.8. evs_publ_handl
440 480
 
441 481
    This function is called when handling Publish requests. Most
442
-   contain body correctitude check.
482
+   contain body correctness check.
443 483
 
444 484
 ...
445 485
 typedef int (publ_handling_t)(struct sip_msg*);
446 486
 ..
447 487
      _________________________________________________________
448 488
 
449
-2.8. evs_subs_handl
489
+2.9. evs_subs_handl
450 490
 
451 491
    It is not compulsory. Should contain event specific handling
452 492
    for Subscription requests.
... ...
@@ -457,6 +497,48 @@ typedef int (subs_handling_t)(struct sip_msg*);
457 497
 ..
458 498
      _________________________________________________________
459 499
 
500
+2.10. contains_event
501
+
502
+   Field type:
503
+..
504
+typedef pres_ev_t* (*contains_event_t)(str* name,
505
+event_t* parsed_event);
506
+...
507
+
508
+   The function parses the event name received as a parameter and
509
+   searches the result in the list. It returns the found event or
510
+   NULL, if not found. If the second argument is an allocated
511
+   event_t* structure it fills it with the result of the parsing.
512
+     _________________________________________________________
513
+
514
+2.11. get_event_list
515
+
516
+   Field type:
517
+...
518
+typedef int (*get_event_list_t) (str** ev_list);
519
+...
520
+
521
+   This function returns a string representation of the events
522
+   registered in presence module.( used for Allowed-Events
523
+   header).
524
+     _________________________________________________________
525
+
526
+2.12. update_watchers_status
527
+
528
+   Field type:
529
+...
530
+typedef int (*update_watchers_t)(str pres_uri, pres_ev_t* ev,
531
+str* rules_doc);
532
+...
533
+
534
+   This function is an external command that can be used to
535
+   announce a change in authorization rules for a presentity. It
536
+   updates the stored status and sends a Notify to the watchers
537
+   whose status has changes. (used by presence_xml module when
538
+   notified through an MI command of a change in an xcap
539
+   document).
540
+     _________________________________________________________
541
+
460 542
 Chapter 3. Frequently Asked Questions
461 543
 
462 544
    3.1. Where can I find more about OpenSER?
... ...
@@ -25,11 +25,15 @@
25 25
  * --------
26 26
  *  2007-04-17  initial version (anca)
27 27
  */
28
-#include "bind_presence.h"
28
+
29
+#include <stdio.h>
30
+#include <stdlib.h>
29 31
 #include "../../dprint.h"
30 32
 #include "../../sr_module.h"
33
+#include "presence.h"
34
+#include "bind_presence.h"
31 35
 
32
-int bind_presence(event_api_t* api)
36
+int bind_presence(presence_api_t* api)
33 37
 {
34 38
 	if (!api) {
35 39
 		LOG(L_ERR, "PRESENCE:bind_notifier: Invalid parameter value\n");
... ...
@@ -39,6 +43,7 @@ int bind_presence(event_api_t* api)
39 43
 	api->add_event = add_event;
40 44
 	api->contains_event= contains_event;
41 45
 	api->get_event_list= get_event_list;
46
+	api->update_watchers_status= update_watchers;
42 47
 	return 0;
43 48
 }
44 49
 
... ...
@@ -31,15 +31,18 @@
31 31
 
32 32
 #include "event_list.h"
33 33
 
34
-typedef struct event_api {
34
+typedef int (*update_watchers_t)(str pres_uri, pres_ev_t* ev, str* rules_doc);
35
+
36
+typedef struct presence_api {
35 37
 	add_event_t add_event;
36 38
 	contains_event_t contains_event;
37 39
 	get_event_list_t get_event_list;
38
-} event_api_t;
40
+	update_watchers_t update_watchers_status;
41
+} presence_api_t;
39 42
 
40
-int bind_presence(event_api_t* api);
43
+int bind_presence(presence_api_t* api);
41 44
 
42
-typedef int (*bind_presence_t)(event_api_t* api);
45
+typedef int (*bind_presence_t)(presence_api_t* api);
43 46
 
44 47
 #endif
45 48
 
... ...
@@ -16,7 +16,7 @@
16 16
    </para>
17 17
  		<section>
18 18
 				<title>
19
-				<function moreinfo="none">bind_presence(event_api_t* api)</function>
19
+				<function moreinfo="none">bind_presence(presence_api_t* api)</function>
20 20
 				</title>
21 21
 			<para>
22 22
 				This function binds the presence modules and fills the structure 
... ...
@@ -24,12 +24,15 @@
24 24
 				new event to be handled by presence.
25 25
 			</para>
26 26
 		<example>
27
-		<title><function>event_api_t</function> structure</title>
27
+		<title><function>presence_api_t</function> structure</title>
28 28
 	<programlisting format="linespecific">
29 29
 ...
30
-typedef struct event_api {
30
+typedef struct presence_api {
31 31
 	add_event_t add_event;
32
-} event_api_t;
32
+	contains_event_t contains_event;
33
+	get_event_list_t get_event_list;
34
+	update_watchers_t update_watchers_status;
35
+}presence_api_t;
33 36
 ...
34 37
 </programlisting>
35 38
 		</example>
... ...
@@ -37,99 +40,146 @@ typedef struct event_api {
37 40
 		</section>
38 41
 	
39 42
 	<section>
40
-			<title>
41
-			<function moreinfo="none">add_event(ev_t* event)</function>
42
-			</title>
43
+		<title>
44
+		<function moreinfo="none">add_event</function>
45
+		</title>
46
+		<para>
47
+			Field type:
48
+			<programlisting format="linespecific">
49
+...
50
+typedef int (*add_event_t)(pres_ev_t* event);
51
+...
52
+		</para>
43 53
 		<para>
44 54
 			This function receives as a parameter a structure with event specific
45
-			information and adds it to presence list.
55
+			information and adds it to presence event list.
46 56
 		</para>
47 57
 		<para>
48 58
 		The structure received as a parameter:
49 59
 	<programlisting format="linespecific">
50 60
 ...
51
-typedef struct ev
61
+typedef struct pres_ev
52 62
 {
53 63
 	str name;
54
-	str* param;         // required param 
55
-	str stored_name;
64
+	event_t* evp;
56 65
 	str content_type;
57
-	int default_expires; /* the package default expires*/
66
+	int default_expires;
58 67
 	int type;
59
-/*	it can be: PUBL_TYPE or WINFO_TYPE */
68
+	int etag_not_new;
69
+	/*
70
+	 *  0 - the standard mechanism (allocating new etag
71
+			for each Publish)
72
+	 *  1 - allocating an etag only
73
+			for an initial Publish 
74
+	*/
60 75
 	int req_auth;
61
-/* flag to mark if the event requires authorization*/	
76
+	get_rules_doc_t* get_rules_doc;
62 77
 	apply_auth_t*  apply_auth_nbody;
63
-	is_allowed_t*  is_watcher_allowed;
78
+	is_allowed_t*  get_auth_status;
64 79
 	
80
+	/* an agg_body_t function should be registered
81
+	 * if the event permits having multiple published
82
+	 * states and requires an aggregation of the information
83
+	 * otherwise, this field should be NULL and the last
84
+	 * published state is taken when constructing Notify msg
85
+	 */
65 86
 	agg_nbody_t* agg_nbody;
66 87
 	publ_handling_t  * evs_publ_handl;
67 88
 	subs_handling_t  * evs_subs_handl;
68
-	free_body_t*    free_body;
69
-
70
-/* this two should not be filed when the structure is given as a
71
-	parmeter for add_event function */
72
-	struct ev* wipeer;			
73
-	struct ev* next;
89
+	free_body_t* free_body;
90
+	struct pres_ev* wipeer;			
91
+	struct pres_ev* next;
74 92
 	
75
-}ev_t;
93
+}pres_ev_t;
76 94
 ...
77 95
 </programlisting>
78 96
 		</section>
97
+<section>
98
+		<title>
99
+			<function moreinfo="none">get_rules_doc</function>
100
+		</title>
101
+		<para>
102
+		
103
+		</para>
104
+		<para>
105
+			Filed type:
106
+			<programlisting format="linespecific">
107
+...
108
+typedef int (get_rules_doc_t)(str* user, str* domain, str** rules_doc);
109
+...
110
+			</programlisting>
111
+		</para>
112
+		<para>
113
+		This function returns the authorization rules document that will be
114
+		used in obtaining the status of the subscription and processing the
115
+		notified body. A reference to the document should be put in the 
116
+		auth_rules_doc of the subs_t structure given as a parameter to the
117
+		functions described bellow.
118
+		</para>
119
+</section>	
79 120
 
80 121
 <section>
81 122
 		<title>
82
-			<function moreinfo="none">apply_auth_nbody</function>
123
+			<function moreinfo="none">get_auth_status</function>
83 124
 		</title>
84 125
 		<para>
85
-			This parameter should be a function to be calledfor an event that requires
86
-			authorization, when constructing final body. It is called only if the
87
-			req_auth field is not 0.
126
+			This filed is a function to be called for a subscription request
127
+			to return the state for that subscription according to
128
+			authorization rules. In the auth_rules_doc field of the subs_t
129
+			structure received as a parameter should contain the rules 
130
+			document of the presentity in case, if it exists.
131
+		</para>
132
+		<para>
133
+			It is called only if the req_auth field is not 0. 
88 134
 		</para>
89 135
 		<para>
90 136
 			Filed type:
91 137
 			<programlisting format="linespecific">
92 138
 ...
93
-typedef int (apply_auth_t)(str* , struct subscription*, str* );
94
-..
139
+typedef int (is_allowed_t)(struct subscription* subs);
140
+...
95 141
 			</programlisting>
96 142
 			</para>
97
-</section>			
143
+</section>	
98 144
 
99 145
 <section>
100 146
 		<title>
101
-			<function moreinfo="none">is_watcher_allowed</function>
147
+			<function moreinfo="none">apply_auth_nbody</function>
102 148
 		</title>
103 149
 		<para>
104
-			This filed is a function to be called for a subscription request to
105
-			return the state for that subscription according to authorization rules.
150
+			This parameter should be a function to be called for an event 
151
+			that requires authorization, when constructing final body. 
152
+			The authorization document is taken from the auth_rules_doc
153
+			field of the subs_t structure given as a parameter.
106 154
 			It is called only if the req_auth field is not 0.
107 155
 		</para>
108 156
 		<para>
109 157
 			Filed type:
110 158
 			<programlisting format="linespecific">
111 159
 ...
112
-typedef int (is_allowed_t)(struct subscription* subs);
113
-..
160
+typedef int (apply_auth_t)(str* , struct subscription*, str** );
161
+...
114 162
 			</programlisting>
115 163
 			</para>
116
-</section>	
164
+</section>			
117 165
 
118 166
 <section>
119 167
 		<title>
120 168
 			<function moreinfo="none">agg_nbody</function>
121 169
 		</title>
122 170
 		<para>
123
-			If present, this field marks that the events requires aggregation of states.
124
-			This function receives a body array and should return the final body.
125
-			If not present, it is considered that the event does not require aggregation and
126
-			the most recent published information is used when constructing Notifies.
171
+			If present, this field marks that the events requires aggregation
172
+			of states. This function receives a body array and should return
173
+			the final body.	If not present, it is considered that the event
174
+			does not require aggregation and the most recent published
175
+			information is used when constructing Notifies.
127 176
 		</para>
128 177
 		<para>
129 178
 		Filed type:
130 179
 			<programlisting format="linespecific">
131 180
 ...
132
-typedef str* (agg_nbody_t)(str** body_array, int n, int off_index);
181
+typedef str* (agg_nbody_t)(str* pres_user, str* pres_domain, 
182
+str** body_array, int n, int off_index);
133 183
 ..
134 184
 			</programlisting>
135 185
 		</para>
... ...
@@ -140,10 +190,11 @@ typedef str* (agg_nbody_t)(str** body_array, int n, int off_index);
140 190
 			<function moreinfo="none">free_body</function>
141 191
 		</title>
142 192
 		<para>
143
-			This field must be field in if subsequent processing is performed on the info
144
-			from database before beeing inserted in Notify message body(if agg_nbody
145
-			or apply_auth_nbody fields are filled in). It should match the allocation 
146
-			function used when processing the body.  
193
+			This field must be field in if subsequent processing is performed
194
+			on the info from database before being inserted in Notify
195
+			message body(if agg_nbody or apply_auth_nbody fields are
196
+			filled in). It should match the allocation function used when
197
+			processing the body.  
147 198
 		</para>
148 199
 		<para>
149 200
 		Filed type:
... ...
@@ -161,7 +212,7 @@ typedef void(free_body_t)(char* body);
161 212
 		</title>
162 213
 		<para>
163 214
 		This function is called when handling Publish requests. Most contain 
164
-		body correctitude check.
215
+		body correctness check.
165 216
 		</para>
166 217
 		<para>
167 218
 			<programlisting format="linespecific">
... ...
@@ -190,6 +241,63 @@ typedef int (subs_handling_t)(struct sip_msg*);
190 241
 			</para>
191 242
 </section>	
192 243
 
244
+<section>
245
+	<title>
246
+	<function moreinfo="none">contains_event</function>
247
+	</title>
248
+	<para>
249
+		Field type:
250
+		<programlisting format="linespecific">
251
+..
252
+typedef pres_ev_t* (*contains_event_t)(str* name,
253
+event_t* parsed_event);
254
+...
255
+	</para>
256
+	<para>
257
+	The function parses the event name received as a parameter and searches
258
+	the result in the list. It returns the found event or NULL, if not found. 
259
+	If the second argument is an allocated event_t* structure it fills it
260
+	with the result of the parsing.
261
+	</para>
262
+</section>
263
+
264
+<section>
265
+	<title>
266
+	<function moreinfo="none">get_event_list</function>
267
+	</title>
268
+	<para>
269
+		Field type:
270
+		<programlisting format="linespecific">
271
+...
272
+typedef int (*get_event_list_t) (str** ev_list);
273
+...
274
+	</para>
275
+	<para>
276
+	This function returns a string representation of the events registered
277
+	in presence module.( used for Allowed-Events header).
278
+	</para>
279
+</section>
280
+
281
+<section>
282
+	<title>
283
+	<function moreinfo="none">update_watchers_status</function>
284
+	</title>
285
+	<para>
286
+		Field type:
287
+		<programlisting format="linespecific">
288
+...
289
+typedef int (*update_watchers_t)(str pres_uri, pres_ev_t* ev,
290
+str* rules_doc);
291
+...
292
+	</para>
293
+	<para>
294
+	This function is an external command that can be used to announce a change
295
+	in authorization rules for a presentity. It updates the stored status and
296
+	sends a Notify to the watchers whose status has changes. (used by
297
+	presence_xml module when notified through an MI command of a change in
298
+	an xcap document).
299
+	</para>
300
+</section>
193 301
 
194 302
 </chapter>
195 303
 
... ...
@@ -263,7 +263,7 @@ modparam("presence", "max_expires", 3600)
263 263
 		<title><varname>server_address</varname> (str)</title>
264 264
 		<para>
265 265
 		The presence server address which will become the value of Contact header filed 
266
-		for 200OK replyes to Subscribe and Publish and in Notify messages.
266
+		for 200OK replies to Subscribe and Publish and in Notify messages.
267 267
 		</para>
268 268
 		<example>
269 269
 		<title>Set <varname>server_address</varname> parameter</title>
... ...
@@ -327,7 +327,7 @@ modparam("presence", "fallback2db", 1)
327 327
 		if($hdr(Sender)!= NULL)
328 328
 			handle_publish("$hdr(Sender)");
329 329
 		else
330
-			handle_publish("");
330
+			handle_publish();
331 331
 		t_release();
332 332
 	} 
333 333
 ...
... ...
@@ -48,14 +48,14 @@ event_t* shm_copy_event(event_t* e)
48 48
 	ev= (event_t*)shm_malloc(sizeof(event_t));
49 49
 	if(ev== NULL)
50 50
 	{
51
-		ERR_MEM("shm_copy_event");
51
+		ERR_MEM("PRESENCE","shm_copy_event");
52 52
 	}
53 53
 	memset(ev, 0, sizeof(event_t));
54 54
 
55 55
 	ev->text.s= (char*)shm_malloc(e->text.len* sizeof(char));
56 56
 	if(ev->text.s== NULL)
57 57
 	{
58
-		ERR_MEM("shm_copy_event");
58
+		ERR_MEM("PRESENCE","shm_copy_event");
59 59
 	}
60 60
 	memcpy(ev->text.s, e->text.s, e->text.len);
61 61
 	ev->text.len= e->text.len;
... ...
@@ -67,7 +67,7 @@ event_t* shm_copy_event(event_t* e)
67 67
 		p2= (param_t*)shm_malloc(size);
68 68
 		if(p2== NULL)
69 69
 		{
70
-			ERR_MEM("shm_copy_event");
70
+			ERR_MEM("PRESENCE","shm_copy_event");
71 71
 		}
72 72
 		memset(p2, 0, size);
73 73
 
... ...
@@ -138,13 +138,13 @@ int add_event(pres_ev_t* event)
138 138
 		ev= (pres_ev_t*)shm_malloc(sizeof(pres_ev_t));
139 139
 		if(ev== NULL)
140 140
 		{
141
-			ERR_MEM("add_event");
141
+			ERR_MEM("PRESENCE","add_event");
142 142
 		}
143 143
 		memset(ev, 0, sizeof(pres_ev_t));
144 144
 		ev->name.s= (char*)shm_malloc(event->name.len* sizeof(char));
145 145
 		if(ev->name.s== NULL)
146 146
 		{
147
-			ERR_MEM("add_events");
147
+			ERR_MEM("PRESENCE","add_events");
148 148
 		}
149 149
 		memcpy(ev->name.s, event->name.s, event->name.len);
150 150
 		ev->name.len= event->name.len;
... ...
@@ -168,7 +168,7 @@ int add_event(pres_ev_t* event)
168 168
 	ev->content_type.s=(char*)shm_malloc(event->content_type.len* sizeof(char)) ;
169 169
 	if(ev->content_type.s== NULL)
170 170
 	{
171
-		ERR_MEM("add_event");
171
+		ERR_MEM("PRESENCE","add_event");
172 172
 	}	
173 173
 	ev->content_type.len= event->content_type.len;
174 174
 	memcpy(ev->content_type.s, event->content_type.s, event->content_type.len);
... ...
@@ -198,7 +198,8 @@ int add_event(pres_ev_t* event)
198 198
 	ev->req_auth= event->req_auth;
199 199
 	ev->agg_nbody= event->agg_nbody;
200 200
 	ev->apply_auth_nbody= event->apply_auth_nbody;
201
-	ev->is_watcher_allowed= event->is_watcher_allowed;
201
+	ev->get_auth_status= event->get_auth_status;
202
+	ev->get_rules_doc= event->get_rules_doc;
202 203
 	ev->evs_publ_handl= event->evs_publ_handl;
203 204
 	ev->etag_not_new= event->etag_not_new;
204 205
 	ev->free_body= event->free_body;
... ...
@@ -53,6 +53,7 @@ typedef str* (agg_nbody_t)(str* pres_user, str* pres_domain, str** body_array, i
53 53
  *				with Expires: 0 has just been received
54 54
  *	*/
55 55
 typedef int (is_allowed_t)(struct subscription* subs);
56
+typedef int (get_rules_doc_t)(str* user, str* domain, str** rules_doc);
56 57
 /* return code rules for is_allowed_t
57 58
  *	< 0  if error occured
58 59
  *	=0	 if no change in status(if no xcap document exists)
... ...
@@ -81,8 +82,9 @@ struct pres_ev
81 82
 	 *  apply_auth_nbody    - alter the body according to authorization rules
82 83
 	 */
83 84
 	int req_auth;
85
+	get_rules_doc_t* get_rules_doc;
84 86
 	apply_auth_t*  apply_auth_nbody;
85
-	is_allowed_t*  is_watcher_allowed;
87
+	is_allowed_t*  get_auth_status;
86 88
 	
87 89
 	/* an agg_body_t function should be registered if the event permits having
88 90
 	 * multiple published states and requires an aggregation of the information
... ...
@@ -44,7 +44,7 @@ shtable_t new_shtable()
44 44
 	htable= (subs_entry_t*)shm_malloc(shtable_size* sizeof(subs_entry_t));
45 45
 	if(htable== NULL)
46 46
 	{
47
-		ERR_MEM("new_shtable");
47
+		ERR_MEM("PRESENCE","new_shtable");
48 48
 	}
49 49
 	memset(htable, 0, shtable_size* sizeof(subs_entry_t));
50 50
 	for(i= 0; i< shtable_size; i++)
... ...
@@ -58,7 +58,7 @@ shtable_t new_shtable()
58 58
 		htable[i].entries= (subs_t*)shm_malloc(sizeof(subs_t));
59 59
 		if(htable[i].entries== NULL)
60 60
 		{
61
-			ERR_MEM("new_shtable");
61
+			ERR_MEM("PRESENCE","new_shtable");
62 62
 		}
63 63
 		memset(htable[i].entries, 0, sizeof(subs_t));
64 64
 		htable[i].entries->next= NULL;
... ...
@@ -137,7 +137,7 @@ subs_t* mem_copy_subs(subs_t* s, int mem_type)
137 137
 	memset(dest, 0, size);
138 138
 	if(dest== NULL)
139 139
 	{
140
-		ERR_MEM("mem_copy_subs");
140
+		ERR_MEM("PRESENCE","mem_copy_subs");
141 141
 	}
142 142
 	size= sizeof(subs_t);
143 143
 
... ...
@@ -303,7 +303,7 @@ phtable_t* new_phtable()
303 303
 	htable= (phtable_t*)shm_malloc(phtable_size* sizeof(phtable_t));
304 304
 	if(htable== NULL)
305 305
 	{
306
-		ERR_MEM("new_phtable");
306
+		ERR_MEM("PRESENCE","new_phtable");
307 307
 	}
308 308
 	memset(htable, 0, phtable_size* sizeof(phtable_t));
309 309
 
... ...
@@ -318,7 +318,7 @@ phtable_t* new_phtable()
318 318
 		htable[i].entries= (pres_entry_t*)shm_malloc(sizeof(pres_entry_t));
319 319
 		if(htable[i].entries== NULL)
320 320
 		{
321
-			ERR_MEM("new_phtable");
321
+			ERR_MEM("PRESENCE","new_phtable");
322 322
 		}
323 323
 		memset(htable[i].entries, 0, sizeof(pres_entry_t));
324 324
 		htable[i].entries->next= NULL;
... ...
@@ -403,7 +403,7 @@ int insert_phtable(str* pres_uri, int event)
403 403
 	if(p== NULL)
404 404
 	{
405 405
 		lock_release(&pres_htable[hash_code].lock);
406
-		ERR_MEM("insert_phtable");
406
+		ERR_MEM("PRESENCE","insert_phtable");
407 407
 	}
408 408
 	memset(p, 0, size);
409 409
 
... ...
@@ -35,7 +35,7 @@
35 35
 #define REMOTE_TYPE   1<<1
36 36
 #define LOCAL_TYPE    1<<2
37 37
 
38
-#define ERR_MEM(func)  LOG(L_ERR, "PRESENCE: %s: ERROR No more memory\n", func);\
38
+#define ERR_MEM(module, func)  LOG(L_ERR, "%s:%s:ERROR No more memory\n", module,func);\
39 39
 						goto error
40 40
 
41 41
 #define CONT_COPY(buf, dest, source)\
... ...
@@ -306,7 +306,7 @@ int get_wi_subs_db(subs_t* subs, watcher_t** watchers)
306 306
 		w= (watcher_t*)pkg_malloc(sizeof(watcher_t));
307 307
 		if(w== NULL)
308 308
 		{
309
-			ERR_MEM("get_wi_subs_db");
309
+			ERR_MEM("PRESENCE","get_wi_subs_db");
310 310
 		}
311 311
 		w->status= row_vals[status_col].val.int_val;
312 312
 		if(uandd_to_uri(from_user, from_domain, &w->uri)<0)
... ...
@@ -364,7 +364,7 @@ str* get_wi_notify_body(subs_t* subs, subs_t* watcher_subs)
364 364
 	watchers= (watcher_t*)pkg_malloc(sizeof(watcher_t));
365 365
 	if(watchers== NULL)
366 366
 	{
367
-		ERR_MEM("get_wi_notify_body");
367
+		ERR_MEM("PRESENCE","get_wi_notify_body");
368 368
 	}
369 369
 	memset(watchers, 0, sizeof(watcher_t));
370 370
 
... ...
@@ -373,7 +373,7 @@ str* get_wi_notify_body(subs_t* subs, subs_t* watcher_subs)
373 373
 		w= (watcher_t *)pkg_malloc(sizeof(watcher_t));
374 374
 		if(w== NULL)
375 375
 		{
376
-			ERR_MEM("get_wi_notify_body");
376
+			ERR_MEM("PRESENCE","get_wi_notify_body");
377 377
 		}
378 378
 		memset(w, 0, sizeof(watcher_t));
379 379
 
... ...
@@ -391,7 +391,7 @@ str* get_wi_notify_body(subs_t* subs, subs_t* watcher_subs)
391 391
 		{
392 392
 			pkg_free(w->uri.s);
393 393
 			pkg_free(w);
394
-			ERR_MEM("get_wi_notify_body");
394
+			ERR_MEM("PRESENCE","get_wi_notify_body");
395 395
 		}
396 396
 		to64frombits((unsigned char *)w->id.s,
397 397
 				(const unsigned char*)w->uri.s, w->uri.len );
... ...
@@ -447,7 +447,7 @@ str* get_wi_notify_body(subs_t* subs, subs_t* watcher_subs)
447 447
 			if(w== NULL)
448 448
 			{
449 449
 				lock_release(&subs_htable[hash_code].lock);
450
-				ERR_MEM("get_wi_notify_body");
450
+				ERR_MEM("PRESENCE","get_wi_notify_body");
451 451
 			}
452 452
 			w->status= s->status;
453 453
 			if(uandd_to_uri(s->from_user, s->from_domain, &w->uri)<0)
... ...
@@ -931,6 +931,13 @@ int get_subs_db(str* pres_uri, pres_ev_t* event, str* sender,
931 931
 	query_vals[n_query_cols].val.str_val = event->name;
932 932
 	n_query_cols++;
933 933
 
934
+	query_cols[n_query_cols] = "status";
935
+	query_ops[n_query_cols] = OP_EQ;
936
+	query_vals[n_query_cols].type = DB_INT;
937
+	query_vals[n_query_cols].nul = 0;
938
+	query_vals[n_query_cols].val.int_val = ACTIVE_STATUS;
939
+	n_query_cols++;
940
+
934 941
 	if(sender)
935 942
 	{	
936 943
 		DBG("PRESENCE:get_subs_db: Should not send Notify to: [uri]= %.*s\n",
... ...
@@ -1069,9 +1076,14 @@ int update_in_list(subs_t* s, subs_t* s_array, int n)
1069 1076
 	subs_t* ls;
1070 1077
 
1071 1078
 	ls= s_array->next;
1072
-
1079
+	DBG("PRESENCE:update_in_list....n= %d\n", n);
1073 1080
 	for(i = 0; i< n; i++)
1074 1081
 	{
1082
+		if(ls== NULL)
1083
+		{
1084
+			LOG(L_ERR, "PRESENCE:update_in_list: ERROR wrong records count\n");
1085
+			return -1;
1086
+		}
1075 1087
 		if(ls->event== s->event && 
1076 1088
 		ls->pres_uri.len== s->pres_uri.len &&
1077 1089
 		strncmp(ls->pres_uri.s, s->pres_uri.s, s->pres_uri.len)==0 &&
... ...
@@ -1098,12 +1110,13 @@ subs_t* get_subs_dialog(str* pres_uri, pres_ev_t* event, str* sender)
1098 1110
 	unsigned int hash_code;
1099 1111
 	subs_t* s= NULL, *s_new;
1100 1112
 	subs_t* s_array= NULL;
1101
-	int n;
1102
-
1113
+	int n= 0;
1114
+	
1115
+	/* get only active subscriptions */
1103 1116
 	s_array= (subs_t*)pkg_malloc(sizeof(subs_t));
1104 1117
 	if(s_array== NULL)
1105 1118
 	{
1106
-		ERR_MEM("get_subs_dialog");
1119
+		ERR_MEM("PRESENCE","get_subs_dialog");
1107 1120
 	}
1108 1121
 	memset(s_array, 0, sizeof(subs_t));
1109 1122
 
... ...
@@ -1138,7 +1151,7 @@ subs_t* get_subs_dialog(str* pres_uri, pres_ev_t* event, str* sender)
1138 1151
 			
1139 1152
 			if(s->db_flag== UPDATEDB_FLAG)
1140 1153
 			{
1141
-				if(update_in_list(s, s_array, n)< 0)
1154
+				if(n>0 && update_in_list(s, s_array, n)< 0)
1142 1155
 				{
1143 1156
 					LOG(L_ERR, "PRESENCE: get_subs_dialog: ERROR"
1144 1157
 							" updating subscription in list\n");
... ...
@@ -1149,7 +1162,8 @@ subs_t* get_subs_dialog(str* pres_uri, pres_ev_t* event, str* sender)
1149 1162
 			}
1150 1163
 		}
1151 1164
 
1152
-		if(s->event== event && s->pres_uri.len== pres_uri->len &&
1165
+		if(s->status== ACTIVE_STATUS && 
1166
+			s->event== event && s->pres_uri.len== pres_uri->len &&
1153 1167
 			strncmp(s->pres_uri.s, pres_uri->s, pres_uri->len)== 0)
1154 1168
 		{
1155 1169
 			if(sender && sender->len== s->contact.len && 
... ...
@@ -1178,7 +1192,7 @@ error:
1178 1192
 	
1179 1193
 }
1180 1194
 
1181
-int publ_notify(presentity_t* p, str* body, str* offline_etag)
1195
+int publ_notify(presentity_t* p, str* body, str* offline_etag, str* rules_doc)
1182 1196
 {
1183 1197
 	str* notify_body = NULL;
1184 1198
 	subs_t* subs_array= NULL, *s= NULL;
... ...
@@ -1223,6 +1237,7 @@ int publ_notify(presentity_t* p, str* body, str* offline_etag)
1223 1237
 	s= subs_array->next;
1224 1238
 	while(s)
1225 1239
 	{
1240
+		s->auth_rules_doc= rules_doc;
1226 1241
 		if(notify(s, NULL, notify_body?notify_body:body, 0)< 0 )
1227 1242
 		{
1228 1243
 			LOG(L_ERR, "PRESENCE: publ_notify: Could not send notify for"
... ...
@@ -1241,7 +1256,7 @@ done:
1241 1256
 	{
1242 1257
 		if(notify_body->s)
1243 1258
 		{
1244
-			if(	p->event->agg_nbody== NULL && 	p->event->apply_auth_nbody== NULL)
1259
+			if(	p->event->agg_nbody== NULL && p->event->apply_auth_nbody== NULL)
1245 1260
 				pkg_free(notify_body->s);
1246 1261
 			else
1247 1262
 				p->event->free_body(notify_body->s);
... ...
@@ -1340,8 +1355,10 @@ int send_notify_request(subs_t* subs, subs_t * watcher_subs,
1340 1355
 	if(n_body!= NULL && subs->status== ACTIVE_STATUS)
1341 1356
 	{
1342 1357
 		if( subs->event->req_auth)
1343
-		{	
1344
-			if( subs->event->apply_auth_nbody(n_body, subs, &notify_body)< 0)
1358
+		{
1359
+			
1360
+			if(subs->auth_rules_doc &&
1361
+				subs->event->apply_auth_nbody(n_body, subs, &notify_body)< 0)
1345 1362
 			{
1346 1363
 				LOG(L_ERR, "PRESENCE:send_notify_request: "
1347 1364
 						"ERROR in function apply_auth_nbody\n");
... ...
@@ -1387,8 +1404,8 @@ int send_notify_request(subs_t* subs, subs_t * watcher_subs,
1387 1404
 				if(subs->event->req_auth)
1388 1405
 				{
1389 1406
 					 
1390
-					if(subs->event->apply_auth_nbody(notify_body,
1391
-								subs, &final_body)< 0)
1407
+					if(subs->auth_rules_doc && 
1408
+					subs->event->apply_auth_nbody(notify_body,subs,&final_body)<0)
1392 1409
 					{
1393 1410
 						LOG(L_ERR, "PRESENCE:send_notify_request: ERROR in function"
1394 1411
 								" apply_auth\n");
... ...
@@ -1407,15 +1424,6 @@ int send_notify_request(subs_t* subs, subs_t * watcher_subs,
1407 1424
 	
1408 1425
 jump_over_body:
1409 1426
 
1410
-	/* built extra headers */	
1411
-
1412
-	DBG("PRESENCE:send_notify_request: build notify to user= %.*s domain= %.*s"
1413
-		" for event= %.*s\n", subs->from_user.len, subs->from_user.s,
1414
-		subs->from_domain.len, subs->from_domain.s,subs->event->name.len,
1415
-		subs->event->name.s);
1416
-
1417
-	printf_subs(subs);
1418
-
1419 1427
 	/* build extra headers */
1420 1428
 	if( build_str_hdr( subs, notify_body?1:0, &str_hdr)< 0 )
1421 1429
 	{
... ...
@@ -1629,14 +1637,14 @@ c_back_param* shm_dup_cbparam(subs_t* w_subs, subs_t* subs)
1629 1637
 	cb_param= (c_back_param*)shm_malloc(sizeof(c_back_param));
1630 1638
 	if(cb_param== NULL)
1631 1639
 	{
1632
-		ERR_MEM("shm_dup_cbparam");
1640
+		ERR_MEM("PRESENCE","shm_dup_cbparam");
1633 1641
 	}
1634 1642
 	memset(cb_param, 0, sizeof(c_back_param));
1635 1643
 
1636 1644
 	cb_param->pres_uri.s= (char*)shm_malloc(subs->pres_uri.len* sizeof(char));
1637 1645
 	if(cb_param->pres_uri.s== NULL)
1638 1646
 	{
1639
-		ERR_MEM("shm_dup_cbparam");
1647
+		ERR_MEM("PRESENCE","shm_dup_cbparam");
1640 1648
 	}
1641 1649
 	memcpy(cb_param->pres_uri.s, subs->pres_uri.s, subs->pres_uri.len);
1642 1650
 	cb_param->pres_uri.len= subs->pres_uri.len;
... ...
@@ -1645,7 +1653,7 @@ c_back_param* shm_dup_cbparam(subs_t* w_subs, subs_t* subs)
1645 1653
 			(subs->event->name.len* sizeof(char));
1646 1654
 	if(cb_param->ev_name.s== NULL)
1647 1655
 	{
1648
-		ERR_MEM("shm_dup_cbparam");
1656
+		ERR_MEM("PRESENCE","shm_dup_cbparam");
1649 1657
 	}
1650 1658
 	memcpy(cb_param->ev_name.s, subs->event->name.s,
1651 1659
 			subs->event->name.len);
... ...
@@ -1654,7 +1662,7 @@ c_back_param* shm_dup_cbparam(subs_t* w_subs, subs_t* subs)
1654 1662
 	cb_param->to_tag.s= (char*)shm_malloc(subs->to_tag.len*sizeof(char));
1655 1663
 	if(cb_param->to_tag.s== NULL)
1656 1664
 	{
1657
-		ERR_MEM("shm_dup_cbparam");
1665
+		ERR_MEM("PRESENCE","shm_dup_cbparam");
1658 1666
 	}
1659 1667
 	memcpy(cb_param->to_tag.s, subs->to_tag.s ,subs->to_tag.len) ;
1660 1668
 	cb_param->to_tag.len= subs->to_tag.len;
... ...
@@ -1728,7 +1736,7 @@ str* create_winfo_xml(watcher_t* watchers, char* version,
1728 1736
 	res= (char*)pkg_malloc(sizeof(char)*(resource.len+ 1));
1729 1737
 	if(res== NULL)
1730 1738
 	{
1731
-		ERR_MEM("create_winfo_xml");
1739
+		ERR_MEM("PRESENCE","create_winfo_xml");
1732 1740
 	}
1733 1741
 	memcpy(res, resource.s, resource.len);
1734 1742
 	res[resource.len]= '\0';
... ...
@@ -1777,7 +1785,7 @@ str* create_winfo_xml(watcher_t* watchers, char* version,
1777 1785
     body = (str*)pkg_malloc(sizeof(str));
1778 1786
 	if(body == NULL)
1779 1787
 	{
1780
-		ERR_MEM("create_winfo_xml");	
1788
+		ERR_MEM("PRESENCE","create_winfo_xml");	
1781 1789
 	}
1782 1790
 	memset(body, 0, sizeof(str));
1783 1791
 
... ...
@@ -68,7 +68,7 @@ void printf_subs(subs_t* subs);
68 68
 
69 69
 int query_db_notify(str* pres_uri,pres_ev_t* event, subs_t* watcher_subs );
70 70
 
71
-int publ_notify(presentity_t* p, str* body, str* offline_etag);
71
+int publ_notify(presentity_t* p, str* body, str* offline_etag, str* rules_doc);
72 72
 
73 73
 int notify(subs_t* subs, subs_t* watcher_subs, str* n_body, int force_null_body);
74 74
 
... ...
@@ -51,6 +51,7 @@
51 51
 #include "../sl/sl_api.h"
52 52
 #include "../../pt.h"
53 53
 #include "../../mi/mi.h"
54
+#include "../pua/hash.h"
54 55
 #include "publish.h"
55 56
 #include "subscribe.h"
56 57
 #include "event_list.h"
... ...
@@ -97,7 +98,8 @@ int handle_publish(struct sip_msg*, char*, char*);
97 98
 int handle_subscribe(struct sip_msg*, char*, char*);
98 99
 int stored_pres_info(struct sip_msg* msg, char* pres_uri, char* s);
99 100
 static int fixup_presence(void** param, int param_no);
100
-struct mi_root* refreshWatchers(struct mi_root* cmd, void* param);
101
+struct mi_root* mi_refreshWatchers(struct mi_root* cmd, void* param);
102
+int get_pw_dialogs(subs_t* subs, unsigned int hash_code, subs_t** subs_array);
101 103
 
102 104
 int counter =0;
103 105
 int pid = 0;
... ...
@@ -115,7 +117,7 @@ phtable_t* pres_htable;
115 117
 
116 118
 static cmd_export_t cmds[]=
117 119
 {
118
-	{"handle_publish",		handle_publish,	     0,	   0,        REQUEST_ROUTE},
120
+	{"handle_publish",		handle_publish,	     0,	   0,         REQUEST_ROUTE},
119 121
 	{"handle_publish",		handle_publish,	     1,fixup_presence,REQUEST_ROUTE},
120 122
 	{"handle_subscribe",	handle_subscribe,	 0,	   0,         REQUEST_ROUTE},
121 123
 	{"bind_presence",(cmd_function)bind_presence,1,    0,            0         },
... ...
@@ -139,8 +141,8 @@ static param_export_t params[]={
139 141
 };
140 142
 
141 143
 static mi_export_t mi_cmds[] = {
142
-	{ "refreshWatchers", refreshWatchers,    0,  0,  0},
143
-	{ 0, 0, 0, 0}
144
+	{ "refreshWatchers", mi_refreshWatchers,    0,  0,  0},
145
+	{  0,                0,                     0,  0,  0}
144 146
 };
145 147
 
146 148
 /** module exports */
... ...
@@ -436,15 +438,19 @@ static int fixup_presence(void** param, int param_no)
436 438
  *  mi cmd: refreshWatchers
437 439
  *			<presentity_uri> 
438 440
  *			<event>
441
+ *			?? should I receive the changed doc also?? 
442
+ *			(faster- does not require a query) 
439 443
  * */
440 444
 
441
-struct mi_root* refreshWatchers(struct mi_root* cmd, void* param)
445
+struct mi_root* mi_refreshWatchers(struct mi_root* cmd, void* param)
442 446
 {
443 447
 	struct mi_node* node= NULL;
444 448
 	str pres_uri, event;
449
+	struct sip_uri uri;
445 450
 	pres_ev_t* ev;
451
+	str* rules_doc;
446 452
 
447
-	DBG("PRESENCE:refreshWatchers: start\n");
453
+	DBG("PRESENCE:mi_refreshWatchers: start\n");
448 454
 	
449 455
 	node = cmd->node.kids;
450 456
 	if(node == NULL)
... ...
@@ -452,9 +458,9 @@ struct mi_root* refreshWatchers(struct mi_root* cmd, void* param)
452 458
 
453 459
 	/* Get presentity URI */
454 460
 	pres_uri = node->value;
455
-	if(pres_uri.s == NULL || pres_uri.s== 0)
461
+	if(pres_uri.s == NULL || pres_uri.len== 0)
456 462
 	{
457
-		LOG(L_ERR, "PRESENCE:refreshWatchers: empty uri\n");
463
+		LOG(L_ERR, "PRESENCE:mi_refreshWatchers: empty uri\n");
458 464
 		return init_mi_tree(404, "Empty presentity URI", 20);
459 465
 	}
460 466
 	
... ...
@@ -464,32 +470,256 @@ struct mi_root* refreshWatchers(struct mi_root* cmd, void* param)
464 470
 	event= node->value;
465 471
 	if(event.s== NULL || event.len== 0)
466 472
 	{
467
-		LOG(L_ERR, "PRESENCE:refreshWatchers: "
473
+		LOG(L_ERR, "PRESENCE:mi_refreshWatchers: "
468 474
 		    "empty event parameter\n");
469 475
 		return init_mi_tree(400, "Empty event parameter", 21);
470 476
 	}
471
-	DBG("PRESENCE:refreshWatchers: event '%.*s'\n",
477
+	DBG("PRESENCE:mi_refreshWatchers: event '%.*s'\n",
472 478
 	    event.len, event.s);
473 479
 	
474 480
 	if(node->next!= NULL)
475 481
 	{
476
-		LOG(L_ERR, "PRESENCE:refreshWatchers: Too many parameters\n");
482
+		LOG(L_ERR, "PRESENCE:mi_refreshWatchers: Too many parameters\n");
477 483
 		return init_mi_tree(400, "Too many parameters", 19);
478 484
 	}
479 485
 
486
+	if(parse_uri(pres_uri.s, pres_uri.len, &uri)< 0)
487
+	{
488
+		LOG(L_ERR, "PRESENCE:mi_refreshWatchers: ERROR parsing uri\n");
489
+		goto error;
490
+	}
491
+
480 492
 	ev= contains_event(&event, NULL);
481 493
 	if(ev== NULL)
482 494
 	{
483
-		LOG(L_ERR, "PRESENCE:refreshWatchers: ERROR wrong event parameter\n");
495
+		LOG(L_ERR, "PRESENCE:mi_refreshWatchers: ERROR wrong event parameter\n");
484 496
 		return 0;
485
-	}	
486
-	if(query_db_notify(&pres_uri, ev, NULL)< 0)
497
+	}
498
+
499
+	if(ev->get_rules_doc(&uri.user,&uri.host,&rules_doc)< 0 || rules_doc==0
500
+			|| rules_doc->s== NULL)
501
+	{
502
+		LOG(L_ERR, "PRESENCE:mi_refreshWatchers:ERROR getting rules doc\n");
503
+		goto error;
504
+	}
505
+
506
+	if(update_watchers(pres_uri, ev, rules_doc)< 0)
507
+	{
508
+		LOG(L_ERR, "PRESENCE:mi_refreshWatchers:ERROR updating watchers\n");
509
+		goto error;
510
+	}
511
+
512
+	return init_mi_tree(200, "OK", 2);
513
+
514
+error:
515
+	if(rules_doc)
516
+	{
517
+		if(rules_doc->s)
518
+			pkg_free(rules_doc->s);
519
+		pkg_free(rules_doc);
520
+	}
521
+	return 0;
522
+}
523
+
524
+int update_watchers(str pres_uri, pres_ev_t* ev, str* rules_doc)
525
+{
526
+	subs_t subs;
527
+	db_key_t query_cols[3], result_cols[5], update_cols[5];
528
+	db_val_t query_vals[3], update_vals[2];
529
+	int n_update_cols= 0, n_result_cols= 0, n_query_cols = 0;
530
+	db_res_t* result= NULL;
531
+	db_row_t *row ;	
532
+	db_val_t *row_vals ;
533
+	int i;
534
+	str w_user, w_domain, reason;
535
+	int status;
536
+	int status_col, w_user_col, w_domain_col, reason_col;
537
+	int u_status_col, u_reason_col;
538
+	subs_t* subs_array= NULL,* s;
539
+	unsigned int hash_code;
540
+				
541
+	if(ev->content_type.s== NULL)
487 542
 	{
488
-		LOG(L_ERR, "PRESENCE:refreshWatchers: ERROR while sending notify");
543
+		ev= contains_event(&ev->name, NULL);
544
+		if(ev== NULL)
545
+		{
546
+			LOG(L_ERR,"PRESENCE:update_watchers:ERROR wrong event parameter\n");
547
+			return 0;
548
+		}
549
+	}
550
+
551
+	subs.pres_uri= pres_uri;
552
+	subs.event= ev;
553
+	subs.auth_rules_doc= rules_doc;
554
+
555
+	/* update in watchers_table */
556
+	query_cols[n_query_cols]= "p_uri";
557
+	query_vals[n_query_cols].nul= 0;
558
+	query_vals[n_query_cols].type= DB_STR;
559
+	query_vals[n_query_cols].val.str_val= pres_uri;
560
+	n_query_cols++;
561
+
562
+	query_cols[n_query_cols]= "event";
563
+	query_vals[n_query_cols].nul= 0;
564
+	query_vals[n_query_cols].type= DB_STR;
565
+	query_vals[n_query_cols].val.str_val= ev->name;
566
+	n_query_cols++;
567
+
568
+	result_cols[status_col= n_result_cols++]= "status";
569
+	result_cols[reason_col= n_result_cols++]= "reason";
570
+	result_cols[w_user_col= n_result_cols++]= "w_user";
571
+	result_cols[w_domain_col= n_result_cols++]= "w_domain";
572
+	
573
+	update_cols[u_status_col= n_update_cols]= "status";
574
+	update_vals[u_status_col].nul= 0;
575
+	update_vals[u_status_col].type= DB_INT;
576
+	n_update_cols++;
577
+
578
+	update_cols[u_reason_col= n_update_cols]= "reason";
579
+	update_vals[u_reason_col].nul= 0;
580
+	update_vals[u_reason_col].type= DB_STR;
581
+	n_update_cols++;
582
+
583
+	if (pa_dbf.use_table(pa_db, watchers_table) < 0) 
584
+	{
585
+		LOG(L_ERR, "PRESENCE:update_watchers: ERROR in use_table\n");
586
+		goto error;
587
+	}
588
+
589
+	if(pa_dbf.query(pa_db, query_cols, 0, query_vals, result_cols,n_query_cols,
590
+				n_result_cols, 0, &result)< 0)
591
+	{
592
+		LOG(L_ERR, "PRESENCE:update_watchers: ERROR in sql query\n");
593
+		goto error;
594
+	}
595
+	if(result== NULL)
489 596
 		return 0;
490
-	}	
597
+
598
+	if(result->n<= 0)
599
+		goto done;
600
+
601
+	hash_code= core_hash(&pres_uri, &ev->name, shtable_size);
602
+	lock_get(&subs_htable[hash_code].lock);
603
+
604
+	for(i = 0; i< result->n; i++)
605
+	{
606
+		row= &result->rows[i];
607
+		row_vals = ROW_VALUES(row);
608
+
609
+		status= row_vals[status_col].val.int_val;
491 610
 	
492
-	return init_mi_tree(200, "OK", 2);
611
+		reason.s= (char*)row_vals[reason_col].val.string_val;
612
+		reason.len= reason.s?strlen(reason.s):0;
613
+
614
+		w_user.s= (char*)row_vals[w_user_col].val.string_val;
615
+		w_user.len= strlen(w_user.s);
616
+
617
+		w_domain.s= (char*)row_vals[w_domain_col].val.string_val;
618
+		w_domain.len= strlen(w_domain.s);
619
+
620
+		subs.from_user= w_user;
621
+		subs.from_domain= w_domain;
622
+
623
+		if(ev->get_auth_status(&subs)< 0)
624
+		{
625
+			LOG(L_ERR, "PRESENCE:update_watchers: ERROR while getting status"
626
+					" from rules document\n");
627
+			lock_release(&subs_htable[hash_code].lock);
628
+			goto error;
629
+		}
630
+		if(subs.status!= status || reason.len!= subs.reason.len ||
631
+			(reason.s && subs.reason.s && strncmp(reason.s, subs.reason.s,
632
+												  reason.len)))
633
+		{
634
+			/* update in watchers_table */
635
+			update_vals[u_status_col].val.int_val= subs.status;
636
+			update_vals[u_reason_col].val.str_val= subs.reason;
637
+			if (pa_dbf.use_table(pa_db, watchers_table) < 0) 
638
+			{
639
+				LOG(L_ERR, "PRESENCE:update_watchers: ERROR in use_table\n");
640
+				lock_release(&subs_htable[hash_code].lock);
641
+				goto error;
642
+			}
643
+
644
+			if(pa_dbf.update(pa_db, query_cols, 0, query_vals, update_cols,
645
+						update_vals, n_query_cols, 2)< 0)
646
+			{
647
+				LOG(L_ERR, "PRESENCE:update_watchers: ERROR in sql update\n");
648
+				lock_release(&subs_htable[hash_code].lock);
649
+				goto error;
650
+			}
651
+			/* save in the list all affected dialogs */
652
+			if(get_pw_dialogs(&subs, hash_code, &subs_array)< 0)
653
+			{
654
+				LOG(L_ERR, "PRESENCE:update_watchers: ERROR ERROR extracting"
655
+						"from [watcher]=%.*s@%.*s to [presentity]=%.*s\n",
656
+						w_user.len, w_user.s, w_domain.len, w_domain.s, 
657
+						pres_uri.len, pres_uri.s);
658
+				lock_release(&subs_htable[hash_code].lock);
659
+				goto error;
660
+			}
661
+		}
662
+			
663
+	}
664
+	lock_release(&subs_htable[hash_code].lock);
665
+
666
+	s= subs_array;
667
+
668
+	while(s)
669
+	{
670
+		if(notify(s, NULL, NULL, 0)< 0)
671
+		{
672
+			LOG(L_ERR, "PRESENCE:update_watchers: ERROR sending"
673
+					" Notify request\n");
674
+			goto error;
675
+		}
676
+		s= s->next;
677
+	}
678
+	
679
+done:
680
+	pa_dbf.free_result(pa_db, result);
681
+	free_subs_list(subs_array, PKG_MEM_TYPE);
682
+	return 0;
683
+
684
+error:
685
+	if(result)
686
+		pa_dbf.free_result(pa_db, result);
687
+	free_subs_list(subs_array, PKG_MEM_TYPE);
688
+	return 0;
493 689
 }
494 690
 
691
+int get_pw_dialogs(subs_t* subs, unsigned int hash_code, subs_t** subs_array)
692
+{
693
+	subs_t* s, *cs;
694
+	
695
+	s= subs_htable[hash_code].entries->next;
696
+	
697
+	while(s)
698
+	{
699
+		if(s->event== subs->event && s->pres_uri.len== subs->pres_uri.len &&
700
+			s->from_user.len== subs->from_user.len && 
701
+			s->from_domain.len==subs->from_domain.len &&
702
+			strncmp(s->pres_uri.s, subs->pres_uri.s, subs->pres_uri.len)== 0 &&
703
+			strncmp(s->from_user.s, subs->from_user.s, s->from_user.len)== 0 &&
704
+			strncmp(s->from_domain.s,subs->from_domain.s,s->from_domain.len)==0)
705
+		{
706
+			s->status= subs->status;
707
+			s->reason= subs->reason;
708
+			s->db_flag= UPDATEDB_FLAG;
709
+
710
+			cs= mem_copy_subs(s, PKG_MEM_TYPE);
711
+			if(cs== NULL)
712
+			{
713
+				LOG(L_ERR, "PRESENCE:get_pw_dialogs:ERROR copying subs_t"
714
+						" stucture\n");
715
+				return -1;
716
+			}
717
+			cs->next= (*subs_array);
718
+			(*subs_array)= cs;
719
+
720
+		}
721
+		s= s->next;
722
+	}
723
+	return 0;
495 724
 
725
+}
... ...
@@ -69,4 +69,6 @@ extern shtable_t subs_htable;
69 69
 extern int phtable_size;
70 70
 extern phtable_t* pres_htable;
71 71
 
72
+int update_watchers(str pres_uri, pres_ev_t* ev, str* rules_doc);
73
+
72 74
 #endif /* PA_MOD_H */
... ...
@@ -237,9 +237,18 @@ int update_presentity(struct sip_msg* msg, presentity_t* presentity, str* body,
237 237
 	char* dot= NULL;
238 238
 	str etag= {0, 0};
239 239
 	str cur_etag= {0, 0};
240
+	str* rules_doc= NULL;
240 241
 
241
-	if( !use_db )
242
-		return 0;
242
+	if(presentity->event->req_auth)
243
+	{
244
+		/* get rules_document */
245
+		if(presentity->event->get_rules_doc(&presentity->user,
246
+					&presentity->domain, &rules_doc))
247
+		{
248
+			LOG(L_ERR, "PRESENCE:update_presentity: ERROR getting rules doc\n");
249
+			goto error;
250
+		}
251
+	}
243 252
 
244 253
 	query_cols[n_query_cols] = "domain";
245 254
 	query_ops[n_query_cols] = OP_EQ;
... ...
@@ -270,45 +279,6 @@ int update_presentity(struct sip_msg* msg, presentity_t* presentity, str* body,
270 279
 	n_query_cols++;
271 280
 
272 281
 	result_cols[0]= "expires"; 
273
-	if(presentity->expires == 0 && !new_t ) 
274
-	{
275
-		if( publ_send200ok(msg, presentity->expires, presentity->etag)< 0)
276
-		{
277
-			LOG(L_ERR, "PRESENCE:update_presentity: ERROR while sending 200OK\n");
278
-			return -1;
279
-		}
280
-		if( publ_notify( presentity, body, &presentity->etag)< 0 )
281
-		{
282