]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
add group concept
authorAnthony Minessale <anthony.minessale@gmail.com>
Tue, 23 Dec 2008 17:36:50 +0000 (17:36 +0000)
committerAnthony Minessale <anthony.minessale@gmail.com>
Tue, 23 Dec 2008 17:36:50 +0000 (17:36 +0000)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@10917 d0543943-73ff-0310-b7d9-9358b9ac24b2

src/include/switch_xml.h
src/mod/applications/mod_commands/mod_commands.c
src/mod/applications/mod_dptools/mod_dptools.c
src/mod/applications/mod_voicemail/mod_voicemail.c
src/mod/endpoints/mod_sofia/sofia_reg.c
src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c
src/switch_ivr.c
src/switch_xml.c

index 5fd96dc464f3c5b15eb74e2f5dd1972d9a1448a8..260b2552b5b3bf1e768f2c5413182a9d591181fe 100644 (file)
@@ -142,6 +142,7 @@ SWITCH_DECLARE(switch_xml_t) switch_xml_child(switch_xml_t xml, const char *name
 ///\param value the value
 ///\return an xml node or NULL
 SWITCH_DECLARE(switch_xml_t) switch_xml_find_child(switch_xml_t node, const char *childname, const char *attrname, const char *value);
+SWITCH_DECLARE(switch_xml_t) switch_xml_find_child_multi(switch_xml_t node, const char *childname, ...);
 
 ///\brief returns the next tag of the same name in the same section and depth or NULL
 ///\ if not found
@@ -334,11 +335,20 @@ SWITCH_DECLARE(switch_status_t) switch_xml_locate(const char *section,
                                                                                                  switch_event_t *params);
 
 SWITCH_DECLARE(switch_status_t) switch_xml_locate_domain(const char *domain_name, switch_event_t *params, switch_xml_t *root, switch_xml_t *domain);
+
+SWITCH_DECLARE(switch_status_t) switch_xml_locate_group(const char *group_name,
+                                                                                                               const char *domain_name, 
+                                                                                                               switch_xml_t *root,
+                                                                                                               switch_xml_t *domain,
+                                                                                                               switch_xml_t *group,
+                                                                                                               switch_event_t *params);
+
 SWITCH_DECLARE(switch_status_t) switch_xml_locate_user(const char *key,
                                                                                                           const char *user_name,
                                                                                                           const char *domain_name,
                                                                                                           const char *ip,
-                                                                                                          switch_xml_t *root, switch_xml_t *domain, switch_xml_t *user, switch_event_t *params);
+                                                                                                          switch_xml_t *root, switch_xml_t *domain, switch_xml_t *user, switch_xml_t *ingroup, 
+                                                                                                          switch_event_t *params);
 
 ///\brief open a config in the core registry
 ///\param file_path the name of the config section e.g. modules.conf
index d948086463563a5a873f94b36cbb1ff19f537f49..bc77405d4dcd37746f4a58c1c61a24530e2e122b 100644 (file)
@@ -77,6 +77,245 @@ SWITCH_STANDARD_API(time_test_function)
        return SWITCH_STATUS_SUCCESS;
 }
 
+SWITCH_STANDARD_API(group_call_function)
+{
+       char *domain;
+       char *group_name = NULL;
+       char *flags;
+       int ok = 0;
+       switch_channel_t *channel = NULL;
+       char *fp = NULL;
+       const char *call_delim = ",";
+
+       if (switch_strlen_zero(cmd)) {
+               goto end;
+       }
+
+       if (session) {
+               channel = switch_core_session_get_channel(session);
+       }
+
+       group_name = strdup(cmd);
+       switch_assert(group_name);
+
+       if ((flags = strchr(group_name, '+'))) {
+               *flags++ = '\0';
+               for (fp = flags; fp && *fp; fp++) {
+                       switch(*fp) {
+                       case 'F':
+                               call_delim = "|";
+                               break;
+                       case 'A':
+                               call_delim = ",";
+                               break;
+                       default:
+                               break;
+                       }
+               }
+       }
+       
+       domain = strchr(group_name, '@');
+       
+       if (domain) {
+               *domain++ = '\0';
+       } else {
+               domain = switch_core_get_variable("domain");
+       }
+       
+       if (!switch_strlen_zero(domain)) {
+               switch_xml_t xml, x_domain, x_group;
+               switch_event_t *params;
+               switch_stream_handle_t dstream = { 0 };
+
+               SWITCH_STANDARD_STREAM(dstream);
+
+               switch_event_create(&params, SWITCH_EVENT_REQUEST_PARAMS);
+               switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "group", group_name);
+               switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "domain", domain);
+               switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "action", "group_call");
+               
+               if (switch_xml_locate_group(group_name, domain, &xml, &x_domain, &x_group, params) == SWITCH_STATUS_SUCCESS) {
+                       switch_xml_t x_user, x_users, x_param, x_params;
+                       
+                       if ((x_users = switch_xml_child(x_group, "users"))) {
+                               ok++;
+                               
+                               for(x_user = switch_xml_child(x_users, "user"); x_user; x_user = x_user->next) {
+                                       const char *id = switch_xml_attr_soft(x_user, "id");
+                                       const char *dest = NULL;
+                                       char *d_dest = NULL;
+                                       
+                                       if ((x_params = switch_xml_child(x_domain, "params"))) {
+                                               for (x_param = switch_xml_child(x_params, "param"); x_param; x_param = x_param->next) {
+                                                       const char *var = switch_xml_attr(x_param, "name");
+                                                       const char *val = switch_xml_attr(x_param, "value");
+
+                                                       if (!strcasecmp(var, "group-dial-string")) {
+                                                               dest = val;
+                                                               break;
+                                                       }
+
+                                                       if (!strcasecmp(var, "dial-string")) {
+                                                               dest = val;
+                                                       }
+                                               }
+                                       }
+
+                                       if ((x_params = switch_xml_child(x_group, "params"))) {
+                                               for (x_param = switch_xml_child(x_params, "param"); x_param; x_param = x_param->next) {
+                                                       const char *var = switch_xml_attr(x_param, "name");
+                                                       const char *val = switch_xml_attr(x_param, "value");
+
+                                                       if (!strcasecmp(var, "group-dial-string")) {
+                                                               dest = val;
+                                                               break;
+                                                       }
+
+                                                       if (!strcasecmp(var, "dial-string")) {
+                                                               dest = val;
+                                                       }
+                                               }
+                                       }
+
+                                       if ((x_params = switch_xml_child(x_user, "params"))) {
+                                               for (x_param = switch_xml_child(x_params, "param"); x_param; x_param = x_param->next) {
+                                                       const char *var = switch_xml_attr(x_param, "name");
+                                                       const char *val = switch_xml_attr(x_param, "value");
+                                                       
+                                                       if (!strcasecmp(var, "group-dial-string")) {
+                                                               dest = val;
+                                                               break;
+                                                       }
+
+                                                       if (!strcasecmp(var, "dial-string")) {
+                                                               dest = val;
+                                                       }
+                                               }
+                                       }
+                                       
+                                       if (dest) {
+                                               if (channel) {
+                                                       switch_channel_set_variable(channel, "dialed_group", group_name);
+                                                       switch_channel_set_variable(channel, "dialed_user", id);
+                                                       switch_channel_set_variable(channel, "dialed_domain", domain);
+                                                       d_dest = switch_channel_expand_variables(channel, dest);
+                                               } else {
+                                                       switch_event_del_header(params, "dialed_user");
+                                                       switch_event_del_header(params, "dialed_group");
+                                                       switch_event_del_header(params, "dialed_domain");
+                                                       switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "dialed_user", id);
+                                                       switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "dialed_group", group_name);
+                                                       switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "dialed_domain", domain);
+                                                       d_dest = switch_event_expand_headers(params, dest);
+                                               }
+                                       } else {
+                                               d_dest = switch_mprintf("user/%s@%s", id, domain);
+                                       }
+                                       
+                                       if (d_dest) {
+                                               if (!switch_stristr("error/", d_dest)) {
+                                                       dstream.write_function(&dstream, "%s%s", d_dest, call_delim);
+                                               }
+                                       
+                                               if (d_dest != dest) {
+                                                       free(d_dest);
+                                               }
+                                       }
+                               }
+
+                               if (ok && dstream.data) {
+                                       char *data = (char *) dstream.data;
+                                       char c = end_of(data);
+                                       char *p;
+
+                                       if (c == ',' || c == '|') {
+                                               end_of(data) = '\0';
+                                       }
+                                       
+                                       for (p = data; p && *p; p++) {
+                                               if (*p == '{') {
+                                                       *p = '[';
+                                               } else if (*p == '}') {
+                                                       *p = ']';
+                                               }
+                                       }
+
+
+                                       stream->write_function(stream, "%s", data);
+                                       free(dstream.data);
+                               } else {
+                                       ok = 0;
+                               }
+                               
+                       }
+                       switch_xml_free(xml);
+               }
+               switch_event_destroy(&params);
+       }
+
+ end:
+
+       switch_safe_free(group_name);
+       
+       if (!ok) {
+               stream->write_function(stream, "error/NO_ROUTE_DESTINATION");
+       }
+
+       return SWITCH_STATUS_SUCCESS;
+}
+
+
+SWITCH_STANDARD_API(in_group_function)
+{
+       switch_xml_t x_domain, xml = NULL, x_user = NULL, x_group;
+       int argc;
+       char *mydata = NULL, *argv[2], *user, *domain;
+       char delim = ',';
+       switch_event_t *params = NULL;
+       const char *rval = "false";
+       char *group;
+       
+       if (switch_strlen_zero(cmd) || !(mydata = strdup(cmd))) {
+               goto end;
+       }
+
+       if ((argc = switch_separate_string(mydata, delim, argv, (sizeof(argv) / sizeof(argv[0])))) < 2) {
+               goto end;
+       }
+
+       user = argv[0];
+       group = argv[1];
+
+       if ((domain = strchr(user, '@'))) {
+               *domain++ = '\0';
+       } else {
+               domain = switch_core_get_variable("domain");
+       }
+
+       switch_event_create(&params, SWITCH_EVENT_REQUEST_PARAMS);
+       switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "user", user);
+       switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "domain", domain);
+
+       if (switch_xml_locate_group(group, domain, &xml, &x_domain, &x_group, params) == SWITCH_STATUS_SUCCESS) {
+               switch_xml_t x_users;
+               if ((x_users = switch_xml_child(x_group, "users"))) {
+                       if ((x_user = switch_xml_find_child(x_users, "user", "id", user))) {
+                               rval = "true";
+                       }
+               }
+       }
+
+  end:
+       
+       stream->write_function(stream, "%s", rval);
+       
+       switch_xml_free(xml);
+       free(mydata);
+       switch_event_destroy(&params);
+
+       return SWITCH_STATUS_SUCCESS;
+}
+
 SWITCH_STANDARD_API(user_data_function)
 {
        switch_xml_t x_domain, xml = NULL, x_user = NULL, x_param, x_params;
@@ -111,7 +350,7 @@ SWITCH_STANDARD_API(user_data_function)
        switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "type", type);
        switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "key", key);
 
-       if (key && type && switch_xml_locate_user("id", user, domain, NULL, &xml, &x_domain, &x_user, params) == SWITCH_STATUS_SUCCESS) {
+       if (key && type && switch_xml_locate_user("id", user, domain, NULL, &xml, &x_domain, &x_user, NULL, params) == SWITCH_STATUS_SUCCESS) {
                if (!strcmp(type, "attr")) {
                        const char *attr = switch_xml_attr_soft(x_user, key);
                        stream->write_function(stream, "%s", attr);
@@ -201,7 +440,7 @@ static switch_status_t _find_user(const char *cmd, switch_core_session_t *sessio
                goto end;
        }
 
-       if (switch_xml_locate_user(key, user, domain, NULL, &xml, &x_domain, &x_user, NULL) != SWITCH_STATUS_SUCCESS) {
+       if (switch_xml_locate_user(key, user, domain, NULL, &xml, &x_domain, &x_user, NULL, NULL) != SWITCH_STATUS_SUCCESS) {
                err = "can't find user";
                goto end;
        }
@@ -2940,6 +3179,9 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
        switch_api_interface_t *commands_api_interface;
        *module_interface = switch_loadable_module_create_module_interface(pool, modname);
 
+       SWITCH_ADD_API(commands_api_interface, "group_call", "Generate a dial string to call a group", group_call_function, "<group>[@<domain>]");
+       SWITCH_ADD_API(commands_api_interface, "in_group", "determine if a user is in a group", in_group_function, "<user>[@<domain>] <group_name>");
+
        SWITCH_ADD_API(commands_api_interface, "uuid_flush_dtmf", "Flush dtmf on a given uuid", uuid_flush_dtmf_function, "<uuid>");
        SWITCH_ADD_API(commands_api_interface, "md5", "md5", md5_function, "<data>");
        SWITCH_ADD_API(commands_api_interface, "hupall", "hupall", hupall_api_function, "<cause> [<var> <value>]");
index 52fc3e9060b705d6fdd41162ccfd4f48097e7fa4..958c79b6dc99e8b056998f602996612ef09bc21b 100644 (file)
@@ -2002,6 +2002,108 @@ static switch_call_cause_t error_outgoing_channel(switch_core_session_t *session
        return cause;
 }
 
+
+/* fake chan_group */
+switch_endpoint_interface_t *group_endpoint_interface;
+static switch_call_cause_t group_outgoing_channel(switch_core_session_t *session,
+                                                                                                switch_event_t *var_event,
+                                                                                                switch_caller_profile_t *outbound_profile,
+                                                                                                switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags);
+switch_io_routines_t group_io_routines = {
+       /*.outgoing_channel */ group_outgoing_channel
+};
+
+static switch_call_cause_t group_outgoing_channel(switch_core_session_t *session,
+                                                                                                switch_event_t *var_event,
+                                                                                                switch_caller_profile_t *outbound_profile,
+                                                                                                switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags)
+{
+       char *group;
+       switch_call_cause_t cause;
+       char *template = NULL, *dest = NULL;
+       switch_originate_flag_t myflags = SOF_NONE;
+       char *cid_name_override = NULL;
+       char *cid_num_override = NULL;
+       const char *var;
+       unsigned int timelimit = 60;
+       char *domain = NULL;
+       switch_channel_t *new_channel = NULL;
+
+       group = strdup(outbound_profile->destination_number);
+
+       if (!group) goto done;
+       
+       if ((domain = strchr(group, '@'))) {
+               *domain++ = '\0';
+       } else {
+               domain = switch_core_get_variable("domain");
+       }
+       
+       if (!domain) {
+               goto done;
+       }
+
+       template = switch_mprintf("${group_call(%s@%s)}", group, domain);
+       
+       if (session) {
+               switch_channel_t *channel = switch_core_session_get_channel(session);
+               dest = switch_channel_expand_variables(channel, template);
+               if ((var = switch_channel_get_variable(channel, SWITCH_CALL_TIMEOUT_VARIABLE))) {
+                       timelimit = atoi(var);
+               }
+       } else if (var_event) {
+               dest = switch_event_expand_headers(var_event, template);
+       }
+       if (!dest) {
+               goto done;
+       }
+       
+       if (var_event) {
+               cid_name_override = switch_event_get_header(var_event, "origination_caller_id_name");
+               cid_num_override = switch_event_get_header(var_event, "origination_caller_id_number");
+               if ((var = switch_event_get_header(var_event, SWITCH_CALL_TIMEOUT_VARIABLE))) {
+                       timelimit = atoi(var);
+               }
+       }
+       
+       if ((flags & SOF_FORKED_DIAL)) {
+               myflags |= SOF_NOBLOCK;
+       }
+       
+       
+       if (switch_ivr_originate(session, new_session, &cause, dest, timelimit, NULL, 
+                                                        cid_name_override, cid_num_override, NULL, var_event, myflags) == SWITCH_STATUS_SUCCESS) {
+               const char *context;
+               switch_caller_profile_t *cp;
+               
+               new_channel = switch_core_session_get_channel(*new_session);
+               
+               if ((context = switch_channel_get_variable(new_channel, "group_context"))) {
+                       if ((cp = switch_channel_get_caller_profile(new_channel))) {
+                               cp->context = switch_core_strdup(cp->pool, context);
+                       }
+               }
+               switch_core_session_rwunlock(*new_session);
+       }
+
+
+ done:
+
+       if (dest && dest != template) {
+               switch_safe_free(dest);
+       }
+       
+       switch_safe_free(template);     
+
+       if (cause == SWITCH_CAUSE_NONE) {
+               cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+       }
+
+       return cause;
+}
+
+
+
 /* fake chan_user */
 switch_endpoint_interface_t *user_endpoint_interface;
 static switch_call_cause_t user_outgoing_channel(switch_core_session_t *session,
@@ -2017,7 +2119,7 @@ static switch_call_cause_t user_outgoing_channel(switch_core_session_t *session,
                                                                                                 switch_caller_profile_t *outbound_profile,
                                                                                                 switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags)
 {
-       switch_xml_t x_domain = NULL, xml = NULL, x_user = NULL, x_param, x_params;
+       switch_xml_t x_domain = NULL, xml = NULL, x_user = NULL, x_group = NULL, x_param, x_params;
        char *user = NULL, *domain = NULL;
        const char *dest = NULL;
        static switch_call_cause_t cause = SWITCH_CAUSE_NONE;
@@ -2030,20 +2132,24 @@ static switch_call_cause_t user_outgoing_channel(switch_core_session_t *session,
 
        user = strdup(outbound_profile->destination_number);
 
-       if (!user)
-               goto done;
+       if (!user) goto done;
 
-       if (!(domain = strchr(user, '@'))) {
+       if ((domain = strchr(user, '@'))) {
+               *domain++ = '\0';
+       } else {
+               domain = switch_core_get_variable("domain");
+       }
+       
+       if (!domain) {
                goto done;
        }
-
-       *domain++ = '\0';
+       
 
        switch_event_create(&params, SWITCH_EVENT_REQUEST_PARAMS);
        switch_assert(params);
        switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "as_channel", "true");
 
-       if (switch_xml_locate_user("id", user, domain, NULL, &xml, &x_domain, &x_user, params) != SWITCH_STATUS_SUCCESS) {
+       if (switch_xml_locate_user("id", user, domain, NULL, &xml, &x_domain, &x_user, &x_group, params) != SWITCH_STATUS_SUCCESS) {
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Can't find user [%s@%s]\n", user, domain);
                cause = SWITCH_CAUSE_SUBSCRIBER_ABSENT;
                goto done;
@@ -2061,6 +2167,18 @@ static switch_call_cause_t user_outgoing_channel(switch_core_session_t *session,
                }
        }
 
+       if ((x_params = switch_xml_child(x_group, "params"))) {
+               for (x_param = switch_xml_child(x_params, "param"); x_param; x_param = x_param->next) {
+                       const char *var = switch_xml_attr(x_param, "name");
+                       const char *val = switch_xml_attr(x_param, "value");
+
+                       if (!strcasecmp(var, "dial-string")) {
+                               dest = val;
+                               break;
+                       }
+               }
+       }
+
        if ((x_params = switch_xml_child(x_user, "params"))) {
                for (x_param = switch_xml_child(x_params, "param"); x_param; x_param = x_param->next) {
                        const char *var = switch_xml_attr(x_param, "name");
@@ -2107,6 +2225,9 @@ static switch_call_cause_t user_outgoing_channel(switch_core_session_t *session,
                                switch_event_dup(&event, var_event);
                                switch_event_del_header(event, "dialer_user");
                                switch_event_del_header(event, "dialer_domain");
+                               if ((var = switch_event_get_header(var_event, SWITCH_CALL_TIMEOUT_VARIABLE))) {
+                                       timelimit = atoi(var);
+                               }
                        } else {
                                switch_event_create(&event, SWITCH_EVENT_REQUEST_PARAMS);
                                switch_assert(event);
@@ -2318,6 +2439,10 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load)
        error_endpoint_interface->interface_name = "error";
        error_endpoint_interface->io_routines = &error_io_routines;
 
+       group_endpoint_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_ENDPOINT_INTERFACE);
+       group_endpoint_interface->interface_name = "group";
+       group_endpoint_interface->io_routines = &group_io_routines;
+
        user_endpoint_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_ENDPOINT_INTERFACE);
        user_endpoint_interface->interface_name = "user";
        user_endpoint_interface->io_routines = &user_io_routines;
index 1f10b361bcd5fc22f4f037c4ef8e45c27b68fbe2..901270f0bb548d16a0efb2aa6d80f047dc8b4e92 100644 (file)
@@ -1888,7 +1888,7 @@ static void voicemail_check_main(switch_core_session_t *session, const char *pro
                                        switch_channel_event_set_data(channel, params);
                                        
                                        if (switch_xml_locate_user("id", myid, domain_name, switch_channel_get_variable(channel, "network_addr"),
-                                                                                          &xx_domain_root, &xx_domain, &xx_user, params) == SWITCH_STATUS_SUCCESS) {
+                                                                                          &xx_domain_root, &xx_domain, &xx_user, NULL, params) == SWITCH_STATUS_SUCCESS) {
                                                switch_xml_free(xx_domain_root);
                                        }
 
@@ -1981,7 +1981,7 @@ static void voicemail_check_main(switch_core_session_t *session, const char *pro
                                        
                                        
                                        if (switch_xml_locate_user("id", myid, domain_name, switch_channel_get_variable(channel, "network_addr"),
-                                                                                          &x_domain_root, &x_domain, &x_user, params) != SWITCH_STATUS_SUCCESS) {
+                                                                                          &x_domain_root, &x_domain, &x_user, NULL, params) != SWITCH_STATUS_SUCCESS) {
                                                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Can't find user [%s@%s]\n", myid, domain_name);
                                                ok = 0;
                                        }
@@ -2679,7 +2679,7 @@ static switch_status_t voicemail_leave_main(switch_core_session_t *session, cons
                switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "mailbox", id);
 
                if (switch_xml_locate_user("id", id, domain_name, switch_channel_get_variable(channel, "network_addr"),
-                                                                  &x_domain_root, &x_domain, &x_user, params) == SWITCH_STATUS_SUCCESS) {
+                                                                  &x_domain_root, &x_domain, &x_user, NULL, params) == SWITCH_STATUS_SUCCESS) {
                        if ((x_params = switch_xml_child(x_user, "params"))) {
                                for (x_param = switch_xml_child(x_params, "param"); x_param; x_param = x_param->next) {
                                        const char *var = switch_xml_attr_soft(x_param, "name");
index 57b85f5e2d6d20ff61cd77692a8a48318df89a92..52bd376962c6d1b86fe1952ab4f4cfe02c9b0525 100644 (file)
@@ -1394,7 +1394,7 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile, sip_authorization_t co
        const char *a1_hash = NULL;
        char *sql;
        char *mailbox = NULL;
-       switch_xml_t domain, xml = NULL, user, param, uparams, dparams;
+       switch_xml_t domain, xml = NULL, user, param, uparams, dparams, group, gparams = NULL;
        char hexdigest[2 * SU_MD5_DIGEST_SIZE + 1] = "";
        char *domain_name = NULL;
        switch_event_t *params = NULL;
@@ -1529,7 +1529,7 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile, sip_authorization_t co
        }
 
        if (switch_xml_locate_user("id", switch_strlen_zero(username) ? "nobody" : username, 
-                                                          domain_name, ip, &xml, &domain, &user, params) != SWITCH_STATUS_SUCCESS) {
+                                                          domain_name, ip, &xml, &domain, &user, &group, params) != SWITCH_STATUS_SUCCESS) {
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Can't find user [%s@%s]\n"
                                                  "You must define a domain called '%s' in your directory and add a user with the id=\"%s\" attribute\n"
                                                  "and you must configure your device to use the proper domain in it's authentication credentials.\n"
@@ -1545,6 +1545,9 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile, sip_authorization_t co
 
        dparams = switch_xml_child(domain, "params");
        uparams = switch_xml_child(user, "params");
+       if (group) {
+               gparams = switch_xml_child(group, "params");
+       }
 
        if (!(dparams || uparams)) {
                ret = AUTH_OK;
@@ -1575,6 +1578,30 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile, sip_authorization_t co
                }
        }
 
+       if (gparams) {
+               for (param = switch_xml_child(gparams, "param"); param; param = param->next) {
+                       const char *var = switch_xml_attr_soft(param, "name");
+                       const char *val = switch_xml_attr_soft(param, "value");
+
+                       if (!strcasecmp(var, "sip-forbid-register") && switch_true(val)) {
+                               ret = AUTH_FORBIDDEN;
+                               goto end;
+                       }
+
+                       if (!strcasecmp(var, "password")) {
+                               passwd = val;
+                       }
+
+                       if (!strcasecmp(var, "auth-acl")) {
+                               auth_acl = val;
+                       }
+
+                       if (!strcasecmp(var, "a1-hash")) {
+                               a1_hash = val;
+                       }
+               }
+       }
+
        if (uparams) {
                for (param = switch_xml_child(uparams, "param"); param; param = param->next) {
                        const char *var = switch_xml_attr_soft(param, "name");
@@ -1670,7 +1697,7 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile, sip_authorization_t co
                        switch_event_create(v_event, SWITCH_EVENT_REQUEST_PARAMS);
                }
                if (v_event && *v_event) {
-                       switch_xml_t xparams[2];
+                       switch_xml_t xparams[3];
                        int i = 0;
 
                        switch_event_add_header_string(*v_event, SWITCH_STACK_BOTTOM, "sip_mailbox", mailbox);
@@ -1684,11 +1711,15 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile, sip_authorization_t co
                                xparams[i++] = dparams;
                        }
 
+                       if (group && (gparams = switch_xml_child(group, "variables"))) {
+                               xparams[i++] = gparams;
+                       }
+
                        if ((uparams = switch_xml_child(user, "variables"))) {
                                xparams[i++] = uparams;
                        }
 
-                       if (dparams || uparams) {
+                       if (i <= 3) {
                                int j = 0;
 
                                for (j = 0; j < i; j++) {
index 6f23642b02a3db644a90cbb2bf08bd47f02d3d07..c80169c9367697398d356635e52c1d0631540e5a 100644 (file)
@@ -206,7 +206,7 @@ static abyss_bool http_directory_auth(TSession * r, char *domain_name)
                                switch_assert(params);
                                switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "mailbox", "check");
 
-                               if (switch_xml_locate_user("id", user, domain_name, NULL, &x_domain_root, &x_domain, &x_user, params) != SWITCH_STATUS_SUCCESS) {
+                               if (switch_xml_locate_user("id", user, domain_name, NULL, &x_domain_root, &x_domain, &x_user, NULL, params) != SWITCH_STATUS_SUCCESS) {
                                        switch_event_destroy(&params);
                                        goto fail;
                                }
index 64fa497084e8892856b385d87be87ba25a527079..d3bd1bc9d550aff05973aea709ef9d7eac00be53 100644 (file)
@@ -1920,7 +1920,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_say(switch_core_session_t *session, c
 
 SWITCH_DECLARE(switch_status_t) switch_ivr_set_user(switch_core_session_t *session, const char *data)
 {
-       switch_xml_t x_domain, xml = NULL, x_user, x_param, x_params;
+       switch_xml_t x_domain, xml = NULL, x_user, x_param, x_params, x_group = NULL;
        char *user, *mailbox, *domain;
        switch_channel_t *channel = switch_core_session_get_channel(session);
        switch_status_t status = SWITCH_STATUS_FALSE;
@@ -1937,7 +1937,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_set_user(switch_core_session_t *sessi
 
        *domain++ = '\0';
 
-       if (switch_xml_locate_user("id", user, domain, NULL, &xml, &x_domain, &x_user, NULL) != SWITCH_STATUS_SUCCESS) {
+       if (switch_xml_locate_user("id", user, domain, NULL, &xml, &x_domain, &x_user, &x_group, NULL) != SWITCH_STATUS_SUCCESS) {
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "can't find user [%s@%s]\n", user, domain);
                goto done;
        }
@@ -1959,6 +1959,17 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_set_user(switch_core_session_t *sessi
                }
        }
 
+       if (x_group && (x_params = switch_xml_child(x_group, "variables"))) {
+               for (x_param = switch_xml_child(x_params, "variable"); x_param; x_param = x_param->next) {
+                       const char *var = switch_xml_attr(x_param, "name");
+                       const char *val = switch_xml_attr(x_param, "value");
+
+                       if (var && val) {
+                               switch_channel_set_variable(channel, var, val);
+                       }
+               }
+       }
+
        if ((x_params = switch_xml_child(x_user, "variables"))) {
                for (x_param = switch_xml_child(x_params, "variable"); x_param; x_param = x_param->next) {
                        const char *var = switch_xml_attr(x_param, "name");
index 268312cb8a22794a58d5926d818892d3ece8bc81..d303f67b6aa67be1d9f81782a21ebbbeb150e5ff 100644 (file)
@@ -300,6 +300,62 @@ SWITCH_DECLARE(switch_xml_t) switch_xml_find_child(switch_xml_t node, const char
        return p;
 }
 
+SWITCH_DECLARE(switch_xml_t) switch_xml_find_child_multi(switch_xml_t node, const char *childname, ...)
+{
+       switch_xml_t p = NULL;
+       const char *names[256] = {0};
+       const char *vals[256] = {0};
+       int x, i = 0;
+       va_list ap;
+       const char *attrname, *value;
+
+       va_start(ap, childname);
+       
+       while(i < 255) {
+               if ((attrname = va_arg(ap, const char *))) {
+                       value = va_arg(ap, const char *);
+               }
+               if (attrname && value) {
+                       names[i] = attrname;
+                       vals[i] = value;
+               } else {
+                       break;
+               }
+               i++;
+       }
+
+       va_end(ap);
+
+       if (!(childname && i)) {
+               return node;
+       }
+       
+       for (p = switch_xml_child(node, childname); p; p = p->next) {
+               for (x = 0; x < i; x++) {
+                       if (names[x] && vals[x]) {
+                               const char *aname = switch_xml_attr(p, names[x]);
+
+                               if (aname) {
+                                       if (*vals[x] == '!') {
+                                               const char *sval = vals[x] + 1;
+                                               if (sval && strcasecmp(aname, sval)) {
+                                                       goto done;
+                                               }
+                                       } else {
+                                               if (!strcasecmp(aname, vals[x])) {
+                                                       goto done;
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+
+ done:
+
+       return p;
+}
+
 // returns the first child tag with the given name or NULL if not found
 SWITCH_DECLARE(switch_xml_t) switch_xml_child(switch_xml_t xml, const char *name)
 {
@@ -1528,6 +1584,93 @@ SWITCH_DECLARE(switch_status_t) switch_xml_locate_domain(const char *domain_name
        return status;
 }
 
+SWITCH_DECLARE(switch_status_t) switch_xml_locate_group(const char *group_name,
+                                                                                                               const char *domain_name, 
+                                                                                                               switch_xml_t *root,
+                                                                                                               switch_xml_t *domain,
+                                                                                                               switch_xml_t *group,
+                                                                                                               switch_event_t *params)
+{
+       switch_status_t status = SWITCH_STATUS_FALSE;
+       switch_event_t *my_params = NULL;
+       switch_xml_t groups = NULL;
+
+       *root = NULL;
+       *group = NULL;
+       *domain = NULL;
+
+       if (!params) {
+               switch_event_create(&my_params, SWITCH_EVENT_REQUEST_PARAMS);
+               switch_assert(my_params);
+               params = my_params;
+       }
+
+       if (group_name) {
+               switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "group_name", group_name);
+       }
+
+       if (domain_name) {
+               switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "domain", domain_name);
+       }
+
+       if ((status = switch_xml_locate_domain(domain_name, params, root, domain)) != SWITCH_STATUS_SUCCESS) {
+               goto end;
+       }
+       
+       status = SWITCH_STATUS_FALSE;
+
+       if ((groups = switch_xml_child(*domain, "groups"))) {
+               if ((*group = switch_xml_find_child(groups, "group", "name", group_name))) {
+                       status = SWITCH_STATUS_SUCCESS;
+               }
+       }
+
+ end:
+
+       if (my_params) {
+               switch_event_destroy(&my_params);
+       }
+
+       return status;
+}
+
+
+static switch_status_t find_user_in_tag(switch_xml_t tag, const char *ip, const char *user_name, const char *key, switch_event_t *params, switch_xml_t *user)
+{
+       const char *type = "!pointer";
+       const char *val;
+
+       if (params && (val = switch_event_get_header(params, "user_type"))) {
+               if (!strcasecmp(val, "any")) {
+                       type = NULL;
+               } else {
+                       type = val;
+               }
+       }
+
+       if (ip) {
+               if ((*user = switch_xml_find_child_multi(tag, "user", "ip", ip, "type", type, NULL))) {
+                       return SWITCH_STATUS_SUCCESS;
+               }
+       } 
+
+       if (user_name) {
+               if (params && switch_event_get_header(params, (char *) "mailbox")) {
+                       if ((*user = switch_xml_find_child_multi(tag, "user", "mailbox", user_name, "type", type, NULL))) {
+                               return SWITCH_STATUS_SUCCESS;
+                       }
+               }
+
+               if ((*user = switch_xml_find_child_multi(tag, "user", key, user_name, "type", type, NULL))) {
+                       return SWITCH_STATUS_SUCCESS;
+               }
+       }
+       
+       return SWITCH_STATUS_FALSE;
+       
+}
+
+
 SWITCH_DECLARE(switch_status_t) switch_xml_locate_user(const char *key,
                                                                                                           const char *user_name,
                                                                                                           const char *domain_name, 
@@ -1535,11 +1678,13 @@ SWITCH_DECLARE(switch_status_t) switch_xml_locate_user(const char *key,
                                                                                                           switch_xml_t *root,
                                                                                                           switch_xml_t *domain,
                                                                                                           switch_xml_t *user,
+                                                                                                          switch_xml_t *ingroup,
                                                                                                           switch_event_t *params)
 {
        switch_status_t status = SWITCH_STATUS_FALSE;
-       switch_event_t *my_params = NULL;
-
+       switch_event_t *my_params = NULL, *search_params = NULL;
+       switch_xml_t group = NULL, groups = NULL, users = NULL;
+       
        *root = NULL;
        *user = NULL;
        *domain = NULL;
@@ -1570,26 +1715,27 @@ SWITCH_DECLARE(switch_status_t) switch_xml_locate_user(const char *key,
        
        status = SWITCH_STATUS_FALSE;
 
-       if (ip) {
-               if ((*user = switch_xml_find_child(*domain, "user", "ip", ip))) {
-                       status = SWITCH_STATUS_SUCCESS;
-                       goto end;
-               }
-       } 
+       if (params != my_params) {
+               search_params = params;
+       }
 
-       if (user_name) {
-               if (params != my_params && switch_event_get_header(params, (char *) "mailbox")) {
-                       if ((*user = switch_xml_find_child(*domain, "user", "mailbox", user_name))) {
-                               status = SWITCH_STATUS_SUCCESS;
-                               goto end;
+       if ((groups = switch_xml_child(*domain, "groups"))) {
+               for (group = switch_xml_child(groups, "group"); group; group = group->next) {
+                       if ((users = switch_xml_child(group, "users"))) {
+                               if ((status = find_user_in_tag(users, ip, user_name, key, params, user)) == SWITCH_STATUS_SUCCESS) {
+                                       if (ingroup) {
+                                               *ingroup = group;
+                                       }
+                                       break;
+                               }
                        }
                }
+       }
 
-               if ((*user = switch_xml_find_child(*domain, "user", key, user_name))) {
-                       status = SWITCH_STATUS_SUCCESS;
-                       goto end;
-               }
+       if (status != SWITCH_STATUS_SUCCESS) {
+               status = find_user_in_tag(*domain, ip, user_name, key, params, user);
        }
+       
 
  end: