aboutsummaryrefslogtreecommitdiffstats
path: root/funcs
diff options
context:
space:
mode:
authortilghman <tilghman@f38db490-d61c-443f-a65b-d21fe96a405b>2009-04-29 18:53:01 +0000
committertilghman <tilghman@f38db490-d61c-443f-a65b-d21fe96a405b>2009-04-29 18:53:01 +0000
commit8fc2c0f7245703d3dde31d7fa035f3f28c82daeb (patch)
tree972bdf8f96c18f1b9667469307af69385f4a75f3 /funcs
parent6d9e0aa8817729e7914bb1b3fafe02dc96ae41b5 (diff)
Merge str_substitution branch.
This branch adds additional methods to dialplan functions, whereby the result buffers are now dynamic buffers, which can be expanded to the size of any result. No longer are variable substitutions limited to 4095 bytes of data. In addition, the common case of needing buffers much smaller than that will enable substitution to only take up the amount of memory actually needed. The existing variable substitution routines are still available, but users of those API calls should transition to using the dynamic-buffer APIs. Reviewboard: http://reviewboard.digium.com/r/174/ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@191140 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'funcs')
-rw-r--r--funcs/func_aes.c78
-rw-r--r--funcs/func_base64.c50
-rw-r--r--funcs/func_blacklist.c17
-rw-r--r--funcs/func_callerid.c2
-rw-r--r--funcs/func_curl.c110
-rw-r--r--funcs/func_cut.c70
-rw-r--r--funcs/func_db.c1
-rw-r--r--funcs/func_dialplan.c1
-rw-r--r--funcs/func_env.c3
-rw-r--r--funcs/func_extstate.c1
-rw-r--r--funcs/func_groupcount.c2
-rw-r--r--funcs/func_lock.c3
-rw-r--r--funcs/func_logic.c45
-rw-r--r--funcs/func_md5.c1
-rw-r--r--funcs/func_module.c1
-rw-r--r--funcs/func_rand.c1
-rw-r--r--funcs/func_sha1.c1
-rw-r--r--funcs/func_speex.c6
-rw-r--r--funcs/func_strings.c163
-rw-r--r--funcs/func_sysinfo.c1
-rw-r--r--funcs/func_timeout.c1
-rw-r--r--funcs/func_vmcount.c1
22 files changed, 449 insertions, 110 deletions
diff --git a/funcs/func_aes.c b/funcs/func_aes.c
index 87319fa77..770ce3ae7 100644
--- a/funcs/func_aes.c
+++ b/funcs/func_aes.c
@@ -31,6 +31,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/pbx.h"
#include "asterisk/app.h"
#include "asterisk/aes.h"
+#include "asterisk/strings.h"
#define AES_BLOCK_SIZE 16
@@ -71,15 +72,15 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
static int aes_helper(struct ast_channel *chan, const char *cmd, char *data,
- char *buf, size_t len)
+ char *buf, struct ast_str **str, ssize_t maxlen)
{
unsigned char curblock[AES_BLOCK_SIZE] = { 0, };
- char *tmp;
+ char *tmp = NULL;
char *tmpP;
int data_len, encrypt;
+ int keylen, len, tmplen, elen = 0;
ast_aes_encrypt_key ecx; /* AES 128 Encryption context */
ast_aes_decrypt_key dcx;
-
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(key);
AST_APP_ARG(data);
@@ -92,22 +93,37 @@ static int aes_helper(struct ast_channel *chan, const char *cmd, char *data,
return -1;
}
- if (strlen(args.key) != AES_BLOCK_SIZE) { /* key must be of 16 characters in length, 128 bits */
- ast_log(LOG_WARNING, "Syntax: %s(<key>,<data>) - <key> parameter must be exactly 16 characters!\n", cmd);
+ if ((keylen = strlen(args.key)) != AES_BLOCK_SIZE) { /* key must be of 16 characters in length, 128 bits */
+ ast_log(LOG_WARNING, "Syntax: %s(<key>,<data>) - <key> parameter must be exactly 16 characters%s!\n", cmd, keylen < 16 ? " - padding" : "");
return -1;
}
- ast_aes_encrypt_key((unsigned char *) args.key, &ecx); /* encryption: plaintext -> encryptedtext -> base64 */
- ast_aes_decrypt_key((unsigned char *) args.key, &dcx); /* decryption: base64 -> encryptedtext -> plaintext */
- tmp = ast_calloc(1, len); /* requires a tmp buffer for the base64 decode */
- tmpP = tmp;
+ if (buf) {
+ len = maxlen;
+ } else if (maxlen == -1) {
+ len = ast_str_size(*str);
+ } else if (maxlen > 0) {
+ len = maxlen;
+ } else {
+ len = INT_MAX;
+ }
+ ast_debug(3, "len=%d\n", len);
+
encrypt = strcmp("AES_DECRYPT", cmd); /* -1 if encrypting, 0 if decrypting */
+ /* Round up the buffer to an even multiple of 16, plus 1 */
+ tmplen = (strlen(args.data) / 16 + 1) * 16 + 1;
+ tmp = ast_calloc(1, tmplen);
+ tmpP = tmp;
if (encrypt) { /* if decrypting first decode src to base64 */
- ast_copy_string(tmp, args.data, len);
+ /* encryption: plaintext -> encryptedtext -> base64 */
+ ast_aes_encrypt_key((unsigned char *) args.key, &ecx);
+ strcpy(tmp, args.data);
data_len = strlen(tmp);
} else {
- data_len = ast_base64decode((unsigned char *) tmp, args.data, len);
+ /* decryption: base64 -> encryptedtext -> plaintext */
+ ast_aes_decrypt_key((unsigned char *) args.key, &dcx);
+ data_len = ast_base64decode((unsigned char *) tmp, args.data, tmplen);
}
if (data_len >= len) { /* make sure to not go over buffer len */
@@ -116,8 +132,11 @@ static int aes_helper(struct ast_channel *chan, const char *cmd, char *data,
}
while (data_len > 0) {
+ /* Tricky operation. We first copy the data into curblock, then
+ * the data is encrypted or decrypted and put back into the original
+ * buffer. */
memset(curblock, 0, AES_BLOCK_SIZE);
- memcpy(curblock, tmpP, (data_len < AES_BLOCK_SIZE) ? data_len : AES_BLOCK_SIZE);
+ memcpy(curblock, tmpP, AES_BLOCK_SIZE);
if (encrypt) {
ast_aes_encrypt(curblock, (unsigned char *) tmpP, &ecx);
} else {
@@ -125,26 +144,53 @@ static int aes_helper(struct ast_channel *chan, const char *cmd, char *data,
}
tmpP += AES_BLOCK_SIZE;
data_len -= AES_BLOCK_SIZE;
+ elen += AES_BLOCK_SIZE;
}
if (encrypt) { /* if encrypting encode result to base64 */
- ast_base64encode(buf, (unsigned char *) tmp, strlen(tmp), len);
+ if (buf) {
+ ast_base64encode(buf, (unsigned char *) tmp, elen, len);
+ } else {
+ if (maxlen >= 0) {
+ ast_str_make_space(str, maxlen ? maxlen : elen * 4 / 3 + 2);
+ }
+ ast_base64encode(ast_str_buffer(*str), (unsigned char *) tmp, elen, ast_str_size(*str));
+ ast_str_update(*str);
+ }
} else {
- memcpy(buf, tmp, len);
+ if (buf) {
+ memcpy(buf, tmp, len);
+ } else {
+ ast_str_set(str, maxlen, "%s", tmp);
+ }
}
ast_free(tmp);
return 0;
}
+static int aes_buf_helper(struct ast_channel *chan, const char *cmd, char *data,
+ char *buf, size_t maxlen)
+{
+ return aes_helper(chan, cmd, data, buf, NULL, maxlen);
+}
+
+static int aes_str_helper(struct ast_channel *chan, const char *cmd, char *data,
+ struct ast_str **buf, ssize_t maxlen)
+{
+ return aes_helper(chan, cmd, data, NULL, buf, maxlen);
+}
+
static struct ast_custom_function aes_encrypt_function = {
.name = "AES_ENCRYPT",
- .read = aes_helper,
+ .read = aes_buf_helper,
+ .read2 = aes_str_helper,
};
static struct ast_custom_function aes_decrypt_function = {
.name = "AES_DECRYPT",
- .read = aes_helper,
+ .read = aes_buf_helper,
+ .read2 = aes_str_helper,
};
static int unload_module(void)
diff --git a/funcs/func_base64.c b/funcs/func_base64.c
index 28805b943..a68cf9bda 100644
--- a/funcs/func_base64.c
+++ b/funcs/func_base64.c
@@ -29,6 +29,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/module.h"
#include "asterisk/pbx.h" /* function register/unregister */
#include "asterisk/utils.h"
+#include "asterisk/strings.h"
/*** DOCUMENTATION
<function name="BASE64_ENCODE" language="en_US">
@@ -59,40 +60,61 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
</function>
***/
-static int base64_encode(struct ast_channel *chan, const char *cmd, char *data,
- char *buf, size_t len)
+static int base64_helper(struct ast_channel *chan, const char *cmd, char *data,
+ char *buf, struct ast_str **str, ssize_t len)
{
if (ast_strlen_zero(data)) {
- ast_log(LOG_WARNING, "Syntax: BASE64_ENCODE(<data>) - missing argument!\n");
+ ast_log(LOG_WARNING, "Syntax: %s(<data>) - missing argument!\n", cmd);
return -1;
}
- ast_base64encode(buf, (unsigned char *) data, strlen(data), len);
+ if (cmd[7] == 'E') {
+ if (buf) {
+ ast_base64encode(buf, (unsigned char *) data, strlen(data), len);
+ } else {
+ if (len >= 0) {
+ ast_str_make_space(str, len ? len : ast_str_strlen(*str) + strlen(data) * 4 / 3 + 2);
+ }
+ ast_base64encode(ast_str_buffer(*str) + ast_str_strlen(*str), (unsigned char *) data, strlen(data), ast_str_size(*str) - ast_str_strlen(*str));
+ ast_str_update(*str);
+ }
+ } else {
+ if (buf) {
+ ast_base64decode((unsigned char *) buf, data, len);
+ } else {
+ if (len >= 0) {
+ ast_str_make_space(str, len ? len : ast_str_strlen(*str) + strlen(data) * 3 / 4 + 2);
+ }
+ ast_base64decode((unsigned char *) ast_str_buffer(*str) + ast_str_strlen(*str), data, ast_str_size(*str) - ast_str_strlen(*str));
+ ast_str_update(*str);
+ }
+ }
return 0;
}
-static int base64_decode(struct ast_channel *chan, const char *cmd, char *data,
+static int base64_buf_helper(struct ast_channel *chan, const char *cmd, char *data,
char *buf, size_t len)
{
- if (ast_strlen_zero(data)) {
- ast_log(LOG_WARNING, "Syntax: BASE64_DECODE(<base_64 string>) - missing argument!\n");
- return -1;
- }
-
- ast_base64decode((unsigned char *) buf, data, len);
+ return base64_helper(chan, cmd, data, buf, NULL, len);
+}
- return 0;
+static int base64_str_helper(struct ast_channel *chan, const char *cmd, char *data,
+ struct ast_str **buf, ssize_t len)
+{
+ return base64_helper(chan, cmd, data, NULL, buf, len);
}
static struct ast_custom_function base64_encode_function = {
.name = "BASE64_ENCODE",
- .read = base64_encode,
+ .read = base64_buf_helper,
+ .read2 = base64_str_helper,
};
static struct ast_custom_function base64_decode_function = {
.name = "BASE64_DECODE",
- .read = base64_decode,
+ .read = base64_buf_helper,
+ .read2 = base64_str_helper,
};
static int unload_module(void)
diff --git a/funcs/func_blacklist.c b/funcs/func_blacklist.c
index 304ba9bdf..a765242d4 100644
--- a/funcs/func_blacklist.c
+++ b/funcs/func_blacklist.c
@@ -70,9 +70,26 @@ static int blacklist_read(struct ast_channel *chan, const char *cmd, char *data,
return 0;
}
+static int blacklist_read2(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **str, ssize_t len)
+{
+ /* 2 bytes is a single integer, plus terminating null */
+ if (ast_str_size(*str) - ast_str_strlen(*str) < 2) {
+ if (len > ast_str_size(*str) || len == 0) {
+ ast_str_make_space(str, len ? len : ast_str_strlen(*str) + 2);
+ }
+ }
+ if (ast_str_size(*str) - ast_str_strlen(*str) >= 2) {
+ int res = blacklist_read(chan, cmd, data, ast_str_buffer(*str) + ast_str_strlen(*str), 2);
+ ast_str_update(*str);
+ return res;
+ }
+ return -1;
+}
+
static struct ast_custom_function blacklist_function = {
.name = "BLACKLIST",
.read = blacklist_read,
+ .read2 = blacklist_read2,
};
static int unload_module(void)
diff --git a/funcs/func_callerid.c b/funcs/func_callerid.c
index 8bce770a2..3968e9438 100644
--- a/funcs/func_callerid.c
+++ b/funcs/func_callerid.c
@@ -274,12 +274,14 @@ static int callerid_write(struct ast_channel *chan, const char *cmd, char *data,
static struct ast_custom_function callerid_function = {
.name = "CALLERID",
.read = callerid_read,
+ .read_max = 256,
.write = callerid_write,
};
static struct ast_custom_function callerpres_function = {
.name = "CALLERPRES",
.read = callerpres_read,
+ .read_max = 50,
.write = callerpres_write,
};
diff --git a/funcs/func_curl.c b/funcs/func_curl.c
index d4f34b850..b7918836d 100644
--- a/funcs/func_curl.c
+++ b/funcs/func_curl.c
@@ -276,7 +276,7 @@ yuck:
return 0;
}
-static int acf_curlopt_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
+static int acf_curlopt_helper(struct ast_channel *chan, const char *cmd, char *data, char *buf, struct ast_str **bufstr, ssize_t len)
{
struct ast_datastore *store;
struct global_curl_info *list[2] = { &global_curl_info, NULL };
@@ -303,38 +303,78 @@ static int acf_curlopt_read(struct ast_channel *chan, const char *cmd, char *dat
AST_LIST_TRAVERSE(list[i], cur, list) {
if (cur->key == key) {
if (ot == OT_BOOLEAN || ot == OT_INTEGER) {
- snprintf(buf, len, "%ld", (long)cur->value);
+ if (buf) {
+ snprintf(buf, len, "%ld", (long) cur->value);
+ } else {
+ ast_str_set(bufstr, len, "%ld", (long) cur->value);
+ }
} else if (ot == OT_INTEGER_MS) {
- if ((long)cur->value % 1000 == 0) {
- snprintf(buf, len, "%ld", (long)cur->value / 1000);
+ if ((long) cur->value % 1000 == 0) {
+ if (buf) {
+ snprintf(buf, len, "%ld", (long)cur->value / 1000);
+ } else {
+ ast_str_set(bufstr, len, "%ld", (long) cur->value / 1000);
+ }
} else {
- snprintf(buf, len, "%.3f", (double)((long)cur->value) / 1000.0);
+ if (buf) {
+ snprintf(buf, len, "%.3f", (double) ((long) cur->value) / 1000.0);
+ } else {
+ ast_str_set(bufstr, len, "%.3f", (double) ((long) cur->value) / 1000.0);
+ }
}
} else if (ot == OT_STRING) {
ast_debug(1, "Found entry %p, with key %d and value %p\n", cur, cur->key, cur->value);
- ast_copy_string(buf, cur->value, len);
+ if (buf) {
+ ast_copy_string(buf, cur->value, len);
+ } else {
+ ast_str_set(bufstr, 0, "%s", (char *) cur->value);
+ }
} else if (key == CURLOPT_PROXYTYPE) {
if (0) {
#if CURLVERSION_ATLEAST(7,15,2)
} else if ((long)cur->value == CURLPROXY_SOCKS4) {
- ast_copy_string(buf, "socks4", len);
+ if (buf) {
+ ast_copy_string(buf, "socks4", len);
+ } else {
+ ast_str_set(bufstr, 0, "socks4");
+ }
#endif
#if CURLVERSION_ATLEAST(7,18,0)
} else if ((long)cur->value == CURLPROXY_SOCKS4A) {
- ast_copy_string(buf, "socks4a", len);
+ if (buf) {
+ ast_copy_string(buf, "socks4a", len);
+ } else {
+ ast_str_set(bufstr, 0, "socks4a");
+ }
#endif
} else if ((long)cur->value == CURLPROXY_SOCKS5) {
- ast_copy_string(buf, "socks5", len);
+ if (buf) {
+ ast_copy_string(buf, "socks5", len);
+ } else {
+ ast_str_set(bufstr, 0, "socks5");
+ }
#if CURLVERSION_ATLEAST(7,18,0)
} else if ((long)cur->value == CURLPROXY_SOCKS5_HOSTNAME) {
- ast_copy_string(buf, "socks5hostname", len);
+ if (buf) {
+ ast_copy_string(buf, "socks5hostname", len);
+ } else {
+ ast_str_set(bufstr, 0, "socks5hostname");
+ }
#endif
#if CURLVERSION_ATLEAST(7,10,0)
} else if ((long)cur->value == CURLPROXY_HTTP) {
- ast_copy_string(buf, "http", len);
+ if (buf) {
+ ast_copy_string(buf, "http", len);
+ } else {
+ ast_str_set(bufstr, 0, "http");
+ }
#endif
} else {
- ast_copy_string(buf, "unknown", len);
+ if (buf) {
+ ast_copy_string(buf, "unknown", len);
+ } else {
+ ast_str_set(bufstr, 0, "unknown");
+ }
}
}
break;
@@ -349,6 +389,16 @@ static int acf_curlopt_read(struct ast_channel *chan, const char *cmd, char *dat
return cur ? 0 : -1;
}
+static int acf_curlopt_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
+{
+ return acf_curlopt_helper(chan, cmd, data, buf, NULL, len);
+}
+
+static int acf_curlopt_read2(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
+{
+ return acf_curlopt_helper(chan, cmd, data, NULL, buf, len);
+}
+
static size_t WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data)
{
register int realsize = size * nmemb;
@@ -391,7 +441,7 @@ static void curl_instance_cleanup(void *data)
AST_THREADSTORAGE_CUSTOM(curl_instance, curl_instance_init, curl_instance_cleanup);
-static int acf_curl_exec(struct ast_channel *chan, const char *cmd, char *info, char *buf, size_t len)
+static int acf_curl_helper(struct ast_channel *chan, const char *cmd, char *info, char *buf, struct ast_str **input_str, ssize_t len)
{
struct ast_str *str = ast_str_create(16);
int ret = -1;
@@ -405,15 +455,17 @@ static int acf_curl_exec(struct ast_channel *chan, const char *cmd, char *info,
int hashcompat = 0;
AST_LIST_HEAD(global_curl_info, curl_settings) *list = NULL;
- *buf = '\0';
-
+ if (buf) {
+ *buf = '\0';
+ }
+
if (ast_strlen_zero(info)) {
ast_log(LOG_WARNING, "CURL requires an argument (URL)\n");
ast_free(str);
return -1;
}
- AST_STANDARD_APP_ARGS(args, info);
+ AST_STANDARD_APP_ARGS(args, info);
if (chan) {
ast_autoservice_start(chan);
@@ -483,11 +535,19 @@ static int acf_curl_exec(struct ast_channel *chan, const char *cmd, char *info,
rowcount++;
}
pbx_builtin_setvar_helper(chan, "~ODBCFIELDS~", ast_str_buffer(fields));
- ast_copy_string(buf, ast_str_buffer(values), len);
+ if (buf) {
+ ast_copy_string(buf, ast_str_buffer(values), len);
+ } else {
+ ast_str_set(input_str, len, "%s", ast_str_buffer(values));
+ }
ast_free(fields);
ast_free(values);
} else {
- ast_copy_string(buf, ast_str_buffer(str), len);
+ if (buf) {
+ ast_copy_string(buf, ast_str_buffer(str), len);
+ } else {
+ ast_str_set(input_str, len, "%s", ast_str_buffer(str));
+ }
}
ret = 0;
}
@@ -495,10 +555,20 @@ static int acf_curl_exec(struct ast_channel *chan, const char *cmd, char *info,
if (chan)
ast_autoservice_stop(chan);
-
+
return ret;
}
+static int acf_curl_exec(struct ast_channel *chan, const char *cmd, char *info, char *buf, size_t len)
+{
+ return acf_curl_helper(chan, cmd, info, buf, NULL, len);
+}
+
+static int acf_curl2_exec(struct ast_channel *chan, const char *cmd, char *info, struct ast_str **buf, ssize_t len)
+{
+ return acf_curl_helper(chan, cmd, info, NULL, buf, len);
+}
+
struct ast_custom_function acf_curl = {
.name = "CURL",
.synopsis = "Retrieves the contents of a URL",
@@ -507,6 +577,7 @@ struct ast_custom_function acf_curl = {
" url - URL to retrieve\n"
" post-data - Optional data to send as a POST (GET is default action)\n",
.read = acf_curl_exec,
+ .read2 = acf_curl2_exec,
};
struct ast_custom_function acf_curlopt = {
@@ -532,6 +603,7 @@ struct ast_custom_function acf_curlopt = {
" hashcompat - Result data will be compatible for use with HASH()\n"
"",
.read = acf_curlopt_read,
+ .read2 = acf_curlopt_read2,
.write = acf_curlopt_write,
};
diff --git a/funcs/func_cut.c b/funcs/func_cut.c
index 3a3c2f309..437ebf621 100644
--- a/funcs/func_cut.c
+++ b/funcs/func_cut.c
@@ -77,9 +77,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
</function>
***/
-/* Maximum length of any variable */
-#define MAXRESULT 1024
-
struct sortable_keys {
char *key;
float value;
@@ -151,7 +148,7 @@ static int sort_internal(struct ast_channel *chan, char *data, char *buffer, siz
return 0;
}
-static int cut_internal(struct ast_channel *chan, char *data, char *buffer, size_t buflen)
+static int cut_internal(struct ast_channel *chan, char *data, struct ast_str **buf, ssize_t buflen)
{
char *parse;
size_t delim_consumed;
@@ -160,8 +157,7 @@ static int cut_internal(struct ast_channel *chan, char *data, char *buffer, size
AST_APP_ARG(delimiter);
AST_APP_ARG(field);
);
-
- *buffer = '\0';
+ struct ast_str *str = ast_str_create(16);
parse = ast_strdupa(data);
@@ -169,31 +165,30 @@ static int cut_internal(struct ast_channel *chan, char *data, char *buffer, size
/* Check and parse arguments */
if (args.argc < 3) {
+ ast_free(str);
return ERROR_NOARG;
} else {
- char d, ds[2] = "";
+ char ds[2] = "";
char *tmp = alloca(strlen(args.varname) + 4);
- char varvalue[MAXRESULT], *tmp2=varvalue;
if (tmp) {
snprintf(tmp, strlen(args.varname) + 4, "${%s}", args.varname);
} else {
+ ast_free(str);
return ERROR_NOMEM;
}
if (ast_get_encoded_char(args.delimiter, ds, &delim_consumed))
ast_copy_string(ds, "-", sizeof(ds));
- /* String form of the delimiter, for use with strsep(3) */
- d = *ds;
-
- pbx_substitute_variables_helper(chan, tmp, tmp2, MAXRESULT - 1);
+ ast_str_substitute_variables(&str, 0, chan, tmp);
- if (tmp2) {
+ if (ast_str_strlen(str)) {
int curfieldnum = 1;
+ char *tmp2 = ast_str_buffer(str);
while (tmp2 != NULL && args.field != NULL) {
char *nextgroup = strsep(&(args.field), "&");
- int num1 = 0, num2 = MAXRESULT;
+ int num1 = 0, num2 = INT_MAX;
char trashchar;
if (sscanf(nextgroup, "%d-%d", &num1, &num2) == 2) {
@@ -203,18 +198,19 @@ static int cut_internal(struct ast_channel *chan, char *data, char *buffer, size
num1 = 0;
} else if ((sscanf(nextgroup, "%d%c", &num1, &trashchar) == 2) && (trashchar == '-')) {
/* range with start */
- num2 = MAXRESULT;
+ num2 = INT_MAX;
} else if (sscanf(nextgroup, "%d", &num1) == 1) {
/* single number */
num2 = num1;
} else {
+ ast_free(str);
return ERROR_USAGE;
}
/* Get to start, if any */
if (num1 > 0) {
- while (tmp2 != (char *)NULL + 1 && curfieldnum < num1) {
- tmp2 = strchr(tmp2, d) + 1;
+ while (tmp2 != NULL && curfieldnum < num1) {
+ tmp2 = strchr(tmp2 + 1, ds[0]);
curfieldnum++;
}
}
@@ -223,25 +219,16 @@ static int cut_internal(struct ast_channel *chan, char *data, char *buffer, size
if ((num1 > 0) && (curfieldnum > num1))
ast_log(LOG_WARNING, "We're already past the field you wanted?\n");
- /* Re-null tmp2 if we added 1 to NULL */
- if (tmp2 == (char *)NULL + 1)
- tmp2 = NULL;
-
/* Output fields until we either run out of fields or num2 is reached */
while (tmp2 != NULL && curfieldnum <= num2) {
char *tmp3 = strsep(&tmp2, ds);
- int curlen = strlen(buffer);
-
- if (curlen)
- snprintf(buffer + curlen, buflen - curlen, "%c%s", d, tmp3);
- else
- snprintf(buffer, buflen, "%s", tmp3);
-
+ ast_str_append(buf, buflen, "%s%s", ast_str_strlen(*buf) ? ds : "", tmp3);
curfieldnum++;
}
}
}
}
+ ast_free(str);
return 0;
}
@@ -269,6 +256,32 @@ static int acf_sort_exec(struct ast_channel *chan, const char *cmd, char *data,
static int acf_cut_exec(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
{
int ret = -1;
+ struct ast_str *str = ast_str_create(16);
+
+ switch (cut_internal(chan, data, &str, len)) {
+ case ERROR_NOARG:
+ ast_log(LOG_ERROR, "Syntax: CUT(<varname>,<char-delim>,<range-spec>) - missing argument!\n");
+ break;
+ case ERROR_NOMEM:
+ ast_log(LOG_ERROR, "Out of memory\n");
+ break;
+ case ERROR_USAGE:
+ ast_log(LOG_ERROR, "Usage: CUT(<varname>,<char-delim>,<range-spec>)\n");
+ break;
+ case 0:
+ ret = 0;
+ ast_copy_string(buf, ast_str_buffer(str), len);
+ break;
+ default:
+ ast_log(LOG_ERROR, "Unknown internal error\n");
+ }
+ ast_free(str);
+ return ret;
+}
+
+static int acf_cut_exec2(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
+{
+ int ret = -1;
switch (cut_internal(chan, data, buf, len)) {
case ERROR_NOARG:
@@ -298,6 +311,7 @@ struct ast_custom_function acf_sort = {
struct ast_custom_function acf_cut = {
.name = "CUT",
.read = acf_cut_exec,
+ .read2 = acf_cut_exec2,
};
static int unload_module(void)
diff --git a/funcs/func_db.c b/funcs/func_db.c
index 5fa753f6d..736fb0d75 100644
--- a/funcs/func_db.c
+++ b/funcs/func_db.c
@@ -201,6 +201,7 @@ static int function_db_exists(struct ast_channel *chan, const char *cmd,
static struct ast_custom_function db_exists_function = {
.name = "DB_EXISTS",
.read = function_db_exists,
+ .read_max = 2,
};
static int function_db_delete(struct ast_channel *chan, const char *cmd,
diff --git a/funcs/func_dialplan.c b/funcs/func_dialplan.c
index 0e371d2c8..1968a8b66 100644
--- a/funcs/func_dialplan.c
+++ b/funcs/func_dialplan.c
@@ -105,6 +105,7 @@ static int isexten_function_read(struct ast_channel *chan, const char *cmd, char
static struct ast_custom_function isexten_function = {
.name = "DIALPLAN_EXISTS",
.read = isexten_function_read,
+ .read_max = 2,
};
static int unload_module(void)
diff --git a/funcs/func_env.c b/funcs/func_env.c
index 707e96a12..70a87776b 100644
--- a/funcs/func_env.c
+++ b/funcs/func_env.c
@@ -230,7 +230,8 @@ static struct ast_custom_function env_function = {
static struct ast_custom_function stat_function = {
.name = "STAT",
- .read = stat_read
+ .read = stat_read,
+ .read_max = 12,
};
static struct ast_custom_function file_function = {
diff --git a/funcs/func_extstate.c b/funcs/func_extstate.c
index 7f2288560..d3c7ba4b7 100644
--- a/funcs/func_extstate.c
+++ b/funcs/func_extstate.c
@@ -122,6 +122,7 @@ static int extstate_read(struct ast_channel *chan, const char *cmd, char *data,
static struct ast_custom_function extstate_function = {
.name = "EXTENSION_STATE",
.read = extstate_read,
+ .read_max = 12,
};
static int unload_module(void)
diff --git a/funcs/func_groupcount.c b/funcs/func_groupcount.c
index ecb927467..81c4c97c9 100644
--- a/funcs/func_groupcount.c
+++ b/funcs/func_groupcount.c
@@ -134,6 +134,7 @@ static int group_count_function_read(struct ast_channel *chan, const char *cmd,
static struct ast_custom_function group_count_function = {
.name = "GROUP_COUNT",
.read = group_count_function_read,
+ .read_max = 12,
};
static int group_match_count_function_read(struct ast_channel *chan,
@@ -159,6 +160,7 @@ static int group_match_count_function_read(struct ast_channel *chan,
static struct ast_custom_function group_match_count_function = {
.name = "GROUP_MATCH_COUNT",
.read = group_match_count_function_read,
+ .read_max = 12,
.write = NULL,
};
diff --git a/funcs/func_lock.c b/funcs/func_lock.c
index d6df6d0ef..de8377a9c 100644
--- a/funcs/func_lock.c
+++ b/funcs/func_lock.c
@@ -324,16 +324,19 @@ static int trylock_read(struct ast_channel *chan, const char *cmd, char *data, c
static struct ast_custom_function lock_function = {
.name = "LOCK",
.read = lock_read,
+ .read_max = 2,
};
static struct ast_custom_function trylock_function = {
.name = "TRYLOCK",
.read = trylock_read,
+ .read_max = 2,
};
static struct ast_custom_function unlock_function = {
.name = "UNLOCK",
.read = unlock_read,
+ .read_max = 2,
};
static int unload_module(void)
diff --git a/funcs/func_logic.c b/funcs/func_logic.c
index 6ec3a0847..27734ed78 100644
--- a/funcs/func_logic.c
+++ b/funcs/func_logic.c
@@ -223,25 +223,40 @@ static int set(struct ast_channel *chan, const char *cmd, char *data, char *buf,
return 0;
}
-static int acf_import(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
+static int set2(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **str, ssize_t len)
+{
+ if (len > -1) {
+ ast_str_make_space(str, len == 0 ? strlen(data) : len);
+ }
+ return set(chan, cmd, data, ast_str_buffer(*str), ast_str_size(*str));
+}
+
+static int import_helper(struct ast_channel *chan, const char *cmd, char *data, char *buf, struct ast_str **str, ssize_t len)
{
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(channel);
AST_APP_ARG(varname);
);
AST_STANDARD_APP_ARGS(args, data);
-
- buf[0] = '\0';
+ if (buf) {
+ *buf = '\0';
+ }
if (!ast_strlen_zero(args.varname)) {
struct ast_channel *chan2;
if ((chan2 = ast_channel_get_by_name(args.channel))) {
char *s = alloca(strlen(args.varname) + 4);
- sprintf(s, "${%s}", args.varname);
- ast_channel_lock(chan2);
- pbx_substitute_variables_helper(chan2, s, buf, len);
- ast_channel_unlock(chan2);
+ if (s) {
+ sprintf(s, "${%s}", args.varname);
+ ast_channel_lock(chan2);
+ if (buf) {
+ pbx_substitute_variables_helper(chan2, s, buf, len);
+ } else {
+ ast_str_substitute_variables(str, len, chan2, s);
+ }
+ ast_channel_unlock(chan2);
+ }
chan2 = ast_channel_unref(chan2);
}
}
@@ -249,19 +264,32 @@ static int acf_import(struct ast_channel *chan, const char *cmd, char *data, cha
return 0;
}
+static int import_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
+{
+ return import_helper(chan, cmd, data, buf, NULL, len);
+}
+
+static int import_read2(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **str, ssize_t len)
+{
+ return import_helper(chan, cmd, data, NULL, str, len);
+}
+
static struct ast_custom_function isnull_function = {
.name = "ISNULL",
.read = isnull,
+ .read_max = 2,
};
static struct ast_custom_function set_function = {
.name = "SET",
.read = set,
+ .read2 = set2,
};
static struct ast_custom_function exists_function = {
.name = "EXISTS",
.read = exists,
+ .read_max = 2,
};
static struct ast_custom_function if_function = {
@@ -276,7 +304,8 @@ static struct ast_custom_function if_time_function = {
static struct ast_custom_function import_function = {
.name = "IMPORT",
- .read = acf_import,
+ .read = import_read,
+ .read2 = import_read2,
};
static int unload_module(void)
diff --git a/funcs/func_md5.c b/funcs/func_md5.c
index 23b35489a..7c61d9f8c 100644
--- a/funcs/func_md5.c
+++ b/funcs/func_md5.c
@@ -64,6 +64,7 @@ static int md5(struct ast_channel *chan, const char *cmd, char *data,
static struct ast_custom_function md5_function = {
.name = "MD5",
.read = md5,
+ .read_max = 33,
};
static int unload_module(void)
diff --git a/funcs/func_module.c b/funcs/func_module.c
index a7cf73164..44ec08e4d 100644
--- a/funcs/func_module.c
+++ b/funcs/func_module.c
@@ -65,6 +65,7 @@ static int ifmodule_read(struct ast_channel *chan, const char *cmd, char *data,
static struct ast_custom_function ifmodule_function = {
.name = "IFMODULE",
.read = ifmodule_read,
+ .read_max = 2,
};
diff --git a/funcs/func_rand.c b/funcs/func_rand.c
index 079723686..c49e63a44 100644
--- a/funcs/func_rand.c
+++ b/funcs/func_rand.c
@@ -87,6 +87,7 @@ static int acf_rand_exec(struct ast_channel *chan, const char *cmd,
static struct ast_custom_function acf_rand = {
.name = "RAND",
.read = acf_rand_exec,
+ .read_max = 12,
};
static int unload_module(void)
diff --git a/funcs/func_sha1.c b/funcs/func_sha1.c
index 973bc5c07..985e11a38 100644
--- a/funcs/func_sha1.c
+++ b/funcs/func_sha1.c
@@ -74,6 +74,7 @@ static int sha1(struct ast_channel *chan, const char *cmd, char *data,
static struct ast_custom_function sha1_function = {
.name = "SHA1",
.read = sha1,
+ .read_max = 42,
};
static int unload_module(void)
diff --git a/funcs/func_speex.c b/funcs/func_speex.c
index a3a5345ed..edfa3579b 100644
--- a/funcs/func_speex.c
+++ b/funcs/func_speex.c
@@ -337,13 +337,15 @@ static int speex_read(struct ast_channel *chan, const char *cmd, char *data, cha
static struct ast_custom_function agc_function = {
.name = "AGC",
.write = speex_write,
- .read = speex_read
+ .read = speex_read,
+ .read_max = 22,
};
static struct ast_custom_function denoise_function = {
.name = "DENOISE",
.write = speex_write,
- .read = speex_read
+ .read = speex_read,
+ .read_max = 22,
};
static int unload_module(void)
diff --git a/funcs/func_strings.c b/funcs/func_strings.c
index 35211ab85..a2ba285d4 100644
--- a/funcs/func_strings.c
+++ b/funcs/func_strings.c
@@ -343,10 +343,11 @@ AST_THREADSTORAGE(result_buf);
</function>
***/
-static int function_fieldqty(struct ast_channel *chan, const char *cmd,
- char *parse, char *buf, size_t len)
+static int function_fieldqty_helper(struct ast_channel *chan, const char *cmd,
+ char *parse, char *buf, struct ast_str **sbuf, ssize_t len)
{
- char *varsubst, varval[8192], *varval2 = varval;
+ char *varsubst;
+ struct ast_str *str = ast_str_create(16);
int fieldcount = 0;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(varname);
@@ -355,6 +356,10 @@ static int function_fieldqty(struct ast_channel *chan, const char *cmd,
char delim[2] = "";
size_t delim_used;
+ if (!str) {
+ return -1;
+ }
+
AST_STANDARD_APP_ARGS(args, parse);
if (args.delim) {
ast_get_encoded_char(args.delim, delim, &delim_used);
@@ -362,27 +367,47 @@ static int function_fieldqty(struct ast_channel *chan, const char *cmd,
varsubst = alloca(strlen(args.varname) + 4);
sprintf(varsubst, "${%s}", args.varname);
- pbx_substitute_variables_helper(chan, varsubst, varval, sizeof(varval) - 1);
- if (ast_strlen_zero(varval2))
+ ast_str_substitute_variables(&str, 0, chan, varsubst);
+ if (ast_str_strlen(str) == 0) {
fieldcount = 0;
- else {
- while (strsep(&varval2, delim))
+ } else {
+ char *varval = ast_str_buffer(str);
+ while (strsep(&varval, delim)) {
fieldcount++;
+ }
}
} else {
fieldcount = 1;
}
- snprintf(buf, len, "%d", fieldcount);
+ if (sbuf) {
+ ast_str_set(sbuf, len, "%d", fieldcount);
+ } else {
+ snprintf(buf, len, "%d", fieldcount);
+ }
+ ast_free(str);
return 0;
}
+static int function_fieldqty(struct ast_channel *chan, const char *cmd,
+ char *parse, char *buf, size_t len)
+{
+ return function_fieldqty_helper(chan, cmd, parse, buf, NULL, len);
+}
+
+static int function_fieldqty_str(struct ast_channel *chan, const char *cmd,
+ char *parse, struct ast_str **buf, ssize_t len)
+{
+ return function_fieldqty_helper(chan, cmd, parse, NULL, buf, len);
+}
+
static struct ast_custom_function fieldqty_function = {
.name = "FIELDQTY",
.read = function_fieldqty,
+ .read2 = function_fieldqty_str,
};
-static int listfilter(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
+static int listfilter(struct ast_channel *chan, const char *cmd, char *parse, char *buf, struct ast_str **bufstr, ssize_t len)
{
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(listname);
@@ -392,11 +417,18 @@ static int listfilter(struct ast_channel *chan, const char *cmd, char *parse, ch
const char *orig_list, *ptr;
const char *begin, *cur, *next;
int dlen, flen, first = 1;
- struct ast_str *result = ast_str_thread_get(&result_buf, 16);
+ struct ast_str *result, **result_ptr = &result;
char *delim;
AST_STANDARD_APP_ARGS(args, parse);
+ if (buf) {
+ result = ast_str_thread_get(&result_buf, 16);
+ } else {
+ /* Place the result directly into the output buffer */
+ result_ptr = bufstr;
+ }
+
if (args.argc < 3) {
ast_log(LOG_ERROR, "Usage: LISTFILTER(<listname>,<delimiter>,<fieldvalue>)\n");
return -1;
@@ -416,7 +448,11 @@ static int listfilter(struct ast_channel *chan, const char *cmd, char *parse, ch
/* If the string isn't there, just copy out the string and be done with it. */
if (!(ptr = strstr(orig_list, args.fieldvalue))) {
- ast_copy_string(buf, orig_list, len);
+ if (buf) {
+ ast_copy_string(buf, orig_list, len);
+ } else {
+ ast_str_set(result_ptr, len, "%s", orig_list);
+ }
if (chan) {
ast_channel_unlock(chan);
}
@@ -436,7 +472,9 @@ static int listfilter(struct ast_channel *chan, const char *cmd, char *parse, ch
ast_str_reset(result);
/* Enough space for any result */
- ast_str_make_space(&result, strlen(orig_list) + 1);
+ if (len > -1) {
+ ast_str_make_space(result_ptr, len ? len : strlen(orig_list) + 1);
+ }
begin = orig_list;
next = strstr(begin, delim);
@@ -456,10 +494,10 @@ static int listfilter(struct ast_channel *chan, const char *cmd, char *parse, ch
} else {
/* Copy field to output */
if (!first) {
- ast_str_append(&result, 0, "%s", delim);
+ ast_str_append(result_ptr, len, "%s", delim);
}
- ast_str_append_substr(&result, 0, begin, cur - begin + 1);
+ ast_str_append_substr(result_ptr, len, begin, cur - begin + 1);
first = 0;
begin = cur + dlen;
}
@@ -468,14 +506,27 @@ static int listfilter(struct ast_channel *chan, const char *cmd, char *parse, ch
ast_channel_unlock(chan);
}
- ast_copy_string(buf, ast_str_buffer(result), len);
+ if (buf) {
+ ast_copy_string(buf, ast_str_buffer(result), len);
+ }
return 0;
}
+static int listfilter_read(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
+{
+ return listfilter(chan, cmd, parse, buf, NULL, len);
+}
+
+static int listfilter_read2(struct ast_channel *chan, const char *cmd, char *parse, struct ast_str **buf, ssize_t len)
+{
+ return listfilter(chan, cmd, parse, NULL, buf, len);
+}
+
static struct ast_custom_function listfilter_function = {
.name = "LISTFILTER",
- .read = listfilter,
+ .read = listfilter_read,
+ .read2 = listfilter_read2,
};
static int filter(struct ast_channel *chan, const char *cmd, char *parse, char *buf,
@@ -679,16 +730,15 @@ static int array(struct ast_channel *chan, const char *cmd, char *var,
static int hashkeys_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
{
struct ast_var_t *newvar;
- int plen;
- char prefix[80];
- snprintf(prefix, sizeof(prefix), HASH_PREFIX, data);
- plen = strlen(prefix);
+ struct ast_str *prefix = ast_str_alloca(80);
+ ast_str_set(&prefix, -1, HASH_PREFIX, data);
memset(buf, 0, len);
+
AST_LIST_TRAVERSE(&chan->varshead, newvar, entries) {
- if (strncasecmp(prefix, ast_var_name(newvar), plen) == 0) {
+ if (strncasecmp(ast_str_buffer(prefix), ast_var_name(newvar), ast_str_strlen(prefix)) == 0) {
/* Copy everything after the prefix */
- strncat(buf, ast_var_name(newvar) + plen, len - strlen(buf) - 1);
+ strncat(buf, ast_var_name(newvar) + ast_str_strlen(prefix), len - strlen(buf) - 1);
/* Trim the trailing ~ */
buf[strlen(buf) - 1] = ',';
}
@@ -698,6 +748,29 @@ static int hashkeys_read(struct ast_channel *chan, const char *cmd, char *data,
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(&chan->varshead, newvar, entries) {
+ if (strncasecmp(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];
@@ -773,6 +846,7 @@ static struct ast_custom_function hash_function = {
static struct ast_custom_function hashkeys_function = {
.name = "HASHKEYS",
.read = hashkeys_read,
+ .read2 = hashkeys_read2,
};
static struct ast_custom_function array_function = {
@@ -824,6 +898,7 @@ static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf,
static struct ast_custom_function len_function = {
.name = "LEN",
.read = len,
+ .read_max = 12,
};
static int acf_strftime(struct ast_channel *chan, const char *cmd, char *parse,
@@ -915,9 +990,23 @@ static int function_eval(struct ast_channel *chan, const char *cmd, char *data,
return 0;
}
+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,
+ .read2 = function_eval2,
};
static int keypadhash(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
@@ -969,9 +1058,24 @@ static int string_toupper(struct ast_channel *chan, const char *cmd, char *data,
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,
+ .read2 = string_toupper2,
};
static int string_tolower(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
@@ -983,9 +1087,24 @@ static int string_tolower(struct ast_channel *chan, const char *cmd, char *data,
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,
+ .read2 = string_tolower2,
};
static int array_remove(struct ast_channel *chan, const char *cmd, char *var, char *buf, size_t len, int beginning)
diff --git a/funcs/func_sysinfo.c b/funcs/func_sysinfo.c
index 16e9632d5..8fdfda3f1 100644
--- a/funcs/func_sysinfo.c
+++ b/funcs/func_sysinfo.c
@@ -86,6 +86,7 @@ static struct ast_custom_function sysinfo_function = {
.synopsis = "Returns system information specified by parameter.",
.syntax = "SYSINFO(<parameter>)",
.read = sysinfo_helper,
+ .read_max = 22,
.desc =
"Returns information from a given parameter\n"
" Options:\n"
diff --git a/funcs/func_timeout.c b/funcs/func_timeout.c
index 2b3a000b4..caa562834 100644
--- a/funcs/func_timeout.c
+++ b/funcs/func_timeout.c
@@ -191,6 +191,7 @@ static int timeout_write(struct ast_channel *chan, const char *cmd, char *data,
static struct ast_custom_function timeout_function = {
.name = "TIMEOUT",
.read = timeout_read,
+ .read_max = 22,
.write = timeout_write,
};
diff --git a/funcs/func_vmcount.c b/funcs/func_vmcount.c
index f79669b6d..550070891 100644
--- a/funcs/func_vmcount.c
+++ b/funcs/func_vmcount.c
@@ -97,6 +97,7 @@ static int acf_vmcount_exec(struct ast_channel *chan, const char *cmd, char *arg
struct ast_custom_function acf_vmcount = {
.name = "VMCOUNT",
.read = acf_vmcount_exec,
+ .read_max = 12,
};
static int unload_module(void)