diff --git a/src/include/switch_channel.h b/src/include/switch_channel.h index 90c3e0011a..0ea6c271d7 100644 --- a/src/include/switch_channel.h +++ b/src/include/switch_channel.h @@ -400,6 +400,14 @@ SWITCH_DECLARE(switch_channel_state_t) switch_channel_name_state(char *name); */ SWITCH_DECLARE(void) switch_channel_event_set_data(switch_channel_t *channel, switch_event_t *event); +/*! + \brief Expand varaibles in a string based on the variables in a paticular channel + \param channel channel to expand the variables from + \param in the original string + \return the original string if no expansion takes place otherwise a new string that must be freed + \note it's necessary to test if the return val is the same as the input and free the string if it is not. +*/ +SWITCH_DECLARE(char *) switch_channel_expand_variables(switch_channel_t *channel, char *in); // These may go away SWITCH_DECLARE(switch_status_t) switch_channel_set_raw_mode (switch_channel_t *channel, int freq, int bits, int channels, int ms, int kbps); diff --git a/src/mod/dialplans/mod_dialplan_xml/mod_dialplan_xml.c b/src/mod/dialplans/mod_dialplan_xml/mod_dialplan_xml.c index a293245faf..11002c7254 100644 --- a/src/mod/dialplans/mod_dialplan_xml/mod_dialplan_xml.c +++ b/src/mod/dialplans/mod_dialplan_xml/mod_dialplan_xml.c @@ -174,17 +174,16 @@ static int parse_exten(switch_core_session_t *session, switch_xml_t xexten, swit char *cmd = switch_core_session_strdup(session, field + 1); char *arg; + SWITCH_STANDARD_STREAM(stream); + if (cmd) { if ((arg = strchr(cmd, ' '))) { *arg++ = '\0'; } - stream.data = retbuf; - stream.end = stream.data; - stream.data_size = sizeof(retbuf); - stream.write_function = switch_console_stream_write; if (switch_api_execute(cmd, arg, session, &stream) == SWITCH_STATUS_SUCCESS) { field_data = retbuf; } + free(stream.data); } } else { field_data = switch_caller_get_field_by_name(caller_profile, field); diff --git a/src/mod/loggers/mod_console/mod_console.c b/src/mod/loggers/mod_console/mod_console.c index 2145a5231f..e3ab2a0d77 100644 --- a/src/mod/loggers/mod_console/mod_console.c +++ b/src/mod/loggers/mod_console/mod_console.c @@ -128,7 +128,7 @@ static switch_status_t switch_console_logger(const switch_log_node_t *node, swit } if (!log_hash || (((all_level > - 1) || lookup) && level >= node->level)) { - fprintf(handle, node->data); + fprintf(handle, "%s", node->data); } } else { fprintf(stderr, "HELP I HAVE NO CONSOLE TO LOG TO!\n"); diff --git a/src/switch_channel.c b/src/switch_channel.c index 35cb669a1f..860a223122 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -999,3 +999,125 @@ SWITCH_DECLARE(switch_status_t) switch_channel_perform_answer(switch_channel_t * return SWITCH_STATUS_FALSE; } + +SWITCH_DECLARE(char *) switch_channel_expand_variables(switch_channel_t *channel, char *in) +{ + char *p, *c; + char *data, *indup; + int sp = 0, len = 0, olen = 0, vtype = 0, br = 0, vnamepos, vvalpos, cpos, ppos, block = 128; + char *sub_val = NULL, *func_val = NULL; + + if (!strchr(in, '$') && !strchr(in, '&')) { + return in; + } + + olen = strlen(in); + indup = strdup(in); + + if ((data = malloc(olen))) { + memset(data, 0, olen); + c = data; + for(p = indup; *p; p++) { + vtype = 0; + + if (*p == '$') { + vtype = 1; + } + if (*p == '&') { + vtype = 2; + } + + if (vtype) { + char *s = p, *e, *vname, *vval = NULL; + int nlen; + s++; + if (*s == '{') { + br = 1; + s++; + } + + e = s; + vname = s; + while (*e) { + if (!br && *e == ' ') { + *e++ = '\0'; + sp++; + break; + } + if (br == 1 && *e == '}') { + br = 0; + *e++ = '\0'; + break; + } + if (vtype == 2) { + if (*e == '(') { + *e++ = '\0'; + vval = e; + br = 2; + } + if (br == 2 && *e == ')') { + *e++ = '\0'; + br = 0; + break; + } + } + e++; + } + p = e; + + if (vtype == 1) { + sub_val = switch_channel_get_variable(channel, vname); + } else { + switch_stream_handle_t stream = {0}; + + SWITCH_STANDARD_STREAM(stream); + + if (stream.data) { + if (switch_api_execute(vname, vval, channel->session, &stream) == SWITCH_STATUS_SUCCESS) { + func_val = stream.data; + sub_val = func_val; + } else { + free(stream.data); + } + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n"); + free(data); + free(indup); + return in; + } + } + nlen = strlen(sub_val); + if (len + nlen >= olen) { + olen += block; + cpos = c - data; + ppos = p - data; + vnamepos = vname - data; + vvalpos = vval - data; + data = realloc(data, olen); + + c = data + cpos; + p = data + ppos; + vname = data + vnamepos; + vname = data + vvalpos; + } + + len += nlen; + strcat(c, sub_val); + c += nlen; + + if (func_val) { + free(func_val); + func_val = NULL; + } + } + if (sp) { + *c++ = ' '; + sp = 0; + } + *c++ = *p; + len++; + } + } + free(indup); + return data; +} diff --git a/src/switch_core.c b/src/switch_core.c index 3a4345e2fc..575653bc0f 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -2435,6 +2435,7 @@ static void switch_core_standard_on_execute(switch_core_session_t *session) } while (switch_channel_get_state(session->channel) == CS_EXECUTE && extension->current_application) { + char *expanded; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Execute %s(%s)\n", extension->current_application->application_name, extension->current_application->application_data); @@ -2454,13 +2455,25 @@ static void switch_core_standard_on_execute(switch_core_session_t *session) return; } + if ((expanded = switch_channel_expand_variables(session->channel, extension->current_application->application_data)) != + extension->current_application->application_data) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Expanded String %s(%s)\n", + extension->current_application->application_name, + expanded); + } + if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_EXECUTE) == SWITCH_STATUS_SUCCESS) { switch_channel_event_set_data(session->channel, event); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Application", "%s", extension->current_application->application_name); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Application-Data", "%s", extension->current_application->application_data); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Application-Data-Orig", "%s", extension->current_application->application_data); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Application-Data", "%s", expanded); switch_event_fire(&event); } - application_interface->application_function(session, extension->current_application->application_data); + application_interface->application_function(session, expanded); + + if (expanded != extension->current_application->application_data) { + free(expanded); + } extension->current_application = extension->current_application->next; } diff --git a/src/switch_log.c b/src/switch_log.c index 5de702a46b..4f82a4586a 100644 --- a/src/switch_log.c +++ b/src/switch_log.c @@ -223,7 +223,7 @@ SWITCH_DECLARE(void) switch_log_printf(switch_text_channel_t channel, char *file } } else { if (level == SWITCH_LOG_CONSOLE || !LOG_QUEUE || !THREAD_RUNNING) { - fprintf(handle, data); + fprintf(handle, "%s", data); free(data); } else if (level <= MAX_LEVEL) { switch_log_node_t *node;