From ed100f44eaa06d00429b8ef20664ef6e7e3d70e3 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 23 Dec 2008 17:36:50 +0000 Subject: [PATCH] add group concept git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@10917 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- src/include/switch_xml.h | 12 +- .../applications/mod_commands/mod_commands.c | 246 +++++++++++++++++- .../applications/mod_dptools/mod_dptools.c | 139 +++++++++- .../mod_voicemail/mod_voicemail.c | 6 +- src/mod/endpoints/mod_sofia/sofia_reg.c | 39 ++- src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c | 2 +- src/switch_ivr.c | 15 +- src/switch_xml.c | 182 +++++++++++-- 8 files changed, 603 insertions(+), 38 deletions(-) diff --git a/src/include/switch_xml.h b/src/include/switch_xml.h index 5fd96dc464..260b2552b5 100644 --- a/src/include/switch_xml.h +++ b/src/include/switch_xml.h @@ -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 diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c index d948086463..bc77405d4d 100644 --- a/src/mod/applications/mod_commands/mod_commands.c +++ b/src/mod/applications/mod_commands/mod_commands.c @@ -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(¶ms, 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(¶ms); + } + + 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(¶ms, 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(¶ms); + + 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, "[@]"); + SWITCH_ADD_API(commands_api_interface, "in_group", "determine if a user is in a group", in_group_function, "[@] "); + SWITCH_ADD_API(commands_api_interface, "uuid_flush_dtmf", "Flush dtmf on a given uuid", uuid_flush_dtmf_function, ""); SWITCH_ADD_API(commands_api_interface, "md5", "md5", md5_function, ""); SWITCH_ADD_API(commands_api_interface, "hupall", "hupall", hupall_api_function, " [ ]"); diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index 52fc3e9060..958c79b6dc 100644 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -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(¶ms, 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; diff --git a/src/mod/applications/mod_voicemail/mod_voicemail.c b/src/mod/applications/mod_voicemail/mod_voicemail.c index 1f10b361bc..901270f0bb 100644 --- a/src/mod/applications/mod_voicemail/mod_voicemail.c +++ b/src/mod/applications/mod_voicemail/mod_voicemail.c @@ -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"); diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c index 57b85f5e2d..52bd376962 100644 --- a/src/mod/endpoints/mod_sofia/sofia_reg.c +++ b/src/mod/endpoints/mod_sofia/sofia_reg.c @@ -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++) { diff --git a/src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c b/src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c index 6f23642b02..c80169c936 100644 --- a/src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c +++ b/src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c @@ -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(¶ms); goto fail; } diff --git a/src/switch_ivr.c b/src/switch_ivr.c index 64fa497084..d3bd1bc9d5 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -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"); diff --git a/src/switch_xml.c b/src/switch_xml.c index 268312cb8a..d303f67b6a 100644 --- a/src/switch_xml.c +++ b/src/switch_xml.c @@ -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,27 +1715,28 @@ 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: if (my_params) {