re-factor variable/function name parsing, and add substring support to function results (issue #5284)

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@6695 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1.2-netsec
Kevin P. Fleming 20 years ago
parent 6c54fa36dd
commit 7eb43aa05d

127
pbx.c

@ -908,60 +908,102 @@ static struct ast_exten *pbx_find_extension(struct ast_channel *chan, struct ast
return NULL;
}
/* Note that it's negative -- that's important later. */
#define DONT_HAVE_LENGTH 0x80000000
static int parse_variable_name(char *var, int *offset, int *length, int *isfunc)
{
char *varchar, *offsetchar = NULL;
int parens=0;
*offset = 0;
*length = DONT_HAVE_LENGTH;
*isfunc = 0;
for (varchar=var; *varchar; varchar++) {
switch (*varchar) {
case '(':
(*isfunc)++;
parens++;
break;
case ')':
parens--;
break;
case ':':
if (parens == 0) {
offsetchar = varchar + 1;
*varchar = '\0';
goto pvn_endfor;
}
}
}
pvn_endfor:
if (offsetchar) {
sscanf(offsetchar, "%d:%d", offset, length);
return 1;
} else {
return 0;
}
}
static char *substring(char *value, int offset, int length, char *workspace, size_t workspace_len)
{
char *ret = workspace;
/* No need to do anything */
if (offset == 0 && length==-1) {
return value;
}
ast_copy_string(workspace, value, workspace_len);
if (abs(offset) > strlen(ret)) { /* Offset beyond string */
if (offset >= 0)
offset = strlen(ret);
else
offset =- strlen(ret);
}
/* Detect too-long length */
if ((offset < 0 && length > -offset) || (offset >= 0 && offset+length > strlen(ret))) {
if (offset >= 0)
length = strlen(ret)-offset;
else
length = strlen(ret)+offset;
}
/* Bounce up to the right offset */
if (offset >= 0)
ret += offset;
else
ret += strlen(ret)+offset;
/* Chop off at the requisite length */
if (length >= 0)
ret[length] = '\0';
return ret;
}
/*--- pbx_retrieve_variable: Support for Asterisk built-in variables and
functions in the dialplan
---*/
void pbx_retrieve_variable(struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
{
char *first,*second;
char tmpvar[80];
time_t thistime;
struct tm brokentime;
int offset,offset2;
int offset, offset2, isfunc;
struct ast_var_t *variables;
if (c)
headp=&c->varshead;
*ret=NULL;
if ((first=strchr(var,':'))) { /* : Remove characters counting from end or start of string */
ast_copy_string(tmpvar, var, sizeof(tmpvar));
first = strchr(tmpvar, ':');
if (!first)
first = tmpvar + strlen(tmpvar);
*first='\0';
pbx_retrieve_variable(c,tmpvar,ret,workspace,workspacelen - 1, headp);
ast_copy_string(tmpvar, var, sizeof(tmpvar));
if (parse_variable_name(tmpvar, &offset, &offset2, &isfunc)) {
pbx_retrieve_variable(c, tmpvar, ret, workspace, workspacelen, headp);
if (!(*ret))
return;
offset=atoi(first+1); /* The number of characters,
positive: remove # of chars from start
negative: keep # of chars from end */
if ((second=strchr(first+1,':'))) {
*second='\0';
offset2 = atoi(second+1); /* Number of chars to copy */
} else if (offset >= 0) {
offset2 = strlen(*ret)-offset; /* Rest of string */
} else {
offset2 = abs(offset);
}
if (abs(offset) > strlen(*ret)) { /* Offset beyond string */
if (offset >= 0)
offset = strlen(*ret);
else
offset =- strlen(*ret);
}
if ((offset < 0 && offset2 > -offset) || (offset >= 0 && offset+offset2 > strlen(*ret))) {
if (offset >= 0)
offset2 = strlen(*ret)-offset;
else
offset2 = strlen(*ret)+offset;
}
if (offset >= 0)
*ret += offset;
else
*ret += strlen(*ret)+offset;
(*ret)[offset2] = '\0'; /* Cut at offset2 position */
*ret = substring(*ret, offset, offset2, workspace, workspacelen);
} else if (c && !strncmp(var, "CALL", 4)) {
if (!strncmp(var + 4, "ER", 2)) {
if (!strncmp(var + 6, "ID", 2)) {
@ -1386,7 +1428,7 @@ static void pbx_substitute_variables_helper_full(struct ast_channel *c, struct v
{
char *cp4;
const char *tmp, *whereweare;
int length;
int length, offset, offset2, isfunction;
char *workspace = NULL;
char *ltmp = NULL, *var = NULL;
char *nextvar, *nextexp, *nextthing;
@ -1477,7 +1519,8 @@ static void pbx_substitute_variables_helper_full(struct ast_channel *c, struct v
workspace[0] = '\0';
if (var[len - 1] == ')') {
parse_variable_name(var, &offset, &offset2, &isfunction);
if (isfunction) {
/* Evaluate function */
cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE);
@ -1487,6 +1530,8 @@ static void pbx_substitute_variables_helper_full(struct ast_channel *c, struct v
pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp);
}
if (cp4) {
cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE);
length = strlen(cp4);
if (length > count)
length = count;

Loading…
Cancel
Save