aboutsummaryrefslogtreecommitdiffstats
path: root/pbx.c
diff options
context:
space:
mode:
authorkpfleming <kpfleming@f38db490-d61c-443f-a65b-d21fe96a405b>2005-04-03 21:32:33 +0000
committerkpfleming <kpfleming@f38db490-d61c-443f-a65b-d21fe96a405b>2005-04-03 21:32:33 +0000
commit613385598fa0d53cf36b0fcd5ec4095ef4a0868a (patch)
treee63036882572c60a418a0c8d5ede07f53fba2ebc /pbx.c
parent0990055d319b997c718b0ef8340145fdcf3e2b6a (diff)
add 'early-match' wildcard for extension patterns (bug #3889)
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@5370 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'pbx.c')
-rwxr-xr-xpbx.c38
1 files changed, 30 insertions, 8 deletions
diff --git a/pbx.c b/pbx.c
index aa1d11bef..8522b470a 100755
--- a/pbx.c
+++ b/pbx.c
@@ -633,6 +633,9 @@ static void pbx_destroy(struct ast_pbx *p)
case '.':\
/* Must match */\
return 1;\
+ case '+':\
+ /* Early match */\
+ return 2;\
case ' ':\
case '-':\
/* Ignore these characters */\
@@ -645,6 +648,9 @@ static void pbx_destroy(struct ast_pbx *p)
data++;\
pattern++;\
}\
+ /* If we ran off the end of the data and the pattern ends in '+', match */\
+ if (match && !*data && (*pattern == '+'))\
+ return 2;\
}
int ast_extension_match(const char *pattern, const char *data)
@@ -673,8 +679,9 @@ int ast_extension_close(const char *pattern, const char *data, int needmore)
return 1;
}
EXTENSION_MATCH_CORE(data,pattern,match);
- /* If there's more or we don't care about more, return non-zero, otlherwise it's a miss */
- if (!needmore || *pattern) {
+ /* If there's more or we don't care about more, or if it's a possible early match,
+ return non-zero; otherwise it's a miss */
+ if (!needmore || *pattern || match == 2) {
return match;
} else
return 0;
@@ -754,15 +761,23 @@ static struct ast_exten *pbx_find_extension(struct ast_channel *chan, struct ast
while(tmp) {
/* Match context */
if (bypass || !strcmp(tmp->name, context)) {
+ struct ast_exten *earlymatch = NULL;
+
if (*status < STATUS_NO_EXTENSION)
*status = STATUS_NO_EXTENSION;
- eroot = tmp->root;
- while(eroot) {
+ for (eroot = tmp->root; eroot; eroot=eroot->next) {
+ int match = 0;
/* Match extension */
if ((((action != HELPER_MATCHMORE) && ast_extension_match(eroot->exten, exten)) ||
- ((action == HELPER_CANMATCH) && (ast_extension_close(eroot->exten, exten, 0))) ||
- ((action == HELPER_MATCHMORE) && (ast_extension_close(eroot->exten, exten, 1)))) &&
- (!eroot->matchcid || matchcid(eroot->cidmatch, callerid))) {
+ ((action == HELPER_CANMATCH) && (ast_extension_close(eroot->exten, exten, 0))) ||
+ ((action == HELPER_MATCHMORE) && (match = ast_extension_close(eroot->exten, exten, 1)))) &&
+ (!eroot->matchcid || matchcid(eroot->cidmatch, callerid))) {
+
+ if (action == HELPER_MATCHMORE && match == 2 && !earlymatch) {
+ /* It matched an extension ending in a '+' wildcard
+ So ignore it for now, unless there's a better match */
+ earlymatch = eroot;
+ } else {
e = eroot;
if (*status < STATUS_NO_PRIORITY)
*status = STATUS_NO_PRIORITY;
@@ -783,8 +798,15 @@ static struct ast_exten *pbx_find_extension(struct ast_channel *chan, struct ast
}
e = e->peer;
}
+ }
}
- eroot = eroot->next;
+ }
+ if (earlymatch) {
+ /* Bizarre logic for HELPER_MATCHMORE. We return zero to break out
+ of the loop waiting for more digits, and _then_ match (normally)
+ the extension we ended up with. We got an early-matching wildcard
+ pattern, so return NULL to break out of the loop. */
+ return NULL;
}
/* Check alternative switches */
sw = tmp->alts;