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