Skip to content
Snippets Groups Projects
Commit fc0b625d authored by Kevin P. Fleming's avatar Kevin P. Fleming
Browse files

make While() able to find the matching EndWhile() for when the condition is zero (issue #5145)

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@6586 65c4cc65-6c06-0410-ace0-fbb531ad65f3
parent 16cd2019
No related branches found
No related tags found
No related merge requests found
...@@ -27,6 +27,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") ...@@ -27,6 +27,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/pbx.h" #include "asterisk/pbx.h"
#include "asterisk/module.h" #include "asterisk/module.h"
#include "asterisk/lock.h" #include "asterisk/lock.h"
#include "asterisk/options.h"
#define ALL_DONE(u,ret) {LOCAL_USER_REMOVE(u); return ret;} #define ALL_DONE(u,ret) {LOCAL_USER_REMOVE(u); return ret;}
...@@ -108,6 +109,81 @@ static char *get_index(struct ast_channel *chan, const char *prefix, int index) ...@@ -108,6 +109,81 @@ static char *get_index(struct ast_channel *chan, const char *prefix, int index)
return pbx_builtin_getvar_helper(chan, varname); return pbx_builtin_getvar_helper(chan, varname);
} }
static struct ast_exten *find_matching_priority(struct ast_context *c, const char *exten, int priority, const char *callerid)
{
struct ast_exten *e;
struct ast_include *i;
struct ast_context *c2;
for (e=ast_walk_context_extensions(c, NULL); e; e=ast_walk_context_extensions(c, e)) {
if (ast_extension_match(ast_get_extension_name(e), exten)) {
int needmatch = ast_get_extension_matchcid(e);
if ((needmatch && ast_extension_match(ast_get_extension_cidmatch(e), callerid)) ||
(!needmatch)) {
/* This is the matching extension we want */
struct ast_exten *p;
for (p=ast_walk_extension_priorities(e, NULL); p; p=ast_walk_extension_priorities(e, p)) {
if (priority != ast_get_extension_priority(p))
continue;
return p;
}
}
}
}
/* No match; run through includes */
for (i=ast_walk_context_includes(c, NULL); i; i=ast_walk_context_includes(c, i)) {
for (c2=ast_walk_contexts(NULL); c2; c2=ast_walk_contexts(c2)) {
if (!strcmp(ast_get_context_name(c2), ast_get_include_name(i))) {
e = find_matching_priority(c2, exten, priority, callerid);
if (e)
return e;
}
}
}
return NULL;
}
static int find_matching_endwhile(struct ast_channel *chan)
{
struct ast_context *c;
int res=-1;
if (ast_lock_contexts()) {
ast_log(LOG_ERROR, "Failed to lock contexts list\n");
return -1;
}
for (c=ast_walk_contexts(NULL); c; c=ast_walk_contexts(c)) {
struct ast_exten *e;
if (!ast_lock_context(c)) {
if (!strcmp(ast_get_context_name(c), chan->context)) {
/* This is the matching context we want */
int cur_priority = chan->priority + 1, level=1;
for (e = find_matching_priority(c, chan->exten, cur_priority, chan->cid.cid_num); e; e = find_matching_priority(c, chan->exten, ++cur_priority, chan->cid.cid_num)) {
if (!strcasecmp(ast_get_extension_app(e), "WHILE")) {
level++;
} else if (!strcasecmp(ast_get_extension_app(e), "ENDWHILE")) {
level--;
}
if (level == 0) {
res = cur_priority;
break;
}
}
}
ast_unlock_context(c);
if (res > 0) {
break;
}
}
}
ast_unlock_contexts();
return res;
}
static int _while_exec(struct ast_channel *chan, void *data, int end) static int _while_exec(struct ast_channel *chan, void *data, int end)
{ {
...@@ -181,6 +257,15 @@ static int _while_exec(struct ast_channel *chan, void *data, int end) ...@@ -181,6 +257,15 @@ static int _while_exec(struct ast_channel *chan, void *data, int end)
if ((goto_str=pbx_builtin_getvar_helper(chan, end_varname))) { if ((goto_str=pbx_builtin_getvar_helper(chan, end_varname))) {
pbx_builtin_setvar_helper(chan, end_varname, NULL); pbx_builtin_setvar_helper(chan, end_varname, NULL);
ast_parseable_goto(chan, goto_str); ast_parseable_goto(chan, goto_str);
} else {
int pri = find_matching_endwhile(chan);
if (pri > 0) {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Jumping to priority %d\n", pri);
chan->priority = pri;
} else {
ast_log(LOG_WARNING, "Couldn't find matching EndWhile? (While at %s@%s priority %d)\n", chan->context, chan->exten, chan->priority);
}
} }
ALL_DONE(u,res); ALL_DONE(u,res);
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment