Bug 6099 - cleanup of parse_variable_name and pbx_retrieve_variable

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@7911 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1.4
Tilghman Lesher 20 years ago
parent 335cd7d3a2
commit 8d42b1eb74

380
pbx.c

@ -821,40 +821,33 @@ static struct ast_exten *pbx_find_extension(struct ast_channel *chan, struct ast
/* Note that it's negative -- that's important later. */ /* Note that it's negative -- that's important later. */
#define DONT_HAVE_LENGTH 0x80000000 #define DONT_HAVE_LENGTH 0x80000000
/*! \brief extract offset:length from variable name.
* Returns 1 if there is a offset:length part, which is
* trimmed off (values go into variables)
*/
static int parse_variable_name(char *var, int *offset, int *length, int *isfunc) static int parse_variable_name(char *var, int *offset, int *length, int *isfunc)
{ {
char *varchar, *offsetchar = NULL;
int parens=0; int parens=0;
*offset = 0; *offset = 0;
*length = DONT_HAVE_LENGTH; *length = DONT_HAVE_LENGTH;
*isfunc = 0; *isfunc = 0;
for (varchar = var; *varchar; varchar++) { for (; *var; var++) {
switch (*varchar) { if (*var == '(') {
case '(':
(*isfunc)++; (*isfunc)++;
parens++; parens++;
break; } else if (*var == ')') {
case ')':
parens--; parens--;
break; } else if (*var == ':' && parens == 0) {
case ':': *var++ = '\0';
if (parens == 0) { sscanf(var, "%d:%d", offset, length);
offsetchar = varchar + 1; return 1; /* offset:length valid */
*varchar = '\0';
goto pvn_endfor;
}
} }
} }
pvn_endfor: return 0;
if (offsetchar) {
sscanf(offsetchar, "%d:%d", offset, length);
return 1;
} else {
return 0;
}
} }
/*! \brief takes a substring. It is ok to call with value == workspace. */
static char *substring(char *value, int offset, int length, char *workspace, size_t workspace_len) static char *substring(char *value, int offset, int length, char *workspace, size_t workspace_len)
{ {
char *ret = workspace; char *ret = workspace;
@ -899,204 +892,171 @@ static char *substring(char *value, int offset, int length, char *workspace, siz
---*/ ---*/
void pbx_retrieve_variable(struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp) void pbx_retrieve_variable(struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
{ {
char tmpvar[80]; const char not_found = '\0';
time_t thistime; char tmpvar[80], *deprecated = NULL;
struct tm brokentime; const char *s; /* the result */
int offset, offset2, isfunc; int offset, length;
struct ast_var_t *variables; int i, need_substring;
char *deprecated = NULL; struct varshead *places[2] = { headp, &globals }; /* list of places where we may look */
if (c) if (c) {
headp=&c->varshead; places[0] = &c->varshead;
*ret=NULL; }
ast_copy_string(tmpvar, var, sizeof(tmpvar)); /*
if (parse_variable_name(tmpvar, &offset, &offset2, &isfunc)) { * Make a copy of var because parse_variable_name() modifies the string.
pbx_retrieve_variable(c, tmpvar, ret, workspace, workspacelen, headp); * Then if called directly, we might need to run substring() on the result;
if (!(*ret)) * remember this for later in 'need_substring', 'offset' and 'length'
return; */
*ret = substring(*ret, offset, offset2, workspace, workspacelen); ast_copy_string(tmpvar, var, sizeof(tmpvar)); /* parse_variable_name modifies the string */
} else if (c && !strncmp(var, "CALL", 4)) { need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */);
if (!strncmp(var + 4, "ER", 2)) {
if (!strncmp(var + 6, "ID", 2)) { /*
if (!var[8]) { /* CALLERID */ * Look first into predefined variables, then into variable lists.
if (c->cid.cid_num) { * s == &not_found (set at the beginning) means that we did not find a
if (c->cid.cid_name) { * matching variable and need to look into more places.
snprintf(workspace, workspacelen, "\"%s\" <%s>", c->cid.cid_name, c->cid.cid_num); * If s != &not_found, s is a valid result string as follows:
} else { * s = NULL if the variable does not have a value;
ast_copy_string(workspace, c->cid.cid_num, workspacelen); * s = workspace if the result has been assembled there;
} * s != workspace in case we have a string, that needs to be copied
*ret = workspace; * (the ast_copy_string is done once for all at the end).
} else if (c->cid.cid_name) { * Deprecated variables have the replacement indicated in 'deprecated'.
ast_copy_string(workspace, c->cid.cid_name, workspacelen); */
*ret = workspace; s = &not_found; /* default value */
} else if (c) { /* This group requires a valid channel */
*ret = NULL; /* Names with common parts are looked up a piece at a time using strncmp. */
deprecated = "CALLERID(all)"; if (!strncmp(var, "CALL", 4)) {
} else if (!strcmp(var + 8, "NUM")) { if (!strncmp(var + 4, "ER", 2)) {
/* CALLERIDNUM */ if (!strncmp(var + 6, "ID", 2)) {
if (c->cid.cid_num) { if (!var[8]) { /* CALLERID */
ast_copy_string(workspace, c->cid.cid_num, workspacelen); if (c->cid.cid_num) {
*ret = workspace; if (c->cid.cid_name) {
} else snprintf(workspace, workspacelen, "\"%s\" <%s>",
*ret = NULL; c->cid.cid_name, c->cid.cid_num);
deprecated = "CALLERID(num)"; s = workspace;
} else if (!strcmp(var + 8, "NAME")) { } else {
/* CALLERIDNAME */ s = c->cid.cid_num;
if (c->cid.cid_name) { }
ast_copy_string(workspace, c->cid.cid_name, workspacelen); } else
*ret = workspace; s = c->cid.cid_name; /* possibly empty */
} else deprecated = "CALLERID(all)";
*ret = NULL; } else if (!strcmp(var + 8, "NUM")) { /* CALLERIDNUM */
deprecated = "CALLERID(name)"; s = c->cid.cid_num;
} else deprecated = "CALLERID(num)";
goto icky; } else if (!strcmp(var + 8, "NAME")) { /* CALLERIDNAME */
} else if (!strcmp(var + 6, "ANI")) { s = c->cid.cid_name;
/* CALLERANI */ deprecated = "CALLERID(name)";
if (c->cid.cid_ani) {
ast_copy_string(workspace, c->cid.cid_ani, workspacelen);
*ret = workspace;
} else
*ret = NULL;
deprecated = "CALLERID(ANI)";
} else
goto icky;
} else if (!strncmp(var + 4, "ING", 3)) {
if (!strcmp(var + 7, "PRES")) {
/* CALLINGPRES */
snprintf(workspace, workspacelen, "%d", c->cid.cid_pres);
*ret = workspace;
} else if (!strcmp(var + 7, "ANI2")) {
/* CALLINGANI2 */
snprintf(workspace, workspacelen, "%d", c->cid.cid_ani2);
*ret = workspace;
} else if (!strcmp(var + 7, "TON")) {
/* CALLINGTON */
snprintf(workspace, workspacelen, "%d", c->cid.cid_ton);
*ret = workspace;
} else if (!strcmp(var + 7, "TNS")) {
/* CALLINGTNS */
snprintf(workspace, workspacelen, "%d", c->cid.cid_tns);
*ret = workspace;
} else
goto icky;
} else
goto icky;
} else if (c && !strcmp(var, "DNID")) {
if (c->cid.cid_dnid) {
ast_copy_string(workspace, c->cid.cid_dnid, workspacelen);
*ret = workspace;
} else
*ret = NULL;
deprecated = "CALLERID(DNID)";
} else if (c && !strcmp(var, "HINT")) {
if (!ast_get_hint(workspace, workspacelen, NULL, 0, c, c->context, c->exten))
*ret = NULL;
else
*ret = workspace;
} else if (c && !strcmp(var, "HINTNAME")) {
if (!ast_get_hint(NULL, 0, workspace, workspacelen, c, c->context, c->exten))
*ret = NULL;
else
*ret = workspace;
} else if (c && !strcmp(var, "EXTEN")) {
ast_copy_string(workspace, c->exten, workspacelen);
*ret = workspace;
} else if (c && !strcmp(var, "RDNIS")) {
if (c->cid.cid_rdnis) {
ast_copy_string(workspace, c->cid.cid_rdnis, workspacelen);
*ret = workspace;
} else
*ret = NULL;
deprecated = "CALLERID(RDNIS)";
} else if (c && !strcmp(var, "CONTEXT")) {
ast_copy_string(workspace, c->context, workspacelen);
*ret = workspace;
} else if (c && !strcmp(var, "PRIORITY")) {
snprintf(workspace, workspacelen, "%d", c->priority);
*ret = workspace;
} else if (c && !strcmp(var, "CHANNEL")) {
ast_copy_string(workspace, c->name, workspacelen);
*ret = workspace;
} else if (!strcmp(var, "EPOCH")) {
snprintf(workspace, workspacelen, "%u",(int)time(NULL));
*ret = workspace;
} else if (!strcmp(var, "DATETIME")) {
thistime=time(NULL);
localtime_r(&thistime, &brokentime);
snprintf(workspace, workspacelen, "%02d%02d%04d-%02d:%02d:%02d",
brokentime.tm_mday,
brokentime.tm_mon+1,
brokentime.tm_year+1900,
brokentime.tm_hour,
brokentime.tm_min,
brokentime.tm_sec
);
*ret = workspace;
deprecated = "STRFTIME(${EPOCH},,\%m\%d\%Y-\%H:\%M:\%S)";
} else if (!strcmp(var, "TIMESTAMP")) {
thistime=time(NULL);
localtime_r(&thistime, &brokentime);
/* 20031130-150612 */
snprintf(workspace, workspacelen, "%04d%02d%02d-%02d%02d%02d",
brokentime.tm_year+1900,
brokentime.tm_mon+1,
brokentime.tm_mday,
brokentime.tm_hour,
brokentime.tm_min,
brokentime.tm_sec
);
*ret = workspace;
deprecated = "STRFTIME(${EPOCH},,\%Y\%m\%d-\%H\%M\%S)";
} else if (c && !strcmp(var, "UNIQUEID")) {
snprintf(workspace, workspacelen, "%s", c->uniqueid);
*ret = workspace;
} else if (c && !strcmp(var, "HANGUPCAUSE")) {
snprintf(workspace, workspacelen, "%d", c->hangupcause);
*ret = workspace;
} else if (c && !strcmp(var, "ACCOUNTCODE")) {
ast_copy_string(workspace, c->accountcode, workspacelen);
*ret = workspace;
deprecated = "CDR(accountcode)";
} else if (c && !strcmp(var, "LANGUAGE")) {
ast_copy_string(workspace, c->language, workspacelen);
*ret = workspace;
deprecated = "LANGUAGE()";
} else {
icky:
if (headp) {
AST_LIST_TRAVERSE(headp,variables,entries) {
#if 0
ast_log(LOG_WARNING,"Comparing variable '%s' with '%s'\n",var,ast_var_name(variables));
#endif
if (strcasecmp(ast_var_name(variables),var)==0) {
const char *s = ast_var_value(variables);
if (s) {
ast_copy_string(workspace, s, workspacelen);
*ret = workspace;
} }
break; } else if (!strcmp(var + 6, "ANI")) { /* CALLERANI */
s = c->cid.cid_ani;
deprecated = "CALLERID(ANI)";
}
} else if (!strncmp(var + 4, "ING", 3)) {
if (!strcmp(var + 7, "PRES")) { /* CALLINGPRES */
snprintf(workspace, workspacelen, "%d", c->cid.cid_pres);
s = workspace;
} else if (!strcmp(var + 7, "ANI2")) { /* CALLINGANI2 */
snprintf(workspace, workspacelen, "%d", c->cid.cid_ani2);
s = workspace;
} else if (!strcmp(var + 7, "TON")) { /* CALLINGTON */
snprintf(workspace, workspacelen, "%d", c->cid.cid_ton);
s = workspace;
} else if (!strcmp(var + 7, "TNS")) { /* CALLINGTNS */
snprintf(workspace, workspacelen, "%d", c->cid.cid_tns);
s = workspace;
} }
} }
} else if (!strcmp(var, "DNID")) {
s = c->cid.cid_dnid;
deprecated = "CALLERID(DNID)";
} else if (!strcmp(var, "HINT")) {
s = ast_get_hint(workspace, workspacelen, NULL, 0, c, c->context, c->exten) ? workspace : NULL;
} else if (!strcmp(var, "HINTNAME")) {
s = ast_get_hint(NULL, 0, workspace, workspacelen, c, c->context, c->exten) ? workspace : NULL;
} else if (!strcmp(var, "EXTEN")) {
s = c->exten;
} else if (!strcmp(var, "RDNIS")) {
s = c->cid.cid_rdnis;
deprecated = "CALLERID(RDNIS)";
} else if (!strcmp(var, "CONTEXT")) {
s = c->context;
} else if (!strcmp(var, "PRIORITY")) {
snprintf(workspace, workspacelen, "%d", c->priority);
s = workspace;
} 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;
} else if (!strcmp(var, "ACCOUNTCODE")) {
s = c->accountcode;
deprecated = "CDR(accountcode)";
} else if (!strcmp(var, "LANGUAGE")) {
s = c->language;
deprecated = "LANGUAGE()";
} }
if (!(*ret)) { }
/* Try globals */ if (s == &not_found) { /* look for more */
AST_LIST_TRAVERSE(&globals,variables,entries) { time_t thistime;
#if 0 struct tm brokentime;
ast_log(LOG_WARNING,"Comparing variable '%s' with '%s'\n",var,ast_var_name(variables));
#endif if (!strcmp(var, "EPOCH")) {
if (strcasecmp(ast_var_name(variables),var)==0) { snprintf(workspace, workspacelen, "%u",(int)time(NULL));
const char *s = ast_var_value(variables); s = workspace;
if (s) { } else if (!strcmp(var, "DATETIME")) {
ast_copy_string(workspace, s, workspacelen); thistime=time(NULL);
*ret = workspace; localtime_r(&thistime, &brokentime);
} snprintf(workspace, workspacelen, "%02d%02d%04d-%02d:%02d:%02d",
} brokentime.tm_mday,
brokentime.tm_mon+1,
brokentime.tm_year+1900,
brokentime.tm_hour,
brokentime.tm_min,
brokentime.tm_sec
);
s = workspace;
deprecated = "STRFTIME(${EPOCH},,\%d\%m\%Y-\%H:\%M:\%S)";
} else if (!strcmp(var, "TIMESTAMP")) {
thistime=time(NULL);
localtime_r(&thistime, &brokentime);
/* 20031130-150612 */
snprintf(workspace, workspacelen, "%04d%02d%02d-%02d%02d%02d",
brokentime.tm_year+1900,
brokentime.tm_mon+1,
brokentime.tm_mday,
brokentime.tm_hour,
brokentime.tm_min,
brokentime.tm_sec
);
s = workspace;
deprecated = "STRFTIME(${EPOCH},,\%Y\%m\%d-\%H\%M\%S)";
}
}
/* if not found, look into chanvars or global vars */
for (i = 0; s == &not_found && i < (sizeof(places) / sizeof(places[0])); i++) {
struct ast_var_t *variables;
if (!places[i])
continue;
AST_LIST_TRAVERSE(places[i], variables, entries) {
if (strcasecmp(ast_var_name(variables), var)==0) {
s = ast_var_value(variables);
break;
} }
} }
} }
if (deprecated) { if (s == &not_found || s == NULL)
ast_log(LOG_WARNING, "${%s} is deprecated. Please use ${%s} instead.\n", var, deprecated); *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 (deprecated)
ast_log(LOG_WARNING, "${%s} is deprecated. Please use ${%s} instead.\n", var, deprecated);
} }
/*! \brief CLI function to show installed custom functions /*! \brief CLI function to show installed custom functions

Loading…
Cancel
Save