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