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