From 13e77721bc8b56a8635be3e4d7efa0f6ff3d69b7 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 15 May 2018 17:11:16 -0500 Subject: [PATCH] FS-11165: [freeswitch-core] Add more regex handling to dmachine #resolve --- src/switch_ivr_async.c | 67 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 60 insertions(+), 7 deletions(-) diff --git a/src/switch_ivr_async.c b/src/switch_ivr_async.c index bb574ee828..bdbbe390b5 100644 --- a/src/switch_ivr_async.c +++ b/src/switch_ivr_async.c @@ -40,6 +40,9 @@ struct switch_ivr_dmachine_binding { char *digits; + char *repl; + int first_match; + char *substituted; int32_t key; uint8_t rmatch; switch_ivr_dmachine_callback_t callback; @@ -258,6 +261,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_bind(switch_ivr_dmachine_t * switch_size_t len; dm_binding_head_t *headp; const char *msg = ""; + char *repl = NULL; + char *digits_; if (strlen(digits) > DMACHINE_MAX_DIGIT_LEN -1) { return SWITCH_STATUS_FALSE; @@ -286,16 +291,28 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_bind(switch_ivr_dmachine_t * binding = switch_core_alloc(dmachine->pool, sizeof(*binding)); - if (*digits == '~') { + digits_ = switch_core_strdup(dmachine->pool, digits); + + if (*digits_ == '=') { + binding->first_match = 1; + digits_++; + } + + if (*digits_ == '~') { binding->is_regex = 1; - digits++; + digits_++; + if ((repl = strchr(digits_, '~')) && *(repl+1) == '~') { + *repl++ = '\0'; + *repl++ = '\0'; + } } binding->key = key; - binding->digits = switch_core_strdup(dmachine->pool, digits); + binding->digits = digits_; binding->is_priority = is_priority; binding->callback = callback; binding->user_data = user_data; + binding->repl = repl; if (headp->tail) { headp->tail->next = binding; @@ -349,13 +366,44 @@ static dm_match_t switch_ivr_dmachine_check_match(switch_ivr_dmachine_t *dmachin for(bp = dmachine->realm->binding_list; bp; bp = bp->next) { if (bp->is_regex) { - switch_status_t r_status = switch_regex_match(dmachine->digits, bp->digits); + if (bp->repl) { + int ovector[30] = { 0 }; + int proceed = 0; + switch_regex_t *re = NULL; - bp->rmatch = r_status == SWITCH_STATUS_SUCCESS; + + proceed = switch_regex_perform(dmachine->digits, bp->digits, &re, ovector, sizeof(ovector) / sizeof(ovector[0])); + + if (proceed) { + char *substituted = NULL; + switch_size_t len; + + len = (strlen(dmachine->digits) + strlen(bp->digits) + 10) * proceed; + substituted = malloc(len); + switch_assert(substituted); + memset(substituted, 0, len); + switch_perform_substitution(re, proceed, bp->repl, dmachine->digits, substituted, len, ovector); + + if (!bp->substituted || strcmp(substituted, bp->substituted)) { + bp->substituted = switch_core_strdup(dmachine->pool, substituted); + } + free(substituted); + switch_regex_safe_free(re); + bp->rmatch = 1; + } else { + bp->substituted = NULL; + bp->rmatch = 0; + } + } else { + switch_status_t r_status = switch_regex_match(dmachine->digits, bp->digits); + bp->rmatch = r_status == SWITCH_STATUS_SUCCESS; + } rmatches++; pmatches++; + if (bp->rmatch && bp->first_match) break; + } else { if (!strncmp(dmachine->digits, bp->digits, strlen(dmachine->digits))) { pmatches++; @@ -383,7 +431,7 @@ static dm_match_t switch_ivr_dmachine_check_match(switch_ivr_dmachine_t *dmachin for(bp = dmachine->realm->binding_list; bp; bp = bp->next) { if (bp->is_regex) { if (bp->rmatch) { - if ((bp->is_priority && ! ematches) || is_timeout || (bp == dmachine->realm->binding_list && !bp->next)) { + if (bp->first_match || (bp->is_priority && ! ematches) || is_timeout || (bp == dmachine->realm->binding_list && !bp->next)) { best = DM_MATCH_EXACT; exact_bp = bp; break; @@ -434,7 +482,12 @@ static dm_match_t switch_ivr_dmachine_check_match(switch_ivr_dmachine_t *dmachin if (r_bp) { dmachine->last_matching_binding = r_bp; - switch_set_string(dmachine->last_matching_digits, dmachine->digits); + + if (r_bp->substituted) { + switch_set_string(dmachine->last_matching_digits, r_bp->substituted); + } else { + switch_set_string(dmachine->last_matching_digits, dmachine->digits); + } best = DM_MATCH_EXACT; }