130 static char *if_app =
"If";
131 static char *elseif_app =
"ElseIf";
132 static char *else_app =
"Else";
133 static char *stop_app =
"EndIf";
134 static char *exit_app =
"ExitIf";
138 static const char *get_index(
struct ast_channel *chan,
const char *prefix,
int idx)
140 char varname[VAR_SIZE];
142 snprintf(varname, VAR_SIZE,
"%s_%d", prefix, idx);
152 for (e = ast_walk_context_extensions(c, NULL); e; e = ast_walk_context_extensions(c, e)) {
154 int needmatch = ast_get_extension_matchcid(e);
159 for (p = ast_walk_extension_priorities(e, NULL); p; p = ast_walk_extension_priorities(e, p)) {
160 if (priority != ast_get_extension_priority(p))
169 for (idx = 0; idx < ast_context_includes_count(c); idx++) {
170 const struct ast_include *i = ast_context_includes_get(c, idx);
172 for (c2 = ast_walk_contexts(NULL); c2; c2 = ast_walk_contexts(c2)) {
173 if (!strcmp(ast_get_context_name(c2), ast_get_include_name(i))) {
174 e = find_matching_priority(c2, exten, priority, callerid);
183 static int find_matching_endif(
struct ast_channel *chan,
const char *otherapp)
189 ast_log(LOG_ERROR,
"Failed to lock contexts list\n");
193 for (c = ast_walk_contexts(NULL); c; c = ast_walk_contexts(c)) {
197 if (!strcmp(ast_get_context_name(c), ast_channel_context(chan))) {
200 int cur_priority = ast_channel_priority(chan) + 1, level = 1;
202 for (e = find_matching_priority(c, ast_channel_exten(chan), cur_priority,
203 S_COR(ast_channel_caller(chan)->
id.
number.valid, ast_channel_caller(chan)->
id.
number.str, NULL));
205 e = find_matching_priority(c, ast_channel_exten(chan), ++cur_priority,
206 S_COR(ast_channel_caller(chan)->
id.
number.valid, ast_channel_caller(chan)->
id.
number.str, NULL))) {
208 if (!strcasecmp(ast_get_extension_app(e),
"IF")) {
210 }
else if (!strcasecmp(ast_get_extension_app(e),
"ENDIF")) {
214 if (!otherapp && level == 0) {
217 }
else if (otherapp && level == 1 && !strcasecmp(ast_get_extension_app(e), otherapp)) {
233 static int if_helper(
struct ast_channel *chan,
const char *
data,
int end)
236 const char *if_pri = NULL;
237 char *my_name = NULL;
238 const char *
label = NULL;
239 char varname[VAR_SIZE + 3];
240 char end_varname[
sizeof(varname) + 4];
241 const char *prefix =
"IF";
243 int used_index_i = -1, x = 0;
244 char used_index[VAR_SIZE] =
"0", new_index[VAR_SIZE] =
"0";
251 if (get_index(chan, prefix, x)) {
258 snprintf(used_index,
sizeof(used_index),
"%d", used_index_i);
259 snprintf(new_index,
sizeof(new_index),
"%d", used_index_i + 1);
261 size = strlen(ast_channel_context(chan)) + strlen(ast_channel_exten(chan)) + 32;
263 memset(my_name, 0, size);
264 snprintf(my_name, size,
"%s_%s_%d", ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan));
266 ast_channel_lock(chan);
273 snprintf(varname,
sizeof(varname),
"%s_%s", prefix, label);
276 snprintf(end_varname,
sizeof(end_varname),
"END_%s",varname);
278 ast_channel_unlock(chan);
282 const char *goto_str;
286 snprintf(end_varname,
sizeof(end_varname),
"END_%s",varname);
287 ast_channel_lock(chan);
293 endifpri = end == 2 ? ast_channel_priority(chan) : find_matching_endif(chan, NULL);
297 }
else if (end <= 1 && (pri = find_matching_endif(chan,
"ElseIf")) > 0 && pri < endifpri) {
300 ast_verb(3,
"Taking conditional false branch, jumping to priority %d\n", pri);
301 ast_channel_priority_set(chan, pri);
302 }
else if (end <= 1 && (pri = find_matching_endif(chan,
"Else")) > 0 && pri < endifpri) {
305 ast_verb(3,
"Taking absolute false branch, jumping to priority %d\n", pri);
306 ast_channel_priority_set(chan, pri);
310 ast_verb(3,
"Exiting conditional, jumping to priority %d\n", pri);
311 ast_channel_priority_set(chan, pri);
312 }
else if (end == 4) {
313 ast_log(LOG_WARNING,
"Couldn't find matching EndIf? (If at %s@%s priority %d)\n", ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan));
316 ast_channel_unlock(chan);
320 if (end <= 1 && !if_pri) {
322 size = strlen(ast_channel_context(chan)) + strlen(ast_channel_exten(chan)) + 32;
324 memset(goto_str, 0, size);
325 snprintf(goto_str, size,
"%s,%s,%d", ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan));
327 }
else if (end > 1 && if_pri) {
329 snprintf(end_varname,
sizeof(end_varname),
"END_%s", varname);
332 size = strlen(ast_channel_context(chan)) + strlen(ast_channel_exten(chan)) + 32;
334 memset(goto_str, 0, size);
335 snprintf(goto_str, size,
"%s,%s,%d", ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan)+1);
344 static int if_exec(
struct ast_channel *chan,
const char *data) {
345 return if_helper(chan, data, 0);
348 static int elseif_exec(
struct ast_channel *chan,
const char *data) {
349 return if_helper(chan, data, 1);
352 static int end_exec(
struct ast_channel *chan,
const char *data) {
353 return if_helper(chan, data, 2);
356 static int else_exec(
struct ast_channel *chan,
const char *data) {
357 return if_helper(chan, data, 3);
360 static int exit_exec(
struct ast_channel *chan,
const char *data) {
361 return if_helper(chan, data, 4);
364 static int unload_module(
void)
377 static int load_module(
void)
390 AST_MODULE_INFO_STANDARD_EXTENDED(
ASTERISK_GPL_KEY,
"If Branch and Conditional Execution");
ast_include: include= support in extensions.conf
int ast_unlock_context(struct ast_context *con)
Main Channel structure associated with a channel.
Asterisk main include file. File version handling, generic pbx functions.
ast_exten: An extension The dialplan is saved as a linked list with each context having it's own link...
int pbx_checkcondition(const char *condition)
Evaluate a condition.
int ast_rdlock_contexts(void)
Read locks the context list.
int ast_unregister_application(const char *app)
Unregister an application.
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
General Asterisk PBX channel definitions.
#define ast_strdupa(s)
duplicate a string in memory from the stack
int ast_parseable_goto(struct ast_channel *chan, const char *goto_string)
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Core PBX routines and definitions.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
int ast_unlock_contexts(void)
Unlocks contexts.
int ast_extension_match(const char *pattern, const char *extension)
Determine if a given extension matches a given pattern (in NXX format)
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
#define ASTERISK_GPL_KEY
The text the key() function should return.
Asterisk module definitions.
ast_context: An extension context
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
int ast_rdlock_context(struct ast_context *con)
Read locks a given context.