Newer
Older
if (strncmp(prefix, ast_var_name(var), len) == 0) {
AST_LIST_REMOVE_CURRENT(entries);
Tilghman Lesher
committed
ast_free(var);
}
}
AST_LIST_TRAVERSE_SAFE_END
}
static int exec_clearhash(struct ast_channel *chan, const char *data)
{
char prefix[80];
snprintf(prefix, sizeof(prefix), HASH_PREFIX, data ? (char *)data : "null");
clearvar_prefix(chan, prefix);
return 0;
}
static int array(struct ast_channel *chan, const char *cmd, char *var,
AST_DECLARE_APP_ARGS(arg1,
);
AST_DECLARE_APP_ARGS(arg2,
char *origvar = "", *value2, varname[256];
int i, ishash = 0;
}
value2 = ast_strdupa(value);
if (!strcmp(cmd, "HASH")) {
const char *var2 = pbx_builtin_getvar_helper(chan, "~ODBCFIELDS~");
origvar = var;
if (var2)
var = ast_strdupa(var2);
else {
if (chan)
ast_autoservice_stop(chan);
return -1;
ishash = 1;
}
/* The functions this will generally be used with are SORT and ODBC_*, which
* both return comma-delimited lists. However, if somebody uses literal lists,
* their commas will be translated to vertical bars by the load, and I don't
* want them to be surprised by the result. Hence, we prefer commas as the
* delimiter, but we'll fall back to vertical bars if commas aren't found.
*/
ast_debug(1, "array (%s=%s)\n", var, S_OR(value2, ""));
Tilghman Lesher
committed
AST_STANDARD_APP_ARGS(arg1, var);
Tilghman Lesher
committed
AST_STANDARD_APP_ARGS(arg2, value2);
for (i = 0; i < arg1.argc; i++) {
ast_debug(1, "array set value (%s=%s)\n", arg1.var[i],
if (i < arg2.argc) {
if (ishash) {
if (origvar[0] == '_') {
if (origvar[1] == '_') {
snprintf(varname, sizeof(varname), "__" HASH_FORMAT, origvar + 2, arg1.var[i]);
} else {
snprintf(varname, sizeof(varname), "_" HASH_FORMAT, origvar + 1, arg1.var[i]);
}
} else {
snprintf(varname, sizeof(varname), HASH_FORMAT, origvar, arg1.var[i]);
}
pbx_builtin_setvar_helper(chan, varname, arg2.val[i]);
} else {
pbx_builtin_setvar_helper(chan, arg1.var[i], arg2.val[i]);
}
} else {
/* We could unset the variable, by passing a NULL, but due to
* pushvar semantics, that could create some undesired behavior. */
if (ishash) {
snprintf(varname, sizeof(varname), HASH_FORMAT, origvar, arg1.var[i]);
pbx_builtin_setvar_helper(chan, varname, "");
} else {
pbx_builtin_setvar_helper(chan, arg1.var[i], "");
}
static int hashkeys_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
{
struct ast_var_t *newvar;
struct ast_str *prefix = ast_str_alloca(80);
ast_str_set(&prefix, -1, HASH_PREFIX, data);
memset(buf, 0, len);
AST_LIST_TRAVERSE(ast_channel_varshead(chan), newvar, entries) {
if (strncmp(ast_str_buffer(prefix), ast_var_name(newvar), ast_str_strlen(prefix)) == 0) {
/* Copy everything after the prefix */
strncat(buf, ast_var_name(newvar) + ast_str_strlen(prefix), len - strlen(buf) - 1);
/* Trim the trailing ~ */
buf[strlen(buf) - 1] = ',';
}
}
/* Trim the trailing comma */
buf[strlen(buf) - 1] = '\0';
return 0;
}
static int hashkeys_read2(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
{
struct ast_var_t *newvar;
struct ast_str *prefix = ast_str_alloca(80);
char *tmp;
ast_str_set(&prefix, -1, HASH_PREFIX, data);
AST_LIST_TRAVERSE(ast_channel_varshead(chan), newvar, entries) {
if (strncmp(ast_str_buffer(prefix), ast_var_name(newvar), ast_str_strlen(prefix)) == 0) {
/* Copy everything after the prefix */
ast_str_append(buf, len, "%s", ast_var_name(newvar) + ast_str_strlen(prefix));
/* Trim the trailing ~ */
tmp = ast_str_buffer(*buf);
tmp[ast_str_strlen(*buf) - 1] = ',';
}
}
/* Trim the trailing comma */
tmp = ast_str_buffer(*buf);
tmp[ast_str_strlen(*buf) - 1] = '\0';
return 0;
}
static int hash_write(struct ast_channel *chan, const char *cmd, char *var, const char *value)
{
char varname[256];
AST_DECLARE_APP_ARGS(arg,
AST_APP_ARG(hashname);
AST_APP_ARG(hashkey);
);
Tilghman Lesher
committed
if (!strchr(var, ',')) {
/* Single argument version */
return array(chan, "HASH", var, value);
}
AST_STANDARD_APP_ARGS(arg, var);
if (arg.hashname[0] == '_') {
if (arg.hashname[1] == '_') {
snprintf(varname, sizeof(varname), "__" HASH_FORMAT, arg.hashname + 2, arg.hashkey);
} else {
snprintf(varname, sizeof(varname), "_" HASH_FORMAT, arg.hashname + 1, arg.hashkey);
}
} else {
snprintf(varname, sizeof(varname), HASH_FORMAT, arg.hashname, arg.hashkey);
}
pbx_builtin_setvar_helper(chan, varname, value);
return 0;
}
static int hash_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
{
char varname[256];
const char *varvalue;
AST_DECLARE_APP_ARGS(arg,
AST_APP_ARG(hashname);
AST_APP_ARG(hashkey);
);
AST_STANDARD_APP_ARGS(arg, data);
if (arg.argc == 2) {
snprintf(varname, sizeof(varname), HASH_FORMAT, arg.hashname, arg.hashkey);
varvalue = pbx_builtin_getvar_helper(chan, varname);
if (varvalue)
ast_copy_string(buf, varvalue, len);
else
*buf = '\0';
} else if (arg.argc == 1) {
char colnames[4096];
int i;
AST_DECLARE_APP_ARGS(arg2,
AST_APP_ARG(col)[100];
);
/* Get column names, in no particular order */
hashkeys_read(chan, "HASHKEYS", arg.hashname, colnames, sizeof(colnames));
pbx_builtin_setvar_helper(chan, "~ODBCFIELDS~", colnames);
Mark Michelson
committed
AST_STANDARD_APP_ARGS(arg2, colnames);
*buf = '\0';
/* Now get the corresponding column values, in exactly the same order */
for (i = 0; i < arg2.argc; i++) {
snprintf(varname, sizeof(varname), HASH_FORMAT, arg.hashname, arg2.col[i]);
varvalue = pbx_builtin_getvar_helper(chan, varname);
strncat(buf, varvalue, len - strlen(buf) - 1);
strncat(buf, ",", len - strlen(buf) - 1);
}
/* Strip trailing comma */
buf[strlen(buf) - 1] = '\0';
}
return 0;
}
static struct ast_custom_function hash_function = {
.name = "HASH",
.write = hash_write,
.read = hash_read,
};
static struct ast_custom_function hashkeys_function = {
.name = "HASHKEYS",
.read = hashkeys_read,
};
static struct ast_custom_function array_function = {
.write = array,
static int quote(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
{
char *bufptr = buf, *dataptr = data;
if (len < 3){ /* at least two for quotes and one for binary zero */
ast_log(LOG_ERROR, "Not enough buffer\n");
return -1;
}
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "No argument specified!\n");
ast_copy_string(buf, "\"\"", len);
return 0;
}
for (; bufptr < buf + len - 3; dataptr++) {
if (*dataptr == '\\') {
*bufptr++ = '\\';
*bufptr++ = '\\';
} else if (*dataptr == '"') {
*bufptr++ = '\\';
*bufptr++ = '"';
} else if (*dataptr == '\0') {
break;
} else {
*bufptr++ = *dataptr;
}
}
*bufptr++ = '"';
*bufptr = '\0';
}
static struct ast_custom_function quote_function = {
.name = "QUOTE",
static int csv_quote(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
{
char *bufptr = buf, *dataptr = data;
if (len < 3) { /* at least two for quotes and one for binary zero */
ast_log(LOG_ERROR, "Not enough buffer\n");
return -1;
}
if (ast_strlen_zero(data)) {
ast_copy_string(buf, "\"\"", len);
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
return 0;
}
*bufptr++ = '"';
for (; bufptr < buf + len - 3; dataptr++){
if (*dataptr == '"') {
*bufptr++ = '"';
*bufptr++ = '"';
} else if (*dataptr == '\0') {
break;
} else {
*bufptr++ = *dataptr;
}
}
*bufptr++ = '"';
*bufptr='\0';
return 0;
}
static struct ast_custom_function csv_quote_function = {
.name = "CSV_QUOTE",
.read = csv_quote,
};
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
{
int length = 0;
length = strlen(data);
snprintf(buf, buflen, "%d", length);
static struct ast_custom_function len_function = {
.read = len,
Kevin P. Fleming
committed
static int acf_strftime(struct ast_channel *chan, const char *cmd, char *parse,
char *buf, size_t buflen)
Kevin P. Fleming
committed
{
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(epoch);
AST_APP_ARG(timezone);
AST_APP_ARG(format);
struct timeval when;
Tilghman Lesher
committed
struct ast_tm tm;
Kevin P. Fleming
committed
buf[0] = '\0';
AST_STANDARD_APP_ARGS(args, parse);
ast_get_timeval(args.epoch, &when, ast_tvnow(), NULL);
ast_localtime(&when, &tm, args.timezone);
if (!args.format)
args.format = "%c";
if (ast_strftime(buf, buflen, args.format, &tm) <= 0)
ast_log(LOG_WARNING, "C function strftime() output nothing?!!\n");
buf[buflen - 1] = '\0';
Kevin P. Fleming
committed
}
static struct ast_custom_function strftime_function = {
Kevin P. Fleming
committed
.name = "STRFTIME",
.read = acf_strftime,
};
static int acf_strptime(struct ast_channel *chan, const char *cmd, char *data,
char *buf, size_t buflen)
AST_APP_ARG(timestring);
AST_APP_ARG(timezone);
AST_APP_ARG(format);
struct ast_tm tm;
buf[0] = '\0';
if (!data) {
ast_log(LOG_ERROR,
"Asterisk function STRPTIME() requires an argument.\n");
return -1;
}
AST_STANDARD_APP_ARGS(args, data);
if (ast_strlen_zero(args.format)) {
ast_log(LOG_ERROR,
Tilghman Lesher
committed
"No format supplied to STRPTIME(<timestring>,<timezone>,<format>)");
if (!ast_strptime(args.timestring, args.format, &tm)) {
ast_log(LOG_WARNING, "STRPTIME() found no time specified within the string\n");
struct timeval when;
when = ast_mktime(&tm, args.timezone);
snprintf(buf, buflen, "%d", (int) when.tv_sec);
static struct ast_custom_function strptime_function = {
.name = "STRPTIME",
.read = acf_strptime,
};
static int function_eval(struct ast_channel *chan, const char *cmd, char *data,
char *buf, size_t buflen)
ast_log(LOG_WARNING, "EVAL requires an argument: EVAL(<string>)\n");
pbx_substitute_variables_helper(chan, data, buf, buflen - 1);
static int function_eval2(struct ast_channel *chan, const char *cmd, char *data,
struct ast_str **buf, ssize_t buflen)
{
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "EVAL requires an argument: EVAL(<string>)\n");
return -1;
}
ast_str_substitute_variables(buf, buflen, chan, data);
return 0;
}
static struct ast_custom_function eval_function = {
.name = "EVAL",
.read = function_eval,
static int keypadhash(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
{
char *bufptr, *dataptr;
for (bufptr = buf, dataptr = data; bufptr < buf + buflen - 1; dataptr++) {
if (*dataptr == '\0') {
*bufptr++ = '\0';
break;
} else if (*dataptr == '1') {
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
*bufptr++ = '1';
} else if (strchr("AaBbCc2", *dataptr)) {
*bufptr++ = '2';
} else if (strchr("DdEeFf3", *dataptr)) {
*bufptr++ = '3';
} else if (strchr("GgHhIi4", *dataptr)) {
*bufptr++ = '4';
} else if (strchr("JjKkLl5", *dataptr)) {
*bufptr++ = '5';
} else if (strchr("MmNnOo6", *dataptr)) {
*bufptr++ = '6';
} else if (strchr("PpQqRrSs7", *dataptr)) {
*bufptr++ = '7';
} else if (strchr("TtUuVv8", *dataptr)) {
*bufptr++ = '8';
} else if (strchr("WwXxYyZz9", *dataptr)) {
*bufptr++ = '9';
} else if (*dataptr == '0') {
*bufptr++ = '0';
}
}
buf[buflen - 1] = '\0';
return 0;
}
static struct ast_custom_function keypadhash_function = {
.name = "KEYPADHASH",
.read = keypadhash,
};
static int string_toupper(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
{
char *bufptr = buf, *dataptr = data;
while ((bufptr < buf + buflen - 1) && (*bufptr++ = toupper(*dataptr++)));
return 0;
}
static int string_toupper2(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t buflen)
{
char *bufptr, *dataptr = data;
if (buflen > -1) {
ast_str_make_space(buf, buflen > 0 ? buflen : strlen(data) + 1);
}
bufptr = ast_str_buffer(*buf);
while ((bufptr < ast_str_buffer(*buf) + ast_str_size(*buf) - 1) && (*bufptr++ = toupper(*dataptr++)));
ast_str_update(*buf);
return 0;
}
static struct ast_custom_function toupper_function = {
.name = "TOUPPER",
.read = string_toupper,
};
static int string_tolower(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
{
char *bufptr = buf, *dataptr = data;
while ((bufptr < buf + buflen - 1) && (*bufptr++ = tolower(*dataptr++)));
return 0;
}
static int string_tolower2(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t buflen)
{
char *bufptr, *dataptr = data;
if (buflen > -1) {
ast_str_make_space(buf, buflen > 0 ? buflen : strlen(data) + 1);
}
bufptr = ast_str_buffer(*buf);
while ((bufptr < ast_str_buffer(*buf) + ast_str_size(*buf) - 1) && (*bufptr++ = tolower(*dataptr++)));
ast_str_update(*buf);
return 0;
}
static struct ast_custom_function tolower_function = {
.name = "TOLOWER",
.read = string_tolower,
};
Tilghman Lesher
committed
static int shift_pop(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
Tilghman Lesher
committed
#define beginning (cmd[0] == 'S') /* SHIFT */
char *after, delimiter[2] = ",", *varsubst;
size_t unused;
struct ast_str *before = ast_str_thread_get(&result_buf, 16);
char *(*search_func)(const char *s, int c) = (beginning ? strchr : strrchr);
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(var);
AST_APP_ARG(delimiter);
);
Tilghman Lesher
committed
if (!before) {
return -1;
}
Tilghman Lesher
committed
AST_STANDARD_APP_ARGS(args, data);
if (ast_strlen_zero(args.var)) {
Tilghman Lesher
committed
ast_log(LOG_WARNING, "%s requires a variable name\n", cmd);
return -1;
}
varsubst = ast_alloca(strlen(args.var) + 4);
Tilghman Lesher
committed
sprintf(varsubst, "${%s}", args.var);
ast_str_substitute_variables(&before, 0, chan, varsubst);
Tilghman Lesher
committed
if (args.argc > 1 && !ast_strlen_zero(args.delimiter)) {
ast_get_encoded_char(args.delimiter, delimiter, &unused);
Tilghman Lesher
committed
if (!ast_str_strlen(before)) {
/* Nothing to pop */
return -1;
}
Tilghman Lesher
committed
if (!(after = search_func(ast_str_buffer(before), delimiter[0]))) {
/* Only one entry in array */
ast_str_set(buf, len, "%s", ast_str_buffer(before));
pbx_builtin_setvar_helper(chan, args.var, "");
} else {
*after++ = '\0';
Tilghman Lesher
committed
ast_str_set(buf, len, "%s", beginning ? ast_str_buffer(before) : after);
pbx_builtin_setvar_helper(chan, args.var, beginning ? after : ast_str_buffer(before));
}
return 0;
Tilghman Lesher
committed
#undef beginning
}
static struct ast_custom_function shift_function = {
.name = "SHIFT",
Tilghman Lesher
committed
.read2 = shift_pop,
};
static struct ast_custom_function pop_function = {
.name = "POP",
Tilghman Lesher
committed
.read2 = shift_pop,
Tilghman Lesher
committed
static int unshift_push(struct ast_channel *chan, const char *cmd, char *data, const char *new_value)
Tilghman Lesher
committed
#define beginning (cmd[0] == 'U') /* UNSHIFT */
char delimiter[2] = ",", *varsubst;
size_t unused;
struct ast_str *buf, *previous_value;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(var);
AST_APP_ARG(delimiter);
);
Tilghman Lesher
committed
if (!(buf = ast_str_thread_get(&result_buf, 16)) ||
!(previous_value = ast_str_thread_get(&tmp_buf, 16))) {
return -1;
}
Tilghman Lesher
committed
AST_STANDARD_APP_ARGS(args, data);
Tilghman Lesher
committed
if (ast_strlen_zero(args.var)) {
ast_log(LOG_WARNING, "%s requires a variable name\n", cmd);
return -1;
}
Tilghman Lesher
committed
if (args.argc > 1 && !ast_strlen_zero(args.delimiter)) {
ast_get_encoded_char(args.delimiter, delimiter, &unused);
varsubst = ast_alloca(strlen(args.var) + 4);
Tilghman Lesher
committed
sprintf(varsubst, "${%s}", args.var);
ast_str_substitute_variables(&previous_value, 0, chan, varsubst);
Tilghman Lesher
committed
if (!ast_str_strlen(previous_value)) {
ast_str_set(&buf, 0, "%s", new_value);
Tilghman Lesher
committed
ast_str_set(&buf, 0, "%s%c%s",
beginning ? new_value : ast_str_buffer(previous_value),
delimiter[0],
beginning ? ast_str_buffer(previous_value) : new_value);
}
pbx_builtin_setvar_helper(chan, args.var, ast_str_buffer(buf));
return 0;
Tilghman Lesher
committed
#undef beginning
}
static struct ast_custom_function push_function = {
.name = "PUSH",
Tilghman Lesher
committed
.write = unshift_push,
Tilghman Lesher
committed
static struct ast_custom_function unshift_function = {
.name = "UNSHIFT",
.write = unshift_push,
};
static int passthru(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
Tilghman Lesher
committed
ast_str_set(buf, len, "%s", data);
return 0;
Tilghman Lesher
committed
static struct ast_custom_function passthru_function = {
.name = "PASSTHRU",
.read2 = passthru,
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
AST_TEST_DEFINE(test_FIELDNUM)
{
int i, res = AST_TEST_PASS;
struct ast_channel *chan;
struct ast_str *str;
char expression[256];
struct {
const char *fields;
const char *delim;
const char *field;
const char *expected;
} test_args[] = {
{"abc,def,ghi,jkl", "\\,", "ghi", "3"},
{"abc def ghi jkl", " ", "abc", "1"},
{"abc/def/ghi/jkl", "\\\\x2f", "def", "2"},
{"abc$def$ghi$jkl", "", "ghi", "0"},
{"abc,def,ghi,jkl", "-", "", "0"},
{"abc-def-ghi-jkl", "-", "mno", "0"}
};
switch (cmd) {
case TEST_INIT:
info->name = "func_FIELDNUM_test";
info->category = "/funcs/func_strings/";
info->summary = "Test FIELDNUM function";
info->description = "Verify FIELDNUM behavior";
return AST_TEST_NOT_RUN;
case TEST_EXECUTE:
break;
}
if (!(chan = ast_dummy_channel_alloc())) {
ast_test_status_update(test, "Unable to allocate dummy channel\n");
return AST_TEST_FAIL;
}
if (!(str = ast_str_create(16))) {
ast_test_status_update(test, "Unable to allocate dynamic string buffer\n");
ast_channel_release(chan);
return AST_TEST_FAIL;
}
for (i = 0; i < ARRAY_LEN(test_args); i++) {
struct ast_var_t *var = ast_var_assign("FIELDS", test_args[i].fields);
AST_LIST_INSERT_HEAD(ast_channel_varshead(chan), var, entries);
snprintf(expression, sizeof(expression), "${FIELDNUM(%s,%s,%s)}", var->name, test_args[i].delim, test_args[i].field);
ast_str_substitute_variables(&str, 0, chan, expression);
AST_LIST_REMOVE(ast_channel_varshead(chan), var, entries);
ast_var_delete(var);
if (strcasecmp(ast_str_buffer(str), test_args[i].expected)) {
ast_test_status_update(test, "Evaluation of '%s' returned '%s' instead of the expected value '%s'\n",
expression, ast_str_buffer(str), test_args[i].expected);
res = AST_TEST_FAIL;
break;
}
}
ast_free(str);
ast_channel_release(chan);
return res;
}
AST_TEST_DEFINE(test_FILTER)
{
int i, res = AST_TEST_PASS;
const char *test_strings[][2] = {
{"A-R", "DAHDI"},
{"A\\-R", "A"},
{"\\x41-R", "DAHDI"},
{"0-9A-Ca-c", "0042133333A12212"},
{"0-9a-cA-C_+\\-", "0042133333A12212"},
{NULL, NULL},
};
switch (cmd) {
case TEST_INIT:
info->name = "func_FILTER_test";
Tilghman Lesher
committed
info->category = "/funcs/func_strings/";
info->summary = "Test FILTER function";
info->description = "Verify FILTER behavior";
return AST_TEST_NOT_RUN;
case TEST_EXECUTE:
break;
}
for (i = 0; test_strings[i][0]; i++) {
char tmp[256], tmp2[256] = "";
snprintf(tmp, sizeof(tmp), "${FILTER(%s,0042133333&DAHDI/g1/2212)}", test_strings[i][0]);
pbx_substitute_variables_helper(NULL, tmp, tmp2, sizeof(tmp2) - 1);
if (strcmp(test_strings[i][1], tmp2)) {
ast_test_status_update(test, "Format string '%s' substituted to '%s'. Expected '%s'.\n", test_strings[i][0], tmp2, test_strings[i][1]);
res = AST_TEST_FAIL;
}
}
return res;
}
AST_TEST_DEFINE(test_STRREPLACE)
{
int i, res = AST_TEST_PASS;
struct ast_channel *chan; /* dummy channel */
struct ast_str *str; /* fancy string for holding comparing value */
const char *test_strings[][5] = {
{"Weasels have eaten my telephone system", "have eaten my", "are eating our", "", "Weasels are eating our telephone system"}, /*Test normal conditions */
{"Did you know twenty plus two is twenty-two?", "twenty", "thirty", NULL, "Did you know thirty plus two is thirty-two?"}, /* Test no third comma */
{"foofoofoofoofoofoofoo", "foofoo", "bar", NULL, "barbarbarfoo"}, /* Found string within previous match */
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
{"My pet dog once ate a dog who sat on a dog while eating a corndog.", "dog", "cat", "3", "My pet cat once ate a cat who sat on a cat while eating a corndog."},
{"One and one and one is three", "and", "plus", "1", "One plus one and one is three"}, /* Test <max-replacements> = 1*/
{"", "fhqwagads", "spelunker", NULL, ""}, /* Empty primary string */
{"Part of this string is missing.", "missing", NULL, NULL, "Part of this string is ."}, /* Empty replace string */
{"'Accidentally' left off a bunch of stuff.", NULL, NULL, NULL, ""}, /* Deliberate error test from too few args */
{"This test will also error.", "", "", "", ""}, /* Deliberate error test from blank find string */
{"This is an \"escape character\" test.", "\\\"escape character\\\"", "evil", NULL, "This is an evil test."}
};
switch (cmd) {
case TEST_INIT:
info->name = "func_STRREPLACE_test";
info->category = "/funcs/func_strings/";
info->summary = "Test STRREPLACE function";
info->description = "Verify STRREPLACE behavior";
return AST_TEST_NOT_RUN;
case TEST_EXECUTE:
break;
}
if (!(chan = ast_dummy_channel_alloc())) {
ast_test_status_update(test, "Unable to allocate dummy channel\n");
return AST_TEST_FAIL;
}
if (!(str = ast_str_create(64))) {
ast_test_status_update(test, "Unable to allocate dynamic string buffer\n");
ast_channel_release(chan);
return AST_TEST_FAIL;
}
for (i = 0; i < ARRAY_LEN(test_strings); i++) {
char tmp[512], tmp2[512] = "";
struct ast_var_t *var = ast_var_assign("test_string", test_strings[i][0]);
AST_LIST_INSERT_HEAD(ast_channel_varshead(chan), var, entries);
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
if (test_strings[i][3]) {
snprintf(tmp, sizeof(tmp), "${STRREPLACE(%s,%s,%s,%s)}", "test_string", test_strings[i][1], test_strings[i][2], test_strings[i][3]);
} else if (test_strings[i][2]) {
snprintf(tmp, sizeof(tmp), "${STRREPLACE(%s,%s,%s)}", "test_string", test_strings[i][1], test_strings[i][2]);
} else if (test_strings[i][1]) {
snprintf(tmp, sizeof(tmp), "${STRREPLACE(%s,%s)}", "test_string", test_strings[i][1]);
} else {
snprintf(tmp, sizeof(tmp), "${STRREPLACE(%s)}", "test_string");
}
ast_str_substitute_variables(&str, 0, chan, tmp);
if (strcmp(test_strings[i][4], ast_str_buffer(str))) {
ast_test_status_update(test, "Format string '%s' substituted to '%s'. Expected '%s'.\n", test_strings[i][0], tmp2, test_strings[i][4]);
res = AST_TEST_FAIL;
}
}
ast_free(str);
ast_channel_release(chan);
return res;
}
static int unload_module(void)
{
int res = 0;
AST_TEST_UNREGISTER(test_FIELDNUM);
AST_TEST_UNREGISTER(test_FILTER);
res |= ast_custom_function_unregister(&fieldqty_function);
res |= ast_custom_function_unregister(&fieldnum_function);
res |= ast_custom_function_unregister(&filter_function);
Tilghman Lesher
committed
res |= ast_custom_function_unregister(&replace_function);
res |= ast_custom_function_unregister(&strreplace_function);
Tilghman Lesher
committed
res |= ast_custom_function_unregister(&listfilter_function);
res |= ast_custom_function_unregister(®ex_function);
res |= ast_custom_function_unregister(&array_function);
res |= ast_custom_function_unregister("e_function);
res |= ast_custom_function_unregister(&csv_quote_function);
res |= ast_custom_function_unregister(&len_function);
res |= ast_custom_function_unregister(&strftime_function);
res |= ast_custom_function_unregister(&strptime_function);
res |= ast_custom_function_unregister(&eval_function);
res |= ast_custom_function_unregister(&keypadhash_function);
res |= ast_custom_function_unregister(&hashkeys_function);
res |= ast_custom_function_unregister(&hash_function);
res |= ast_unregister_application(app_clearhash);
res |= ast_custom_function_unregister(&toupper_function);
res |= ast_custom_function_unregister(&tolower_function);
res |= ast_custom_function_unregister(&shift_function);
res |= ast_custom_function_unregister(&pop_function);
res |= ast_custom_function_unregister(&push_function);
res |= ast_custom_function_unregister(&unshift_function);
Tilghman Lesher
committed
res |= ast_custom_function_unregister(&passthru_function);
return res;
}
static int load_module(void)
{
int res = 0;
AST_TEST_REGISTER(test_FIELDNUM);
AST_TEST_REGISTER(test_FILTER);
res |= ast_custom_function_register(&fieldqty_function);
res |= ast_custom_function_register(&fieldnum_function);
res |= ast_custom_function_register(&filter_function);
Tilghman Lesher
committed
res |= ast_custom_function_register(&replace_function);
res |= ast_custom_function_register(&strreplace_function);
Tilghman Lesher
committed
res |= ast_custom_function_register(&listfilter_function);
res |= ast_custom_function_register(®ex_function);
res |= ast_custom_function_register(&array_function);
res |= ast_custom_function_register("e_function);
res |= ast_custom_function_register(&csv_quote_function);
res |= ast_custom_function_register(&len_function);
res |= ast_custom_function_register(&strftime_function);
res |= ast_custom_function_register(&strptime_function);
res |= ast_custom_function_register(&eval_function);
res |= ast_custom_function_register(&keypadhash_function);
res |= ast_custom_function_register(&hashkeys_function);
res |= ast_custom_function_register(&hash_function);
res |= ast_register_application_xml(app_clearhash, exec_clearhash);
res |= ast_custom_function_register(&toupper_function);
res |= ast_custom_function_register(&tolower_function);
res |= ast_custom_function_register(&shift_function);
res |= ast_custom_function_register(&pop_function);
res |= ast_custom_function_register(&push_function);
res |= ast_custom_function_register(&unshift_function);
Tilghman Lesher
committed
res |= ast_custom_function_register(&passthru_function);
return res;
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "String handling dialplan functions");