Explorar o código

* Module: presence

Introduced a dew function auth_status() that can be used to check from
script if a watcher is allowed to subscriber event 'presence' of a
presentity.
Juha Heinanen %!s(int64=16) %!d(string=hai) anos
pai
achega
c737bb20f2

+ 127 - 101
modules_k/presence/README

@@ -1,19 +1,28 @@
-
 Presence Module
 Presence Module
 
 
 Anca-Maria Vamanu
 Anca-Maria Vamanu
 
 
    voice-system.ro
    voice-system.ro
 
 
+Juha Heinanen
+
+   TutPro Inc.
+
 Edited by
 Edited by
 
 
 Anca-Maria Vamanu
 Anca-Maria Vamanu
 
 
+Edited by
+
+Juha Heinanen
+
    Copyright © 2006 voice-system.ro
    Copyright © 2006 voice-system.ro
+
+   Copyright © 2009 Juha Heinanen
    Revision History
    Revision History
-   Revision $Revision$ $Date: 2008-08-06 12:08:33 +0200
-   (Wed, 06 Aug 2008) $
-     _________________________________________________________
+   Revision $Revision: 4594 $ $Date: 2008-08-06 13:08:33 +0300
+                              (Wed, 06 Aug 2008) $
+     __________________________________________________________
 
 
    Table of Contents
    Table of Contents
 
 
@@ -44,33 +53,34 @@ Anca-Maria Vamanu
 
 
         1.4. Exported Functions
         1.4. Exported Functions
 
 
-              1.4.1. handle_publish(char* sender_uri) 
-              1.4.2. handle_subscribe() 
+              1.4.1. handle_publish(char* sender_uri)
+              1.4.2. handle_subscribe()
+              1.4.3. auth_status(watcher_uri, presentity_uri)
 
 
         1.5. Exported MI Functions
         1.5. Exported MI Functions
 
 
-              1.5.1. refreshWatchers 
-              1.5.2. cleanup 
+              1.5.1. refreshWatchers
+              1.5.2. cleanup
 
 
         1.6. Installation
         1.6. Installation
 
 
    2. Developer Guide
    2. Developer Guide
 
 
-        2.1. bind_presence(presence_api_t* api) 
-        2.2. add_event 
-        2.3. get_rules_doc 
-        2.4. get_auth_status 
-        2.5. apply_auth_nbody 
-        2.6. agg_nbody 
-        2.7. free_body 
-        2.8. aux_body_processing 
-        2.9. aux_free_body 
-        2.10. evs_publ_handl 
-        2.11. evs_subs_handl 
-        2.12. contains_event 
-        2.13. get_event_list 
-        2.14. update_watchers_status 
-        2.15. get_sphere 
+        2.1. bind_presence(presence_api_t* api)
+        2.2. add_event
+        2.3. get_rules_doc
+        2.4. get_auth_status
+        2.5. apply_auth_nbody
+        2.6. agg_nbody
+        2.7. free_body
+        2.8. aux_body_processing
+        2.9. aux_free_body
+        2.10. evs_publ_handl
+        2.11. evs_subs_handl
+        2.12. contains_event
+        2.13. get_event_list
+        2.14. update_watchers_status
+        2.15. get_sphere
 
 
    List of Examples
    List of Examples
 
 
@@ -90,6 +100,7 @@ Anca-Maria Vamanu
    1.14. Set enable_sphere_check parameter
    1.14. Set enable_sphere_check parameter
    1.15. handle_publish usage
    1.15. handle_publish usage
    1.16. handle_subscribe usage
    1.16. handle_subscribe usage
+   1.17. auth_status usage
    2.1. presence_api_t structure
    2.1. presence_api_t structure
 
 
 Chapter 1. Admin Guide
 Chapter 1. Admin Guide
@@ -104,19 +115,18 @@ Chapter 1. Admin Guide
    presence, presence.winfo, dialog;sla from the presence_xml
    presence, presence.winfo, dialog;sla from the presence_xml
    module and message-summary from the presence_mwi module.
    module and message-summary from the presence_mwi module.
 
 
-   The module uses database storage and memory caching (to
-   improve performance). The SIP SUBSCRIBE dialog information is
-   stored in memory and is periodically updated in the database,
-   while for PUBLISH only the presence or absence of stored info
-   for a certain resource is maintained in memory to avoid
-   unnecessary, costly database operations. It is possible to
-   disable in-memory caching by configurng a fallback to database
-   mode (by setting module parameter "fallback2db"). In this
-   mode, in case a searched record is not found in cache, the
-   search is continued in database. This is useful for an
-   architecture in which processing and memory load might be
-   divided on several Kamailio instances, maybe on different
-   servers using the same database.
+   The module uses database storage and memory caching (to improve
+   performance). The SIP SUBSCRIBE dialog information is stored in
+   memory and is periodically updated in the database, while for
+   PUBLISH only the presence or absence of stored info for a
+   certain resource is maintained in memory to avoid unnecessary,
+   costly database operations. It is possible to disable in-memory
+   caching by configurng a fallback to database mode (by setting
+   module parameter "fallback2db"). In this mode, in case a
+   searched record is not found in cache, the search is continued
+   in database. This is useful for an architecture in which
+   processing and memory load might be divided on several Kamailio
+   instances, maybe on different servers using the same database.
 
 
    The module implements several API functions, that can be used
    The module implements several API functions, that can be used
    by other modules. In fact, it can be used only as a resource
    by other modules. In fact, it can be used only as a resource
@@ -149,7 +159,7 @@ Chapter 1. Admin Guide
    Otherwise, it is used as a 'library', for its exported
    Otherwise, it is used as a 'library', for its exported
    functions.
    functions.
 
 
-   Default value is "NULL". 
+   Default value is "NULL".
 
 
    Example 1.1. Set db_url parameter
    Example 1.1. Set db_url parameter
 ...
 ...
@@ -162,7 +172,7 @@ modparam("presence", "db_url",
    The name of the db table where PUBLISH presence information is
    The name of the db table where PUBLISH presence information is
    stored.
    stored.
 
 
-   Default value is "presentity". 
+   Default value is "presentity".
 
 
    Example 1.2. Set presentity_table parameter
    Example 1.2. Set presentity_table parameter
 ...
 ...
@@ -174,7 +184,7 @@ modparam("presence", "presentity_table", "presentity")
    The name of the db table where active subscription information
    The name of the db table where active subscription information
    is stored.
    is stored.
 
 
-   Default value is "active_watchers". 
+   Default value is "active_watchers".
 
 
    Example 1.3. Set active_watchers_table parameter
    Example 1.3. Set active_watchers_table parameter
 ...
 ...
@@ -185,7 +195,7 @@ modparam("presence", "active_watchers_table", "active_watchers")
 
 
    The name of the db table where subscription states are stored.
    The name of the db table where subscription states are stored.
 
 
-   Default value is "watchers". 
+   Default value is "watchers".
 
 
    Example 1.4. Set watchers_table parameter
    Example 1.4. Set watchers_table parameter
 ...
 ...
@@ -198,7 +208,7 @@ modparam("presence", "watchers_table", "watchers")
    messages stored in database.
    messages stored in database.
 
 
    Default value is "100". A zero or negative value disables this
    Default value is "100". A zero or negative value disables this
-   activity. 
+   activity.
 
 
    Example 1.5. Set clean_period parameter
    Example 1.5. Set clean_period parameter
 ...
 ...
@@ -211,7 +221,7 @@ modparam("presence", "clean_period", 100)
    the database.
    the database.
 
 
    Default value is "100". A zero or negative value disables
    Default value is "100". A zero or negative value disables
-   synchronization. 
+   synchronization.
 
 
    Example 1.6. Set db_update_period parameter
    Example 1.6. Set db_update_period parameter
 ...
 ...
@@ -220,10 +230,10 @@ modparam("presence", "db_update_period", 100)
 
 
 1.3.7. to_tag_pref (str)
 1.3.7. to_tag_pref (str)
 
 
-   The prefix used when generating to_tag when sending replies
-   for SUBSCRIBE requests.
+   The prefix used when generating to_tag when sending replies for
+   SUBSCRIBE requests.
 
 
-   Default value is "10". 
+   Default value is "10".
 
 
    Example 1.7. Set to_tag_pref parameter
    Example 1.7. Set to_tag_pref parameter
 ...
 ...
@@ -232,12 +242,12 @@ modparam("presence", "to_tag_pref", 'pres')
 
 
 1.3.8. expires_offset (int)
 1.3.8. expires_offset (int)
 
 
-   The value in seconds that should be subtracted from the
-   expires value when sending a 200OK for a publish. It is used
-   for forcing the client cu send an update before the old
-   publish expires.
+   The value in seconds that should be subtracted from the expires
+   value when sending a 200OK for a publish. It is used for
+   forcing the client cu send an update before the old publish
+   expires.
 
 
-   Default value is "0". 
+   Default value is "0".
 
 
    Example 1.8. Set expires_offset parameter
    Example 1.8. Set expires_offset parameter
 ...
 ...
@@ -249,7 +259,7 @@ modparam("presence", "expires_offset", 10)
    The the maximum admissible expires value for PUBLISH/SUBSCRIBE
    The the maximum admissible expires value for PUBLISH/SUBSCRIBE
    message (in seconds).
    message (in seconds).
 
 
-   Default value is "3600". 
+   Default value is "3600".
 
 
    Example 1.9. Set max_expires parameter
    Example 1.9. Set max_expires parameter
 ...
 ...
@@ -259,8 +269,8 @@ modparam("presence", "max_expires", 3600)
 1.3.10. server_address (str)
 1.3.10. server_address (str)
 
 
    The presence server address which will become the value of
    The presence server address which will become the value of
-   Contact header filed for 200OK replies to Subscribe and
-   Publish and in Notify messages.
+   Contact header filed for 200OK replies to Subscribe and Publish
+   and in Notify messages.
 
 
    Example 1.10. Set server_address parameter
    Example 1.10. Set server_address parameter
 ...
 ...
@@ -270,10 +280,10 @@ modparam("presence", "server_address", "sip:10.10.10.10:5060")
 1.3.11. fallback2db (int)
 1.3.11. fallback2db (int)
 
 
    Setting this parameter enables a fallback to db mode of
    Setting this parameter enables a fallback to db mode of
-   operation. In this mode, in case a searched record is not
-   found in cache, the search is continued in database. Useful
-   for an architecture in which processing and memory load might
-   be divided on more servers using the same database.
+   operation. In this mode, in case a searched record is not found
+   in cache, the search is continued in database. Useful for an
+   architecture in which processing and memory load might be
+   divided on more servers using the same database.
 
 
    Example 1.11. Set fallback2db parameter
    Example 1.11. Set fallback2db parameter
 ...
 ...
@@ -286,7 +296,7 @@ modparam("presence", "fallback2db", 1)
    dialogs. This parameter will be used as the power of 2 when
    dialogs. This parameter will be used as the power of 2 when
    computing table size.
    computing table size.
 
 
-   Default value is "9 (512)". 
+   Default value is "9 (512)".
 
 
    Example 1.12. Set subs_htable_size parameter
    Example 1.12. Set subs_htable_size parameter
 ...
 ...
@@ -299,7 +309,7 @@ modparam("presence", "subs_htable_size", 11)
    This parameter will be used as the power of 2 when computing
    This parameter will be used as the power of 2 when computing
    table size.
    table size.
 
 
-   Default value is "9 (512)". 
+   Default value is "9 (512)".
 
 
    Example 1.13. Set pres_htable_size parameter
    Example 1.13. Set pres_htable_size parameter
 ...
 ...
@@ -308,14 +318,14 @@ modparam("presence", "pres_htable_size", 11)
 
 
 1.3.14. enable_sphere_check (int)
 1.3.14. enable_sphere_check (int)
 
 
-   This parameter is a flag that should be set if permission
-   rules include sphere checking. The sphere information is
-   expected to be present in the RPID body published by the
-   presentity. The flag is introduced as this check requires
-   extra processing that should be avoided if this feature is not
-   supported by the clients.
+   This parameter is a flag that should be set if permission rules
+   include sphere checking. The sphere information is expected to
+   be present in the RPID body published by the presentity. The
+   flag is introduced as this check requires extra processing that
+   should be avoided if this feature is not supported by the
+   clients.
 
 
-   Default value is "0 ". 
+   Default value is "0 ".
 
 
    Example 1.14. Set enable_sphere_check parameter
    Example 1.14. Set enable_sphere_check parameter
 ...
 ...
@@ -379,6 +389,25 @@ if(method=="SUBSCRIBE")
     handle_subscribe();
     handle_subscribe();
 ...
 ...
 
 
+1.4.3.  auth_status(watcher_uri, presentity_uri)
+
+   The function checks if watcher is authorized to subscribe
+   presence of presentity. Both watcher_uri and presentity_uri are
+   pseudo variables. Function returns ACTIVE_STATUS, if
+   subscription is allowed and PENDING_STATUS, TERMINATED_STATUS,
+   or WAITING_STATUS otherwise. See presence/subscribe.h for the
+   corresponding integer codes. In case of error, function returns
+   -1.
+
+   This function can be used from REQUEST_ROUTE.
+
+   Example 1.17. auth_status usage
+...
+if((method=="MESSAGE") && (auth_status("$fu", $ru"))) {
+    t_relay();
+}
+...
+
 1.5. Exported MI Functions
 1.5. Exported MI Functions
 
 
 1.5.1.  refreshWatchers
 1.5.1.  refreshWatchers
@@ -394,8 +423,7 @@ if(method=="SUBSCRIBE")
      * event : the event package
      * event : the event package
      * refresh type : it distinguishes between the two different
      * refresh type : it distinguishes between the two different
        types of events that can trigger a refresh:
        types of events that can trigger a refresh:
-          + a change in watchers authentication: refresh type= 0
-            ;
+          + a change in watchers authentication: refresh type= 0 ;
           + a statical update in published state (either through
           + a statical update in published state (either through
             direct update in db table or by modifying the pidf
             direct update in db table or by modifying the pidf
             manipulation document, if pidf_manipulation parameter
             manipulation document, if pidf_manipulation parameter
@@ -422,7 +450,6 @@ if(method=="SUBSCRIBE")
                 :cleanup:fifo_reply
                 :cleanup:fifo_reply
                 _empty_line_
                 _empty_line_
 
 
-
 1.6. Installation
 1.6. Installation
 
 
    The module requires 3 tables in the Kamailio database:
    The module requires 3 tables in the Kamailio database:
@@ -435,8 +462,8 @@ if(method=="SUBSCRIBE")
 
 
 Chapter 2. Developer Guide
 Chapter 2. Developer Guide
 
 
-   The module provides the following functions that can be used
-   in other Kamailio modules.
+   The module provides the following functions that can be used in
+   other Kamailio modules.
 
 
 2.1.  bind_presence(presence_api_t* api)
 2.1.  bind_presence(presence_api_t* api)
 
 
@@ -515,21 +542,21 @@ typedef struct pres_ev
         publ_handling_t  * evs_publ_handl;
         publ_handling_t  * evs_publ_handl;
         subs_handling_t  * evs_subs_handl;
         subs_handling_t  * evs_subs_handl;
         free_body_t* free_body;
         free_body_t* free_body;
-    /* sometimes it is necessary that a module make changes for a body
-for each
-     * active watcher (e.g. setting the "version" parameter in an XML d
-ocument.
-     * If a module registers the aux_body_processing callback, it gets
-called for
-     * each watcher. It either gets the body received by the PUBLISH, o
-r the body
+    /* sometimes it is necessary that a module make changes for a body f
+or each
+     * active watcher (e.g. setting the "version" parameter in an XML do
+cument.
+     * If a module registers the aux_body_processing callback, it gets c
+alled for
+     * each watcher. It either gets the body received by the PUBLISH, or
+ the body
      * generated by the agg_nbody function.
      * generated by the agg_nbody function.
-     * The module can deceide if it makes a copy of the original body,
-which is then
-     * manipulated, or if it works directly in the original body. If th
-e module makes a
-     * copy of the original body, it also has to register the aux_free_
-body() to
+     * The module can deceide if it makes a copy of the original body, w
+hich is then
+     * manipulated, or if it works directly in the original body. If the
+ module makes a
+     * copy of the original body, it also has to register the aux_free_b
+ody() to
      * free this "per watcher" body.
      * free this "per watcher" body.
      */
      */
     aux_body_processing_t* aux_body_processing;
     aux_body_processing_t* aux_body_processing;
@@ -573,8 +600,8 @@ typedef int (is_allowed_t)(struct subscription* subs);
    This parameter should be a function to be called for an event
    This parameter should be a function to be called for an event
    that requires authorization, when constructing final body. The
    that requires authorization, when constructing final body. The
    authorization document is taken from the auth_rules_doc field
    authorization document is taken from the auth_rules_doc field
-   of the subs_t structure given as a parameter. It is called
-   only if the req_auth field is not 0.
+   of the subs_t structure given as a parameter. It is called only
+   if the req_auth field is not 0.
 
 
    Filed type:
    Filed type:
 ...
 ...
@@ -586,9 +613,8 @@ typedef int (apply_auth_t)(str* , struct subscription*, str** );
    If present, this field marks that the events requires
    If present, this field marks that the events requires
    aggregation of states. This function receives a body array and
    aggregation of states. This function receives a body array and
    should return the final body. If not present, it is considered
    should return the final body. If not present, it is considered
-   that the event does not require aggregation and the most
-   recent published information is used when constructing
-   Notifies.
+   that the event does not require aggregation and the most recent
+   published information is used when constructing Notifies.
 
 
    Filed type:
    Filed type:
 ...
 ...
@@ -600,9 +626,9 @@ str** body_array, int n, int off_index);
 
 
    This field must be field in if subsequent processing is
    This field must be field in if subsequent processing is
    performed on the info from database before being inserted in
    performed on the info from database before being inserted in
-   Notify message body(if agg_nbody or apply_auth_nbody fields
-   are filled in). It should match the allocation function used
-   when processing the body.
+   Notify message body(if agg_nbody or apply_auth_nbody fields are
+   filled in). It should match the allocation function used when
+   processing the body.
 
 
    Filed type:
    Filed type:
 ...
 ...
@@ -613,16 +639,16 @@ typedef void(free_body_t)(char* body);
 
 
    This field must be set if the module needs to manipulate the
    This field must be set if the module needs to manipulate the
    NOTIFY body for each watcher. E.g. if the XML body includes a
    NOTIFY body for each watcher. E.g. if the XML body includes a
-   'version' parameter which will be increased for each NOTIFY,
-   on a "per watcher" basis. The module can either allocate a new
+   'version' parameter which will be increased for each NOTIFY, on
+   a "per watcher" basis. The module can either allocate a new
    buffer for the new body an return it (aux_free_body function
    buffer for the new body an return it (aux_free_body function
    must be set too) or it manipualtes the original body directly
    must be set too) or it manipualtes the original body directly
    and returns NULL.
    and returns NULL.
 
 
    Filed type:
    Filed type:
 ...
 ...
-typedef str* (aux_body_processing_t)(struct subscription *subs, str* bo
-dy);
+typedef str* (aux_body_processing_t)(struct subscription *subs, str* bod
+y);
 ..
 ..
 
 
 2.9.  aux_free_body
 2.9.  aux_free_body
@@ -706,7 +732,7 @@ str* rules_doc);
 typedef char* (*pres_get_sphere_t)(str* pres_uri);
 typedef char* (*pres_get_sphere_t)(str* pres_uri);
 ...
 ...
 
 
-   This function searches for a sphere definition in the
-   published information if this has type RPID. If not found
-   returns NULL. (the return value is allocated in private memory
-   and should be freed)
+   This function searches for a sphere definition in the published
+   information if this has type RPID. If not found returns NULL.
+   (the return value is allocated in private memory and should be
+   freed)

+ 21 - 2
modules_k/presence/doc/presence.xml

@@ -28,6 +28,14 @@
 		</otheraddr>
 		</otheraddr>
 		</address>
 		</address>
 	    </author>
 	    </author>
+	    <author>
+		<firstname>Juha</firstname>
+		<surname>Heinanen</surname>
+		<affiliation><orgname>TutPro Inc.</orgname></affiliation>
+		<address>
+		<email>[email protected]</email>
+		</address>
+	    </author>
 	    <editor>
 	    <editor>
 		<firstname>Anca-Maria</firstname>
 		<firstname>Anca-Maria</firstname>
 		<surname>Vamanu</surname>
 		<surname>Vamanu</surname>
@@ -35,15 +43,26 @@
 		    <email>[email protected]</email>
 		    <email>[email protected]</email>
 		</address>
 		</address>
 	    </editor>
 	    </editor>
+	    <editor>
+		<firstname>Juha</firstname>
+		<surname>Heinanen</surname>
+		<address>
+		    <email>[email protected]</email>
+		</address>
+	    </editor>
 	</authorgroup>
 	</authorgroup>
 	<copyright>
 	<copyright>
 	    <year>2006</year>
 	    <year>2006</year>
 	    <holder>&voicesystem;</holder>
 	    <holder>&voicesystem;</holder>
 	</copyright>
 	</copyright>
+	<copyright>
+	    <year>2009</year>
+	    <holder>Juha Heinanen</holder>
+	</copyright>
 	<revhistory>
 	<revhistory>
 	    <revision>
 	    <revision>
-		<revnumber>$Revision$</revnumber>
-		<date>$Date$</date>
+		<revnumber>$Revision: 4594 $</revnumber>
+		<date>$Date: 2008-08-06 13:08:33 +0300 (Wed, 06 Aug 2008) $</date>
 	    </revision>
 	    </revision>
 	</revhistory>
 	</revhistory>
   </bookinfo>
   </bookinfo>

+ 30 - 0
modules_k/presence/doc/presence_admin.xml

@@ -449,6 +449,36 @@ modparam("presence", "enable_sphere_check", 1)
 if(method=="SUBSCRIBE")
 if(method=="SUBSCRIBE")
     handle_subscribe();
     handle_subscribe();
 ...
 ...
+</programlisting>
+		</example>
+	</section>
+
+	<section>
+		<title>
+		<function moreinfo="none">auth_status(watcher_uri, presentity_uri)</function>
+		</title>
+		<para>
+		The function checks if watcher is authorized to subscribe
+		presence of presentity.  Both watcher_uri and
+		presentity_uri are pseudo variables.  Function returns
+		ACTIVE_STATUS, if subscription is allowed and
+		PENDING_STATUS, TERMINATED_STATUS, or WAITING_STATUS
+		otherwise.  See presence/subscribe.h for the
+		corresponding integer codes.  In case of error, function
+		returns -1.
+		</para>
+		<para>
+		This function can be used from REQUEST_ROUTE.
+		</para>
+
+		<example>
+		<title><function>auth_status</function> usage</title>
+		<programlisting format="linespecific">
+...
+if((method=="MESSAGE") &amp;&amp; (auth_status("$fu", $ru"))) {
+    t_relay();
+}
+...
 </programlisting>
 </programlisting>
 		</example>
 		</example>
 	</section>
 	</section>

+ 96 - 0
modules_k/presence/presence.c

@@ -74,6 +74,7 @@
 #include "event_list.h"
 #include "event_list.h"
 #include "bind_presence.h"
 #include "bind_presence.h"
 #include "notify.h"
 #include "notify.h"
+#include "../../mod_fix.h"
 
 
 MODULE_VERSION
 MODULE_VERSION
 
 
@@ -117,6 +118,7 @@ static struct mi_root* mi_cleanup(struct mi_root* cmd, void* param);
 static int update_pw_dialogs(subs_t* subs, unsigned int hash_code, subs_t** subs_array);
 static int update_pw_dialogs(subs_t* subs, unsigned int hash_code, subs_t** subs_array);
 int update_watchers_status(str pres_uri, pres_ev_t* ev, str* rules_doc);
 int update_watchers_status(str pres_uri, pres_ev_t* ev, str* rules_doc);
 static int mi_child_init(void);
 static int mi_child_init(void);
+static int auth_status(struct sip_msg* _msg, char* _sp1, char* _sp2);
 
 
 int counter =0;
 int counter =0;
 int pid = 0;
 int pid = 0;
@@ -138,6 +140,7 @@ static cmd_export_t cmds[]=
 	{"handle_publish",  (cmd_function)handle_publish,  0,fixup_presence,0, REQUEST_ROUTE},
 	{"handle_publish",  (cmd_function)handle_publish,  0,fixup_presence,0, REQUEST_ROUTE},
 	{"handle_publish",  (cmd_function)handle_publish,  1,fixup_presence, 0, REQUEST_ROUTE},
 	{"handle_publish",  (cmd_function)handle_publish,  1,fixup_presence, 0, REQUEST_ROUTE},
 	{"handle_subscribe",(cmd_function)handle_subscribe,0,fixup_subscribe,0, REQUEST_ROUTE},
 	{"handle_subscribe",(cmd_function)handle_subscribe,0,fixup_subscribe,0, REQUEST_ROUTE},
+ 	{"auth_status",     (cmd_function)auth_status, 2, fixup_pvar_pvar, fixup_free_pvar_pvar, REQUEST_ROUTE},
 	{"bind_presence",   (cmd_function)bind_presence,   1,     0,         0,  0},
 	{"bind_presence",   (cmd_function)bind_presence,   1,     0,         0,  0},
 	{ 0,                    0,                         0,     0,         0,  0}
 	{ 0,                    0,                         0,     0,         0,  0}
 };
 };
@@ -1074,3 +1077,96 @@ static int update_pw_dialogs(subs_t* subs, unsigned int hash_code, subs_t** subs
 	
 	
     return 0;
     return 0;
 }
 }
+
+static int auth_status(struct sip_msg* _msg, char* _sp1, char* _sp2)
+{
+    pv_spec_t *sp;
+    pv_value_t pv_val;
+    str watcher_uri, presentity_uri, event;
+    struct sip_uri uri;
+    pres_ev_t* ev;
+    str* rules_doc = NULL;
+    subs_t subs;
+    int res;
+
+    sp = (pv_spec_t *)_sp1;
+
+    if (sp && (pv_get_spec_value(_msg, sp, &pv_val) == 0)) {
+	if (pv_val.flags & PV_VAL_STR) {
+	    watcher_uri = pv_val.rs;
+	    if (watcher_uri.len == 0 || watcher_uri.s == NULL) {
+		LM_ERR("missing watcher uri\n");
+		return -1;
+	    }
+	} else {
+	    LM_ERR("watcher pseudo variable value is not string\n");
+	    return -1;
+	}
+    } else {
+	LM_ERR("cannot get watcher pseudo variable value\n");
+	return -1;
+    }
+
+    sp = (pv_spec_t *)_sp2;
+
+    if (sp && (pv_get_spec_value(_msg, sp, &pv_val) == 0)) {
+	if (pv_val.flags & PV_VAL_STR) {
+	    presentity_uri = pv_val.rs;
+	    if (presentity_uri.len == 0 || presentity_uri.s == NULL) {
+		LM_DBG("missing presentity uri\n");
+		return -1;
+	    }
+	} else {
+	    LM_ERR("presentity pseudo variable value is not string\n");
+	    return -1;
+	}
+    } else {
+	LM_ERR("cannot get presentity pseudo variable value\n");
+	return -1;
+    }
+
+    event.s = "presence";
+    event.len = 8;
+
+    ev = contains_event(&event, NULL);
+    if (ev == NULL) {
+	LM_ERR("event is not registered\n");
+	return -1;
+    }
+    if (ev->get_rules_doc == NULL) {
+	LM_DBG("event does not require authorization");
+	return ACTIVE_STATUS;
+    }
+    if (parse_uri(presentity_uri.s, presentity_uri.len, &uri) < 0) {
+	LM_ERR("failed to parse presentity uri\n");
+	return -1;
+    }
+    res = ev->get_rules_doc(&uri.user, &uri.host, &rules_doc);
+    if ((res < 0) || (rules_doc == NULL) || (rules_doc->s == NULL)) {
+	LM_DBG( "no xcap rules doc found for presentity uri\n");
+	return PENDING_STATUS;
+    }
+
+    if (parse_uri(watcher_uri.s, watcher_uri.len, &uri) < 0) {
+	LM_ERR("failed to parse watcher uri\n");
+	goto err;
+    }
+
+    subs.from_user = uri.user;
+    subs.from_domain = uri.host;
+    subs.pres_uri = presentity_uri;
+    subs.auth_rules_doc = rules_doc;
+    if (ev->get_auth_status(&subs) < 0) {
+	LM_ERR( "getting status from rules document\n");
+	goto err;
+    }
+    LM_INFO("subs.status= %d\n", subs.status);
+    pkg_free(rules_doc->s);
+    pkg_free(rules_doc);
+    return subs.status;
+
+ err:
+    pkg_free(rules_doc->s);
+    pkg_free(rules_doc);
+    return -1;
+}