Merge str_substitution branch.
[asterisk/asterisk.git] / funcs / func_strings.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2005-2006, Digium, Inc.
5  * Portions Copyright (C) 2005, Tilghman Lesher.  All rights reserved.
6  * Portions Copyright (C) 2005, Anthony Minessale II
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*! \file
20  *
21  * \brief String manipulation dialplan functions
22  *
23  * \author Tilghman Lesher
24  * \author Anothony Minessale II 
25  * \ingroup functions
26  */
27
28 #include "asterisk.h"
29
30 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
31
32 #include <regex.h>
33 #include <ctype.h>
34
35 #include "asterisk/module.h"
36 #include "asterisk/channel.h"
37 #include "asterisk/pbx.h"
38 #include "asterisk/utils.h"
39 #include "asterisk/app.h"
40 #include "asterisk/localtime.h"
41
42 AST_THREADSTORAGE(result_buf);
43
44 /*** DOCUMENTATION
45         <function name="FIELDQTY" language="en_US">
46                 <synopsis>
47                         Count the fields with an arbitrary delimiter
48                 </synopsis>
49                 <syntax>
50                         <parameter name="varname" required="true" />
51                         <parameter name="delim" required="true" />
52                 </syntax>
53                 <description>
54                         <para>Example: ${FIELDQTY(ex-amp-le,-)} returns 3</para>
55                 </description>
56         </function>
57         <function name="LISTFILTER" language="en_US">
58                 <synopsis>Remove an item from a list, by name.</synopsis>
59                 <syntax>
60                         <parameter name="varname" required="true" />
61                         <parameter name="delim" required="true" default="," />
62                         <parameter name="value" required="true" />
63                 </syntax>
64                 <description>
65                         <para>Remove <replaceable>value</replaceable> from the list contained in the <replaceable>varname</replaceable>
66                         variable, where the list delimiter is specified by the <replaceable>delim</replaceable> parameter.  This is
67                         very useful for removing a single channel name from a list of channels, for example.</para>
68                 </description>
69         </function>
70         <function name="FILTER" language="en_US">
71                 <synopsis>
72                         Filter the string to include only the allowed characters
73                 </synopsis>
74                 <syntax>
75                         <parameter name="allowed-chars" required="true" />
76                         <parameter name="string" required="true" />
77                 </syntax>
78                 <description>
79                         <para>Permits all characters listed in <replaceable>allowed-chars</replaceable>, 
80                         filtering all others outs. In addition to literally listing the characters, 
81                         you may also use ranges of characters (delimited by a <literal>-</literal></para>
82                         <para>Hexadecimal characters started with a <literal>\x</literal>(i.e. \x20)</para>
83                         <para>Octal characters started with a <literal>\0</literal> (i.e. \040)</para>
84                         <para>Also <literal>\t</literal>,<literal>\n</literal> and <literal>\r</literal> are recognized.</para> 
85                         <note><para>If you want the <literal>-</literal> character it needs to be prefixed with a 
86                         <literal>\</literal></para></note>
87                 </description>
88         </function>
89         <function name="REGEX" language="en_US">
90                 <synopsis>
91                         Check string against a regular expression.
92                 </synopsis>
93                 <syntax argsep=" ">
94                         <parameter name="&quot;regular expression&quot;" required="true" />
95                         <parameter name="string" required="true" />
96                 </syntax>
97                 <description>
98                         <para>Return <literal>1</literal> on regular expression match or <literal>0</literal> otherwise</para>
99                         <para>Please note that the space following the double quotes separating the 
100                         regex from the data is optional and if present, is skipped. If a space is 
101                         desired at the beginning of the data, then put two spaces there; the second 
102                         will not be skipped.</para>
103                 </description>
104         </function>
105         <application name="ClearHash" language="en_US">
106                 <synopsis>
107                         Clear the keys from a specified hashname.
108                 </synopsis>
109                 <syntax>
110                         <parameter name="hashname" required="true" />
111                 </syntax>
112                 <description>
113                         <para>Clears all keys out of the specified <replaceable>hashname</replaceable>.</para>
114                 </description>
115         </application>
116         <function name="HASH" language="en_US">
117                 <synopsis>
118                         Implementation of a dialplan associative array
119                 </synopsis>
120                 <syntax>
121                         <parameter name="hashname" required="true" />
122                         <parameter name="hashkey" />
123                 </syntax>
124                 <description>
125                         <para>In two arguments mode, gets and sets values to corresponding keys within
126                         a named associative array. The single-argument mode will only work when assigned
127                         to from a function defined by func_odbc</para>
128                 </description>
129         </function>
130         <function name="HASHKEYS" language="en_US">
131                 <synopsis>
132                         Retrieve the keys of the HASH() function.
133                 </synopsis>
134                 <syntax>
135                         <parameter name="hashname" required="true" />
136                 </syntax>
137                 <description>
138                         <para>Returns a comma-delimited list of the current keys of the associative array 
139                         defined by the HASH() function. Note that if you iterate over the keys of 
140                         the result, adding keys during iteration will cause the result of the HASHKEYS()
141                         function to change.</para>
142                 </description>
143         </function>
144         <function name="KEYPADHASH" language="en_US">
145                 <synopsis>
146                         Hash the letters in string into equivalent keypad numbers.
147                 </synopsis>
148                 <syntax>
149                         <parameter name="string" required="true" />
150                 </syntax>
151                 <description>
152                         <para>Example: ${KEYPADHASH(Les)} returns "537"</para>
153                 </description>
154         </function>
155         <function name="ARRAY" language="en_US">
156                 <synopsis>
157                         Allows setting multiple variables at once.
158                 </synopsis>
159                 <syntax>
160                         <parameter name="var1" required="true" />
161                         <parameter name="var2" required="false" multiple="true" />
162                         <parameter name="varN" required="false" />
163                 </syntax>
164                 <description>
165                         <para>The comma-delimited list passed as a value to which the function is set will 
166                         be interpreted as a set of values to which the comma-delimited list of 
167                         variable names in the argument should be set.</para>
168                         <para>Example: Set(ARRAY(var1,var2)=1,2) will set var1 to 1 and var2 to 2</para>
169                 </description>
170         </function>
171         <function name="STRPTIME" language="en_US">
172                 <synopsis>
173                         Returns the epoch of the arbitrary date/time string structured as described by the format.
174                 </synopsis>
175                 <syntax>
176                         <parameter name="datetime" required="true" />
177                         <parameter name="timezone" required="true" />
178                         <parameter name="format" required="true" />
179                 </syntax>
180                 <description>
181                         <para>This is useful for converting a date into <literal>EPOCH</literal> time, 
182                         possibly to pass to an application like SayUnixTime or to calculate the difference
183                         between the two date strings</para>
184                         <para>Example: ${STRPTIME(2006-03-01 07:30:35,America/Chicago,%Y-%m-%d %H:%M:%S)} returns 1141219835</para>
185                 </description>
186         </function>
187         <function name="STRFTIME" language="en_US">
188                 <synopsis>
189                         Returns the current date/time in the specified format.
190                 </synopsis>
191                 <syntax>
192                         <parameter name="epoch" />
193                         <parameter name="timezone" />
194                         <parameter name="format" />
195                 </syntax>
196                 <description>
197                         <para>STRFTIME supports all of the same formats as the underlying C function
198                         <emphasis>strftime(3)</emphasis>.
199                         It also supports the following format: <literal>%[n]q</literal> - fractions of a second,
200                         with leading zeros.</para>
201                         <para>Example: <literal>%3q</literal> will give milliseconds and <literal>%1q</literal>
202                         will give tenths of a second. The default is set at milliseconds (n=3).
203                         The common case is to use it in combination with %S, as in <literal>%S.%3q</literal>.</para>
204                 </description>
205                 <see-also>
206                         <ref type="manpage">strftime(3)</ref>
207                 </see-also>
208         </function>
209         <function name="EVAL" language="en_US">
210                 <synopsis>
211                         Evaluate stored variables
212                 </synopsis>
213                 <syntax>
214                         <parameter name="variable" required="true" />
215                 </syntax>
216                 <description>
217                         <para>Using EVAL basically causes a string to be evaluated twice.
218                         When a variable or expression is in the dialplan, it will be
219                         evaluated at runtime. However, if the results of the evaluation
220                         is in fact another variable or expression, using EVAL will have it
221                         evaluated a second time.</para>
222                         <para>Example: If the <variable>MYVAR</variable> contains
223                         <variable>OTHERVAR</variable>, then the result of ${EVAL(
224                         <variable>MYVAR</variable>)} in the dialplan will be the
225                         contents of <variable>OTHERVAR</variable>. Normally just
226                         putting <variable>MYVAR</variable> in the dialplan the result
227                         would be <variable>OTHERVAR</variable>.</para>
228                 </description>
229         </function>
230         <function name="TOUPPER" language="en_US">
231                 <synopsis>
232                         Convert string to all uppercase letters.
233                 </synopsis>
234                 <syntax>
235                         <parameter name="string" required="true" />
236                 </syntax>
237                 <description>
238                         <para>Example: ${TOUPPER(Example)} returns "EXAMPLE"</para>
239                 </description>
240         </function>
241         <function name="TOLOWER" language="en_US">
242                 <synopsis>
243                         Convert string to all lowercase letters.
244                 </synopsis>
245                 <syntax>
246                         <parameter name="string" required="true" />
247                 </syntax>
248                 <description>
249                         <para>Example: ${TOLOWER(Example)} returns "example"</para>
250                 </description>
251         </function>
252         <function name="LEN" language="en_US">
253                 <synopsis>
254                         Return the length of the string given.
255                 </synopsis>
256                 <syntax>
257                         <parameter name="string" required="true" />
258                 </syntax>
259                 <description>
260                         <para>Example: ${LEN(example)} returns 7</para>
261                 </description>
262         </function>
263         <function name="QUOTE" language="en_US">
264                 <synopsis>
265                         Quotes a given string, escaping embedded quotes as necessary
266                 </synopsis>
267                 <syntax>
268                         <parameter name="string" required="true" />
269                 </syntax>
270                 <description>
271                         <para>Example: ${QUOTE(ab"c"de)} will return "abcde"</para>
272                 </description>
273         </function>
274         <function name="SHIFT" language="en_US">
275                 <synopsis>
276                         Removes and returns the first item off of a variable containing delimited text
277                 </synopsis>
278                 <syntax>
279                         <parameter name="varname" required="true" />
280                         <parameter name="delimiter" required="false" default="," />
281                 </syntax>
282                 <description>
283                         <para>Example:</para>
284                         <para>exten => s,1,Set(array=one,two,three)</para>
285                         <para>exten => s,n,While($["${SET(var=${SHIFT(array)})}" != ""])</para>
286                         <para>exten => s,n,NoOp(var is ${var})</para>
287                         <para>exten => s,n,EndWhile</para>
288                         <para>This would iterate over each value in array, left to right, and
289                                 would result in NoOp(var is one), NoOp(var is two), and
290                                 NoOp(var is three) being executed.
291                         </para>
292                 </description>
293         </function>     
294         <function name="POP" language="en_US">
295                 <synopsis>
296                         Removes and returns the last item off of a variable containing delimited text
297                 </synopsis>
298                 <syntax>
299                         <parameter name="varname" required="true" />
300                         <parameter name="delimiter" required="false" default="," />
301                 </syntax>
302                 <description>
303                         <para>Example:</para>
304                         <para>exten => s,1,Set(array=one,two,three)</para>
305                         <para>exten => s,n,While($["${SET(var=${POP(array)})}" != ""])</para>
306                         <para>exten => s,n,NoOp(var is ${var})</para>
307                         <para>exten => s,n,EndWhile</para>
308                         <para>This would iterate over each value in array, right to left, and
309                                 would result in NoOp(var is three), NoOp(var is two), and
310                                 NoOp(var is one) being executed.
311                         </para>
312                 </description>
313         </function>     
314         <function name="PUSH" language="en_US">
315                 <synopsis>
316                         Appends one or more values to the end of a variable containing delimited text
317                 </synopsis>
318                 <syntax>
319                         <parameter name="varname" required="true" />
320                         <parameter name="delimiter" required="false" default="," />
321                 </syntax>
322                 <description>
323                         <para>Example: Set(PUSH(array)=one,two,three) would append one,
324                                 two, and three to the end of the values stored in the variable
325                                 "array".
326                         </para>
327                 </description>
328         </function>
329         <function name="UNSHIFT" language="en_US">
330                 <synopsis>
331                         Inserts one or more values to the beginning of a variable containing delimited text
332                 </synopsis>
333                 <syntax>
334                         <parameter name="varname" required="true" />
335                         <parameter name="delimiter" required="false" default="," />
336                 </syntax>
337                 <description>
338                         <para>Example: Set(UNSHIFT(array)=one,two,three) would insert one,
339                                 two, and three before the values stored in the variable
340                                 "array".
341                         </para>
342                 </description>
343         </function>
344  ***/
345
346 static int function_fieldqty_helper(struct ast_channel *chan, const char *cmd,
347                              char *parse, char *buf, struct ast_str **sbuf, ssize_t len)
348 {
349         char *varsubst;
350         struct ast_str *str = ast_str_create(16);
351         int fieldcount = 0;
352         AST_DECLARE_APP_ARGS(args,
353                              AST_APP_ARG(varname);
354                              AST_APP_ARG(delim);
355                 );
356         char delim[2] = "";
357         size_t delim_used;
358
359         if (!str) {
360                 return -1;
361         }
362
363         AST_STANDARD_APP_ARGS(args, parse);
364         if (args.delim) {
365                 ast_get_encoded_char(args.delim, delim, &delim_used);
366
367                 varsubst = alloca(strlen(args.varname) + 4);
368
369                 sprintf(varsubst, "${%s}", args.varname);
370                 ast_str_substitute_variables(&str, 0, chan, varsubst);
371                 if (ast_str_strlen(str) == 0) {
372                         fieldcount = 0;
373                 } else {
374                         char *varval = ast_str_buffer(str);
375                         while (strsep(&varval, delim)) {
376                                 fieldcount++;
377                         }
378                 }
379         } else {
380                 fieldcount = 1;
381         }
382         if (sbuf) {
383                 ast_str_set(sbuf, len, "%d", fieldcount);
384         } else {
385                 snprintf(buf, len, "%d", fieldcount);
386         }
387
388         ast_free(str);
389         return 0;
390 }
391
392 static int function_fieldqty(struct ast_channel *chan, const char *cmd,
393                              char *parse, char *buf, size_t len)
394 {
395         return function_fieldqty_helper(chan, cmd, parse, buf, NULL, len);
396 }
397
398 static int function_fieldqty_str(struct ast_channel *chan, const char *cmd,
399                                  char *parse, struct ast_str **buf, ssize_t len)
400 {
401         return function_fieldqty_helper(chan, cmd, parse, NULL, buf, len);
402 }
403
404 static struct ast_custom_function fieldqty_function = {
405         .name = "FIELDQTY",
406         .read = function_fieldqty,
407         .read2 = function_fieldqty_str,
408 };
409
410 static int listfilter(struct ast_channel *chan, const char *cmd, char *parse, char *buf, struct ast_str **bufstr, ssize_t len)
411 {
412         AST_DECLARE_APP_ARGS(args,
413                 AST_APP_ARG(listname);
414                 AST_APP_ARG(delimiter);
415                 AST_APP_ARG(fieldvalue);
416         );
417         const char *orig_list, *ptr;
418         const char *begin, *cur, *next;
419         int dlen, flen, first = 1;
420         struct ast_str *result, **result_ptr = &result;
421         char *delim;
422
423         AST_STANDARD_APP_ARGS(args, parse);
424
425         if (buf) {
426                 result = ast_str_thread_get(&result_buf, 16);
427         } else {
428                 /* Place the result directly into the output buffer */
429                 result_ptr = bufstr;
430         }
431
432         if (args.argc < 3) {
433                 ast_log(LOG_ERROR, "Usage: LISTFILTER(<listname>,<delimiter>,<fieldvalue>)\n");
434                 return -1;
435         }
436
437         /* If we don't lock the channel, the variable could disappear out from underneath us. */
438         if (chan) {
439                 ast_channel_lock(chan);
440         }
441         if (!(orig_list = pbx_builtin_getvar_helper(chan, args.listname))) {
442                 ast_log(LOG_ERROR, "List variable '%s' not found\n", args.listname);
443                 if (chan) {
444                         ast_channel_unlock(chan);
445                 }
446                 return -1;
447         }
448
449         /* If the string isn't there, just copy out the string and be done with it. */
450         if (!(ptr = strstr(orig_list, args.fieldvalue))) {
451                 if (buf) {
452                         ast_copy_string(buf, orig_list, len);
453                 } else {
454                         ast_str_set(result_ptr, len, "%s", orig_list);
455                 }
456                 if (chan) {
457                         ast_channel_unlock(chan);
458                 }
459                 return 0;
460         }
461
462         dlen = strlen(args.delimiter);
463         delim = alloca(dlen + 1);
464         ast_get_encoded_str(args.delimiter, delim, dlen + 1);
465
466         if ((dlen = strlen(delim)) == 0) {
467                 delim = ",";
468                 dlen = 1;
469         }
470
471         flen = strlen(args.fieldvalue);
472
473         ast_str_reset(result);
474         /* Enough space for any result */
475         if (len > -1) {
476                 ast_str_make_space(result_ptr, len ? len : strlen(orig_list) + 1);
477         }
478
479         begin = orig_list;
480         next = strstr(begin, delim);
481
482         do {
483                 /* Find next boundary */
484                 if (next) {
485                         cur = next;
486                         next = strstr(cur + dlen, delim);
487                 } else {
488                         cur = strchr(begin + dlen, '\0');
489                 }
490
491                 if (flen == cur - begin && !strncmp(begin, args.fieldvalue, flen)) {
492                         /* Skip field */
493                         begin += flen + dlen;
494                 } else {
495                         /* Copy field to output */
496                         if (!first) {
497                                 ast_str_append(result_ptr, len, "%s", delim);
498                         }
499
500                         ast_str_append_substr(result_ptr, len, begin, cur - begin + 1);
501                         first = 0;
502                         begin = cur + dlen;
503                 }
504         } while (*cur != '\0');
505         if (chan) {
506                 ast_channel_unlock(chan);
507         }
508
509         if (buf) {
510                 ast_copy_string(buf, ast_str_buffer(result), len);
511         }
512
513         return 0;
514 }
515
516 static int listfilter_read(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
517 {
518         return listfilter(chan, cmd, parse, buf, NULL, len);
519 }
520
521 static int listfilter_read2(struct ast_channel *chan, const char *cmd, char *parse, struct ast_str **buf, ssize_t len)
522 {
523         return listfilter(chan, cmd, parse, NULL, buf, len);
524 }
525
526 static struct ast_custom_function listfilter_function = {
527         .name = "LISTFILTER",
528         .read = listfilter_read,
529         .read2 = listfilter_read2,
530 };
531
532 static int filter(struct ast_channel *chan, const char *cmd, char *parse, char *buf,
533                   size_t len)
534 {
535         AST_DECLARE_APP_ARGS(args,
536                              AST_APP_ARG(allowed);
537                              AST_APP_ARG(string);
538         );
539         char *outbuf = buf, ac;
540         char allowed[256] = "";
541         size_t allowedlen = 0;
542
543         AST_STANDARD_APP_ARGS(args, parse);
544
545         if (!args.string) {
546                 ast_log(LOG_ERROR, "Usage: FILTER(<allowed-chars>,<string>)\n");
547                 return -1;
548         }
549
550         /* Expand ranges */
551         for (; *(args.allowed) && allowedlen < sizeof(allowed); ) {
552                 char c1 = 0, c2 = 0;
553                 size_t consumed = 0;
554
555                 if (ast_get_encoded_char(args.allowed, &c1, &consumed))
556                         return -1;
557                 args.allowed += consumed;
558
559                 if (*(args.allowed) == '-') {
560                         if (ast_get_encoded_char(args.allowed + 1, &c2, &consumed))
561                                 c2 = -1;
562                         args.allowed += consumed + 1;
563
564                         /*!\note
565                          * Looks a little strange, until you realize that we can overflow
566                          * the size of a char.
567                          */
568                         for (ac = c1; ac != c2 && allowedlen < sizeof(allowed) - 1; ac++)
569                                 allowed[allowedlen++] = ac;
570                         allowed[allowedlen++] = ac;
571
572                         ast_debug(4, "c1=%d, c2=%d\n", c1, c2);
573
574                         /* Decrement before the loop increment */
575                         (args.allowed)--;
576                 } else
577                         allowed[allowedlen++] = c1;
578         }
579
580         ast_debug(1, "Allowed: %s\n", allowed);
581
582         for (; *(args.string) && (buf + len - 1 > outbuf); (args.string)++) {
583                 if (strchr(allowed, *(args.string)))
584                         *outbuf++ = *(args.string);
585         }
586         *outbuf = '\0';
587
588         return 0;
589 }
590
591 static struct ast_custom_function filter_function = {
592         .name = "FILTER",
593         .read = filter,
594 };
595
596 static int regex(struct ast_channel *chan, const char *cmd, char *parse, char *buf,
597                  size_t len)
598 {
599         AST_DECLARE_APP_ARGS(args,
600                              AST_APP_ARG(null);
601                              AST_APP_ARG(reg);
602                              AST_APP_ARG(str);
603         );
604         int errcode;
605         regex_t regexbuf;
606
607         buf[0] = '\0';
608
609         AST_NONSTANDARD_APP_ARGS(args, parse, '"');
610
611         if (args.argc != 3) {
612                 ast_log(LOG_ERROR, "Unexpected arguments: should have been in the form '\"<regex>\" <string>'\n");
613                 return -1;
614         }
615         if ((*args.str == ' ') || (*args.str == '\t'))
616                 args.str++;
617
618         ast_debug(1, "FUNCTION REGEX (%s)(%s)\n", args.reg, args.str);
619
620         if ((errcode = regcomp(&regexbuf, args.reg, REG_EXTENDED | REG_NOSUB))) {
621                 regerror(errcode, &regexbuf, buf, len);
622                 ast_log(LOG_WARNING, "Malformed input %s(%s): %s\n", cmd, parse, buf);
623                 return -1;
624         }
625         
626         strcpy(buf, regexec(&regexbuf, args.str, 0, NULL, 0) ? "0" : "1");
627
628         regfree(&regexbuf);
629
630         return 0;
631 }
632
633 static struct ast_custom_function regex_function = {
634         .name = "REGEX",
635         .read = regex,
636 };
637
638 #define HASH_PREFIX     "~HASH~%s~"
639 #define HASH_FORMAT     HASH_PREFIX "%s~"
640
641 static char *app_clearhash = "ClearHash";
642
643 /* This function probably should migrate to main/pbx.c, as pbx_builtin_clearvar_prefix() */
644 static void clearvar_prefix(struct ast_channel *chan, const char *prefix)
645 {
646         struct ast_var_t *var;
647         int len = strlen(prefix);
648         AST_LIST_TRAVERSE_SAFE_BEGIN(&chan->varshead, var, entries) {
649                 if (strncasecmp(prefix, ast_var_name(var), len) == 0) {
650                         AST_LIST_REMOVE_CURRENT(entries);
651                         ast_free(var);
652                 }
653         }
654         AST_LIST_TRAVERSE_SAFE_END
655 }
656
657 static int exec_clearhash(struct ast_channel *chan, void *data)
658 {
659         char prefix[80];
660         snprintf(prefix, sizeof(prefix), HASH_PREFIX, data ? (char *)data : "null");
661         clearvar_prefix(chan, prefix);
662         return 0;
663 }
664
665 static int array(struct ast_channel *chan, const char *cmd, char *var,
666                  const char *value)
667 {
668         AST_DECLARE_APP_ARGS(arg1,
669                              AST_APP_ARG(var)[100];
670         );
671         AST_DECLARE_APP_ARGS(arg2,
672                              AST_APP_ARG(val)[100];
673         );
674         char *origvar = "", *value2, varname[256];
675         int i, ishash = 0;
676
677         value2 = ast_strdupa(value);
678         if (!var || !value2)
679                 return -1;
680
681         if (!strcmp(cmd, "HASH")) {
682                 const char *var2 = pbx_builtin_getvar_helper(chan, "~ODBCFIELDS~");
683                 origvar = var;
684                 if (var2)
685                         var = ast_strdupa(var2);
686                 else {
687                         if (chan)
688                                 ast_autoservice_stop(chan);
689                         return -1;
690                 }
691                 ishash = 1;
692         }
693
694         /* The functions this will generally be used with are SORT and ODBC_*, which
695          * both return comma-delimited lists.  However, if somebody uses literal lists,
696          * their commas will be translated to vertical bars by the load, and I don't
697          * want them to be surprised by the result.  Hence, we prefer commas as the
698          * delimiter, but we'll fall back to vertical bars if commas aren't found.
699          */
700         ast_debug(1, "array (%s=%s)\n", var, value2);
701         AST_STANDARD_APP_ARGS(arg1, var);
702
703         AST_STANDARD_APP_ARGS(arg2, value2);
704
705         for (i = 0; i < arg1.argc; i++) {
706                 ast_debug(1, "array set value (%s=%s)\n", arg1.var[i],
707                                 arg2.val[i]);
708                 if (i < arg2.argc) {
709                         if (ishash) {
710                                 snprintf(varname, sizeof(varname), HASH_FORMAT, origvar, arg1.var[i]);
711                                 pbx_builtin_setvar_helper(chan, varname, arg2.val[i]);
712                         } else {
713                                 pbx_builtin_setvar_helper(chan, arg1.var[i], arg2.val[i]);
714                         }
715                 } else {
716                         /* We could unset the variable, by passing a NULL, but due to
717                          * pushvar semantics, that could create some undesired behavior. */
718                         if (ishash) {
719                                 snprintf(varname, sizeof(varname), HASH_FORMAT, origvar, arg1.var[i]);
720                                 pbx_builtin_setvar_helper(chan, varname, "");
721                         } else {
722                                 pbx_builtin_setvar_helper(chan, arg1.var[i], "");
723                         }
724                 }
725         }
726
727         return 0;
728 }
729
730 static int hashkeys_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
731 {
732         struct ast_var_t *newvar;
733         struct ast_str *prefix = ast_str_alloca(80);
734
735         ast_str_set(&prefix, -1, HASH_PREFIX, data);
736         memset(buf, 0, len);
737
738         AST_LIST_TRAVERSE(&chan->varshead, newvar, entries) {
739                 if (strncasecmp(ast_str_buffer(prefix), ast_var_name(newvar), ast_str_strlen(prefix)) == 0) {
740                         /* Copy everything after the prefix */
741                         strncat(buf, ast_var_name(newvar) + ast_str_strlen(prefix), len - strlen(buf) - 1);
742                         /* Trim the trailing ~ */
743                         buf[strlen(buf) - 1] = ',';
744                 }
745         }
746         /* Trim the trailing comma */
747         buf[strlen(buf) - 1] = '\0';
748         return 0;
749 }
750
751 static int hashkeys_read2(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
752 {
753         struct ast_var_t *newvar;
754         struct ast_str *prefix = ast_str_alloca(80);
755         char *tmp;
756
757         ast_str_set(&prefix, -1, HASH_PREFIX, data);
758
759         AST_LIST_TRAVERSE(&chan->varshead, newvar, entries) {
760                 if (strncasecmp(ast_str_buffer(prefix), ast_var_name(newvar), ast_str_strlen(prefix)) == 0) {
761                         /* Copy everything after the prefix */
762                         ast_str_append(buf, len, "%s", ast_var_name(newvar) + ast_str_strlen(prefix));
763                         /* Trim the trailing ~ */
764                         tmp = ast_str_buffer(*buf);
765                         tmp[ast_str_strlen(*buf) - 1] = ',';
766                 }
767         }
768         /* Trim the trailing comma */
769         tmp = ast_str_buffer(*buf);
770         tmp[ast_str_strlen(*buf) - 1] = '\0';
771         return 0;
772 }
773
774 static int hash_write(struct ast_channel *chan, const char *cmd, char *var, const char *value)
775 {
776         char varname[256];
777         AST_DECLARE_APP_ARGS(arg,
778                 AST_APP_ARG(hashname);
779                 AST_APP_ARG(hashkey);
780         );
781
782         if (!strchr(var, ',')) {
783                 /* Single argument version */
784                 return array(chan, "HASH", var, value);
785         }
786
787         AST_STANDARD_APP_ARGS(arg, var);
788         snprintf(varname, sizeof(varname), HASH_FORMAT, arg.hashname, arg.hashkey);
789         pbx_builtin_setvar_helper(chan, varname, value);
790
791         return 0;
792 }
793
794 static int hash_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
795 {
796         char varname[256];
797         const char *varvalue;
798         AST_DECLARE_APP_ARGS(arg,
799                 AST_APP_ARG(hashname);
800                 AST_APP_ARG(hashkey);
801         );
802
803         AST_STANDARD_APP_ARGS(arg, data);
804         if (arg.argc == 2) {
805                 snprintf(varname, sizeof(varname), HASH_FORMAT, arg.hashname, arg.hashkey);
806                 varvalue = pbx_builtin_getvar_helper(chan, varname);
807                 if (varvalue)
808                         ast_copy_string(buf, varvalue, len);
809                 else
810                         *buf = '\0';
811         } else if (arg.argc == 1) {
812                 char colnames[4096];
813                 int i;
814                 AST_DECLARE_APP_ARGS(arg2,
815                         AST_APP_ARG(col)[100];
816                 );
817
818                 /* Get column names, in no particular order */
819                 hashkeys_read(chan, "HASHKEYS", arg.hashname, colnames, sizeof(colnames));
820                 pbx_builtin_setvar_helper(chan, "~ODBCFIELDS~", colnames);
821
822                 AST_STANDARD_APP_ARGS(arg2, colnames);
823                 *buf = '\0';
824
825                 /* Now get the corresponding column values, in exactly the same order */
826                 for (i = 0; i < arg2.argc; i++) {
827                         snprintf(varname, sizeof(varname), HASH_FORMAT, arg.hashname, arg2.col[i]);
828                         varvalue = pbx_builtin_getvar_helper(chan, varname);
829                         strncat(buf, varvalue, len - strlen(buf) - 1);
830                         strncat(buf, ",", len - strlen(buf) - 1);
831                 }
832
833                 /* Strip trailing comma */
834                 buf[strlen(buf) - 1] = '\0';
835         }
836
837         return 0;
838 }
839
840 static struct ast_custom_function hash_function = {
841         .name = "HASH",
842         .write = hash_write,
843         .read = hash_read,
844 };
845
846 static struct ast_custom_function hashkeys_function = {
847         .name = "HASHKEYS",
848         .read = hashkeys_read,
849         .read2 = hashkeys_read2,
850 };
851
852 static struct ast_custom_function array_function = {
853         .name = "ARRAY",
854         .write = array,
855 };
856
857 static int quote(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
858 {
859         char *bufptr = buf, *dataptr = data;
860         *bufptr++ = '"';
861         for (; bufptr < buf + len - 1; dataptr++) {
862                 if (*dataptr == '\\') {
863                         *bufptr++ = '\\';
864                         *bufptr++ = '\\';
865                 } else if (*dataptr == '"') {
866                         *bufptr++ = '\\';
867                         *bufptr++ = '"';
868                 } else if (*dataptr == '\0') {
869                         break;
870                 } else {
871                         *bufptr++ = *dataptr;
872                 }
873         }
874         *bufptr++ = '"';
875         *bufptr = '\0';
876         return 0;
877 }
878
879 static struct ast_custom_function quote_function = {
880         .name = "QUOTE",
881         .read = quote,
882 };
883
884
885 static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf,
886                size_t buflen)
887 {
888         int length = 0;
889
890         if (data)
891                 length = strlen(data);
892
893         snprintf(buf, buflen, "%d", length);
894
895         return 0;
896 }
897
898 static struct ast_custom_function len_function = {
899         .name = "LEN",
900         .read = len,
901         .read_max = 12,
902 };
903
904 static int acf_strftime(struct ast_channel *chan, const char *cmd, char *parse,
905                         char *buf, size_t buflen)
906 {
907         AST_DECLARE_APP_ARGS(args,
908                              AST_APP_ARG(epoch);
909                              AST_APP_ARG(timezone);
910                              AST_APP_ARG(format);
911         );
912         struct timeval when;
913         struct ast_tm tm;
914
915         buf[0] = '\0';
916
917         AST_STANDARD_APP_ARGS(args, parse);
918
919         ast_get_timeval(args.epoch, &when, ast_tvnow(), NULL);
920         ast_localtime(&when, &tm, args.timezone);
921
922         if (!args.format)
923                 args.format = "%c";
924
925         if (ast_strftime(buf, buflen, args.format, &tm) <= 0)
926                 ast_log(LOG_WARNING, "C function strftime() output nothing?!!\n");
927
928         buf[buflen - 1] = '\0';
929
930         return 0;
931 }
932
933 static struct ast_custom_function strftime_function = {
934         .name = "STRFTIME",
935         .read = acf_strftime,
936 };
937
938 static int acf_strptime(struct ast_channel *chan, const char *cmd, char *data,
939                         char *buf, size_t buflen)
940 {
941         AST_DECLARE_APP_ARGS(args,
942                              AST_APP_ARG(timestring);
943                              AST_APP_ARG(timezone);
944                              AST_APP_ARG(format);
945         );
946         struct ast_tm tm;
947
948         buf[0] = '\0';
949
950         if (!data) {
951                 ast_log(LOG_ERROR,
952                                 "Asterisk function STRPTIME() requires an argument.\n");
953                 return -1;
954         }
955
956         AST_STANDARD_APP_ARGS(args, data);
957
958         if (ast_strlen_zero(args.format)) {
959                 ast_log(LOG_ERROR,
960                                 "No format supplied to STRPTIME(<timestring>,<timezone>,<format>)");
961                 return -1;
962         }
963
964         if (!ast_strptime(args.timestring, args.format, &tm)) {
965                 ast_log(LOG_WARNING, "STRPTIME() found no time specified within the string\n");
966         } else {
967                 struct timeval when;
968                 when = ast_mktime(&tm, args.timezone);
969                 snprintf(buf, buflen, "%d", (int) when.tv_sec);
970         }
971
972         return 0;
973 }
974
975 static struct ast_custom_function strptime_function = {
976         .name = "STRPTIME",
977         .read = acf_strptime,
978 };
979
980 static int function_eval(struct ast_channel *chan, const char *cmd, char *data,
981                          char *buf, size_t buflen)
982 {
983         if (ast_strlen_zero(data)) {
984                 ast_log(LOG_WARNING, "EVAL requires an argument: EVAL(<string>)\n");
985                 return -1;
986         }
987
988         pbx_substitute_variables_helper(chan, data, buf, buflen - 1);
989
990         return 0;
991 }
992
993 static int function_eval2(struct ast_channel *chan, const char *cmd, char *data,
994                          struct ast_str **buf, ssize_t buflen)
995 {
996         if (ast_strlen_zero(data)) {
997                 ast_log(LOG_WARNING, "EVAL requires an argument: EVAL(<string>)\n");
998                 return -1;
999         }
1000
1001         ast_str_substitute_variables(buf, buflen, chan, data);
1002
1003         return 0;
1004 }
1005
1006 static struct ast_custom_function eval_function = {
1007         .name = "EVAL",
1008         .read = function_eval,
1009         .read2 = function_eval2,
1010 };
1011
1012 static int keypadhash(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
1013 {
1014         char *bufptr, *dataptr;
1015
1016         for (bufptr = buf, dataptr = data; bufptr < buf + buflen - 1; dataptr++) {
1017                 if (*dataptr == '\0') {
1018                         *bufptr++ = '\0';
1019                         break;
1020                 } else if (*dataptr == '1') {
1021                         *bufptr++ = '1';
1022                 } else if (strchr("AaBbCc2", *dataptr)) {
1023                         *bufptr++ = '2';
1024                 } else if (strchr("DdEeFf3", *dataptr)) {
1025                         *bufptr++ = '3';
1026                 } else if (strchr("GgHhIi4", *dataptr)) {
1027                         *bufptr++ = '4';
1028                 } else if (strchr("JjKkLl5", *dataptr)) {
1029                         *bufptr++ = '5';
1030                 } else if (strchr("MmNnOo6", *dataptr)) {
1031                         *bufptr++ = '6';
1032                 } else if (strchr("PpQqRrSs7", *dataptr)) {
1033                         *bufptr++ = '7';
1034                 } else if (strchr("TtUuVv8", *dataptr)) {
1035                         *bufptr++ = '8';
1036                 } else if (strchr("WwXxYyZz9", *dataptr)) {
1037                         *bufptr++ = '9';
1038                 } else if (*dataptr == '0') {
1039                         *bufptr++ = '0';
1040                 }
1041         }
1042         buf[buflen - 1] = '\0';
1043
1044         return 0;
1045 }
1046
1047 static struct ast_custom_function keypadhash_function = {
1048         .name = "KEYPADHASH",
1049         .read = keypadhash,
1050 };
1051
1052 static int string_toupper(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
1053 {
1054         char *bufptr = buf, *dataptr = data;
1055
1056         while ((bufptr < buf + buflen - 1) && (*bufptr++ = toupper(*dataptr++)));
1057
1058         return 0;
1059 }
1060
1061 static int string_toupper2(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t buflen)
1062 {
1063         char *bufptr, *dataptr = data;
1064
1065         if (buflen > -1) {
1066                 ast_str_make_space(buf, buflen > 0 ? buflen : strlen(data) + 1);
1067         }
1068         bufptr = ast_str_buffer(*buf);
1069         while ((bufptr < ast_str_buffer(*buf) + ast_str_size(*buf) - 1) && (*bufptr++ = toupper(*dataptr++)));
1070         ast_str_update(*buf);
1071
1072         return 0;
1073 }
1074
1075 static struct ast_custom_function toupper_function = {
1076         .name = "TOUPPER",
1077         .read = string_toupper,
1078         .read2 = string_toupper2,
1079 };
1080
1081 static int string_tolower(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
1082 {
1083         char *bufptr = buf, *dataptr = data;
1084
1085         while ((bufptr < buf + buflen - 1) && (*bufptr++ = tolower(*dataptr++)));
1086
1087         return 0;
1088 }
1089
1090 static int string_tolower2(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t buflen)
1091 {
1092         char *bufptr, *dataptr = data;
1093
1094         if (buflen > -1) {
1095                 ast_str_make_space(buf, buflen > 0 ? buflen : strlen(data) + 1);
1096         }
1097         bufptr = ast_str_buffer(*buf);
1098         while ((bufptr < ast_str_buffer(*buf) + ast_str_size(*buf) - 1) && (*bufptr++ = tolower(*dataptr++)));
1099         ast_str_update(*buf);
1100
1101         return 0;
1102 }
1103
1104 static struct ast_custom_function tolower_function = {
1105         .name = "TOLOWER",
1106         .read = string_tolower,
1107         .read2 = string_tolower2,
1108 };
1109
1110 static int array_remove(struct ast_channel *chan, const char *cmd, char *var, char *buf, size_t len, int beginning)
1111 {
1112         const char *tmp;
1113         char *after, *before;
1114         char *(*search_func)(const char *s, int c) = beginning ? strchr : strrchr;
1115         AST_DECLARE_APP_ARGS(args,
1116                 AST_APP_ARG(var);
1117                 AST_APP_ARG(delimiter);
1118         );
1119
1120         if (!chan) {
1121                 ast_log(LOG_WARNING, "%s requires a channel\n", cmd);
1122                 return -1;
1123         }
1124
1125         AST_STANDARD_APP_ARGS(args, var);
1126
1127         if (ast_strlen_zero(args.var)) {
1128                 ast_log(LOG_WARNING, "%s requires a channel variable name\n", cmd);
1129                 return -1;
1130         }
1131
1132         if (args.delimiter && strlen(args.delimiter) != 1) {
1133                 ast_log(LOG_WARNING, "%s delimeters should be a single character\n", cmd);
1134                 return -1;
1135         }
1136
1137         ast_channel_lock(chan);
1138         if (ast_strlen_zero(tmp = pbx_builtin_getvar_helper(chan, args.var))) {
1139                 ast_channel_unlock(chan);
1140                 return 0;
1141         }
1142
1143         before = ast_strdupa(tmp);
1144         ast_channel_unlock(chan);
1145
1146         /* Only one entry in array */
1147         if (!(after = search_func(before, S_OR(args.delimiter, ",")[0]))) {
1148                 ast_copy_string(buf, before, len);
1149                 pbx_builtin_setvar_helper(chan, args.var, "");
1150         } else {
1151                 *after++ = '\0';
1152                 ast_copy_string(buf, beginning ? before : after, len);
1153                 pbx_builtin_setvar_helper(chan, args.var, beginning ? after : before);
1154         }
1155
1156         return 0;
1157
1158 }
1159
1160 static int shift(struct ast_channel *chan, const char *cmd, char *var, char *buf, size_t len)
1161 {
1162         return array_remove(chan, cmd, var, buf, len, 1);
1163 }
1164 static struct ast_custom_function shift_function = {
1165         .name = "SHIFT",
1166         .read = shift,
1167 };
1168
1169 static int pop(struct ast_channel *chan, const char *cmd, char *var, char *buf, size_t len)
1170 {
1171         return array_remove(chan, cmd, var, buf, len, 0);
1172 }
1173
1174 static struct ast_custom_function pop_function = {
1175         .name = "POP",
1176         .read = pop,
1177 };
1178
1179 static int array_insert(struct ast_channel *chan, const char *cmd, char *var, const char *val, int beginning)
1180 {
1181         const char *tmp;
1182         struct ast_str *buf;
1183         AST_DECLARE_APP_ARGS(args,
1184                 AST_APP_ARG(var);
1185                 AST_APP_ARG(delimiter);
1186         );
1187
1188         if (!chan) {
1189                 ast_log(LOG_WARNING, "%s requires a channel\n", cmd);
1190                 return -1;
1191         }
1192
1193         AST_STANDARD_APP_ARGS(args, var);
1194
1195         if (ast_strlen_zero(args.var) || ast_strlen_zero(val)) {
1196                 ast_log(LOG_WARNING, "%s requires a variable, and at least one value\n", cmd);
1197                 return -1;
1198         }
1199
1200         if (args.delimiter && strlen(args.delimiter) != 1) {
1201                 ast_log(LOG_WARNING, "%s delimeters should be a single character\n", cmd);
1202                 return -1;
1203         }
1204
1205         if (!(buf = ast_str_create(32))) {
1206                 ast_log(LOG_ERROR, "Unable to allocate memory for buffer!\n");
1207                 return -1;
1208         }
1209
1210         ast_channel_lock(chan);
1211         if (!(tmp = pbx_builtin_getvar_helper(chan, args.var))) {
1212                 ast_str_set(&buf, 0, "%s", val);
1213         } else {
1214                 ast_str_append(&buf, 0, "%s%s%s", beginning ? val : tmp, S_OR(args.delimiter, ","), beginning ? tmp : val);
1215         }
1216         ast_channel_unlock(chan);
1217
1218         pbx_builtin_setvar_helper(chan, args.var, ast_str_buffer(buf));
1219         ast_free(buf);
1220
1221         return 0;
1222 }
1223
1224 static int push(struct ast_channel *chan, const char *cmd, char *var, const char *val)
1225 {
1226         return array_insert(chan, cmd, var, val, 0);
1227 }
1228
1229 static struct ast_custom_function push_function = {
1230         .name = "PUSH",
1231         .write = push,
1232 };
1233
1234 static int unshift(struct ast_channel *chan, const char *cmd, char *var, const char *val)
1235 {
1236         return array_insert(chan, cmd, var, val, 1);
1237 }
1238
1239 static struct ast_custom_function unshift_function = {
1240         .name = "UNSHIFT",
1241         .write = unshift,
1242 };
1243
1244 static int unload_module(void)
1245 {
1246         int res = 0;
1247
1248         res |= ast_custom_function_unregister(&fieldqty_function);
1249         res |= ast_custom_function_unregister(&filter_function);
1250         res |= ast_custom_function_unregister(&listfilter_function);
1251         res |= ast_custom_function_unregister(&regex_function);
1252         res |= ast_custom_function_unregister(&array_function);
1253         res |= ast_custom_function_unregister(&quote_function);
1254         res |= ast_custom_function_unregister(&len_function);
1255         res |= ast_custom_function_unregister(&strftime_function);
1256         res |= ast_custom_function_unregister(&strptime_function);
1257         res |= ast_custom_function_unregister(&eval_function);
1258         res |= ast_custom_function_unregister(&keypadhash_function);
1259         res |= ast_custom_function_unregister(&hashkeys_function);
1260         res |= ast_custom_function_unregister(&hash_function);
1261         res |= ast_unregister_application(app_clearhash);
1262         res |= ast_custom_function_unregister(&toupper_function);
1263         res |= ast_custom_function_unregister(&tolower_function);
1264         res |= ast_custom_function_unregister(&shift_function);
1265         res |= ast_custom_function_unregister(&pop_function);
1266         res |= ast_custom_function_unregister(&push_function);
1267         res |= ast_custom_function_unregister(&unshift_function);
1268
1269         return res;
1270 }
1271
1272 static int load_module(void)
1273 {
1274         int res = 0;
1275
1276         res |= ast_custom_function_register(&fieldqty_function);
1277         res |= ast_custom_function_register(&filter_function);
1278         res |= ast_custom_function_register(&listfilter_function);
1279         res |= ast_custom_function_register(&regex_function);
1280         res |= ast_custom_function_register(&array_function);
1281         res |= ast_custom_function_register(&quote_function);
1282         res |= ast_custom_function_register(&len_function);
1283         res |= ast_custom_function_register(&strftime_function);
1284         res |= ast_custom_function_register(&strptime_function);
1285         res |= ast_custom_function_register(&eval_function);
1286         res |= ast_custom_function_register(&keypadhash_function);
1287         res |= ast_custom_function_register(&hashkeys_function);
1288         res |= ast_custom_function_register(&hash_function);
1289         res |= ast_register_application_xml(app_clearhash, exec_clearhash);
1290         res |= ast_custom_function_register(&toupper_function);
1291         res |= ast_custom_function_register(&tolower_function);
1292         res |= ast_custom_function_register(&shift_function);
1293         res |= ast_custom_function_register(&pop_function);
1294         res |= ast_custom_function_register(&push_function);
1295         res |= ast_custom_function_register(&unshift_function);
1296
1297         return res;
1298 }
1299
1300 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "String handling dialplan functions");