(closes issue #6019)
Reported by: ssokol Patches: 20080304__bug6019.diff.txt uploaded by Corydon76 (license 14) Tested by: putnopvut git-svn-id: http://svn.digium.com/svn/asterisk/trunk@107231 f38db490-d61c-443f-a65b-d21fe96a405b
This commit is contained in:
parent
5f074afc22
commit
d7a3bcf49b
|
@ -839,6 +839,11 @@ int pbx_set_autofallthrough(int newval);
|
|||
the old linear-search algorithm. Returns previous value. */
|
||||
int pbx_set_extenpatternmatchnew(int newval);
|
||||
|
||||
/*! Set "overrideswitch" field. If set and of nonzero length, all contexts
|
||||
* will be tried directly through the named switch prior to any other
|
||||
* matching within that context. */
|
||||
void pbx_set_overrideswitch(const char *newval);
|
||||
|
||||
/*!
|
||||
* \note This function will handle locking the channel as needed.
|
||||
*/
|
||||
|
|
94
main/pbx.c
94
main/pbx.c
|
@ -123,6 +123,8 @@ AST_APP_OPTIONS(waitexten_opts, {
|
|||
struct ast_context;
|
||||
struct ast_app;
|
||||
|
||||
AST_THREADSTORAGE(switch_data);
|
||||
|
||||
/*!
|
||||
\brief ast_exten: An extension
|
||||
The dialplan is saved as a linked list with each context
|
||||
|
@ -166,7 +168,6 @@ struct ast_sw {
|
|||
char *data; /*!< Data load */
|
||||
int eval;
|
||||
AST_LIST_ENTRY(ast_sw) list;
|
||||
char *tmpdata;
|
||||
char stuff[0];
|
||||
};
|
||||
|
||||
|
@ -413,6 +414,7 @@ static struct varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
|
|||
|
||||
static int autofallthrough = 1;
|
||||
static int extenpatternmatchnew = 0;
|
||||
static char *overrideswitch = NULL;
|
||||
|
||||
/*! \brief Subscription for device state change events */
|
||||
static struct ast_event_sub *device_state_sub;
|
||||
|
@ -1644,6 +1646,7 @@ struct ast_exten *pbx_find_extension(struct ast_channel *chan,
|
|||
struct ast_sw *sw = NULL;
|
||||
struct ast_exten pattern = {NULL, };
|
||||
struct scoreboard score = {0, };
|
||||
struct ast_str *tmpdata = NULL;
|
||||
|
||||
pattern.label = label;
|
||||
pattern.priority = priority;
|
||||
|
@ -1707,6 +1710,65 @@ struct ast_exten *pbx_find_extension(struct ast_channel *chan,
|
|||
log_match_char_tree(tmp->pattern_tree, ":: ");
|
||||
#endif
|
||||
|
||||
do {
|
||||
if (!ast_strlen_zero(overrideswitch)) {
|
||||
char *osw = ast_strdupa(overrideswitch), *name;
|
||||
struct ast_switch *asw;
|
||||
ast_switch_f *aswf = NULL;
|
||||
char *datap;
|
||||
int eval = 0;
|
||||
|
||||
name = strsep(&osw, "/");
|
||||
asw = pbx_findswitch(name);
|
||||
|
||||
if (!asw) {
|
||||
ast_log(LOG_WARNING, "No such switch '%s'\n", name);
|
||||
break;
|
||||
}
|
||||
|
||||
if (osw && strchr(osw, '$')) {
|
||||
eval = 1;
|
||||
}
|
||||
|
||||
if (eval && !(tmpdata = ast_str_thread_get(&switch_data, 512))) {
|
||||
ast_log(LOG_WARNING, "Can't evaluate overrideswitch?!");
|
||||
break;
|
||||
} else if (eval) {
|
||||
/* Substitute variables now */
|
||||
pbx_substitute_variables_helper(chan, osw, tmpdata->str, tmpdata->len);
|
||||
datap = tmpdata->str;
|
||||
} else {
|
||||
datap = osw;
|
||||
}
|
||||
|
||||
/* equivalent of extension_match_core() at the switch level */
|
||||
if (action == E_CANMATCH)
|
||||
aswf = asw->canmatch;
|
||||
else if (action == E_MATCHMORE)
|
||||
aswf = asw->matchmore;
|
||||
else /* action == E_MATCH */
|
||||
aswf = asw->exists;
|
||||
if (!aswf) {
|
||||
res = 0;
|
||||
} else {
|
||||
if (chan) {
|
||||
ast_autoservice_start(chan);
|
||||
}
|
||||
res = aswf(chan, context, exten, priority, callerid, datap);
|
||||
if (chan) {
|
||||
ast_autoservice_stop(chan);
|
||||
}
|
||||
}
|
||||
if (res) { /* Got a match */
|
||||
q->swo = asw;
|
||||
q->data = datap;
|
||||
q->foundcontext = context;
|
||||
/* XXX keep status = STATUS_NO_CONTEXT ? */
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
} while (0);
|
||||
|
||||
if (extenpatternmatchnew) {
|
||||
new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid);
|
||||
eroot = score.exten;
|
||||
|
@ -1828,8 +1890,13 @@ struct ast_exten *pbx_find_extension(struct ast_channel *chan,
|
|||
}
|
||||
/* Substitute variables now */
|
||||
|
||||
if (sw->eval)
|
||||
pbx_substitute_variables_helper(chan, sw->data, sw->tmpdata, SWITCH_DATA_LENGTH - 1);
|
||||
if (sw->eval) {
|
||||
if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) {
|
||||
ast_log(LOG_WARNING, "Can't evaluate switch?!");
|
||||
continue;
|
||||
}
|
||||
pbx_substitute_variables_helper(chan, sw->data, tmpdata->str, tmpdata->len);
|
||||
}
|
||||
|
||||
/* equivalent of extension_match_core() at the switch level */
|
||||
if (action == E_CANMATCH)
|
||||
|
@ -1838,7 +1905,7 @@ struct ast_exten *pbx_find_extension(struct ast_channel *chan,
|
|||
aswf = asw->matchmore;
|
||||
else /* action == E_MATCH */
|
||||
aswf = asw->exists;
|
||||
datap = sw->eval ? sw->tmpdata : sw->data;
|
||||
datap = sw->eval ? tmpdata->str : sw->data;
|
||||
if (!aswf)
|
||||
res = 0;
|
||||
else {
|
||||
|
@ -3618,6 +3685,18 @@ int pbx_set_extenpatternmatchnew(int newval)
|
|||
return oldval;
|
||||
}
|
||||
|
||||
void pbx_set_overrideswitch(const char *newval)
|
||||
{
|
||||
if (overrideswitch) {
|
||||
ast_free(overrideswitch);
|
||||
}
|
||||
if (!ast_strlen_zero(newval)) {
|
||||
overrideswitch = ast_strdup(newval);
|
||||
} else {
|
||||
overrideswitch = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief lookup for a context with a given name,
|
||||
* \retval with conlock held if found.
|
||||
|
@ -5781,11 +5860,6 @@ int ast_context_add_switch2(struct ast_context *con, const char *value,
|
|||
if (data)
|
||||
length += strlen(data);
|
||||
length++;
|
||||
if (eval) {
|
||||
/* Create buffer for evaluation of variables */
|
||||
length += SWITCH_DATA_LENGTH;
|
||||
length++;
|
||||
}
|
||||
|
||||
/* allocate new sw structure ... */
|
||||
if (!(new_sw = ast_calloc(1, length)))
|
||||
|
@ -5803,8 +5877,6 @@ int ast_context_add_switch2(struct ast_context *con, const char *value,
|
|||
strcpy(new_sw->data, "");
|
||||
p++;
|
||||
}
|
||||
if (eval)
|
||||
new_sw->tmpdata = p;
|
||||
new_sw->eval = eval;
|
||||
new_sw->registrar = registrar;
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@ static int write_protect_config = 1;
|
|||
static int autofallthrough_config = 1;
|
||||
static int clearglobalvars_config = 0;
|
||||
static int extenpatternmatchnew_config = 0;
|
||||
static char *overrideswitch_config = NULL;
|
||||
|
||||
AST_MUTEX_DEFINE_STATIC(save_dialplan_lock);
|
||||
|
||||
|
@ -701,7 +702,7 @@ static char *complete_dialplan_add_include(struct ast_cli_args *a)
|
|||
*/
|
||||
static char *handle_cli_dialplan_save(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
||||
{
|
||||
char filename[256];
|
||||
char filename[256], overrideswitch[256] = "";
|
||||
struct ast_context *c;
|
||||
struct ast_config *cfg;
|
||||
struct ast_variable *v;
|
||||
|
@ -781,11 +782,15 @@ static char *handle_cli_dialplan_save(struct ast_cli_entry *e, int cmd, struct a
|
|||
}
|
||||
|
||||
/* fireout general info */
|
||||
fprintf(output, "[general]\nstatic=%s\nwriteprotect=%s\nautofallthrough=%s\nclearglobalvars=%s\nextenpatternmatchnew=%s\n\n",
|
||||
if (overrideswitch_config) {
|
||||
snprintf(overrideswitch, sizeof(overrideswitch), "overrideswitch=%s\n", overrideswitch_config);
|
||||
}
|
||||
fprintf(output, "[general]\nstatic=%s\nwriteprotect=%s\nautofallthrough=%s\nclearglobalvars=%s\n%sextenpatternmatchnew=%s\n\n",
|
||||
static_config ? "yes" : "no",
|
||||
write_protect_config ? "yes" : "no",
|
||||
autofallthrough_config ? "yes" : "no",
|
||||
clearglobalvars_config ? "yes" : "no",
|
||||
overrideswitch_config ? overrideswitch : "",
|
||||
extenpatternmatchnew_config ? "yes" : "no");
|
||||
|
||||
if ((v = ast_variable_browse(cfg, "globals"))) {
|
||||
|
@ -1353,6 +1358,9 @@ static int unload_module(void)
|
|||
{
|
||||
if (static_config && !write_protect_config)
|
||||
ast_cli_unregister(&cli_dialplan_save);
|
||||
if (overrideswitch_config) {
|
||||
ast_free(overrideswitch_config);
|
||||
}
|
||||
ast_cli_unregister_multiple(cli_pbx_config, sizeof(cli_pbx_config) / sizeof(struct ast_cli_entry));
|
||||
ast_context_destroy(NULL, registrar);
|
||||
return 0;
|
||||
|
@ -1369,7 +1377,7 @@ static int pbx_load_config(const char *config_file)
|
|||
struct ast_variable *v;
|
||||
const char *cxt;
|
||||
const char *aft;
|
||||
const char *newpm;
|
||||
const char *newpm, *ovsw;
|
||||
struct ast_flags config_flags = { 0 };
|
||||
cfg = ast_config_load(config_file, config_flags);
|
||||
if (!cfg)
|
||||
|
@ -1383,7 +1391,16 @@ static int pbx_load_config(const char *config_file)
|
|||
if ((newpm = ast_variable_retrieve(cfg, "general", "extenpatternmatchnew")))
|
||||
extenpatternmatchnew_config = ast_true(newpm);
|
||||
clearglobalvars_config = ast_true(ast_variable_retrieve(cfg, "general", "clearglobalvars"));
|
||||
|
||||
if ((ovsw = ast_variable_retrieve(cfg, "general", "overrideswitch"))) {
|
||||
if (overrideswitch_config) {
|
||||
ast_free(overrideswitch_config);
|
||||
}
|
||||
if (!ast_strlen_zero(ovsw)) {
|
||||
overrideswitch_config = ast_strdup(ovsw);
|
||||
} else {
|
||||
overrideswitch_config = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if ((cxt = ast_variable_retrieve(cfg, "general", "userscontext")))
|
||||
ast_copy_string(userscontext, cxt, sizeof(userscontext));
|
||||
|
@ -1640,6 +1657,7 @@ static int pbx_load_module(void)
|
|||
for (con = NULL; (con = ast_walk_contexts(con));)
|
||||
ast_context_verify_includes(con);
|
||||
|
||||
pbx_set_overrideswitch(overrideswitch_config);
|
||||
pbx_set_autofallthrough(autofallthrough_config);
|
||||
pbx_set_extenpatternmatchnew(extenpatternmatchnew_config);
|
||||
|
||||
|
|
Reference in New Issue