From: Brian West Date: Wed, 16 Jan 2008 20:18:09 +0000 (+0000) Subject: add patch from FSCORE-89 thank you X-Git-Tag: v1.0-rc1~657 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9b041ca2b0e7ef31b74dfb4e9a27e753e425c604;p=thirdparty%2Ffreeswitch.git add patch from FSCORE-89 thank you git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@7251 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- diff --git a/docs/AUTHORS b/docs/AUTHORS index e014de0158..11920cc49b 100644 --- a/docs/AUTHORS +++ b/docs/AUTHORS @@ -34,7 +34,8 @@ that much better: Matt Klein Jonas Gauffin - Bugfixes and additions in mod_spidermonkey_odbc Damjan Jovanovic - mod_java - + Juan Jose Comellas - Patch to switch_utils for arg parsing. + A big THANK YOU goes to: Justin Cassidy - Build related cleanups and automatic build setup. diff --git a/src/switch_utils.c b/src/switch_utils.c index a33214e1b0..caefa2eadb 100644 --- a/src/switch_utils.c +++ b/src/switch_utils.c @@ -24,6 +24,7 @@ * Contributor(s): * * Anthony Minessale II + * Juan Jose Comellas * * * switch_utils.c -- Compatability and Helper Code @@ -1004,62 +1005,182 @@ SWITCH_DECLARE(char *) switch_escape_char(switch_memory_pool_t *pool, char *in, return data; } +/* Helper function used when separating strings to unescape a character. The + supported characters are: -SWITCH_DECLARE(unsigned int) switch_separate_string(char *buf, char delim, char **array, int arraylen) + \n linefeed + \r carriage return + \t tab + \s space + + Any other character is returned as it was received. */ +static char unescape_char(char escaped) +{ + char unescaped; + + switch (escaped) { + case 'n': + unescaped = '\n'; + break; + case 'r': + unescaped = '\r'; + break; + case 't': + unescaped = '\t'; + break; + case 's': + unescaped = ' '; + break; + default: + unescaped = escaped; + } + return unescaped; +} + +/* Helper function used when separating strings to remove quotes, leading / + trailing spaces, and to convert escaped characters. */ +static char *cleanup_separated_string(char *str) { - int argc; char *ptr; - int quot = 0; - char qc = '\''; - int x; + char *dest; + char *start; + char *end = NULL; + int inside_quotes = 0; - if (!buf || !array || !arraylen) { - return 0; + /* Skip initial whitespace */ + for (ptr = str; *ptr == ' '; ++ptr) { } - memset(array, 0, arraylen * sizeof(*array)); + for (start = dest = ptr; *ptr; ++ptr) { + if (*ptr == '\\') { + ++ptr; + *dest++ = unescape_char(*ptr); + end = dest; + } else if (*ptr == '\'') { + inside_quotes = (1 - inside_quotes); + } else { + *dest++ = *ptr; + if (*ptr != ' ' || inside_quotes) { + end = dest; + } + } + } + if (end) { + *end = '\0'; + } + return start; +} - ptr = buf; +/* Separate a string using a delimiter that is not a space */ +static unsigned int separate_string_char_delim(char *buf, char delim, char **array, int arraylen) +{ + enum tokenizer_state { + START, + FIND_DELIM + } state = START; + + unsigned int count = 0; + char *ptr = buf; + int inside_quotes = 0; + int i; + + while (*ptr && count < arraylen) { + switch (state) { + case START: + array[count++] = ptr; + state = FIND_DELIM; + break; - for (argc = 0; *ptr && (argc < arraylen - 1); argc++) { - array[argc] = ptr; - for (; *ptr; ptr++) { - if (*ptr == qc) { - if (quot) { - quot--; - } else { - quot++; + case FIND_DELIM: + /* escaped characters are copied verbatim to the destination string */ + if (*ptr == '\\') { + ++ptr; + } else if (*ptr == '\'') { + inside_quotes = (1 - inside_quotes); + } else if (*ptr == delim && !inside_quotes) { + *ptr = '\0'; + state = START; } - } else if ((*ptr == delim) && !quot) { - *ptr++ = '\0'; + ++ptr; break; - } } } - - if (*ptr) { - array[argc++] = ptr; + /* strip quotes, escaped chars and leading / trailing spaces */ + for (i = 0; i < count; ++i) { + array[i] = cleanup_separated_string(array[i]); } + return count; +} - /* strip quotes and leading / trailing spaces */ - for (x = 0; x < argc; x++) { - char *p; +/* Separate a string using a delimiter that is a space */ +static unsigned int separate_string_blank_delim(char *buf, char **array, int arraylen) +{ + enum tokenizer_state { + START, + SKIP_INITIAL_SPACE, + FIND_DELIM, + SKIP_ENDING_SPACE + } state = START; + + unsigned int count = 0; + char *ptr = buf; + int inside_quotes = 0; + int i; - while(*(array[x]) == ' ') { - (array[x])++; - } - p = array[x]; - while((p = strchr(array[x], qc))) { - memmove(p, p+1, strlen(p)); - p++; - } - p = array[x] + (strlen(array[x]) - 1); - while(*p == ' ') { - *p-- = '\0'; + while (*ptr && count < arraylen) { + switch (state) { + case START: + array[count++] = ptr; + state = SKIP_INITIAL_SPACE; + break; + + case SKIP_INITIAL_SPACE: + if (*ptr == ' ') { + ++ptr; + } else { + state = FIND_DELIM; + } + break; + + case FIND_DELIM: + if (*ptr == '\\') { + ++ptr; + } else if (*ptr == '\'') { + inside_quotes = (1 - inside_quotes); + } else if (*ptr == ' ' && !inside_quotes) { + *ptr = '\0'; + state = SKIP_ENDING_SPACE; + } + ++ptr; + break; + + case SKIP_ENDING_SPACE: + if (*ptr == ' ') { + ++ptr; + } else { + state = START; + } + break; } } + /* strip quotes, escaped chars and leading / trailing spaces */ + for (i = 0; i < count; ++i) { + array[i] = cleanup_separated_string(array[i]); + } + return count; +} + +SWITCH_DECLARE(unsigned int) switch_separate_string(char *buf, char delim, char **array, int arraylen) +{ + if (!buf || !array || !arraylen) { + return 0; + } + + memset(array, 0, arraylen * sizeof (*array)); - return argc; + return (delim == ' ' ? + separate_string_blank_delim(buf, array, arraylen) : + separate_string_char_delim(buf, delim, array, arraylen)); } SWITCH_DECLARE(const char *) switch_cut_path(const char *in)