]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
Modifying the behaviour of the dialplan engine
authorAnthony Minessale <anthony.minessale@gmail.com>
Sat, 7 Oct 2006 19:54:04 +0000 (19:54 +0000)
committerAnthony Minessale <anthony.minessale@gmail.com>
Sat, 7 Oct 2006 19:54:04 +0000 (19:54 +0000)
the 'data' field in action tags may now refer to variables and api functions
to be expanded at runtime.

Syntax:

$varname
${varname}
&func_name(func args)

Exception:
variables that are numeric are still expanded at dialplan compile time based on the regex eg $1 $2 etc

Example:

<extension name="1000">
  <condition field="destination_number" expression="^(1000)$">
    <action appplication="my_route_app" data="$1"/>
    <action appplication="bridge" data="$destination"/>
  </condition>
</extension>

Here the $1 is ecaluated before the call begins setting it to 1000 based on the regex ^(1000)$
$destination is evaluated on the fly in execution once the my_route_app has run and has had a
chance to set the variable 'destination' to the correct value.

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2994 d0543943-73ff-0310-b7d9-9358b9ac24b2

src/include/switch_channel.h
src/mod/dialplans/mod_dialplan_xml/mod_dialplan_xml.c
src/mod/loggers/mod_console/mod_console.c
src/switch_channel.c
src/switch_core.c
src/switch_log.c

index 90c3e0011a1342f7cab4a00d8d3b98bb1c4342cd..0ea6c271d748201c82f1fea8c6304be6c021907c 100644 (file)
@@ -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);
index a293245fafbf7b788f4214ff45dffde0a0991afc..11002c7254e318eae761757661347b461473bb1e 100644 (file)
@@ -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);
index 2145a5231fbcf89aef00a30842e83268950f326e..e3ab2a0d770d02ca07c88d7072564e1811a9bcb9 100644 (file)
@@ -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");
index 35cb669a1f43539731a0fba72e762af7d81fc350..860a2231224b9e4dda7efc6c497b5dece7d199a8 100644 (file)
@@ -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;
+}
index 3a4345e2fcbf1fdb230c7ff89950d9afec12c895..575653bc0fc0ac79d90ae8d8811729ca1f4e4a89 100644 (file)
@@ -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;
        }
        
index 5de702a46bd68e844fbc4727e3a5f973ca5f778b..4f82a4586ae1601d2f3f8f8e72e1f02337f58920 100644 (file)
@@ -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;