diff --git a/src/include/switch_utils.h b/src/include/switch_utils.h index 11a4cdc38e..5b0ab1681a 100644 --- a/src/include/switch_utils.h +++ b/src/include/switch_utils.h @@ -910,10 +910,19 @@ SWITCH_DECLARE(int) switch_strcasecmp_any(const char *str, ...); /*! \brief Quote shell argument \param string the string to quote (example: a ' b"' c) - \return the quoted string (gives: 'a '\'' b"'\'' c' for unices, "a ' b ' c" for MS Windows) + \return the quoted string (gives: 'a '\'' b"'\'' c' for unices, "a ' b ' c" for MS Windows), should be freed */ SWITCH_DECLARE(char *) switch_util_quote_shell_arg(const char *string); +/*! + \brief Quote shell argument, allocating from pool if provided + \param string the string to quote (example: a ' b"' c) + \param pool a memory pool to use + \return the quoted string (gives: 'a '\'' b"'\'' c' for unices, "a ' b ' c" for MS Windows), if pool not provided, returned value should be freed +*/ +SWITCH_DECLARE(char *) switch_util_quote_shell_arg_pool(const char *string, switch_memory_pool_t *pool); + + #define SWITCH_READ_ACCEPTABLE(status) (status == SWITCH_STATUS_SUCCESS || status == SWITCH_STATUS_BREAK) SWITCH_DECLARE(char *) switch_url_encode(const char *url, char *buf, size_t len); SWITCH_DECLARE(char *) switch_url_decode(char *s); diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c index cee3428117..f622d4dbe3 100644 --- a/src/mod/applications/mod_commands/mod_commands.c +++ b/src/mod/applications/mod_commands/mod_commands.c @@ -5530,6 +5530,22 @@ SWITCH_STANDARD_API(escape_function) return SWITCH_STATUS_SUCCESS; } +SWITCH_STANDARD_API(quote_shell_arg_function) +{ + switch_memory_pool_t *pool; + + if (zstr(cmd)) { + return SWITCH_STATUS_SUCCESS; + } + + switch_core_new_memory_pool(&pool); + + stream->write_function(stream, "%s", switch_util_quote_shell_arg_pool(cmd, pool)); + + switch_core_destroy_memory_pool(&pool); + return SWITCH_STATUS_SUCCESS; +} + #define UUID_LOGLEVEL_SYNTAX " " SWITCH_STANDARD_API(uuid_loglevel) { @@ -5999,6 +6015,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load) SWITCH_ADD_API(commands_api_interface, "nat_map", "Manage NAT", nat_map_function, "[status|republish|reinit] | [add|del] [tcp|udp] [static]"); SWITCH_ADD_API(commands_api_interface, "originate", "Originate a call", originate_function, ORIGINATE_SYNTAX); SWITCH_ADD_API(commands_api_interface, "pause", "Pause media on a channel", pause_function, PAUSE_SYNTAX); + SWITCH_ADD_API(commands_api_interface, "quote_shell_arg", "Quote/escape a string for use on shell command line", quote_shell_arg_function, ""); SWITCH_ADD_API(commands_api_interface, "regex", "Evaluate a regex", regex_function, "|[|]"); SWITCH_ADD_API(commands_api_interface, "reloadacl", "Reload XML", reload_acl_function, ""); SWITCH_ADD_API(commands_api_interface, "reload", "Reload module", reload_function, UNLOAD_SYNTAX); diff --git a/src/switch_utils.c b/src/switch_utils.c index be6adb94cc..b3c6c40c19 100644 --- a/src/switch_utils.c +++ b/src/switch_utils.c @@ -2352,14 +2352,39 @@ SWITCH_DECLARE(char *) switch_string_replace(const char *string, const char *sea } SWITCH_DECLARE(char *) switch_util_quote_shell_arg(const char *string) +{ + return switch_util_quote_shell_arg_pool(string, NULL); +} + +SWITCH_DECLARE(char *) switch_util_quote_shell_arg_pool(const char *string, switch_memory_pool_t *pool) { 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; + size_t dest_len = 0; + char *dest; - dest = (char *) malloc(sizeof(char) * dest_len); + /* first pass through, figure out how large to make the allocation */ + dest_len = strlen(string) + 1; /* string + null */ + dest_len += 1; /* opening quote */ + for (i = 0; i < string_len; i++) { + switch (string[i]) { +#ifndef WIN32 + case '\'': + /* We replace ' by sq dq sq dq sq, so need 4 additional bytes */ + dest_len += 4; + break; +#endif + } + } + dest_len += 1; /* closing quote */ + + /* if we're given a pool, allocate from it, otherwise use malloc */ + if ( pool ) { + dest = switch_core_alloc(pool, sizeof(char) * dest_len); + } else { + dest = (char *) malloc(sizeof(char) * dest_len); + } switch_assert(dest); #ifdef WIN32 @@ -2377,14 +2402,11 @@ SWITCH_DECLARE(char *) switch_util_quote_shell_arg(const char *string) break; #else case '\'': - /* We replace ' by '\'' */ - dest_len += 3; - tmp = (char *) realloc(dest, sizeof(char) * (dest_len)); - switch_assert(tmp); - dest = tmp; + /* We replace ' by sq dq sq dq sq */ dest[n++] = '\''; - dest[n++] = '\\'; + dest[n++] = '"'; dest[n++] = '\''; + dest[n++] = '"'; dest[n++] = '\''; break; #endif @@ -2393,10 +2415,6 @@ SWITCH_DECLARE(char *) switch_util_quote_shell_arg(const char *string) } } - dest_len += 2; /* +2 for the closing quote and the null character */ - tmp = (char *) realloc(dest, sizeof(char) * (dest_len)); - switch_assert(tmp); - dest = tmp; #ifdef WIN32 dest[n++] = '"'; #else