static void translate_number(char *number, char *profile, char **translated, switch_core_session_t *session, switch_event_t *event) { translate_rule_t *hi = NULL; translate_rule_t *rule = NULL; switch_regex_t *re = NULL; int proceed = 0, ovector[30]; char *substituted = NULL; uint32_t len = 0; if (!profile) { profile = "US"; } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "translating [%s] against [%s] profile\n", number, profile); hi = switch_core_hash_find_rdlock(globals.translate_profiles, (const char *)profile, globals.profile_hash_rwlock); if (!hi) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "can't find key for profile matching [%s]\n", profile); return; } for (rule = hi; rule; rule = rule->next) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s =~ /%s/\n", number, rule->regex); if ((proceed = switch_regex_perform(number, rule->regex, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s matched %s, replacing with %s\n", number, rule->regex, rule->replace); if (!(substituted = malloc(len))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n"); switch_regex_safe_free(re); goto end; } memset(substituted, 0, len); switch_perform_substitution(re, proceed, rule->replace, number, substituted, len, ovector); if ((switch_string_var_check_const(substituted) || switch_string_has_escaped_data(substituted))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "perform variable expansion\n"); if (session) { substituted = switch_channel_expand_variables(switch_core_session_get_channel(session), substituted); } else if (event) { substituted = switch_event_expand_headers(event, substituted); } } break; } } end: *translated = substituted ? substituted : NULL; }
static void parse_naptr(const ldns_rr *naptr, const char *number, enum_record_t **results) { char *str = ldns_rr2str(naptr); char *argv[11] = { 0 }; int i, argc; char *pack[4] = { 0 }; int packc; char *p; int order = 10; int preference = 100; char *service = NULL; char *packstr; char *regex, *replace; if (zstr(str)) { if (str != NULL) { /* In this case ldns_rr2str returned a malloc'd null terminated string */ switch_safe_free(str); } return; } for (p = str; p && *p; p++) { if (*p == '\t') *p = ' '; if (*p == ' ' && *(p+1) == '.') *p = '\0'; } argc = switch_split(str, ' ', argv); for (i = 0; i < argc; i++) { if (i > 0) { strip_quotes(argv[i]); } } service = argv[7]; packstr = argv[8]; if (zstr(service) || zstr(packstr)) { goto end; } if (!zstr(argv[4])) { order = atoi(argv[4]); } if (!zstr(argv[5])) { preference = atoi(argv[5]); } if ((packc = switch_split(packstr, '!', pack))) { regex = pack[1]; replace = pack[2]; } else { goto end; } for (p = replace; p && *p; p++) { if (*p == '\\') { *p = '$'; } } if (service && regex && replace) { switch_regex_t *re = NULL, *re2 = NULL; int proceed = 0, ovector[30]; char *substituted = NULL; char *substituted_2 = NULL; char *orig_uri; char *uri_expanded = NULL; enum_route_t *route; int supported = 0; uint32_t len = 0; if ((proceed = switch_regex_perform(number, regex, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) { if (strchr(regex, '(')) { len = (uint32_t) (strlen(number) + strlen(replace) + 10) * proceed; if (!(substituted = malloc(len))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n"); switch_regex_safe_free(re); goto end; } memset(substituted, 0, len); switch_perform_substitution(re, proceed, replace, number, substituted, len, ovector); orig_uri = substituted; } else { orig_uri = replace; } switch_mutex_lock(MUTEX); for (route = globals.route_order; route; route = route->next) { char *uri = orig_uri; if (strcasecmp(service, route->service)) { continue; } if ((proceed = switch_regex_perform(uri, route->regex, &re2, ovector, sizeof(ovector) / sizeof(ovector[0])))) { switch_event_t *event = NULL; if (strchr(route->regex, '(')) { len = (uint32_t) (strlen(uri) + strlen(route->replace) + 10) * proceed; if (!(substituted_2 = malloc(len))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n"); switch_safe_free(substituted); switch_regex_safe_free(re); switch_regex_safe_free(re2); switch_mutex_unlock(MUTEX); goto end; } memset(substituted_2, 0, len); switch_perform_substitution(re2, proceed, route->replace, uri, substituted_2, len, ovector); uri = substituted_2; } else { uri = route->replace; } switch_event_create(&event, SWITCH_EVENT_REQUEST_PARAMS); uri_expanded = switch_event_expand_headers(event, uri); switch_event_destroy(&event); if (uri_expanded == uri) { uri_expanded = NULL; } else { uri = uri_expanded; } supported++; add_result(results, order, preference, service, uri, supported); } switch_safe_free(uri_expanded); switch_safe_free(substituted_2); switch_regex_safe_free(re2); } switch_mutex_unlock(MUTEX); if (!supported) { add_result(results, order, preference, service, orig_uri, 0); } switch_safe_free(substituted); switch_regex_safe_free(re); } } end: switch_safe_free(str); return; }
SWITCH_DECLARE(switch_status_t) switch_ivr_menu_execute(switch_core_session_t *session, switch_ivr_menu_t *stack, char *name, void *obj) { int reps = 0, errs = 0, timeouts = 0, match = 0, running = 1; char *greeting_sound = NULL, *aptr = NULL; char arg[512]; switch_ivr_action_t todo = SWITCH_IVR_ACTION_DIE; switch_ivr_menu_action_t *ap; switch_ivr_menu_t *menu; switch_channel_t *channel; switch_status_t status = SWITCH_STATUS_SUCCESS; if (++stack->stack_count > 12) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Too many levels of recursion.\n"); switch_goto_status(SWITCH_STATUS_FALSE, end); } if (!session || !stack || zstr(name)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid menu context\n"); switch_goto_status(SWITCH_STATUS_FALSE, end); } channel = switch_core_session_get_channel(session); if (!(menu = switch_ivr_menu_find(stack, name))) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid Menu!\n"); switch_goto_status(SWITCH_STATUS_FALSE, end); } if (!zstr(menu->tts_engine) && !zstr(menu->tts_voice)) { switch_channel_set_variable(channel, "tts_engine", menu->tts_engine); switch_channel_set_variable(channel, "tts_voice", menu->tts_voice); } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Executing IVR menu %s\n", menu->name); switch_channel_set_variable(channel, "ivr_menu_status", "success"); for (reps = 0; running && status == SWITCH_STATUS_SUCCESS; reps++) { if (!switch_channel_ready(channel)) { break; } if (errs == menu->max_failures) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Maximum failures\n"); switch_channel_set_variable(channel, "ivr_menu_status", "failure"); break; } if (timeouts == menu->max_timeouts) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Maximum timeouts\n"); switch_channel_set_variable(channel, "ivr_menu_status", "timeout"); break; } if (reps > 0 && menu->short_greeting_sound) { greeting_sound = menu->short_greeting_sound; } else { greeting_sound = menu->greeting_sound; } match = 0; aptr = NULL; memset(arg, 0, sizeof(arg)); memset(menu->buf, 0, menu->inlen + 1); if (play_and_collect(session, menu, greeting_sound, menu->inlen) == SWITCH_STATUS_TIMEOUT && *menu->buf == '\0') { timeouts++; continue; } if (*menu->buf != '\0') { for (ap = menu->actions; ap; ap = ap->next) { int ok = 0; char substituted[1024]; char *use_arg = ap->arg; if (!zstr(menu->tts_engine) && !zstr(menu->tts_voice)) { switch_channel_set_variable(channel, "tts_engine", menu->tts_engine); switch_channel_set_variable(channel, "tts_voice", menu->tts_voice); } if (ap->re) { switch_regex_t *re = NULL; int ovector[30]; if ((ok = switch_regex_perform(menu->buf, ap->bind, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) { switch_perform_substitution(re, ok, ap->arg, menu->buf, substituted, sizeof(substituted), ovector); use_arg = substituted; } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "action regex [%s] [%s] [%d]\n", menu->buf, ap->bind, ok); switch_regex_safe_free(re); } else { ok = !strcmp(menu->buf, ap->bind); } if (ok) { match++; errs = 0; if (ap->function) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "IVR function on menu '%s' matched '%s' param '%s'\n", menu->name, menu->buf, use_arg); todo = ap->function(menu, use_arg, arg, sizeof(arg), obj); aptr = arg; } else { todo = ap->ivr_action; aptr = use_arg; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "IVR action on menu '%s' matched '%s' param '%s'\n", menu->name, menu->buf, aptr); } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "switch_ivr_menu_execute todo=[%d]\n", todo); switch (todo) { case SWITCH_IVR_ACTION_DIE: status = SWITCH_STATUS_FALSE; break; case SWITCH_IVR_ACTION_PLAYSOUND: status = switch_ivr_play_file(session, NULL, aptr, NULL); break; case SWITCH_IVR_ACTION_EXECMENU: if (!strcmp(aptr, menu->name)) { status = SWITCH_STATUS_SUCCESS; } else { reps = -1; status = switch_ivr_menu_execute(session, stack, aptr, obj); } break; case SWITCH_IVR_ACTION_EXECAPP: { switch_application_interface_t *application_interface; char *app_name; char *app_arg = NULL; status = SWITCH_STATUS_FALSE; if (!zstr(aptr)) { app_name = switch_core_session_strdup(session, aptr); if ((app_arg = strchr(app_name, ' '))) { *app_arg++ = '\0'; } if ((application_interface = switch_loadable_module_get_application_interface(app_name))) { switch_core_session_exec(session, application_interface, app_arg); UNPROTECT_INTERFACE(application_interface); status = SWITCH_STATUS_SUCCESS; } } } break; case SWITCH_IVR_ACTION_BACK: running = 0; status = SWITCH_STATUS_SUCCESS; break; case SWITCH_IVR_ACTION_TOMAIN: switch_set_flag(stack, SWITCH_IVR_MENU_FLAG_FALLTOMAIN); status = SWITCH_STATUS_BREAK; break; case SWITCH_IVR_ACTION_NOOP: status = SWITCH_STATUS_SUCCESS; break; default: switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Invalid TODO!\n"); break; } } } if (switch_test_flag(menu, SWITCH_IVR_MENU_FLAG_STACK)) { /* top level */ if (switch_test_flag(stack, SWITCH_IVR_MENU_FLAG_FALLTOMAIN)) { /* catch the fallback and recover */ switch_clear_flag(stack, SWITCH_IVR_MENU_FLAG_FALLTOMAIN); status = SWITCH_STATUS_SUCCESS; running = 1; continue; } } } if (!match) { if (*menu->buf) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "IVR menu '%s' caught invalid input '%s'\n", menu->name, menu->buf); if (menu->invalid_sound) { play_and_collect(session, menu, menu->invalid_sound, 0); } } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "IVR menu '%s' no input detected\n", menu->name); } errs++; /* breaks are ok too */ if (SWITCH_STATUS_IS_BREAK(status)) { status = SWITCH_STATUS_SUCCESS; } } } if (stack->stack_count == 1) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "exit-sound '%s'\n", menu->exit_sound); if (!zstr(menu->exit_sound)) { status = play_and_collect(session, menu, menu->exit_sound, 0); } } end: stack->stack_count--; return status; }
static int parse_exten(switch_core_session_t *session, switch_caller_profile_t *caller_profile, switch_xml_t xexten, switch_caller_extension_t **extension, const char *exten_name, int recur) { switch_xml_t xcond, xaction, xexpression, xregex; switch_channel_t *channel = switch_core_session_get_channel(session); int proceed = 0, save_proceed = 0; char *expression_expanded = NULL, *field_expanded = NULL; switch_regex_t *re = NULL, *save_re = NULL; int offset = 0; const char *tmp, *tzoff = NULL, *tzname = NULL, *req_nesta = NULL; char nbuf[128] = ""; int req_nest = 1; char space[MAX_RECUR_SPACE] = ""; const char *orig_exten_name = exten_name; check_tz(); if (!exten_name) { exten_name = "_anon_"; } if (!orig_exten_name) { orig_exten_name = "_anon_"; } if (recur) { int i, j = 0, k = 0; if (recur > MAX_RECUR) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Recursion LIMIT!\n"); return 0; } switch_snprintf(nbuf, sizeof(nbuf), "%s_recur_%d", exten_name, recur); exten_name = nbuf; space[j++] = '|'; for (i = 0; i < recur; i++) { for (k = 0; k < RECUR_SPACE; k++) { if (i == recur-1 && k == RECUR_SPACE-1) { space[j++] = ' '; } else { space[j++] = '-'; } } } if ((req_nesta = switch_xml_attr(xexten, "require-nested"))) { req_nest = switch_true(req_nesta); } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG, "%sDialplan: Processing recursive conditions level:%d [%s] require-nested=%s\n", space, recur, exten_name, req_nest ? "TRUE" : "FALSE"); } else { if ((tmp = switch_xml_attr(xexten, "name"))) { exten_name = tmp; } } for (xcond = switch_xml_child(xexten, "condition"); xcond; xcond = xcond->next) { char *field = NULL; char *do_break_a = NULL; char *expression = NULL, *save_expression = NULL, *save_field_data = NULL; char *regex_rule = NULL; const char *field_data = NULL; int ovector[30]; switch_bool_t anti_action = SWITCH_TRUE; break_t do_break_i = BREAK_ON_FALSE; int time_match; check_tz(); time_match = switch_xml_std_datetime_check(xcond, tzoff ? &offset : NULL, tzname); switch_safe_free(field_expanded); switch_safe_free(expression_expanded); field = (char *) switch_xml_attr(xcond, "field"); if ((do_break_a = (char *) switch_xml_attr(xcond, "break"))) { if (!strcasecmp(do_break_a, "on-true")) { do_break_i = BREAK_ON_TRUE; } else if (!strcasecmp(do_break_a, "on-false")) { do_break_i = BREAK_ON_FALSE; } else if (!strcasecmp(do_break_a, "always")) { do_break_i = BREAK_ALWAYS; } else if (!strcasecmp(do_break_a, "never")) { do_break_i = BREAK_NEVER; } else { do_break_a = NULL; } } if (switch_xml_child(xcond, "condition")) { if (!(proceed = parse_exten(session, caller_profile, xcond, extension, orig_exten_name, recur + 1))) { if (do_break_i == BREAK_NEVER) { continue; } goto done; } } if (time_match == 1) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG, "%sDialplan: %s Date/Time Match (PASS) [%s] break=%s\n", space, switch_channel_get_name(channel), exten_name, do_break_a ? do_break_a : "on-false"); anti_action = SWITCH_FALSE; proceed = 1; } else if (time_match == 0) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG, "%sDialplan: %s Date/TimeMatch (FAIL) [%s] break=%s\n", space, switch_channel_get_name(channel), exten_name, do_break_a ? do_break_a : "on-false"); } if ((regex_rule = (char *) switch_xml_attr(xcond, "regex"))) { int all = !strcasecmp(regex_rule, "all"); int xor = !strcasecmp(regex_rule, "xor"); int pass = 0; int fail = 0; int total = 0; switch_channel_del_variable_prefix(channel, "DP_REGEX_MATCH"); for (xregex = switch_xml_child(xcond, "regex"); xregex; xregex = xregex->next) { check_tz(); time_match = switch_xml_std_datetime_check(xregex, tzoff ? &offset : NULL, tzname); if (time_match == 1) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG, "%sDialplan: %s Date/Time Match (PASS) [%s]\n", space, switch_channel_get_name(channel), exten_name); anti_action = SWITCH_FALSE; } else if (time_match == 0) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG, "%sDialplan: %s Date/TimeMatch (FAIL) [%s]\n", space, switch_channel_get_name(channel), exten_name); } if ((xexpression = switch_xml_child(xregex, "expression"))) { expression = switch_str_nil(xexpression->txt); } else { expression = (char *) switch_xml_attr_soft(xregex, "expression"); } if ((expression_expanded = switch_channel_expand_variables(channel, expression)) == expression) { expression_expanded = NULL; } else { expression = expression_expanded; } total++; field = (char *) switch_xml_attr(xregex, "field"); if (field) { if (strchr(field, '$')) { if ((field_expanded = switch_channel_expand_variables(channel, field)) == field) { field_expanded = NULL; field_data = field; } else { field_data = field_expanded; } } else { field_data = switch_caller_get_field_by_name(caller_profile, field); } if (!field_data) { field_data = ""; } if ((proceed = switch_regex_perform(field_data, expression, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG, "%sDialplan: %s Regex (PASS) [%s] %s(%s) =~ /%s/ match=%s\n", space, switch_channel_get_name(channel), exten_name, field, field_data, expression, all ? "all" : "any"); pass++; if (!all && !xor) break; } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG, "%sDialplan: %s Regex (FAIL) [%s] %s(%s) =~ /%s/ match=%s\n", space, switch_channel_get_name(channel), exten_name, field, field_data, expression, all ? "all" : "any"); fail++; if (all && !xor) break; } } else if (time_match == -1) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG, "%sDialplan: %s Absolute Condition [%s] match=%s\n", space, switch_channel_get_name(channel), exten_name, all ? "all" : "any"); pass++; proceed = 1; if (!all && !xor) break; } else if (time_match == 1) { pass++; proceed = 1; if (!all && !xor) break; } if (field && strchr(expression, '(')) { char var[256]; switch_snprintf(var, sizeof(var), "DP_REGEX_MATCH_%d", total); switch_channel_set_variable(channel, var, NULL); switch_capture_regex(re, proceed, field_data, ovector, var, switch_regex_set_var_callback, session); switch_safe_free(save_expression); switch_safe_free(save_field_data); switch_regex_safe_free(save_re); save_expression = strdup(expression); save_field_data = strdup(field_data); save_re = re; save_proceed = proceed; re = NULL; } switch_regex_safe_free(re); switch_safe_free(field_expanded); switch_safe_free(expression_expanded); } if (xor) { if (pass == 1) { anti_action = SWITCH_FALSE; } } else { if ((all && !fail) || (!all && pass)) { anti_action = SWITCH_FALSE; } } switch_safe_free(field_expanded); switch_safe_free(expression_expanded); } else { if ((xexpression = switch_xml_child(xcond, "expression"))) { expression = switch_str_nil(xexpression->txt); } else { expression = (char *) switch_xml_attr_soft(xcond, "expression"); } if ((expression_expanded = switch_channel_expand_variables(channel, expression)) == expression) { expression_expanded = NULL; } else { expression = expression_expanded; } if (field) { if (strchr(field, '$')) { if ((field_expanded = switch_channel_expand_variables(channel, field)) == field) { field_expanded = NULL; field_data = field; } else { field_data = field_expanded; } } else { field_data = switch_caller_get_field_by_name(caller_profile, field); } if (!field_data) { field_data = ""; } if ((proceed = switch_regex_perform(field_data, expression, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG, "%sDialplan: %s Regex (PASS) [%s] %s(%s) =~ /%s/ break=%s\n", space, switch_channel_get_name(channel), exten_name, field, field_data, expression, do_break_a ? do_break_a : "on-false"); anti_action = SWITCH_FALSE; } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG, "%sDialplan: %s Regex (FAIL) [%s] %s(%s) =~ /%s/ break=%s\n", space, switch_channel_get_name(channel), exten_name, field, field_data, expression, do_break_a ? do_break_a : "on-false"); } } else if (time_match == -1) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG, "%sDialplan: %s Absolute Condition [%s]\n", space, switch_channel_get_name(channel), exten_name); anti_action = SWITCH_FALSE; proceed = 1; } } if (save_re) { re = save_re; save_re = NULL; expression = expression_expanded = save_expression; save_expression = NULL; field_data = field_expanded = save_field_data; field = (char *) field_data; save_field_data = NULL; proceed = save_proceed; } if (anti_action) { for (xaction = switch_xml_child(xcond, "anti-action"); xaction; xaction = xaction->next) { const char *application = switch_xml_attr_soft(xaction, "application"); const char *loop = switch_xml_attr(xaction, "loop"); const char *data; const char *inline_ = switch_xml_attr_soft(xaction, "inline"); int xinline = switch_true(inline_); int loop_count = 1; if (!zstr(xaction->txt)) { data = xaction->txt; } else { data = (char *) switch_xml_attr_soft(xaction, "data"); } if (!*extension) { if ((*extension = switch_caller_extension_new(session, exten_name, caller_profile->destination_number)) == 0) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Memory Error!\n"); proceed = 0; goto done; } } if (loop) { loop_count = atoi(loop); } for (;loop_count > 0; loop_count--) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG, "%sDialplan: %s ANTI-Action %s(%s) %s\n", space, switch_channel_get_name(channel), application, data, xinline ? "INLINE" : ""); if (xinline) { exec_app(session, application, data); } else { switch_caller_extension_add_application(session, *extension, application, data); } } proceed = 1; } } else { if (field && strchr(expression, '(')) { switch_channel_set_variable(channel, "DP_MATCH", NULL); switch_capture_regex(re, proceed, field_data, ovector, "DP_MATCH", switch_regex_set_var_callback, session); } for (xaction = switch_xml_child(xcond, "action"); xaction; xaction = xaction->next) { char *application = (char *) switch_xml_attr_soft(xaction, "application"); const char *loop = switch_xml_attr(xaction, "loop"); char *data = NULL; char *substituted = NULL; uint32_t len = 0; char *app_data = NULL; const char *inline_ = switch_xml_attr_soft(xaction, "inline"); int xinline = switch_true(inline_); int loop_count = 1; if (!zstr(xaction->txt)) { data = xaction->txt; } else { data = (char *) switch_xml_attr_soft(xaction, "data"); } if (field && strchr(expression, '(')) { len = (uint32_t) (strlen(data) + strlen(field_data) + 10) * proceed; if (!(substituted = malloc(len))) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Memory Error!\n"); proceed = 0; goto done; } memset(substituted, 0, len); switch_perform_substitution(re, proceed, data, field_data, substituted, len, ovector); app_data = substituted; } else { app_data = data; } if (!*extension) { if ((*extension = switch_caller_extension_new(session, exten_name, caller_profile->destination_number)) == 0) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Memory Error!\n"); proceed = 0; goto done; } } if (loop) { loop_count = atoi(loop); } for (;loop_count > 0; loop_count--) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG, "%sDialplan: %s Action %s(%s) %s\n", space, switch_channel_get_name(channel), application, app_data, xinline ? "INLINE" : ""); if (xinline) { exec_app(session, application, app_data); } else { switch_caller_extension_add_application(session, *extension, application, app_data); } } switch_safe_free(substituted); } } switch_regex_safe_free(re); if (((anti_action == SWITCH_FALSE && do_break_i == BREAK_ON_TRUE) || (anti_action == SWITCH_TRUE && do_break_i == BREAK_ON_FALSE)) || do_break_i == BREAK_ALWAYS) { break; } } done: switch_regex_safe_free(re); switch_safe_free(field_expanded); switch_safe_free(expression_expanded); if (!req_nest) proceed = 1; return proceed; }
static int parse_exten(switch_event_t *event, switch_xml_t xexten, switch_event_t **extension) { switch_xml_t xcond, xaction, xexpression; char *exten_name = (char *) switch_xml_attr(xexten, "name"); int proceed = 0; char *expression_expanded = NULL, *field_expanded = NULL; switch_regex_t *re = NULL; const char *to = switch_event_get_header(event, "to"); const char *tzoff = NULL, *tzname = NULL; int offset = 0; check_tz(); if (!to) { to = "nobody"; } if (!exten_name) { exten_name = "_anon_"; } for (xcond = switch_xml_child(xexten, "condition"); xcond; xcond = xcond->next) { char *field = NULL; char *do_break_a = NULL; char *expression = NULL; const char *field_data = NULL; int ovector[30]; switch_bool_t anti_action = SWITCH_TRUE; break_t do_break_i = BREAK_ON_FALSE; int time_match; check_tz(); time_match = switch_xml_std_datetime_check(xcond, tzoff ? &offset : NULL, tzname); switch_safe_free(field_expanded); switch_safe_free(expression_expanded); if (switch_xml_child(xcond, "condition")) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Nested conditions are not allowed!\n"); proceed = 1; goto done; } field = (char *) switch_xml_attr(xcond, "field"); if ((xexpression = switch_xml_child(xcond, "expression"))) { expression = switch_str_nil(xexpression->txt); } else { expression = (char *) switch_xml_attr_soft(xcond, "expression"); } if ((expression_expanded = switch_event_expand_headers(event, expression)) == expression) { expression_expanded = NULL; } else { expression = expression_expanded; } if ((do_break_a = (char *) switch_xml_attr(xcond, "break"))) { if (!strcasecmp(do_break_a, "on-true")) { do_break_i = BREAK_ON_TRUE; } else if (!strcasecmp(do_break_a, "on-false")) { do_break_i = BREAK_ON_FALSE; } else if (!strcasecmp(do_break_a, "always")) { do_break_i = BREAK_ALWAYS; } else if (!strcasecmp(do_break_a, "never")) { do_break_i = BREAK_NEVER; } else { do_break_a = NULL; } } if (time_match == 1) { switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Chatplan: %s Date/Time Match (PASS) [%s] break=%s\n", to, exten_name, do_break_a ? do_break_a : "on-false"); anti_action = SWITCH_FALSE; } else if (time_match == 0) { switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Chatplan: %s Date/Time Match (FAIL) [%s] break=%s\n", to, exten_name, do_break_a ? do_break_a : "on-false"); } if (field) { if (strchr(field, '$')) { if ((field_expanded = switch_event_expand_headers(event, field)) == field) { field_expanded = NULL; field_data = field; } else { field_data = field_expanded; } } else { field_data = switch_event_get_header(event, field); } if (!field_data) { field_data = ""; } if ((proceed = switch_regex_perform(field_data, expression, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) { switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Chatplan: %s Regex (PASS) [%s] %s(%s) =~ /%s/ break=%s\n", to, exten_name, field, field_data, expression, do_break_a ? do_break_a : "on-false"); anti_action = SWITCH_FALSE; } else { switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Chatplan: %s Regex (FAIL) [%s] %s(%s) =~ /%s/ break=%s\n", to, exten_name, field, field_data, expression, do_break_a ? do_break_a : "on-false"); } } else if (time_match == -1) { switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Chatplan: %s Absolute Condition [%s]\n", to, exten_name); anti_action = SWITCH_FALSE; } if (anti_action) { for (xaction = switch_xml_child(xcond, "anti-action"); xaction; xaction = xaction->next) { const char *application = switch_xml_attr_soft(xaction, "application"); const char *loop = switch_xml_attr(xaction, "loop"); const char *data; const char *inline_ = switch_xml_attr_soft(xaction, "inline"); int xinline = switch_true(inline_); int loop_count = 1; if (!zstr(xaction->txt)) { data = xaction->txt; } else { data = (char *) switch_xml_attr_soft(xaction, "data"); } if (!*extension) { if ((switch_event_create(extension, SWITCH_EVENT_CLONE)) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n"); abort(); } } if (loop) { loop_count = atoi(loop); } for (;loop_count > 0; loop_count--) { switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Chatplan: %s ANTI-Action %s(%s) %s\n", to, application, data, xinline ? "INLINE" : ""); if (xinline) { switch_core_execute_chat_app(event, application, data); } else { switch_event_add_header_string(*extension, SWITCH_STACK_BOTTOM, application, zstr(data) ? "__undef" : data); } } proceed = 1; } } else { if (field && strchr(expression, '(')) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "DP_MATCH", NULL); switch_capture_regex(re, proceed, field_data, ovector, "DP_MATCH", switch_regex_set_event_header_callback, event); } for (xaction = switch_xml_child(xcond, "action"); xaction; xaction = xaction->next) { char *application = (char *) switch_xml_attr_soft(xaction, "application"); const char *loop = switch_xml_attr(xaction, "loop"); char *data = NULL; char *substituted = NULL; uint32_t len = 0; char *app_data = NULL; const char *inline_ = switch_xml_attr_soft(xaction, "inline"); int xinline = switch_true(inline_); int loop_count = 1; if (!zstr(xaction->txt)) { data = xaction->txt; } else { data = (char *) switch_xml_attr_soft(xaction, "data"); } if (field && strchr(expression, '(')) { len = (uint32_t) (strlen(data) + strlen(field_data) + 10) * proceed; if (!(substituted = (char *) malloc(len))) { abort(); } memset(substituted, 0, len); switch_perform_substitution(re, proceed, data, field_data, substituted, len, ovector); app_data = substituted; } else { app_data = data; } if (!*extension) { if ((switch_event_create(extension, SWITCH_EVENT_CLONE)) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n"); abort(); } } if (loop) { loop_count = atoi(loop); } for (;loop_count > 0; loop_count--) { switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Chatplan: %s Action %s(%s) %s\n", to, application, app_data, xinline ? "INLINE" : ""); if (xinline) { switch_core_execute_chat_app(event, application, app_data); } else { switch_event_add_header_string(*extension, SWITCH_STACK_BOTTOM, application, zstr(app_data) ? "__undef" : app_data); } } switch_safe_free(substituted); } } switch_regex_safe_free(re); if (((anti_action == SWITCH_FALSE && do_break_i == BREAK_ON_TRUE) || (anti_action == SWITCH_TRUE && do_break_i == BREAK_ON_FALSE)) || do_break_i == BREAK_ALWAYS) { break; } } done: switch_regex_safe_free(re); switch_safe_free(field_expanded); switch_safe_free(expression_expanded); return proceed; }
static int parse_exten(switch_core_session_t *session, switch_caller_profile_t *caller_profile, switch_xml_t xexten, switch_caller_extension_t **extension) { switch_xml_t xcond, xaction, xexpression; switch_channel_t *channel = switch_core_session_get_channel(session); char *exten_name = (char *) switch_xml_attr(xexten, "name"); int proceed = 0; char *expression_expanded = NULL, *field_expanded = NULL; switch_regex_t *re = NULL; if (!exten_name) { exten_name = "_anon_"; } for (xcond = switch_xml_child(xexten, "condition"); xcond; xcond = xcond->next) { char *field = NULL; char *do_break_a = NULL; char *expression = NULL; const char *field_data = NULL; int ovector[30]; switch_bool_t anti_action = SWITCH_TRUE; break_t do_break_i = BREAK_ON_FALSE; int time_match = switch_xml_std_datetime_check(xcond); switch_safe_free(field_expanded); switch_safe_free(expression_expanded); if (switch_xml_child(xcond, "condition")) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Nested conditions are not allowed!\n"); proceed = 1; goto done; } field = (char *) switch_xml_attr(xcond, "field"); if ((xexpression = switch_xml_child(xcond, "expression"))) { expression = switch_str_nil(xexpression->txt); } else { expression = (char *) switch_xml_attr_soft(xcond, "expression"); } if ((expression_expanded = switch_channel_expand_variables(channel, expression)) == expression) { expression_expanded = NULL; } else { expression = expression_expanded; } if ((do_break_a = (char *) switch_xml_attr(xcond, "break"))) { if (!strcasecmp(do_break_a, "on-true")) { do_break_i = BREAK_ON_TRUE; } else if (!strcasecmp(do_break_a, "on-false")) { do_break_i = BREAK_ON_FALSE; } else if (!strcasecmp(do_break_a, "always")) { do_break_i = BREAK_ALWAYS; } else if (!strcasecmp(do_break_a, "never")) { do_break_i = BREAK_NEVER; } else { do_break_a = NULL; } } if (time_match == 1) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG, "Dialplan: %s Date/Time Match (PASS) [%s] break=%s\n", switch_channel_get_name(channel), exten_name, do_break_a ? do_break_a : "on-false"); anti_action = SWITCH_FALSE; } else if (time_match == 0) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG, "Dialplan: %s Date/Time Match (FAIL) [%s] break=%s\n", switch_channel_get_name(channel), exten_name, do_break_a ? do_break_a : "on-false"); } if (field) { if (strchr(field, '$')) { if ((field_expanded = switch_channel_expand_variables(channel, field)) == field) { field_expanded = NULL; field_data = field; } else { field_data = field_expanded; } } else { field_data = switch_caller_get_field_by_name(caller_profile, field); } if (!field_data) { field_data = ""; } if ((proceed = switch_regex_perform(field_data, expression, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG, "Dialplan: %s Regex (PASS) [%s] %s(%s) =~ /%s/ break=%s\n", switch_channel_get_name(channel), exten_name, field, field_data, expression, do_break_a ? do_break_a : "on-false"); anti_action = SWITCH_FALSE; } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG, "Dialplan: %s Regex (FAIL) [%s] %s(%s) =~ /%s/ break=%s\n", switch_channel_get_name(channel), exten_name, field, field_data, expression, do_break_a ? do_break_a : "on-false"); } } else if (time_match == -1) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG, "Dialplan: %s Absolute Condition [%s]\n", switch_channel_get_name(channel), exten_name); anti_action = SWITCH_FALSE; } if (anti_action) { for (xaction = switch_xml_child(xcond, "anti-action"); xaction; xaction = xaction->next) { const char *application = switch_xml_attr_soft(xaction, "application"); const char *loop = switch_xml_attr(xaction, "loop"); const char *data; const char *inline_ = switch_xml_attr_soft(xaction, "inline"); int xinline = switch_true(inline_); int loop_count = 1; if (!zstr(xaction->txt)) { data = xaction->txt; } else { data = (char *) switch_xml_attr_soft(xaction, "data"); } if (!*extension) { if ((*extension = switch_caller_extension_new(session, exten_name, caller_profile->destination_number)) == 0) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Memory Error!\n"); proceed = 0; goto done; } } if (loop) { loop_count = atoi(loop); } for (;loop_count > 0; loop_count--) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG, "Dialplan: %s ANTI-Action %s(%s) %s\n", switch_channel_get_name(channel), application, data, xinline ? "INLINE" : ""); if (xinline) { exec_app(session, application, data); } else { switch_caller_extension_add_application(session, *extension, application, data); } } proceed = 1; } } else { for (xaction = switch_xml_child(xcond, "action"); xaction; xaction = xaction->next) { char *application = (char *) switch_xml_attr_soft(xaction, "application"); const char *loop = switch_xml_attr(xaction, "loop"); char *data = NULL; char *substituted = NULL; uint32_t len = 0; char *app_data = NULL; const char *inline_ = switch_xml_attr_soft(xaction, "inline"); int xinline = switch_true(inline_); int loop_count = 1; if (!zstr(xaction->txt)) { data = xaction->txt; } else { data = (char *) switch_xml_attr_soft(xaction, "data"); } if (field && strchr(expression, '(')) { len = (uint32_t) (strlen(data) + strlen(field_data) + 10) * proceed; if (!(substituted = malloc(len))) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Memory Error!\n"); proceed = 0; goto done; } memset(substituted, 0, len); switch_perform_substitution(re, proceed, data, field_data, substituted, len, ovector); app_data = substituted; } else { app_data = data; } if (!*extension) { if ((*extension = switch_caller_extension_new(session, exten_name, caller_profile->destination_number)) == 0) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Memory Error!\n"); proceed = 0; goto done; } } if (loop) { loop_count = atoi(loop); } for (;loop_count > 0; loop_count--) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG, "Dialplan: %s Action %s(%s) %s\n", switch_channel_get_name(channel), application, app_data, xinline ? "INLINE" : ""); if (xinline) { exec_app(session, application, app_data); } else { switch_caller_extension_add_application(session, *extension, application, app_data); } } switch_safe_free(substituted); } } switch_regex_safe_free(re); if (((anti_action == SWITCH_FALSE && do_break_i == BREAK_ON_TRUE) || (anti_action == SWITCH_TRUE && do_break_i == BREAK_ON_FALSE)) || do_break_i == BREAK_ALWAYS) { break; } } done: switch_regex_safe_free(re); switch_safe_free(field_expanded); switch_safe_free(expression_expanded); return proceed; }