[asterisk-commits] tilghman: branch tilghman/str_substitution r174214 - in /team/tilghman/str_su...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Sun Feb 8 00:05:56 CST 2009
Author: tilghman
Date: Sun Feb 8 00:05:55 2009
New Revision: 174214
URL: http://svn.digium.com/svn-view/asterisk?view=rev&rev=174214
Log:
String substitution, using ast_str
Modified:
team/tilghman/str_substitution/funcs/func_aes.c
team/tilghman/str_substitution/funcs/func_base64.c
team/tilghman/str_substitution/funcs/func_blacklist.c
team/tilghman/str_substitution/include/asterisk/ast_expr.h
team/tilghman/str_substitution/include/asterisk/pbx.h
team/tilghman/str_substitution/main/ast_expr2f.c
team/tilghman/str_substitution/main/pbx.c
team/tilghman/str_substitution/main/strings.c
Modified: team/tilghman/str_substitution/funcs/func_aes.c
URL: http://svn.digium.com/svn-view/asterisk/team/tilghman/str_substitution/funcs/func_aes.c?view=diff&rev=174214&r1=174213&r2=174214
==============================================================================
--- team/tilghman/str_substitution/funcs/func_aes.c (original)
+++ team/tilghman/str_substitution/funcs/func_aes.c Sun Feb 8 00:05:55 2009
@@ -31,6 +31,7 @@
#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 @@
static int aes_helper(struct ast_channel *chan, const char *cmd, char *data,
- char *buf, size_t len)
+ char *buf, struct ast_str **str, int maxlen)
{
unsigned char curblock[AES_BLOCK_SIZE] = { 0, };
- char *tmp;
+ char *tmp = NULL;
char *tmpP;
- int data_len, encrypt;
+ int data_len, encrypt, i;
+ 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,47 @@
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);
- 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 ((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" : "");
+ if (keylen < 16) {
+ char *newkey = alloca(17);
+ strcpy(newkey, args.key);
+ for (i = keylen; i < 16; i++) {
+ newkey[i] = ' ';
+ }
+ newkey[16] = '\0';
+ args.key = newkey;
+ } else {
+ return -1;
+ }
+ }
+
+ if (buf) {
+ len = maxlen;
+ } else if (maxlen == -1) {
+ len = ast_str_size(*str) - ast_str_strlen(*str);
+ } else if (maxlen > 0) {
+ len = maxlen - ast_str_strlen(*str);
+ } else {
+ len = INT_MAX;
+ }
+
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);
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);
+ tmpP = args.data;
} else {
- data_len = ast_base64decode((unsigned char *) tmp, args.data, len);
+ /* decryption: base64 -> encryptedtext -> plaintext */
+ ast_aes_decrypt_key((unsigned char *) args.key, &dcx);
+ tmpP = tmp;
+ data_len = ast_base64decode((unsigned char *) tmp, args.data, tmplen);
}
if (data_len >= len) { /* make sure to not go over buffer len */
@@ -116,6 +142,9 @@
}
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);
if (encrypt) {
@@ -125,26 +154,53 @@
}
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 : ast_str_strlen(*str) + elen * 4 / 3 + 2);
+ }
+ ast_base64encode(ast_str_buffer(*str) + ast_str_strlen(*str), (unsigned char *) tmp, elen, ast_str_size(*str) - ast_str_strlen(*str));
+ ast_str_update(*str);
+ }
} else {
- memcpy(buf, tmp, len);
+ if (buf) {
+ memcpy(buf, tmp, len);
+ } else {
+ ast_str_append(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, int 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)
Modified: team/tilghman/str_substitution/funcs/func_base64.c
URL: http://svn.digium.com/svn-view/asterisk/team/tilghman/str_substitution/funcs/func_base64.c?view=diff&rev=174214&r1=174213&r2=174214
==============================================================================
--- team/tilghman/str_substitution/funcs/func_base64.c (original)
+++ team/tilghman/str_substitution/funcs/func_base64.c Sun Feb 8 00:05:55 2009
@@ -29,6 +29,7 @@
#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 @@
</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, int 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;
- }
+ return base64_helper(chan, cmd, data, buf, NULL, len);
+}
- ast_base64decode((unsigned char *) buf, data, len);
-
- return 0;
+static int base64_str_helper(struct ast_channel *chan, const char *cmd, char *data,
+ struct ast_str **buf, int 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)
Modified: team/tilghman/str_substitution/funcs/func_blacklist.c
URL: http://svn.digium.com/svn-view/asterisk/team/tilghman/str_substitution/funcs/func_blacklist.c?view=diff&rev=174214&r1=174213&r2=174214
==============================================================================
--- team/tilghman/str_substitution/funcs/func_blacklist.c (original)
+++ team/tilghman/str_substitution/funcs/func_blacklist.c Sun Feb 8 00:05:55 2009
@@ -70,9 +70,26 @@
return 0;
}
+static int blacklist_read2(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **str, int 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)
Modified: team/tilghman/str_substitution/include/asterisk/ast_expr.h
URL: http://svn.digium.com/svn-view/asterisk/team/tilghman/str_substitution/include/asterisk/ast_expr.h?view=diff&rev=174214&r1=174213&r2=174214
==============================================================================
--- team/tilghman/str_substitution/include/asterisk/ast_expr.h (original)
+++ team/tilghman/str_substitution/include/asterisk/ast_expr.h Sun Feb 8 00:05:55 2009
@@ -32,6 +32,7 @@
#endif
int ast_expr(char *expr, char *buf, int length, struct ast_channel *chan);
+int ast_str_expr(struct ast_str **str, int maxlen, struct ast_channel *chan, char *expr);
#if defined(__cplusplus) || defined(c_plusplus)
}
Modified: team/tilghman/str_substitution/include/asterisk/pbx.h
URL: http://svn.digium.com/svn-view/asterisk/team/tilghman/str_substitution/include/asterisk/pbx.h?view=diff&rev=174214&r1=174213&r2=174214
==============================================================================
--- team/tilghman/str_substitution/include/asterisk/pbx.h (original)
+++ team/tilghman/str_substitution/include/asterisk/pbx.h Sun Feb 8 00:05:55 2009
@@ -89,6 +89,7 @@
);
enum ast_doc_src docsrc; /*!< Where the documentation come from */
int (*read)(struct ast_channel *, const char *, char *, char *, size_t); /*!< Read function, if read is supported */
+ int (*read2)(struct ast_channel *, const char *, char *, struct ast_str **, int); /*!< Read function, if read is supported */
int (*write)(struct ast_channel *, const char *, char *, const char *); /*!< Write function, if write is supported */
struct ast_module *mod; /*!< Module this custom function belongs to */
AST_RWLIST_ENTRY(ast_custom_function) acflist;
@@ -415,6 +416,8 @@
* Otherwise, 0 is returned.
*/
int ast_get_hint(char *hint, int maxlen, char *name, int maxnamelen,
+ struct ast_channel *c, const char *context, const char *exten);
+int ast_str_get_hint(struct ast_str **hint, int maxlen, struct ast_str **name, int maxnamelen,
struct ast_channel *c, const char *context, const char *exten);
/*!
@@ -933,19 +936,23 @@
int pbx_builtin_raise_exception(struct ast_channel *chan, void *data);
-void pbx_substitute_variables_helper(struct ast_channel *c,const char *cp1,char *cp2,int count);
+void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count);
void pbx_substitute_variables_varshead(struct varshead *headp, const char *cp1, char *cp2, int count);
void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int cp2_size, size_t *used);
-void ast_str_substitute_variables(struct ast_str **buf, size_t maxlen, struct ast_channel *chan, const char *templ);
+
+char *ast_str_retrieve_variable(struct ast_str **buf, int maxlen, struct ast_channel *chan, struct varshead *headp, const char *var);
+void ast_str_substitute_variables(struct ast_str **buf, int maxlen, struct ast_channel *chan, const char *templ);
+void ast_str_substitute_variables_varshead(struct ast_str **buf, int maxlen, struct varshead *headp, const char *templ);
+void ast_str_substitute_variables_full(struct ast_str **buf, int maxlen, struct ast_channel *c, struct varshead *headp, const char *templ, size_t *used);
int ast_extension_patmatch(const char *pattern, const char *data);
-/*! Set "autofallthrough" flag, if newval is <0, does not acutally set. If
+/*! Set "autofallthrough" flag, if newval is <0, does not actually set. If
set to 1, sets to auto fall through. If newval set to 0, sets to no auto
fall through (reads extension instead). Returns previous value. */
int pbx_set_autofallthrough(int newval);
-/*! Set "extenpatternmatchnew" flag, if newval is <0, does not acutally set. If
+/*! Set "extenpatternmatchnew" flag, if newval is <0, does not actually set. If
set to 1, sets to use the new Trie-based pattern matcher. If newval set to 0, sets to use
the old linear-search algorithm. Returns previous value. */
int pbx_set_extenpatternmatchnew(int newval);
@@ -1024,6 +1031,7 @@
* \return zero on success, non-zero on failure
*/
int ast_func_read(struct ast_channel *chan, const char *function, char *workspace, size_t len);
+int ast_func_read2(struct ast_channel *chan, const char *function, struct ast_str **str, int maxlen);
/*!
* \brief executes a write operation on a function
Modified: team/tilghman/str_substitution/main/ast_expr2f.c
URL: http://svn.digium.com/svn-view/asterisk/team/tilghman/str_substitution/main/ast_expr2f.c?view=diff&rev=174214&r1=174213&r2=174214
==============================================================================
--- team/tilghman/str_substitution/main/ast_expr2f.c (original)
+++ team/tilghman/str_substitution/main/ast_expr2f.c Sun Feb 8 00:05:55 2009
@@ -4152,19 +4152,12 @@
int ast_expr(char *expr, char *buf, int length, struct ast_channel *chan)
{
- struct parse_io io;
+ struct parse_io io = { .string = expr, .chan = chan };
int return_value = 0;
-
- memset(&io, 0, sizeof(io));
- io.string = expr; /* to pass to the error routine */
- io.chan = chan;
-
+
ast_yylex_init(&io.scanner);
-
ast_yy_scan_string(expr, io.scanner);
-
ast_yyparse ((void *) &io);
-
ast_yylex_destroy(io.scanner);
if (!io.val) {
@@ -4195,6 +4188,32 @@
}
return return_value;
}
+
+#if !defined(STANDALONE)
+int ast_str_expr(struct ast_str **str, int maxlen, struct ast_channel *chan, char *expr)
+{
+ struct parse_io io = { .string = expr, .chan = chan };
+
+ ast_yylex_init(&io.scanner);
+ ast_yy_scan_string(expr, io.scanner);
+ ast_yyparse ((void *) &io);
+ ast_yylex_destroy(io.scanner);
+
+ if (!io.val) {
+ ast_str_set(str, maxlen, "0");
+ } else {
+ if (io.val->type == AST_EXPR_number) {
+ int res_length;
+ ast_str_set(str, maxlen, FP___PRINTF, io.val->u.i);
+ } else if (io.val->u.s) {
+ ast_str_set(str, maxlen, "%s", io.val->u.s);
+ free(io.val->u.s);
+ }
+ free(io.val);
+ }
+ return ast_str_strlen(*str);
+}
+#endif
char extra_error_message[4095];
Modified: team/tilghman/str_substitution/main/pbx.c
URL: http://svn.digium.com/svn-view/asterisk/team/tilghman/str_substitution/main/pbx.c?view=diff&rev=174214&r1=174213&r2=174214
==============================================================================
--- team/tilghman/str_substitution/main/pbx.c (original)
+++ team/tilghman/str_substitution/main/pbx.c Sun Feb 8 00:05:55 2009
@@ -2804,6 +2804,54 @@
return ret;
}
+static char *ast_str_substring(struct ast_str *value, int offset, int length)
+{
+ int lr; /* length of the input string after the copy */
+
+ lr = ast_str_strlen(value); /* compute length after copy, so we never go out of the workspace */
+
+ /* Quick check if no need to do anything */
+ if (offset == 0 && length >= lr) /* take the whole string */
+ return ast_str_buffer(value);
+
+ if (offset < 0) { /* translate negative offset into positive ones */
+ offset = lr + offset;
+ if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */
+ offset = 0;
+ }
+
+ /* too large offset result in empty string so we know what to return */
+ if (offset >= lr) {
+ ast_str_reset(value);
+ return ast_str_buffer(value);
+ }
+
+ if (offset > 0) {
+ /* Go ahead and chop off the beginning */
+ memcpy(ast_str_buffer(value), ast_str_buffer(value) + offset, ast_str_strlen(value) - offset);
+ lr -= offset;
+ }
+
+ if (length >= 0 && length < lr) { /* truncate if necessary */
+ char *tmp = ast_str_buffer(value);
+ tmp[length] = '\0';
+ ast_str_update(value);
+ } else if (length < 0) {
+ if (lr > -length) { /* After we remove from the front and from the rear, is there anything left? */
+ char *tmp = ast_str_buffer(value);
+ tmp[lr + length] = '\0';
+ ast_str_update(value);
+ } else {
+ ast_str_reset(value);
+ }
+ } else {
+ /* Nothing to do, but update the buffer length */
+ ast_str_update(value);
+ }
+
+ return ast_str_buffer(value);
+}
+
/*! \brief Support for Asterisk built-in variables in the dialplan
\note See also
@@ -2812,8 +2860,18 @@
*/
void pbx_retrieve_variable(struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
{
+ struct ast_str *str = ast_str_create(16);
+
+ *ret = ast_str_retrieve_variable(&str, 0, c, headp, var);
+ ast_copy_string(workspace, ast_str_buffer(str), workspacelen);
+ *ret = *ret ? workspace : NULL;
+ ast_free(str);
+}
+
+char *ast_str_retrieve_variable(struct ast_str **str, int maxlen, struct ast_channel *c, struct varshead *headp, const char *var)
+{
const char not_found = '\0';
- char *tmpvar;
+ char *tmpvar, *ret;
const char *s; /* the result */
int offset, length;
int i, need_substring;
@@ -2852,47 +2910,48 @@
if (!strncmp(var, "CALL", 4)) {
if (!strncmp(var + 4, "ING", 3)) {
if (!strcmp(var + 7, "PRES")) { /* CALLINGPRES */
- snprintf(workspace, workspacelen, "%d", c->cid.cid_pres);
- s = workspace;
+ ast_str_set(str, maxlen, "%d", c->cid.cid_pres);
+ s = ast_str_buffer(*str);
} else if (!strcmp(var + 7, "ANI2")) { /* CALLINGANI2 */
- snprintf(workspace, workspacelen, "%d", c->cid.cid_ani2);
- s = workspace;
+ ast_str_set(str, maxlen, "%d", c->cid.cid_ani2);
+ s = ast_str_buffer(*str);
} else if (!strcmp(var + 7, "TON")) { /* CALLINGTON */
- snprintf(workspace, workspacelen, "%d", c->cid.cid_ton);
- s = workspace;
+ ast_str_set(str, maxlen, "%d", c->cid.cid_ton);
+ s = ast_str_buffer(*str);
} else if (!strcmp(var + 7, "TNS")) { /* CALLINGTNS */
- snprintf(workspace, workspacelen, "%d", c->cid.cid_tns);
- s = workspace;
+ ast_str_set(str, maxlen, "%d", c->cid.cid_tns);
+ s = ast_str_buffer(*str);
}
}
} else if (!strcmp(var, "HINT")) {
- s = ast_get_hint(workspace, workspacelen, NULL, 0, c, c->context, c->exten) ? workspace : NULL;
+ s = ast_str_get_hint(str, maxlen, NULL, 0, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL;
} else if (!strcmp(var, "HINTNAME")) {
- s = ast_get_hint(NULL, 0, workspace, workspacelen, c, c->context, c->exten) ? workspace : NULL;
+ s = ast_str_get_hint(NULL, 0, str, maxlen, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL;
} else if (!strcmp(var, "EXTEN")) {
s = c->exten;
} else if (!strcmp(var, "CONTEXT")) {
s = c->context;
} else if (!strcmp(var, "PRIORITY")) {
- snprintf(workspace, workspacelen, "%d", c->priority);
- s = workspace;
+ ast_str_set(str, maxlen, "%d", c->priority);
+ s = ast_str_buffer(*str);
} else if (!strcmp(var, "CHANNEL")) {
s = c->name;
} else if (!strcmp(var, "UNIQUEID")) {
s = c->uniqueid;
} else if (!strcmp(var, "HANGUPCAUSE")) {
- snprintf(workspace, workspacelen, "%d", c->hangupcause);
- s = workspace;
+ ast_str_set(str, maxlen, "%d", c->hangupcause);
+ s = ast_str_buffer(*str);
}
}
if (s == ¬_found) { /* look for more */
if (!strcmp(var, "EPOCH")) {
- snprintf(workspace, workspacelen, "%u",(int)time(NULL));
- s = workspace;
+ ast_str_set(str, maxlen, "%u", (int) time(NULL));
+ s = ast_str_buffer(*str);
} else if (!strcmp(var, "SYSTEMNAME")) {
s = ast_config_AST_SYSTEM_NAME;
} else if (!strcmp(var, "ENTITYID")) {
- ast_eid_to_str(workspace, workspacelen, &g_eid);
+ char workspace[20];
+ ast_eid_to_str(workspace, sizeof(workspace), &g_eid);
s = workspace;
}
}
@@ -2912,18 +2971,22 @@
if (places[i] == &globals)
ast_rwlock_unlock(&globalslock);
}
- if (s == ¬_found || s == NULL)
- *ret = NULL;
- else {
- if (s != workspace)
- ast_copy_string(workspace, s, workspacelen);
- *ret = workspace;
- if (need_substring)
- *ret = substring(*ret, offset, length, workspace, workspacelen);
- }
-
- if (c)
+ if (s == ¬_found || s == NULL) {
+ ret = NULL;
+ } else {
+ if (s != ast_str_buffer(*str)) {
+ ast_str_set(str, maxlen, "%s", s);
+ }
+ ret = ast_str_buffer(*str);
+ if (need_substring) {
+ ret = ast_str_substring(*str, offset, length);
+ }
+ }
+
+ if (c) {
ast_channel_unlock(c);
+ }
+ return ret;
}
static void exception_store_free(void *data)
@@ -3317,6 +3380,38 @@
return -1;
}
+int ast_func_read2(struct ast_channel *chan, const char *function, struct ast_str **str, int maxlen)
+{
+ char *copy = ast_strdupa(function);
+ char *args = func_args(copy);
+ struct ast_custom_function *acfptr = ast_custom_function_find(copy);
+
+ if (acfptr == NULL) {
+ ast_log(LOG_ERROR, "Function %s not registered\n", copy);
+ } else if (!acfptr->read && !acfptr->read2) {
+ ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
+ } else {
+ int res;
+ struct ast_module_user *u = NULL;
+ if (acfptr->mod)
+ u = __ast_module_user_add(acfptr->mod, chan);
+ if (acfptr->read2) {
+ /* ast_str enabled */
+ res = acfptr->read2(chan, copy, args, str, maxlen);
+ } else {
+ /* Legacy function pointer, allocate buffer for result */
+ if (maxlen > -1) {
+ ast_str_make_space(str, maxlen ? maxlen : VAR_BUF_SIZE);
+ }
+ res = acfptr->read(chan, copy, args, ast_str_buffer(*str), maxlen > 0 ? maxlen : maxlen < 0 ? ast_str_size(*str) : VAR_BUF_SIZE);
+ }
+ if (acfptr->mod && u)
+ __ast_module_user_remove(acfptr->mod, u);
+ return res;
+ }
+ return -1;
+}
+
int ast_func_write(struct ast_channel *chan, const char *function, const char *value)
{
char *copy = ast_strdupa(function);
@@ -3339,6 +3434,191 @@
}
return -1;
+}
+
+void ast_str_substitute_variables_full(struct ast_str **buf, int maxlen, struct ast_channel *c, struct varshead *headp, const char *templ, size_t *used)
+{
+ /* Substitutes variables into buf, based on string templ */
+ char *cp4;
+ const char *tmp, *whereweare;
+ int orig_size = ast_str_strlen(*buf);
+ int offset, offset2, isfunction;
+ char *nextvar, *nextexp, *nextthing;
+ char *vars, *vare;
+ int pos, brackets, needsub, len;
+ struct ast_str *substr1 = ast_str_create(16), *substr2 = NULL, *substr3 = ast_str_create(16);
+
+ whereweare = tmp = templ;
+ while (!ast_strlen_zero(whereweare)) {
+ /* Assume we're copying the whole remaining string */
+ pos = strlen(whereweare);
+ nextvar = NULL;
+ nextexp = NULL;
+ nextthing = strchr(whereweare, '$');
+ if (nextthing) {
+ switch (nextthing[1]) {
+ case '{':
+ nextvar = nextthing;
+ pos = nextvar - whereweare;
+ break;
+ case '[':
+ nextexp = nextthing;
+ pos = nextexp - whereweare;
+ break;
+ default:
+ pos = 1;
+ }
+ }
+
+ if (pos) {
+ /* Copy that many bytes */
+ ast_str_append_substr(buf, maxlen, whereweare, pos);
+
+ templ += pos;
+ whereweare += pos;
+ }
+
+ if (nextvar) {
+ /* We have a variable. Find the start and end, and determine
+ if we are going to have to recursively call ourselves on the
+ contents */
+ vars = vare = nextvar + 2;
+ brackets = 1;
+ needsub = 0;
+
+ /* Find the end of it */
+ while (brackets && *vare) {
+ if ((vare[0] == '$') && (vare[1] == '{')) {
+ needsub++;
+ } else if (vare[0] == '{') {
+ brackets++;
+ } else if (vare[0] == '}') {
+ brackets--;
+ } else if ((vare[0] == '$') && (vare[1] == '['))
+ needsub++;
+ vare++;
+ }
+ if (brackets)
+ ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
+ len = vare - vars - 1;
+
+ /* Skip totally over variable string */
+ whereweare += (len + 3);
+
+ /* Store variable name (and truncate) */
+ ast_str_set_substr(&substr1, 0, vars, len);
+
+ /* Substitute if necessary */
+ if (needsub) {
+ size_t used;
+ if (!substr2) {
+ substr2 = ast_str_create(16);
+ }
+
+ ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used);
+ vars = ast_str_buffer(substr2);
+ } else {
+ vars = ast_str_buffer(substr1);
+ }
+
+ parse_variable_name(vars, &offset, &offset2, &isfunction);
+ if (isfunction) {
+ /* Evaluate function */
+ if (c || !headp) {
+ cp4 = ast_func_read2(c, vars, &substr3, 0) ? NULL : ast_str_buffer(substr3);
+ } else {
+ struct varshead old;
+ struct ast_channel *bogus = ast_channel_alloc(0, 0, "", "", "", "", "", 0, "Bogus/%p", vars);
+ if (bogus) {
+ memcpy(&old, &bogus->varshead, sizeof(old));
+ memcpy(&bogus->varshead, headp, sizeof(bogus->varshead));
+ cp4 = ast_func_read2(c, vars, &substr3, 0) ? NULL : ast_str_buffer(substr3);
+ /* Don't deallocate the varshead that was passed in */
+ memcpy(&bogus->varshead, &old, sizeof(bogus->varshead));
+ ast_channel_free(bogus);
+ } else {
+ ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n");
+ }
+ }
+ ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)");
+ } else {
+ /* Retrieve variable value */
+ ast_str_retrieve_variable(&substr3, 0, c, headp, vars);
+ cp4 = ast_str_buffer(substr3);
+ }
+ if (cp4) {
+ ast_str_substring(substr3, offset, offset2);
+ ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3));
+ }
+ } else if (nextexp) {
+ /* We have an expression. Find the start and end, and determine
+ if we are going to have to recursively call ourselves on the
+ contents */
+ vars = vare = nextexp + 2;
+ brackets = 1;
+ needsub = 0;
+
+ /* Find the end of it */
+ while (brackets && *vare) {
+ if ((vare[0] == '$') && (vare[1] == '[')) {
+ needsub++;
+ brackets++;
+ vare++;
+ } else if (vare[0] == '[') {
+ brackets++;
+ } else if (vare[0] == ']') {
+ brackets--;
+ } else if ((vare[0] == '$') && (vare[1] == '{')) {
+ needsub++;
+ vare++;
+ }
+ vare++;
+ }
+ if (brackets)
+ ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
+ len = vare - vars - 1;
+
+ /* Skip totally over expression */
+ whereweare += (len + 3);
+
+ /* Store variable name (and truncate) */
+ ast_str_set_substr(&substr1, 0, vars, len);
+
+ /* Substitute if necessary */
+ if (needsub) {
+ size_t used;
+ if (!substr2) {
+ substr2 = ast_str_create(16);
+ }
+
+ ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used);
+ vars = ast_str_buffer(substr2);
+ } else {
+ vars = ast_str_buffer(substr1);
+ }
+
+ if (ast_str_expr(&substr3, 0, c, vars)) {
+ ast_debug(1, "Expression result is '%s'\n", ast_str_buffer(substr3));
+ }
+ ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3));
+ }
+ }
+ *used = ast_str_strlen(*buf) - orig_size;
+ ast_free(substr1);
+ ast_free(substr2);
+ ast_free(substr3);
+}
+
+void ast_str_substitute_variables(struct ast_str **buf, int maxlen, struct ast_channel *chan, const char *templ)
+{
+ size_t used;
+ ast_str_substitute_variables_full(buf, maxlen, chan, NULL, templ, &used);
+}
+
+void ast_str_substitute_variables_varshead(struct ast_str **buf, int maxlen, struct varshead *headp, const char *templ)
+{
+ size_t used;
+ ast_str_substitute_variables_full(buf, maxlen, NULL, headp, templ, &used);
}
void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count, size_t *used)
@@ -4056,6 +4336,26 @@
const char *tmp = ast_get_extension_app_data(e);
if (tmp)
ast_copy_string(name, tmp, namesize);
+ }
+ return -1;
+ }
+ return 0;
+}
+
+/*! \brief Get hint for channel */
+int ast_str_get_hint(struct ast_str **hint, int hintsize, struct ast_str **name, int namesize, struct ast_channel *c, const char *context, const char *exten)
+{
+ struct ast_exten *e = ast_hint_extension(c, context, exten);
+
+ if (e) {
+ if (hint) {
+ ast_str_set(hint, hintsize, "%s", ast_get_extension_app(e));
+ }
+ if (name) {
+ const char *tmp = ast_get_extension_app_data(e);
+ if (tmp) {
+ ast_str_set(name, namesize, "%s", tmp);
+ }
}
return -1;
}
Modified: team/tilghman/str_substitution/main/strings.c
URL: http://svn.digium.com/svn-view/asterisk/team/tilghman/str_substitution/main/strings.c?view=diff&rev=174214&r1=174213&r2=174214
==============================================================================
--- team/tilghman/str_substitution/main/strings.c (original)
+++ team/tilghman/str_substitution/main/strings.c Sun Feb 8 00:05:55 2009
@@ -98,17 +98,6 @@
return res;
}
-void ast_str_substitute_variables(struct ast_str **buf, size_t maxlen, struct ast_channel *chan, const char *template)
-{
- int first = 1;
- do {
- ast_str_make_space(buf, maxlen ? maxlen :
- (first ? strlen(template) * 2 : (*buf)->__AST_STR_LEN * 2));
- pbx_substitute_variables_helper_full(chan, NULL, template, (*buf)->__AST_STR_STR, (*buf)->__AST_STR_LEN - 1, &((*buf)->__AST_STR_USED));
- first = 0;
- } while (maxlen == 0 && (*buf)->__AST_STR_LEN - 5 < (*buf)->__AST_STR_USED);
-}
-
char *__ast_str_helper2(struct ast_str **buf, size_t maxlen, const char *src, size_t maxsrc, int append, int escapecommas)
{
int dynamic = 0;
More information about the asterisk-commits
mailing list