major re-work of dialplan functions, including:
[asterisk/asterisk.git] / funcs / func_strings.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * String manipulation dialplan functions
5  * 
6  * Copyright (C) 2005, Digium, Inc.
7  *
8  * This program is free software, distributed under the terms of
9  * the GNU General Public License
10  */
11
12 #include <stdlib.h>
13 #include <string.h>
14 #include <sys/types.h>
15 #include <regex.h>
16
17 #include "asterisk/channel.h"
18 #include "asterisk/pbx.h"
19 #include "asterisk/logger.h"
20 #include "asterisk/utils.h"
21 #include "asterisk/app.h"
22
23 static char *function_fieldqty(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
24 {
25         char *varname, *varval, workspace[256];
26         char *delim = ast_strdupa(data);
27         int fieldcount = 0;
28
29         if (delim) {
30                 varname = strsep(&delim, "|");
31                 pbx_retrieve_variable(chan, varname, &varval, workspace, sizeof(workspace), NULL);
32                 while (strsep(&varval, delim))
33                         fieldcount++;
34                 snprintf(buf, len, "%d", fieldcount);
35         } else {
36                 ast_log(LOG_ERROR, "Out of memory\n");
37                 strncpy(buf, "1", len);
38         }
39         return buf;
40 }
41
42 #ifndef BUILTIN_FUNC
43 static
44 #endif
45 struct ast_custom_function fieldqty_function = {
46         .name = "FIELDQTY",
47         .synopsis = "Count the fields, with an arbitrary delimiter",
48         .syntax = "FIELDQTY(<varname>,<delim>)",
49         .read = function_fieldqty,
50 };
51
52 static char *builtin_function_regex(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len) 
53 {
54         char *ret_true = "1", *ret_false = "0", *ret;
55         char *arg, *earg, *tmp, errstr[256] = "";
56         int errcode;
57         regex_t regexbuf;
58
59         ret = ret_false; /* convince me otherwise */
60         tmp = ast_strdupa(data);
61         if (tmp) {
62                 /* Regex in quotes */
63                 arg = strchr(tmp, '"');
64                 if (arg) {
65                         arg++;
66                         earg = strrchr(arg, '"');
67                         if (earg) {
68                                 *earg = '\0';
69                         }
70                 } else {
71                         arg = tmp;
72                 }
73
74                 if ((errcode = regcomp(&regexbuf, arg, REG_EXTENDED | REG_NOSUB))) {
75                         regerror(errcode, &regexbuf, errstr, sizeof(errstr));
76                         ast_log(LOG_WARNING, "Malformed input %s(%s): %s\n", cmd, data, errstr);
77                         ret = NULL;
78                 } else {
79                         ret = regexec(&regexbuf, data, 0, NULL, 0) ? ret_false : ret_true;
80                 }
81                 regfree(&regexbuf);
82         } else {
83                 ast_log(LOG_ERROR, "Out of memory in %s(%s)\n", cmd, data);
84         }
85
86         return ret;
87 }
88
89 #ifndef BUILTIN_FUNC
90 static
91 #endif
92 struct ast_custom_function regex_function = {
93         .name = "REGEX",
94         .synopsis = "Regular Expression: Returns 1 if data matches regular expression.",
95         .syntax = "REGEX(\"<regular expression>\" <data>)",
96         .read = builtin_function_regex,
97 };
98
99 static char *builtin_function_len(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len) 
100 {
101         int length = 0;
102         if (data) {
103                 length = strlen(data);
104         }
105         snprintf(buf, len, "%d", length);
106         return buf;
107 }
108
109 #ifndef BUILTIN_FUNC
110 static
111 #endif
112 struct ast_custom_function len_function = {
113         .name = "LEN",
114         .synopsis = "Returns the length of the argument given",
115         .syntax = "LEN(<string>)",
116         .read = builtin_function_len,
117 };