diff --git a/funcs/func_sayfiles.c b/funcs/func_sayfiles.c index 7e0ece2c96..108126ea14 100644 --- a/funcs/func_sayfiles.c +++ b/funcs/func_sayfiles.c @@ -356,6 +356,14 @@ AST_TEST_DEFINE(test_SAYFILES_function) res = AST_TEST_FAIL; } + ast_str_set(&expr, 0, "${SAYFILES(.42,money)}"); + ast_str_substitute_variables(&result, 0, NULL, ast_str_buffer(expr)); + if (strcmp(ast_str_buffer(result), "digits/40&digits/2¢s") != 0) { + ast_test_status_update(test, "SAYFILES(.42,money) test failed ('%s')\n", + ast_str_buffer(result)); + res = AST_TEST_FAIL; + } + ast_str_set(&expr, 0, "${SAYFILES(1.00,money)}"); ast_str_substitute_variables(&result, 0, NULL, ast_str_buffer(expr)); if (strcmp(ast_str_buffer(result), "digits/1&letters/dollar") != 0) { @@ -380,6 +388,14 @@ AST_TEST_DEFINE(test_SAYFILES_function) res = AST_TEST_FAIL; } + ast_str_set(&expr, 0, "${SAYFILES(2,money)}"); + ast_str_substitute_variables(&result, 0, NULL, ast_str_buffer(expr)); + if (strcmp(ast_str_buffer(result), "digits/2&dollars") != 0) { + ast_test_status_update(test, "SAYFILES(2,money) test failed ('%s')\n", + ast_str_buffer(result)); + res = AST_TEST_FAIL; + } + ast_str_set(&expr, 0, "${SAYFILES(2.42,money)}"); ast_str_substitute_variables(&result, 0, NULL, ast_str_buffer(expr)); if (strcmp(ast_str_buffer(result), "digits/2&dollars&and&digits/40&digits/2¢s") != 0) { @@ -388,6 +404,63 @@ AST_TEST_DEFINE(test_SAYFILES_function) res = AST_TEST_FAIL; } + ast_str_set(&expr, 0, "${SAYFILES(2.05,money)}"); + ast_str_substitute_variables(&result, 0, NULL, ast_str_buffer(expr)); + if (strcmp(ast_str_buffer(result), "digits/2&dollars&and&digits/5¢s") != 0) { + ast_test_status_update(test, "SAYFILES(2.05,money) test failed ('%s')\n", + ast_str_buffer(result)); + res = AST_TEST_FAIL; + } + + ast_str_set(&expr, 0, "${SAYFILES(2.051,money)}"); + ast_str_substitute_variables(&result, 0, NULL, ast_str_buffer(expr)); + if (strcmp(ast_str_buffer(result), "digits/2&dollars&and&digits/5¢s") != 0) { + ast_test_status_update(test, "SAYFILES(2.051,money) test failed ('%s')\n", + ast_str_buffer(result)); + res = AST_TEST_FAIL; + } + + /* Invalid amounts */ + ast_str_set(&expr, 0, "${SAYFILES(blah,money)}"); + ast_str_substitute_variables(&result, 0, NULL, ast_str_buffer(expr)); + if (strcmp(ast_str_buffer(result), "digits/0¢s") != 0) { + ast_test_status_update(test, "SAYFILES(blah,money) test failed ('%s')\n", + ast_str_buffer(result)); + res = AST_TEST_FAIL; + } + + ast_str_set(&expr, 0, "${SAYFILES(2blah.05,money)}"); + ast_str_substitute_variables(&result, 0, NULL, ast_str_buffer(expr)); + if (strcmp(ast_str_buffer(result), "digits/2&dollars") != 0) { + ast_test_status_update(test, "SAYFILES(2blah.05,money) test failed ('%s')\n", + ast_str_buffer(result)); + res = AST_TEST_FAIL; + } + + ast_str_set(&expr, 0, "${SAYFILES(2.-05,money)}"); + ast_str_substitute_variables(&result, 0, NULL, ast_str_buffer(expr)); + if (strcmp(ast_str_buffer(result), "digits/2&dollars") != 0) { + ast_test_status_update(test, "SAYFILES(2.-05,money) test failed ('%s')\n", + ast_str_buffer(result)); + res = AST_TEST_FAIL; + } + + ast_str_set(&expr, 0, "${SAYFILES(2. 05,money)}"); + ast_str_substitute_variables(&result, 0, NULL, ast_str_buffer(expr)); + if (strcmp(ast_str_buffer(result), "digits/2&dollars") != 0) { + ast_test_status_update(test, "SAYFILES(2. 05,money) test failed ('%s')\n", + ast_str_buffer(result)); + res = AST_TEST_FAIL; + } + + ast_str_set(&expr, 0, "${SAYFILES(. 05,money)}"); + ast_str_substitute_variables(&result, 0, NULL, ast_str_buffer(expr)); + if (strcmp(ast_str_buffer(result), "digits/0¢s") != 0) { + ast_test_status_update(test, "SAYFILES(. 05,money) test failed ('%s')\n", + ast_str_buffer(result)); + res = AST_TEST_FAIL; + } + ast_free(expr); ast_free(result); diff --git a/main/say.c b/main/say.c index 300581afb7..5002e8fc83 100644 --- a/main/say.c +++ b/main/say.c @@ -56,6 +56,7 @@ #include "asterisk/utils.h" #include "asterisk/app.h" #include "asterisk/test.h" +#include "asterisk/cli.h" /* use ESS */ /* Forward declaration */ static int wait_file(struct ast_channel *chan, const char *ints, const char *file, const char *lang); @@ -353,26 +354,47 @@ static int say_digit_str_full(struct ast_channel *chan, const char *str, const c static struct ast_str* ast_get_money_en_dollars_str(const char *str, const char *lang) { const char *fnr; - - double dollars = 0; - int amt, cents; + int amt, dollars = 0, cents = 0; struct ast_str *fnrecurse = NULL; + struct ast_str *filenames; - struct ast_str *filenames = ast_str_create(20); + if (ast_strlen_zero(str)) { + return NULL; + } + + filenames = ast_str_create(20); if (!filenames) { return NULL; } ast_str_reset(filenames); - if (sscanf(str, "%30lf", &dollars) != 1) { - amt = 0; - } else { /* convert everything to cents */ - amt = dollars * 100; + /* Don't use %f because floating point rounding + * could distort the cents units. Just parse as string. */ + if (str && *str == '.') { + if (sscanf(str, ".%02u", ¢s) < 1) { + dollars = cents = 0; + } else { + /* If we have a space instead of numbers after '.', + * then it's not quite valid. */ + const char *period = strchr(str, '.'); + if (period && !isdigit(*(period + 1))) { + cents = 0; + } + } + } else { + int res = sscanf(str, "%d.%02u", &dollars, ¢s); + if (res < 1) { + dollars = cents = 0; + } else if (res == 2) { + const char *period = strchr(str, '.'); + if (period && !isdigit(*(period + 1))) { + cents = 0; + } + } } + amt = dollars * 100 + cents; /* convert everything to cents */ - /* Just the cents after the dollar decimal point */ - cents = amt - (((int) dollars) * 100); - ast_debug(1, "Cents is %d, amount is %d\n", cents, amt); + ast_debug(1, "Amount is %d (%d dollar%s, %d cent%s)\n", amt, dollars, ESS(dollars), cents, ESS(cents)); if (amt >= 100) { fnrecurse = ast_get_number_str((amt / 100), lang); @@ -9763,8 +9785,6 @@ int ast_say_counted_adjective(struct ast_channel *chan, int num, const char adje return ast_play_and_wait(chan, temp); } - - /*! \brief * remap the 'say' functions to use those in this file */