aboutsummaryrefslogtreecommitdiffstats
path: root/funcs/func_strings.c
diff options
context:
space:
mode:
authortilghman <tilghman@f38db490-d61c-443f-a65b-d21fe96a405b>2007-10-12 17:32:38 +0000
committertilghman <tilghman@f38db490-d61c-443f-a65b-d21fe96a405b>2007-10-12 17:32:38 +0000
commit0505561bf8b277e0ee9c97c3608dc4f1491acf56 (patch)
treefd997786c7cee9c4b82ae96106f4358a2c8491ce /funcs/func_strings.c
parent9b43b973221c9fadbc3caf32c079351b0b0d3038 (diff)
Enable ranges, hexadecimal, octal, and special backslashed characters for the FILTER function
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@85522 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'funcs/func_strings.c')
-rw-r--r--funcs/func_strings.c105
1 files changed, 103 insertions, 2 deletions
diff --git a/funcs/func_strings.c b/funcs/func_strings.c
index db14c07fd..a648c6cda 100644
--- a/funcs/func_strings.c
+++ b/funcs/func_strings.c
@@ -92,6 +92,73 @@ static struct ast_custom_function fieldqty_function = {
.read = function_fieldqty,
};
+static int get_filter_char(const char *stream, char *result, size_t *consumed)
+{
+ int i;
+ *consumed = 1;
+ *result = 0;
+ if (*stream == '\\') {
+ *consumed = 2;
+ switch (*(stream + 1)) {
+ case 'n':
+ *result = '\n';
+ break;
+ case 'r':
+ *result = '\r';
+ break;
+ case 't':
+ *result = '\t';
+ break;
+ case 'x':
+ /* Hexadecimal */
+ if (strchr("0123456789ABCDEFabcdef", *(stream + 2)) && *(stream + 2) != '\0') {
+ *consumed = 3;
+ if (*(stream + 2) <= '9')
+ *result = *(stream + 2) - '0';
+ else if (*(stream + 2) <= 'F')
+ *result = *(stream + 2) - 'A' + 10;
+ else
+ *result = *(stream + 2) - 'a' + 10;
+ } else {
+ ast_log(LOG_ERROR, "Illegal character '%c' in hexadecimal string\n", *(stream + 2));
+ return -1;
+ }
+
+ if (strchr("0123456789ABCDEFabcdef", *(stream + 3)) && *(stream + 3) != '\0') {
+ *consumed = 4;
+ *result <<= 4;
+ if (*(stream + 3) <= '9')
+ *result += *(stream + 3) - '0';
+ else if (*(stream + 3) <= 'F')
+ *result += *(stream + 3) - 'A' + 10;
+ else
+ *result += *(stream + 3) - 'a' + 10;
+ }
+ break;
+ case '0':
+ /* Octal */
+ *consumed = 2;
+ for (i = 2; ; i++) {
+ if (strchr("01234567", *(stream + i)) && *(stream + i) != '\0') {
+ (*consumed)++;
+ ast_debug(5, "result was %d, ", *result);
+ *result <<= 3;
+ *result += *(stream + i) - '0';
+ ast_debug(5, "is now %d\n", *result);
+ } else
+ break;
+ }
+ break;
+ default:
+ *result = *(stream + 1);
+ }
+ } else {
+ *result = *stream;
+ *consumed = 1;
+ }
+ return 0;
+}
+
static int filter(struct ast_channel *chan, const char *cmd, char *parse, char *buf,
size_t len)
{
@@ -99,7 +166,9 @@ static int filter(struct ast_channel *chan, const char *cmd, char *parse, char *
AST_APP_ARG(allowed);
AST_APP_ARG(string);
);
- char *outbuf = buf;
+ char *outbuf = buf, ac;
+ char allowed[256] = "";
+ size_t allowedlen = 0;
AST_STANDARD_APP_ARGS(args, parse);
@@ -108,8 +177,40 @@ static int filter(struct ast_channel *chan, const char *cmd, char *parse, char *
return -1;
}
+ /* Expand ranges */
+ for (; *(args.allowed) && allowedlen < sizeof(allowed); (args.allowed)++) {
+ char c1 = 0, c2 = 0;
+ size_t consumed = 0;
+
+ if (get_filter_char(args.allowed, &c1, &consumed))
+ return -1;
+ args.allowed += consumed;
+
+ if (*(args.allowed) == '-') {
+ if (get_filter_char(args.allowed + 1, &c2, &consumed))
+ c2 = -1;
+ args.allowed += consumed + 1;
+
+ /*!\note
+ * Looks a little strange, until you realize that we can overflow
+ * the size of a char.
+ */
+ for (ac = c1; ac != c2 && allowedlen < sizeof(allowed) - 1; ac++)
+ allowed[allowedlen++] = ac;
+ allowed[allowedlen++] = ac;
+
+ ast_debug(4, "c1=%d, c2=%d\n", c1, c2);
+
+ /* Decrement before the loop increment */
+ (args.allowed)--;
+ } else
+ allowed[allowedlen++] = c1;
+ }
+
+ ast_debug(1, "Allowed: %s\n", allowed);
+
for (; *(args.string) && (buf + len - 1 > outbuf); (args.string)++) {
- if (strchr(args.allowed, *(args.string)))
+ if (strchr(allowed, *(args.string)))
*outbuf++ = *(args.string);
}
*outbuf = '\0';