]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
mod_tts_commandline: quote shell args, create an unique tempfile
authorMathieu Parent <math.parent@gmail.com>
Mon, 21 Sep 2009 08:48:12 +0000 (08:48 +0000)
committerMathieu Parent <math.parent@gmail.com>
Mon, 21 Sep 2009 08:48:12 +0000 (08:48 +0000)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@14931 d0543943-73ff-0310-b7d9-9358b9ac24b2

src/mod/asr_tts/mod_tts_commandline/mod_tts_commandline.c

index 6cbe18f808e3a8ebbefcd69df22ca0cd3e25e8d8..4197d020fee01983c1308079a764b2d9b15fcca9 100644 (file)
@@ -32,6 +32,8 @@
 #include <unistd.h>
 #include <switch.h>
 
+SWITCH_DECLARE(char *) switch_escape_shell_arg(char *string);
+
 SWITCH_MODULE_LOAD_FUNCTION(mod_tts_commandline_load);
 SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_tts_commandline_shutdown);
 SWITCH_MODULE_DEFINITION(mod_tts_commandline, mod_tts_commandline_load, mod_tts_commandline_shutdown, NULL);
@@ -45,14 +47,71 @@ static struct {
 SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_command, globals.command);
 
 struct tts_commandline_data {
-    switch_file_handle_t fh;
+       switch_file_handle_t fh;
        char *voice_name;
        int rate;
-       char file[512];
+       char *file;
 };
 
 typedef struct tts_commandline_data tts_commandline_t;
 
+
+SWITCH_DECLARE(char *) switch_quote_shell_arg(char *string)
+{
+       size_t string_len = strlen(string);
+       size_t i;
+       size_t n = 0;
+       size_t dest_len = string_len + 1; /* +1 for the opening quote  */
+       char *dest, *tmp;
+
+       dest = (char *) malloc(sizeof(char) * dest_len);
+       switch_assert(dest);
+
+#ifdef WIN32
+    dest[n++] = '"';
+#else
+    dest[n++] = '\'';
+#endif
+
+       for (i = 0; i < string_len; i++) {
+               switch (string[i]) {
+#ifdef WIN32
+               case '"':
+               case '%':
+                       dest[n++] = ' ';
+                       break;
+#else
+               case '\'':
+            /* We replace ' by '\'' */
+                       dest_len+=3;
+                       tmp = (char *) realloc(dest, sizeof(char) * (dest_len));
+                       switch_assert(tmp);
+                       dest = tmp;
+                       dest[n++] = '\'';
+                       dest[n++] = '\\';
+                       dest[n++] = '\'';
+                       dest[n++] = '\'';
+                       break;
+#endif
+               default:
+                       dest[n++] = string[i];
+               }
+  }
+  
+dest_len++;
+tmp = (char *) realloc(dest, sizeof(char) * (dest_len));
+switch_assert(tmp);
+dest = tmp;
+#ifdef WIN32
+    dest[n++] = '"';
+#else
+    dest[n++] = '\'';
+#endif
+
+       dest[dest_len] = 0;
+       return dest;
+}
+
 static int load_tts_commandline_config(void)
 {
        char *cf = "tts_commandline.conf";
@@ -75,7 +134,7 @@ static int load_tts_commandline_config(void)
        }
 
        if (switch_strlen_zero(globals.command)) {
-        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No command set, please edit %s\n", cf);   
+           switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No command set, please edit %s\n", cf);   
        }
 
        return SWITCH_STATUS_SUCCESS;
@@ -92,23 +151,31 @@ static void event_handler(switch_event_t *event)
 
 static switch_status_t tts_commandline_speech_open(switch_speech_handle_t *sh, const char *voice_name, int rate, switch_speech_flag_t *flags)
 {
+       switch_uuid_t uuid;
+       char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
+       char outfile[512] = "";
+       
        tts_commandline_t *info = switch_core_alloc(sh->memory_pool, sizeof(*info));
 
        info->voice_name = switch_core_strdup(sh->memory_pool, voice_name);
-    info->rate = rate;
+       info->rate = rate;
+
+       switch_uuid_get(&uuid);
+       switch_uuid_format(uuid_str, &uuid);
 
-       switch_snprintf(info->file, sizeof(info->file), "%s%s.wav", SWITCH_GLOBAL_dirs.temp_dir, "tts_commandline");
-    
-    sh->private_info = info;
-    
-    return SWITCH_STATUS_SUCCESS;
+       switch_snprintf(outfile, sizeof(outfile), "%s%s.tmp.wav", SWITCH_GLOBAL_dirs.temp_dir, uuid_str);
+       info->file = outfile;
+       
+       sh->private_info = info;
+  
+       return SWITCH_STATUS_SUCCESS;
 }
 
 static switch_status_t tts_commandline_speech_close(switch_speech_handle_t *sh, switch_speech_flag_t *flags)
 {
        tts_commandline_t *info = (tts_commandline_t *) sh->private_info;
        assert(info != NULL);
-    
+       
        return SWITCH_STATUS_SUCCESS;
 }
 
@@ -117,31 +184,39 @@ static switch_status_t tts_commandline_speech_feed_tts(switch_speech_handle_t *s
        tts_commandline_t *info = (tts_commandline_t *) sh->private_info;
        assert(info != NULL);
 
-    char *message;
-    char *rate;
+       char *message, *tmp, *rate;
+       
        message = switch_core_strdup(sh->memory_pool, globals.command);
-    message = switch_string_replace(message, "${text}", text);
-    message = switch_string_replace(message, "${voice}", info->voice_name);
-    rate = switch_core_sprintf(sh->memory_pool, "%d", info->rate);
-    message = switch_string_replace(message, "${rate}", rate);
-    message = switch_string_replace(message, "${file}", info->file);
-    switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Executing: %s\n", message);
-    
-    if (switch_system(message, SWITCH_TRUE) < 0) {
-       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to execute command: %s\n", message);
-       return SWITCH_STATUS_FALSE;
-    }
        
-    if (switch_core_file_open(&info->fh,
-                            info->file,
-                            0, //number_of_channels,
-                            0, //samples_per_second,
-                            SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) {
-       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to open file: %s\n", info->file);
-       return SWITCH_STATUS_FALSE;
-    }
-    
-    sh->private_info = info;
+       tmp = switch_quote_shell_arg(text);
+       message = switch_string_replace(message, "${text}", tmp);
+       
+       tmp = switch_quote_shell_arg(info->voice_name);
+       message = switch_string_replace(message, "${voice}", tmp);
+       
+       rate = switch_core_sprintf(sh->memory_pool, "%d", info->rate);
+       message = switch_string_replace(message, "${rate}", rate);
+       
+       tmp = switch_quote_shell_arg(info->file);
+       message = switch_string_replace(message, "${file}", tmp);
+       
+       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Executing: %s\n", message);
+       
+       if (switch_system(message, SWITCH_TRUE) < 0) {
+          switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to execute command: %s\n", message);
+          return SWITCH_STATUS_FALSE;
+       }
+
+       if (switch_core_file_open(&info->fh,
+                               info->file,
+                               0, //number_of_channels,
+                               0, //samples_per_second,
+                               SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) {
+          switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to open file: %s\n", info->file);
+          return SWITCH_STATUS_FALSE;
+       }
+       
+       sh->private_info = info;
 
        return SWITCH_STATUS_SUCCESS;
 }
@@ -150,30 +225,30 @@ static switch_status_t tts_commandline_speech_read_tts(switch_speech_handle_t *s
 {
        tts_commandline_t *info = (tts_commandline_t *) sh->private_info;
        assert(info != NULL);
-    
-    size_t my_datalen = *datalen / 2;
-    
-    if (switch_core_file_read(&info->fh, data, &my_datalen) != SWITCH_STATUS_SUCCESS) {
-        *datalen = my_datalen * 2;
-        return SWITCH_STATUS_FALSE;
-    }
-    *datalen = my_datalen * 2;
-    if(datalen == 0) {
-        return SWITCH_STATUS_BREAK;
-    } else {
-        return SWITCH_STATUS_SUCCESS;
-    }
+       
+       size_t my_datalen = *datalen / 2;
+       
+       if (switch_core_file_read(&info->fh, data, &my_datalen) != SWITCH_STATUS_SUCCESS) {
+           *datalen = my_datalen * 2;
+           return SWITCH_STATUS_FALSE;
+       }
+       *datalen = my_datalen * 2;
+       if(datalen == 0) {
+           return SWITCH_STATUS_BREAK;
+       } else {
+           return SWITCH_STATUS_SUCCESS;
+       }
 }
 
 static void tts_commandline_speech_flush_tts(switch_speech_handle_t *sh)
 {
        tts_commandline_t *info = (tts_commandline_t *) sh->private_info;
        assert(info != NULL);
-    
-    switch_core_file_close(&info->fh);
-    if (unlink(info->file) != 0) {
-        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Sound file [%s] delete failed\n", info->file);
-    }
+       
+       switch_core_file_close(&info->fh);
+       if (unlink(info->file) != 0) {
+           switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Sound file [%s] delete failed\n", info->file);
+       }
 }
 
 static void tts_commandline_text_param_tts(switch_speech_handle_t *sh, char *param, const char *val)
@@ -182,8 +257,8 @@ static void tts_commandline_text_param_tts(switch_speech_handle_t *sh, char *par
        assert(info != NULL);
 
        if (!strcasecmp(param, "voice")) {
-        info->voice_name = switch_core_strdup(sh->memory_pool, val);
-    }
+           info->voice_name = switch_core_strdup(sh->memory_pool, val);
+       }
 }
 
 static void tts_commandline_numeric_param_tts(switch_speech_handle_t *sh, char *param, int val)
@@ -197,8 +272,8 @@ static void tts_commandline_float_param_tts(switch_speech_handle_t *sh, char *pa
 SWITCH_MODULE_LOAD_FUNCTION(mod_tts_commandline_load)
 {
        switch_speech_interface_t *speech_interface;
-       
-    load_tts_commandline_config();
+
+       load_tts_commandline_config();
 
        /* connect my internal structure to the blank pointer passed to me */
        *module_interface = switch_loadable_module_create_module_interface(pool, modname);