aboutsummaryrefslogtreecommitdiffstats
path: root/pbx.c
diff options
context:
space:
mode:
authormarkster <markster@f38db490-d61c-443f-a65b-d21fe96a405b>2003-09-14 00:32:51 +0000
committermarkster <markster@f38db490-d61c-443f-a65b-d21fe96a405b>2003-09-14 00:32:51 +0000
commit1bc2e7eea558632cf43fb6eb0bd40b911df064f4 (patch)
treeb09169a43967d7cac0918ec6aac3e70e49587261 /pbx.c
parent4bb22e9c80b844bcd3030e29931a9b378f26adca (diff)
Revert bug 176 patch entirely
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@1512 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'pbx.c')
-rwxr-xr-xpbx.c426
1 files changed, 78 insertions, 348 deletions
diff --git a/pbx.c b/pbx.c
index 7b86ed45b..8a7dd2fd7 100755
--- a/pbx.c
+++ b/pbx.c
@@ -144,6 +144,7 @@ struct ast_hint {
struct ast_hint *next;
};
+
static int pbx_builtin_prefix(struct ast_channel *, void *);
static int pbx_builtin_suffix(struct ast_channel *, void *);
static int pbx_builtin_stripmsd(struct ast_channel *, void *);
@@ -170,7 +171,6 @@ static int pbx_builtin_saynumber(struct ast_channel *, void *);
static int pbx_builtin_saydigits(struct ast_channel *, void *);
void pbx_builtin_setvar_helper(struct ast_channel *chan, char *name, char *value);
char *pbx_builtin_getvar_helper(struct ast_channel *chan, char *name);
-static int ast_extension_patmatch_repeated(const char *pattern, const char *data, const int num);
static struct varshead globals = AST_LIST_HEAD_INITIALIZER(varshead);
@@ -491,360 +491,92 @@ static void pbx_destroy(struct ast_pbx *p)
free(p);
}
-int patmatch_groupcounter = 0;
-char patmatch_group[80] = "";
-
-/* Derived from code by Steffen Offermann 1991, public domain
- http://www.cs.umu.se/~isak/Snippets/xstrcmp.c
-
- * a regex must start with "_"
- * regex patterns are case-insensitive except characters inside []
- * "." matches zero or more characters (as in * in glob)
- * character ranges as in [0-9a-zA-Z]
- * X,Z,N match 0-9,1-9,2-9 resp.
-
- new additional features:
- * "?" matches any character
- * negation as in [^0] ("any char but 0")
- or [^a-z]
- * explicit quantifiers as in X{2,4} ("from 2 to 4 digits"),
- or X{2,} ("at least 2 digits"),
- or X{2} ("exactly 2 digits"),
- * regex-style quantifiers like ?, + and * are supported by
- "{}" grouping.
- ? <=> {0,1}
- + <=> {1,}
- * <=> {0,}
- * grouping as in N(1X){1,2} ("one or two sequences of 1X")
- * capturing (dependent on AST_PBX_MATCH_CAPTURE)
- With () grouped matches are stored in subsequent numbered global
- variables, starting with $1, $2 and so on.
- * alternation as in (01|0|99) ("01 or 0 or 99")
- */
-int ast_extension_patmatch(const char *pattern, const char *data)
-{
- int i,border=0;
- char *where;
- static char prev = '\0';
- static char groupdata[80] = "";
- static char *group = patmatch_group;
-
- if (option_debug)
- ast_log(LOG_DEBUG, " >>> \"%s\" =~ /%s/\n", data, pattern);
- switch (toupper(*pattern))
- {
- case '\0':
- if (option_debug)
- ast_log(LOG_DEBUG, " !>>> \"%s\" => %s\n", data, !*data ? "OK" : "FAIL");
- return !*data;
-
- case ' ':
- case '-':
- /* Ignore these characters in the pattern */
- return *data && ast_extension_patmatch(pattern+1, data);
-
- case '.' : /* wildcard as '*' in glob(). Match any sequence of characters. 0 or more */
- prev = *pattern;
- if (! *(pattern+1) )
- return 1; /* return *data; => match one or more */
- else
- return ast_extension_patmatch(pattern+1, data) || (*data && ast_extension_patmatch(pattern, data+1));
-
- /* wildcard character: Match any char */
- case '?' :
- prev = *pattern;
- return *data && ast_extension_patmatch(pattern+1, data+1);
-
- case 'X': /* 0-9 */
- prev = *pattern;
- return ((*data >= '0') && (*data <= '9')) && ast_extension_patmatch(pattern+1, data+1);
-
- case 'Z': /* 1-9 */
- prev = *pattern;
- return ((*data >= '1') && (*data <= '9')) && ast_extension_patmatch(pattern+1, data+1);
-
- case 'N': /* 2-9 */
- prev = *pattern;
- return ((*data >= '2') && (*data <= '9')) && ast_extension_patmatch(pattern+1, data+1);
-
- case '{': /* quantifier {n[,m]} */
- {
- char *comma=NULL;
- int cpos;
- where=strchr(pattern,'}');
- if (where) {
- border=(int)(where-pattern);
- comma = strchr(pattern,',');
- }
- if (!where || border > strlen(pattern)) {
- ast_log(LOG_WARNING, "Wrong %s pattern usage\n", pattern);
- return 0;
- } else {
- char tmp[8];
- int from, to;
- if (comma)
- cpos = (int)(comma-pattern);
- else
- cpos = border;
- strncpy(tmp,pattern+1,cpos-1);
- tmp[cpos-1] = '\0';
- from = atoi(tmp);
- if (comma) {
- if (border-cpos > 1) { /* {f,t} */
- strncpy(tmp,comma+1,border-cpos);
- tmp[border-cpos+1] = '\0';
- to = atoi(tmp);
- } else { /* {f,} */
- to = strlen(data); /* may fail if after the group are more pattern chars */
- if (*(pattern+border+1)) {
- to = to - strlen(pattern+border+1) + 1;
- }
- }
- } else { /* {f} */
- if (from == 0) {
- ast_log(LOG_WARNING, "Invalid {0} pattern quantifier %s\n", pattern);
- return 0;
- }
- to = from;
- }
- if (from < 0 || to <= 0 || to < from) {
- ast_log(LOG_WARNING, "Invalid pattern quantifier %s\n", pattern);
- return 0;
- }
-
- if (*group) { /* check for repeated pattern{n,m} in previous group */
- int i;
- for (i=0; i< strlen(group); i++) {
- data--;
- }
- if (option_debug)
- ast_log(LOG_DEBUG, ">>> check for repeated pattern{%d,%d} of group '%s' in data '%s'\n", from, to, group, data);
- strcat(group,".");
- } else {
- if (option_debug)
- ast_log(LOG_DEBUG, ">>> check for repeated pattern{%d,%d} in previous character '%c'\n", from, to, prev);
- data--;
- group[0] = prev;
- group[1] = '.';
- group[2] = '\0';
- }
- *tmp = prev;
- for (i=to; i>=from; i--) {
- if (ast_extension_patmatch_repeated(group,data,i)) break;
- }
- prev = *tmp;
- if (i >= from || !from) { /* if found */
- int l = strlen(groupdata) - strlen(data);
- if (option_debug)
- ast_log(LOG_DEBUG, " >>>> found '%s' in data '%s' after %d runs\n", group, data, i);
- data = data + (i * (strlen(group)- 1)) - 1;
- /* data = data-i+from-1; */ /* possible failure here! */
- if (prev == ')') { /* grouping => capture */
- *(group+strlen(group)-1) = '\0';
- groupdata[l+1] = '\0';
- if (option_debug)
- ast_log(LOG_DEBUG, " >>>>> end of group '%s', data: %s\n", group, groupdata);
- /* capture the found data in variables $1, $2, ... */
-#ifdef AST_PBX_MATCH_CAPTURE
- sprintf(name,"%d",++groupcounter);
- pbx_builtin_setvar_helper(NULL,name,groupdata);
- if (option_verbose > 2)
- ast_log(VERBOSE_PREFIX_3 "global variable $%s set to '%s'\n", name, groupdata);
-#endif
- }
- }
- *group = '\0';
- prev = '\0';
- if (i >= from) { /* found: continue */
- if (option_debug)
- ast_log(LOG_DEBUG, " >>>> found in round %d from %d\n", i, to);
- if (*data) {
- if (*(pattern+border+1)) /* if the tail check fails, try the other rounds */
- if (ast_extension_patmatch(pattern+border+1, data+1))
- return 1;
- else return (ast_extension_patmatch_repeated(group, data, i--) &&
- ast_extension_patmatch(pattern+border+1, data+i));
- else
- return ast_extension_patmatch(pattern+border+1, data+1);
- }
- else
- return 1;
- } else if (from == 0) { /* not found, but special case from=0: no match needed */
- if (option_debug)
- ast_log(LOG_DEBUG, " >>>> not found, but no match needed and data exhausted\n");
- if (*data)
- return ast_extension_patmatch(pattern+border+1, data+1);
- else
- return 1;
- } else /* not found */
- return 0;
- }
- }
- /* unreachable code */
-
- case '(': /* grouping */
- prev = *pattern;
- if (*group) {
- ast_log(LOG_WARNING, "Unexpected subgroup ( in pattern %s\n", pattern);
- return 0;
- }
- where=strchr(pattern,')');
- if (where)
- border=(int)(where-pattern);
- if (!where || border > strlen(pattern)) {
- ast_log(LOG_WARNING, "Wrong (%s) pattern usage\n", pattern);
- return 0;
- }
- strncpy(group,pattern+1,border-1);
- group[border-1] = '\0';
- strcpy(groupdata,data);
- if (option_debug)
- ast_log(LOG_DEBUG, ">>> group '%s' stored, data: '%s'\n", group, groupdata);
- if (strchr(pattern,'|')) { /* alternations */
- char *s, *scopy, *sep, *sepcopy;
- s = scopy = (char *) malloc(strlen(pattern));
- sepcopy = (char *) malloc(strlen(pattern));
- strcpy(s,group);
- while ((sep = strsep(&s,"|"))) {
- strcpy(sepcopy,sep);
- strcat(sepcopy,pattern+border+1);
- if (option_debug)
- ast_log(LOG_DEBUG, " >>>> alternative '%s' =~ /%s/\n", sepcopy, data);
- if (ast_extension_patmatch(sepcopy, data)) break;
- if (!*data) {
- sep = NULL; break;
- }
- }
- free(scopy);
- if (sep) { /* found */
- free(sepcopy);
- return 1;
- } else {
- free(sepcopy);
- return 0;
- }
- } else {
- return ast_extension_patmatch(pattern+1, data);
- }
-
- case ')': /* group end */
- prev = *pattern;
- if (!*group) {
- ast_log(LOG_WARNING, "Unexpected ) in pattern %s\n", pattern);
- return 0;
- } else {
- if (pattern[1] != '{') { /* capture without quantifiers */
- int l = strlen(groupdata) - strlen(data);
- groupdata[l-1] = '\0';
- *(group+strlen(group)-1) = '\0';
- if (option_debug)
- ast_log(LOG_DEBUG, ">>> end of group '%s', data: %s\n", group, groupdata);
-#ifdef AST_PBX_MATCH_CAPTURE
- /* capture the found data in variables $1, $2, ... */
- sprintf(name,"%d",++groupcounter);
- pbx_builtin_setvar_helper(NULL,name,groupdata);
- ast_log(VERBOSE_PREFIX_3 "global variable $%s set to '%s'\n", name, groupdata);
-#endif
- *group = '\0';
- }
- }
- return ast_extension_patmatch(pattern+1, data);
-
- case '|': /* alternation */
- if (!*group) {
- ast_log(LOG_WARNING, "Need group for | in %s\n", pattern);
- return 0;
- }
-
- case '[': /* Character ranges: [0-9a-zA-Z] */
- prev = *pattern;
- pattern++;
- where=strchr(pattern,']');
- if (where)
- border=(int)(where-pattern);
- if (!where || border > strlen(pattern)) {
- ast_log(LOG_WARNING, "Wrong [%s] pattern usage\n", pattern);
- return 0;
- }
- if (*pattern == '^') { /* Negation like [^...] */
- for (i=1; i<border; i++) {
- if (*data==pattern[i])
- return 0;
- else if ((pattern[i+1]=='-') && (i+2<border)) {
- if (*data >= pattern[i] && *data <= pattern[i+2]) {
- return 0;
- } else {
- i+=2;
- continue;
- }
- }
- }
- return ast_extension_patmatch(where+1, data+1);
- } else {
- for (i=0; i<border; i++) {
- if (i+2<border) {
- if (*data==pattern[i])
- return ast_extension_patmatch(where+1, data+1);
- else if (pattern[i+1]=='-') {
- if (*data >= pattern[i] && *data <= pattern[i+2]) {
- return ast_extension_patmatch(where+1, data+1);
- } else {
- i+=2;
- continue;
- }
- }
- }
- }
- }
- break;
-
- default :
- prev = *pattern;
- return (toupper(*pattern) == toupper(*data)) && ast_extension_patmatch(pattern+1, data+1);
- }
- return 0;
-}
-
-/* try exactly num repetitions, from high to from */
-static int ast_extension_patmatch_repeated(const char *pattern, const char *data, const int num)
-{
- int i;
- ast_log(LOG_DEBUG, " >>> try %d repetitions of '%s' in data '%s'\n", num, pattern, data);
- if (num <= 0) return 0;
- for (i=1; i<=num; i++) {
- ast_log(LOG_DEBUG, " >>>> round %d with data %s\n", i, data);
- if (!ast_extension_patmatch(pattern, data)) return 0;
- data = data + strlen(pattern) - 1;
- }
- return 1;
+#define EXTENSION_MATCH_CORE(data,pattern,match) {\
+ /* All patterns begin with _ */\
+ if (pattern[0] != '_') \
+ return 0;\
+ /* Start optimistic */\
+ match=1;\
+ pattern++;\
+ while(match && *data && *pattern && (*pattern != '/')) {\
+ switch(toupper(*pattern)) {\
+ case '[': \
+ {\
+ int i,border=0;\
+ char *where;\
+ match=0;\
+ pattern++;\
+ where=strchr(pattern,']');\
+ if (where)\
+ border=(int)(where-pattern);\
+ if (!where || border > strlen(pattern)) {\
+ ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");\
+ return match;\
+ }\
+ for (i=0; i<border; i++) {\
+ int res=0;\
+ if (i+2<border)\
+ if (pattern[i+1]=='-') {\
+ if (*data >= pattern[i] && *data <= pattern[i+2]) {\
+ res=1;\
+ } else {\
+ i+=2;\
+ continue;\
+ }\
+ }\
+ if (res==1 || *data==pattern[i]) {\
+ match = 1;\
+ break;\
+ }\
+ }\
+ pattern+=border;\
+ break;\
+ }\
+ case 'N':\
+ if ((*data < '2') || (*data > '9'))\
+ match=0;\
+ break;\
+ case 'X':\
+ if ((*data < '0') || (*data > '9'))\
+ match = 0;\
+ break;\
+ case 'Z':\
+ if ((*data < '1') || (*data > '9'))\
+ match = 0;\
+ break;\
+ case '.':\
+ /* Must match */\
+ return 1;\
+ case ' ':\
+ case '-':\
+ /* Ignore these characters */\
+ data--;\
+ break;\
+ default:\
+ if (*data != *pattern)\
+ match =0;\
+ }\
+ data++;\
+ pattern++;\
+ }\
}
int ast_extension_match(char *pattern, char *data)
{
int match;
- patmatch_groupcounter = 0;
- *patmatch_group = '\0';
- if (!*pattern) {
- ast_log(LOG_WARNING, "ast_extension_match: empty pattern\n");
- return 0;
- }
- if (!*data) {
- ast_log(LOG_WARNING, "ast_extension_match: empty data\n");
- return 0;
- }
- if (pattern[0] != '_') {
- match = (strcmp(pattern, data) == 0);
- /* ast_log(LOG_DEBUG, "ast_extension_match %s == /%s/ => %d\n", data, pattern, match); */
- } else {
- match = ast_extension_patmatch(pattern+1,data);
- /* ast_log(LOG_DEBUG, "ast_extension_match %s =~ /%s/ => %d\n", data, pattern+1, match); */
- }
+ /* If they're the same return */
+ if (!strcmp(pattern, data))
+ return 1;
+ EXTENSION_MATCH_CORE(data,pattern,match);
+ /* Must be at the end of both */
+ if (*data || (*pattern && (*pattern != '/')))
+ match = 0;
return match;
}
static int extension_close(char *pattern, char *data, int needmore)
{
- int match=0;
+ int match;
/* If "data" is longer, it can'be a subset of pattern unless
pattern is a pattern match */
if ((strlen(pattern) < strlen(data)) && (pattern[0] != '_'))
@@ -854,9 +586,7 @@ static int extension_close(char *pattern, char *data, int needmore)
(!needmore || (strlen(pattern) > strlen(data)))) {
return 1;
}
- if (pattern[0] == '_') {
- match = ast_extension_patmatch(pattern+1,data);
- }
+ EXTENSION_MATCH_CORE(data,pattern,match);
/* If there's more or we don't care about more, return non-zero, otlherwise it's a miss */
if (!needmore || *pattern) {
return match;