Index: funcs/func_strings.c =================================================================== --- funcs/func_strings.c (revision 336853) +++ funcs/func_strings.c (working copy) @@ -859,14 +859,12 @@ static int strreplace(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len) { - char *starts[len]; /* marks starts of substrings */ char *varsubstr; /* substring for input var */ - int count_len = 0; /* counter for starts */ - char *p; /* tracks position of cursor for search and replace */ + char *start; /* Starting pos of substring search. */ + char *end; /* Ending pos of substring search. */ int find_size; /* length of given find-string */ - int max_matches; /* number of matches we find before terminating search */ - - int x; /* loop counter */ + unsigned max_matches; /* number of matches we find before terminating search */ + unsigned count; /* loop counter */ struct ast_str *str = ast_str_thread_get(&result_buf, 16); /* Holds the data obtained from varname */ AST_DECLARE_APP_ARGS(args, @@ -874,16 +872,25 @@ AST_APP_ARG(find_string); AST_APP_ARG(replace_string); AST_APP_ARG(max_replacements); + AST_APP_ARG(other); /* Any remining unused arguments */ ); - AST_STANDARD_APP_ARGS(args, data); + /* Guarantee output string is empty to start with. */ + ast_str_reset(*buf); - if (!str) { /* If we failed to allocate str, forget it. We failed. */ + if (!str) { + /* We failed to allocate str, forget it. We failed. */ return -1; } - if (args.argc < 2) { /* Didn't receive enough arguments to do anything */ - ast_log(LOG_ERROR, "Usage: %s(,[,, ])\n", cmd); + /* Parse the arguments. */ + AST_STANDARD_APP_ARGS(args, data); + + if (args.argc < 2) { + /* Didn't receive enough arguments to do anything */ + ast_log(LOG_ERROR, + "Usage: %s(,[,,[]])\n", + cmd); return -1; } @@ -892,54 +899,44 @@ return -1; } - /* set varsubstr to the matching variable */ - varsubstr = alloca(strlen(args.varname) + 4); - sprintf(varsubstr, "${%s}", args.varname); - ast_str_substitute_variables(&str, 0, chan, varsubstr); - - p = ast_str_buffer(str); - /* Zero length find strings are a no-no. Kill the function if we run into one. */ if (ast_strlen_zero(args.find_string)) { - ast_log(LOG_ERROR, "The must have length > 0\n"); + ast_log(LOG_ERROR, "No specified\n"); return -1; } find_size = strlen(args.find_string); - /* If the replace string is a null pointer, set it to an empty string */ - if (!args.replace_string) { - args.replace_string = ""; - } + /* set varsubstr to the matching variable */ + varsubstr = alloca(strlen(args.varname) + 4); + sprintf(varsubstr, "${%s}", args.varname); + ast_str_substitute_variables(&str, 0, chan, varsubstr); - /* - * If max_replacements specified and is a number, max_matches will become that. - * otherwise, just go the length of the input string - */ - if (!(args.max_replacements && (max_matches = atoi(args.max_replacements)))) { - max_matches = strlen(p); + /* Determine how many replacements are allowed. */ + if (!args.max_replacements + || (max_matches = atoi(args.max_replacements)) <= 0) { + /* Unlimited replacements are allowed. */ + max_matches = -1; } - /* Iterate through string finding matches until it is exhausted or we reach max_matches */ - for (x = 0; x < max_matches; x++) { - if ((p = strstr(p, args.find_string))) { - starts[count_len++] = p; - *p = '\0'; - p += find_size; - } else { + /* Generate the search and replaced string. */ + start = ast_str_buffer(str); + for (count = 0; count < max_matches; ++count) { + end = strstr(start, args.find_string); + if (!end) { + /* Did not find a matching substring in the remainder. */ break; } - } - p = ast_str_buffer(str); - - /* here we rebuild the string with the replaced words by using fancy ast_string_append on the buffer */ - for (x = 0; x < count_len; x++) { - ast_str_append(buf, len, "%s", p); - p = starts[x]; - p += find_size; - ast_str_append(buf, len, "%s", args.replace_string); + /* Replace the found substring. */ + *end = '\0'; + ast_str_append(buf, len, "%s", start); + if (args.replace_string) { + /* Append the replacement string */ + ast_str_append(buf, len, "%s", args.replace_string); + } + start = end + find_size; } - ast_str_append(buf, len, "%s", p); + ast_str_append(buf, len, "%s", start); return 0; }