aboutsummaryrefslogtreecommitdiffstats
path: root/funcs
diff options
context:
space:
mode:
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)