Wed Aug 7 17:16:05 2019

Asterisk developer's documentation


func_strings.c File Reference

String manipulation dialplan functions. More...

#include "asterisk.h"
#include <regex.h>
#include <ctype.h>
#include "asterisk/module.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/utils.h"
#include "asterisk/app.h"
#include "asterisk/localtime.h"
#include "asterisk/test.h"

Go to the source code of this file.

Defines

#define beginning   (cmd[0] == 'U')
#define beginning   (cmd[0] == 'S')
#define HASH_FORMAT   HASH_PREFIX "%s~"
#define HASH_PREFIX   "~HASH~%s~"

Functions

static int acf_strftime (struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t buflen)
static int acf_strptime (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
static int array (struct ast_channel *chan, const char *cmd, char *var, const char *value)
 AST_MODULE_INFO_STANDARD (ASTERISK_GPL_KEY,"String handling dialplan functions")
 AST_THREADSTORAGE (tmp_buf)
 AST_THREADSTORAGE (result_buf)
static void clearvar_prefix (struct ast_channel *chan, const char *prefix)
static int csv_quote (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static int exec_clearhash (struct ast_channel *chan, const char *data)
static int filter (struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
static int function_eval (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
static int function_eval2 (struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t buflen)
static int function_fieldnum (struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
static int function_fieldnum_helper (struct ast_channel *chan, const char *cmd, char *parse, char *buf, struct ast_str **sbuf, ssize_t len)
static int function_fieldnum_str (struct ast_channel *chan, const char *cmd, char *parse, struct ast_str **buf, ssize_t len)
static int function_fieldqty (struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
static int function_fieldqty_helper (struct ast_channel *chan, const char *cmd, char *parse, char *buf, struct ast_str **sbuf, ssize_t len)
static int function_fieldqty_str (struct ast_channel *chan, const char *cmd, char *parse, struct ast_str **buf, ssize_t len)
static int hash_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static int hash_write (struct ast_channel *chan, const char *cmd, char *var, const char *value)
static int hashkeys_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static int hashkeys_read2 (struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
static int keypadhash (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
static int len (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
static int listfilter (struct ast_channel *chan, const char *cmd, char *parse, char *buf, struct ast_str **bufstr, ssize_t len)
static int listfilter_read (struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
static int listfilter_read2 (struct ast_channel *chan, const char *cmd, char *parse, struct ast_str **buf, ssize_t len)
static int load_module (void)
static int passthru (struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
static int quote (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static int regex (struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
static int replace (struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
static int shift_pop (struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
static int string_tolower (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
static int string_tolower2 (struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t buflen)
static int string_toupper (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
static int string_toupper2 (struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t buflen)
static int unload_module (void)
static int unshift_push (struct ast_channel *chan, const char *cmd, char *data, const char *new_value)

Variables

static char * app_clearhash = "ClearHash"
static struct ast_custom_function array_function
static struct ast_custom_function csv_quote_function
static struct ast_custom_function eval_function
static struct ast_custom_function fieldnum_function
static struct ast_custom_function fieldqty_function
static struct ast_custom_function filter_function
static struct ast_custom_function hash_function
static struct ast_custom_function hashkeys_function
static struct ast_custom_function keypadhash_function
static struct ast_custom_function len_function
static struct ast_custom_function listfilter_function
static struct ast_custom_function passthru_function
static struct ast_custom_function pop_function
static struct ast_custom_function push_function
static struct ast_custom_function quote_function
static struct ast_custom_function regex_function
static struct ast_custom_function replace_function
static struct ast_custom_function shift_function
static struct ast_custom_function strftime_function
static struct ast_custom_function strptime_function
static struct ast_custom_function tolower_function
static struct ast_custom_function toupper_function
static struct ast_custom_function unshift_function

Detailed Description

String manipulation dialplan functions.

Author:
Tilghman Lesher
Anothony Minessale II

Definition in file func_strings.c.


Define Documentation

#define beginning   (cmd[0] == 'U')
#define beginning   (cmd[0] == 'S')

Referenced by shift_pop(), and unshift_push().

#define HASH_FORMAT   HASH_PREFIX "%s~"

Definition at line 887 of file func_strings.c.

Referenced by array(), hash_read(), and hash_write().

#define HASH_PREFIX   "~HASH~%s~"

Definition at line 886 of file func_strings.c.

Referenced by exec_clearhash(), hashkeys_read(), and hashkeys_read2().


Function Documentation

static int acf_strftime ( struct ast_channel chan,
const char *  cmd,
char *  parse,
char *  buf,
size_t  buflen 
) [static]

Definition at line 1230 of file func_strings.c.

References args, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_get_timeval(), ast_localtime(), ast_log(), AST_STANDARD_APP_ARGS, ast_strftime(), ast_tvnow(), format, and LOG_WARNING.

01232 {
01233    AST_DECLARE_APP_ARGS(args,
01234               AST_APP_ARG(epoch);
01235               AST_APP_ARG(timezone);
01236               AST_APP_ARG(format);
01237    );
01238    struct timeval when;
01239    struct ast_tm tm;
01240 
01241    buf[0] = '\0';
01242 
01243    AST_STANDARD_APP_ARGS(args, parse);
01244 
01245    ast_get_timeval(args.epoch, &when, ast_tvnow(), NULL);
01246    ast_localtime(&when, &tm, args.timezone);
01247 
01248    if (!args.format)
01249       args.format = "%c";
01250 
01251    if (ast_strftime(buf, buflen, args.format, &tm) <= 0)
01252       ast_log(LOG_WARNING, "C function strftime() output nothing?!!\n");
01253 
01254    buf[buflen - 1] = '\0';
01255 
01256    return 0;
01257 }

static int acf_strptime ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  buflen 
) [static]

Definition at line 1264 of file func_strings.c.

References args, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), ast_mktime(), AST_STANDARD_APP_ARGS, ast_strlen_zero(), ast_strptime(), format, LOG_ERROR, and LOG_WARNING.

01266 {
01267    AST_DECLARE_APP_ARGS(args,
01268               AST_APP_ARG(timestring);
01269               AST_APP_ARG(timezone);
01270               AST_APP_ARG(format);
01271    );
01272    struct ast_tm tm;
01273 
01274    buf[0] = '\0';
01275 
01276    if (!data) {
01277       ast_log(LOG_ERROR,
01278             "Asterisk function STRPTIME() requires an argument.\n");
01279       return -1;
01280    }
01281 
01282    AST_STANDARD_APP_ARGS(args, data);
01283 
01284    if (ast_strlen_zero(args.format)) {
01285       ast_log(LOG_ERROR,
01286             "No format supplied to STRPTIME(<timestring>,<timezone>,<format>)");
01287       return -1;
01288    }
01289 
01290    if (!ast_strptime(args.timestring, args.format, &tm)) {
01291       ast_log(LOG_WARNING, "STRPTIME() found no time specified within the string\n");
01292    } else {
01293       struct timeval when;
01294       when = ast_mktime(&tm, args.timezone);
01295       snprintf(buf, buflen, "%d", (int) when.tv_sec);
01296    }
01297 
01298    return 0;
01299 }

static int array ( struct ast_channel chan,
const char *  cmd,
char *  var,
const char *  value 
) [static]

Definition at line 913 of file func_strings.c.

References AST_APP_ARG, ast_autoservice_stop(), ast_debug, AST_DECLARE_APP_ARGS, AST_STANDARD_APP_ARGS, ast_strdupa, HASH_FORMAT, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), and S_OR.

Referenced by hash_write().

00915 {
00916    AST_DECLARE_APP_ARGS(arg1,
00917               AST_APP_ARG(var)[100];
00918    );
00919    AST_DECLARE_APP_ARGS(arg2,
00920               AST_APP_ARG(val)[100];
00921    );
00922    char *origvar = "", *value2, varname[256];
00923    int i, ishash = 0;
00924 
00925    if (!var) {
00926       return -1;
00927    }
00928    value2 = ast_strdupa(value);
00929 
00930    if (!strcmp(cmd, "HASH")) {
00931       const char *var2 = pbx_builtin_getvar_helper(chan, "~ODBCFIELDS~");
00932       origvar = var;
00933       if (var2)
00934          var = ast_strdupa(var2);
00935       else {
00936          if (chan)
00937             ast_autoservice_stop(chan);
00938          return -1;
00939       }
00940       ishash = 1;
00941    }
00942 
00943    /* The functions this will generally be used with are SORT and ODBC_*, which
00944     * both return comma-delimited lists.  However, if somebody uses literal lists,
00945     * their commas will be translated to vertical bars by the load, and I don't
00946     * want them to be surprised by the result.  Hence, we prefer commas as the
00947     * delimiter, but we'll fall back to vertical bars if commas aren't found.
00948     */
00949    ast_debug(1, "array (%s=%s)\n", var, S_OR(value2, ""));
00950    AST_STANDARD_APP_ARGS(arg1, var);
00951 
00952    AST_STANDARD_APP_ARGS(arg2, value2);
00953 
00954    for (i = 0; i < arg1.argc; i++) {
00955       ast_debug(1, "array set value (%s=%s)\n", arg1.var[i],
00956             S_OR(arg2.val[i], ""));
00957       if (i < arg2.argc) {
00958          if (ishash) {
00959             if (origvar[0] == '_') {
00960                if (origvar[1] == '_') {
00961                   snprintf(varname, sizeof(varname), "__" HASH_FORMAT, origvar + 2, arg1.var[i]);
00962                } else {
00963                   snprintf(varname, sizeof(varname), "_" HASH_FORMAT, origvar + 1, arg1.var[i]);
00964                }
00965             } else {
00966                snprintf(varname, sizeof(varname), HASH_FORMAT, origvar, arg1.var[i]);
00967             }
00968 
00969             pbx_builtin_setvar_helper(chan, varname, arg2.val[i]);
00970          } else {
00971             pbx_builtin_setvar_helper(chan, arg1.var[i], arg2.val[i]);
00972          }
00973       } else {
00974          /* We could unset the variable, by passing a NULL, but due to
00975           * pushvar semantics, that could create some undesired behavior. */
00976          if (ishash) {
00977             snprintf(varname, sizeof(varname), HASH_FORMAT, origvar, arg1.var[i]);
00978             pbx_builtin_setvar_helper(chan, varname, "");
00979          } else {
00980             pbx_builtin_setvar_helper(chan, arg1.var[i], "");
00981          }
00982       }
00983    }
00984 
00985    return 0;
00986 }

AST_MODULE_INFO_STANDARD ( ASTERISK_GPL_KEY  ,
"String handling dialplan functions"   
)
AST_THREADSTORAGE ( tmp_buf   ) 
AST_THREADSTORAGE ( result_buf   ) 
static void clearvar_prefix ( struct ast_channel chan,
const char *  prefix 
) [static]

Definition at line 892 of file func_strings.c.

References ast_free, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_var_name(), len(), var, and ast_channel::varshead.

Referenced by exec_clearhash().

00893 {
00894    struct ast_var_t *var;
00895    int len = strlen(prefix);
00896    AST_LIST_TRAVERSE_SAFE_BEGIN(&chan->varshead, var, entries) {
00897       if (strncasecmp(prefix, ast_var_name(var), len) == 0) {
00898          AST_LIST_REMOVE_CURRENT(entries);
00899          ast_free(var);
00900       }
00901    }
00902    AST_LIST_TRAVERSE_SAFE_END
00903 }

static int csv_quote ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
) [static]

Definition at line 1177 of file func_strings.c.

References ast_copy_string(), ast_log(), ast_strlen_zero(), and LOG_ERROR.

01178 {
01179    char *bufptr = buf, *dataptr = data;
01180 
01181    if (len < 3) { /* at least two for quotes and one for binary zero */
01182       ast_log(LOG_ERROR, "Not enough buffer\n");
01183       return -1;
01184    }
01185 
01186    if (ast_strlen_zero(data)) {
01187       ast_copy_string(buf, "\"\"", len);
01188       return 0;
01189    }
01190 
01191    *bufptr++ = '"';
01192    for (; bufptr < buf + len - 3; dataptr++){
01193       if (*dataptr == '"') {
01194          *bufptr++ = '"';
01195          *bufptr++ = '"';
01196       } else if (*dataptr == '\0') {
01197          break;
01198       } else {
01199          *bufptr++ = *dataptr;
01200       }
01201    }
01202    *bufptr++ = '"';
01203    *bufptr='\0';
01204    return 0;
01205 }

static int exec_clearhash ( struct ast_channel chan,
const char *  data 
) [static]

Definition at line 905 of file func_strings.c.

References clearvar_prefix(), HASH_PREFIX, and prefix.

Referenced by load_module().

00906 {
00907    char prefix[80];
00908    snprintf(prefix, sizeof(prefix), HASH_PREFIX, data ? (char *)data : "null");
00909    clearvar_prefix(chan, prefix);
00910    return 0;
00911 }

static int filter ( struct ast_channel chan,
const char *  cmd,
char *  parse,
char *  buf,
size_t  len 
) [static]

Note:
Looks a little strange, until you realize that we can overflow the size of a char.

Definition at line 694 of file func_strings.c.

References args, AST_APP_ARG, ast_debug, AST_DECLARE_APP_ARGS, ast_get_encoded_char(), ast_log(), ast_opt_dont_warn, AST_STANDARD_RAW_ARGS, LOG_ERROR, and LOG_WARNING.

Referenced by __ast_data_add(), data_filter_destructor(), data_filter_generate(), data_result_generate(), manager_data_get(), realtime_ldap_base_ap(), set_egress_subscription(), update2_ldap(), and update_ldap().

00696 {
00697    AST_DECLARE_APP_ARGS(args,
00698               AST_APP_ARG(allowed);
00699               AST_APP_ARG(string);
00700    );
00701    char *outbuf = buf;
00702    unsigned char ac;
00703    char allowed[256] = "";
00704    size_t allowedlen = 0;
00705    int32_t bitfield[8] = { 0, }; /* 256 bits */
00706 
00707    AST_STANDARD_RAW_ARGS(args, parse);
00708 
00709    if (!args.string) {
00710       ast_log(LOG_ERROR, "Usage: FILTER(<allowed-chars>,<string>)\n");
00711       return -1;
00712    }
00713 
00714    if (args.allowed[0] == '"' && !ast_opt_dont_warn) {
00715       ast_log(LOG_WARNING, "FILTER allowed characters includes the quote (\") character.  This may not be what you want.\n");
00716    }
00717 
00718    /* Expand ranges */
00719    for (; *(args.allowed);) {
00720       char c1 = 0, c2 = 0;
00721       size_t consumed = 0;
00722 
00723       if (ast_get_encoded_char(args.allowed, &c1, &consumed))
00724          return -1;
00725       args.allowed += consumed;
00726 
00727       if (*(args.allowed) == '-') {
00728          if (ast_get_encoded_char(args.allowed + 1, &c2, &consumed))
00729             c2 = c1;
00730          args.allowed += consumed + 1;
00731 
00732          if ((unsigned char) c2 < (unsigned char) c1 && !ast_opt_dont_warn) {
00733             ast_log(LOG_WARNING, "Range wrapping in FILTER(%s,%s).  This may not be what you want.\n", parse, args.string);
00734          }
00735 
00736          /*!\note
00737           * Looks a little strange, until you realize that we can overflow
00738           * the size of a char.
00739           */
00740          for (ac = (unsigned char) c1; ac != (unsigned char) c2; ac++) {
00741             bitfield[ac / 32] |= 1 << (ac % 32);
00742          }
00743          bitfield[ac / 32] |= 1 << (ac % 32);
00744 
00745          ast_debug(4, "c1=%d, c2=%d\n", c1, c2);
00746       } else {
00747          ac = (unsigned char) c1;
00748          ast_debug(4, "c1=%d, consumed=%d, args.allowed=%s\n", c1, (int) consumed, args.allowed - consumed);
00749          bitfield[ac / 32] |= 1 << (ac % 32);
00750       }
00751    }
00752 
00753    for (ac = 1; ac != 0; ac++) {
00754       if (bitfield[ac / 32] & (1 << (ac % 32))) {
00755          allowed[allowedlen++] = ac;
00756       }
00757    }
00758 
00759    ast_debug(1, "Allowed: %s\n", allowed);
00760 
00761    for (; *(args.string) && (buf + len - 1 > outbuf); (args.string)++) {
00762       if (strchr(allowed, *(args.string)))
00763          *outbuf++ = *(args.string);
00764    }
00765    *outbuf = '\0';
00766 
00767    return 0;
00768 }

static int function_eval ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  buflen 
) [static]

Definition at line 1306 of file func_strings.c.

References ast_log(), ast_strlen_zero(), LOG_WARNING, and pbx_substitute_variables_helper().

01308 {
01309    if (ast_strlen_zero(data)) {
01310       ast_log(LOG_WARNING, "EVAL requires an argument: EVAL(<string>)\n");
01311       return -1;
01312    }
01313 
01314    pbx_substitute_variables_helper(chan, data, buf, buflen - 1);
01315 
01316    return 0;
01317 }

static int function_eval2 ( struct ast_channel chan,
const char *  cmd,
char *  data,
struct ast_str **  buf,
ssize_t  buflen 
) [static]

Definition at line 1319 of file func_strings.c.

References ast_log(), ast_str_substitute_variables(), ast_strlen_zero(), and LOG_WARNING.

01321 {
01322    if (ast_strlen_zero(data)) {
01323       ast_log(LOG_WARNING, "EVAL requires an argument: EVAL(<string>)\n");
01324       return -1;
01325    }
01326 
01327    ast_str_substitute_variables(buf, buflen, chan, data);
01328 
01329    return 0;
01330 }

static int function_fieldnum ( struct ast_channel chan,
const char *  cmd,
char *  parse,
char *  buf,
size_t  len 
) [static]

Definition at line 548 of file func_strings.c.

References function_fieldnum_helper().

00550 {
00551    return function_fieldnum_helper(chan, cmd, parse, buf, NULL, len);
00552 }

static int function_fieldnum_helper ( struct ast_channel chan,
const char *  cmd,
char *  parse,
char *  buf,
struct ast_str **  sbuf,
ssize_t  len 
) [static]

Definition at line 487 of file func_strings.c.

References args, ast_alloca, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_get_encoded_char(), ast_log(), AST_STANDARD_APP_ARGS, ast_str_buffer(), ast_str_set(), ast_str_strlen(), ast_str_substitute_variables(), ast_str_thread_get(), ast_strlen_zero(), LOG_ERROR, result_buf, and str.

Referenced by function_fieldnum(), and function_fieldnum_str().

00489 {
00490    char *varsubst, *field;
00491    struct ast_str *str = ast_str_thread_get(&result_buf, 16);
00492    int fieldindex = 0, res = 0;
00493    AST_DECLARE_APP_ARGS(args,
00494       AST_APP_ARG(varname);
00495       AST_APP_ARG(delim);
00496       AST_APP_ARG(field);
00497    );
00498    char delim[2] = "";
00499    size_t delim_used;
00500 
00501    if (!str) {
00502       return -1;
00503    }
00504 
00505    AST_STANDARD_APP_ARGS(args, parse);
00506 
00507    if (args.argc < 3) {
00508       ast_log(LOG_ERROR, "Usage: FIELDNUM(<listname>,<delimiter>,<fieldvalue>)\n");
00509       res = -1;
00510    } else {
00511       varsubst = ast_alloca(strlen(args.varname) + 4);
00512       sprintf(varsubst, "${%s}", args.varname);
00513 
00514       ast_str_substitute_variables(&str, 0, chan, varsubst);
00515 
00516       if (ast_str_strlen(str) == 0 || ast_strlen_zero(args.delim)) {
00517          fieldindex = 0;
00518       } else if (ast_get_encoded_char(args.delim, delim, &delim_used) == -1) {
00519          res = -1;
00520       } else {
00521          char *varval = ast_str_buffer(str);
00522 
00523          while ((field = strsep(&varval, delim)) != NULL) {
00524             fieldindex++;
00525 
00526             if (!strcasecmp(field, args.field)) {
00527                break;
00528             }
00529          }
00530 
00531          if (!field) {
00532             fieldindex = 0;
00533          }
00534 
00535          res = 0;
00536       }
00537    }
00538 
00539    if (sbuf) {
00540       ast_str_set(sbuf, len, "%d", fieldindex);
00541    } else {
00542       snprintf(buf, len, "%d", fieldindex);
00543    }
00544 
00545    return res;
00546 }

static int function_fieldnum_str ( struct ast_channel chan,
const char *  cmd,
char *  parse,
struct ast_str **  buf,
ssize_t  len 
) [static]

Definition at line 554 of file func_strings.c.

References function_fieldnum_helper().

00556 {
00557    return function_fieldnum_helper(chan, cmd, parse, NULL, buf, len);
00558 }

static int function_fieldqty ( struct ast_channel chan,
const char *  cmd,
char *  parse,
char *  buf,
size_t  len 
) [static]

Definition at line 469 of file func_strings.c.

References function_fieldqty_helper().

00471 {
00472    return function_fieldqty_helper(chan, cmd, parse, buf, NULL, len);
00473 }

static int function_fieldqty_helper ( struct ast_channel chan,
const char *  cmd,
char *  parse,
char *  buf,
struct ast_str **  sbuf,
ssize_t  len 
) [static]

Definition at line 424 of file func_strings.c.

References args, ast_alloca, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_get_encoded_char(), AST_STANDARD_APP_ARGS, ast_str_buffer(), ast_str_set(), ast_str_strlen(), ast_str_substitute_variables(), ast_str_thread_get(), result_buf, and str.

Referenced by function_fieldqty(), and function_fieldqty_str().

00426 {
00427    char *varsubst;
00428    struct ast_str *str = ast_str_thread_get(&result_buf, 16);
00429    int fieldcount = 0;
00430    AST_DECLARE_APP_ARGS(args,
00431               AST_APP_ARG(varname);
00432               AST_APP_ARG(delim);
00433       );
00434    char delim[2] = "";
00435    size_t delim_used;
00436 
00437    if (!str) {
00438       return -1;
00439    }
00440 
00441    AST_STANDARD_APP_ARGS(args, parse);
00442    if (args.delim) {
00443       ast_get_encoded_char(args.delim, delim, &delim_used);
00444 
00445       varsubst = ast_alloca(strlen(args.varname) + 4);
00446 
00447       sprintf(varsubst, "${%s}", args.varname);
00448       ast_str_substitute_variables(&str, 0, chan, varsubst);
00449       if (ast_str_strlen(str) == 0) {
00450          fieldcount = 0;
00451       } else {
00452          char *varval = ast_str_buffer(str);
00453          while (strsep(&varval, delim)) {
00454             fieldcount++;
00455          }
00456       }
00457    } else {
00458       fieldcount = 1;
00459    }
00460    if (sbuf) {
00461       ast_str_set(sbuf, len, "%d", fieldcount);
00462    } else {
00463       snprintf(buf, len, "%d", fieldcount);
00464    }
00465 
00466    return 0;
00467 }

static int function_fieldqty_str ( struct ast_channel chan,
const char *  cmd,
char *  parse,
struct ast_str **  buf,
ssize_t  len 
) [static]

Definition at line 475 of file func_strings.c.

References function_fieldqty_helper().

00477 {
00478    return function_fieldqty_helper(chan, cmd, parse, NULL, buf, len);
00479 }

static int hash_read ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
) [static]

Definition at line 1070 of file func_strings.c.

References AST_APP_ARG, ast_copy_string(), AST_DECLARE_APP_ARGS, ast_log(), AST_STANDARD_APP_ARGS, HASH_FORMAT, hashkeys_read(), LOG_WARNING, pbx_builtin_getvar_helper(), and pbx_builtin_setvar_helper().

01071 {
01072    char varname[256];
01073    const char *varvalue;
01074    AST_DECLARE_APP_ARGS(arg,
01075       AST_APP_ARG(hashname);
01076       AST_APP_ARG(hashkey);
01077    );
01078 
01079    AST_STANDARD_APP_ARGS(arg, data);
01080    if (arg.argc == 2) {
01081       snprintf(varname, sizeof(varname), HASH_FORMAT, arg.hashname, arg.hashkey);
01082       varvalue = pbx_builtin_getvar_helper(chan, varname);
01083       if (varvalue)
01084          ast_copy_string(buf, varvalue, len);
01085       else
01086          *buf = '\0';
01087    } else if (arg.argc == 1) {
01088       char colnames[4096];
01089       int i;
01090       AST_DECLARE_APP_ARGS(arg2,
01091          AST_APP_ARG(col)[100];
01092       );
01093 
01094       if (!chan) {
01095          ast_log(LOG_WARNING, "No channel and only 1 parameter was provided to %s function.\n", cmd);
01096          return -1;
01097       }
01098 
01099       /* Get column names, in no particular order */
01100       hashkeys_read(chan, "HASHKEYS", arg.hashname, colnames, sizeof(colnames));
01101       pbx_builtin_setvar_helper(chan, "~ODBCFIELDS~", colnames);
01102 
01103       AST_STANDARD_APP_ARGS(arg2, colnames);
01104       *buf = '\0';
01105 
01106       /* Now get the corresponding column values, in exactly the same order */
01107       for (i = 0; i < arg2.argc; i++) {
01108          snprintf(varname, sizeof(varname), HASH_FORMAT, arg.hashname, arg2.col[i]);
01109          varvalue = pbx_builtin_getvar_helper(chan, varname);
01110          strncat(buf, varvalue, len - strlen(buf) - 1);
01111          strncat(buf, ",", len - strlen(buf) - 1);
01112       }
01113 
01114       /* Strip trailing comma */
01115       buf[strlen(buf) - 1] = '\0';
01116    }
01117 
01118    return 0;
01119 }

static int hash_write ( struct ast_channel chan,
const char *  cmd,
char *  var,
const char *  value 
) [static]

Definition at line 1042 of file func_strings.c.

References array(), AST_APP_ARG, AST_DECLARE_APP_ARGS, AST_STANDARD_APP_ARGS, HASH_FORMAT, and pbx_builtin_setvar_helper().

01043 {
01044    char varname[256];
01045    AST_DECLARE_APP_ARGS(arg,
01046       AST_APP_ARG(hashname);
01047       AST_APP_ARG(hashkey);
01048    );
01049 
01050    if (!strchr(var, ',')) {
01051       /* Single argument version */
01052       return array(chan, "HASH", var, value);
01053    }
01054 
01055    AST_STANDARD_APP_ARGS(arg, var);
01056    if (arg.hashname[0] == '_') {
01057       if (arg.hashname[1] == '_') {
01058          snprintf(varname, sizeof(varname), "__" HASH_FORMAT, arg.hashname + 2, arg.hashkey);
01059       } else {
01060          snprintf(varname, sizeof(varname), "_" HASH_FORMAT, arg.hashname + 1, arg.hashkey);
01061       }
01062    } else {
01063       snprintf(varname, sizeof(varname), HASH_FORMAT, arg.hashname, arg.hashkey);
01064    }
01065    pbx_builtin_setvar_helper(chan, varname, value);
01066 
01067    return 0;
01068 }

static int hashkeys_read ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
) [static]

Definition at line 988 of file func_strings.c.

References AST_LIST_TRAVERSE, ast_log(), ast_str_alloca, ast_str_buffer(), ast_str_set(), ast_str_strlen(), ast_var_name(), HASH_PREFIX, LOG_WARNING, prefix, and ast_channel::varshead.

Referenced by hash_read().

00989 {
00990    struct ast_var_t *newvar;
00991    struct ast_str *prefix = ast_str_alloca(80);
00992 
00993    if (!chan) {
00994       ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
00995       return -1;
00996    }
00997 
00998    ast_str_set(&prefix, -1, HASH_PREFIX, data);
00999    memset(buf, 0, len);
01000 
01001    AST_LIST_TRAVERSE(&chan->varshead, newvar, entries) {
01002       if (strncasecmp(ast_str_buffer(prefix), ast_var_name(newvar), ast_str_strlen(prefix)) == 0) {
01003          /* Copy everything after the prefix */
01004          strncat(buf, ast_var_name(newvar) + ast_str_strlen(prefix), len - strlen(buf) - 1);
01005          /* Trim the trailing ~ */
01006          buf[strlen(buf) - 1] = ',';
01007       }
01008    }
01009    /* Trim the trailing comma */
01010    buf[strlen(buf) - 1] = '\0';
01011    return 0;
01012 }

static int hashkeys_read2 ( struct ast_channel chan,
const char *  cmd,
char *  data,
struct ast_str **  buf,
ssize_t  len 
) [static]

Definition at line 1014 of file func_strings.c.

References AST_LIST_TRAVERSE, ast_log(), ast_str_alloca, ast_str_append(), ast_str_buffer(), ast_str_set(), ast_str_strlen(), ast_var_name(), HASH_PREFIX, LOG_WARNING, prefix, and ast_channel::varshead.

01015 {
01016    struct ast_var_t *newvar;
01017    struct ast_str *prefix = ast_str_alloca(80);
01018    char *tmp;
01019 
01020    if (!chan) {
01021       ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
01022       return -1;
01023    }
01024 
01025    ast_str_set(&prefix, -1, HASH_PREFIX, data);
01026 
01027    AST_LIST_TRAVERSE(&chan->varshead, newvar, entries) {
01028       if (strncasecmp(ast_str_buffer(prefix), ast_var_name(newvar), ast_str_strlen(prefix)) == 0) {
01029          /* Copy everything after the prefix */
01030          ast_str_append(buf, len, "%s", ast_var_name(newvar) + ast_str_strlen(prefix));
01031          /* Trim the trailing ~ */
01032          tmp = ast_str_buffer(*buf);
01033          tmp[ast_str_strlen(*buf) - 1] = ',';
01034       }
01035    }
01036    /* Trim the trailing comma */
01037    tmp = ast_str_buffer(*buf);
01038    tmp[ast_str_strlen(*buf) - 1] = '\0';
01039    return 0;
01040 }

static int keypadhash ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  buflen 
) [static]

Definition at line 1338 of file func_strings.c.

01339 {
01340    char *bufptr, *dataptr;
01341 
01342    for (bufptr = buf, dataptr = data; bufptr < buf + buflen - 1; dataptr++) {
01343       if (*dataptr == '\0') {
01344          *bufptr++ = '\0';
01345          break;
01346       } else if (*dataptr == '1') {
01347          *bufptr++ = '1';
01348       } else if (strchr("AaBbCc2", *dataptr)) {
01349          *bufptr++ = '2';
01350       } else if (strchr("DdEeFf3", *dataptr)) {
01351          *bufptr++ = '3';
01352       } else if (strchr("GgHhIi4", *dataptr)) {
01353          *bufptr++ = '4';
01354       } else if (strchr("JjKkLl5", *dataptr)) {
01355          *bufptr++ = '5';
01356       } else if (strchr("MmNnOo6", *dataptr)) {
01357          *bufptr++ = '6';
01358       } else if (strchr("PpQqRrSs7", *dataptr)) {
01359          *bufptr++ = '7';
01360       } else if (strchr("TtUuVv8", *dataptr)) {
01361          *bufptr++ = '8';
01362       } else if (strchr("WwXxYyZz9", *dataptr)) {
01363          *bufptr++ = '9';
01364       } else if (*dataptr == '0') {
01365          *bufptr++ = '0';
01366       }
01367    }
01368    buf[buflen - 1] = '\0';
01369 
01370    return 0;
01371 }

static int len ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  buflen 
) [static]

Definition at line 1212 of file func_strings.c.

Referenced by __analog_ss_thread(), __ast_cli_register(), __ast_str_helper(), __get_header(), __rtp_recvfrom(), __rtp_sendto(), _parse(), add_sdp(), ael_token_subst(), aji_io_recv(), aji_recv(), aji_send_header(), aji_send_raw(), aji_start_sasl(), alsa_write(), analog_ss_thread(), aoc_parse_ie(), append_interface(), append_var_and_value_to_filter(), ast_agi_register_multiple(), ast_agi_unregister_multiple(), ast_app_group_set_channel(), ast_callerid_vmwi_generate(), ast_cdr_appenduserfield(), ast_cli_complete(), ast_codec_get_len(), ast_complete_source_filename(), ast_dsp_noise(), ast_dsp_process(), ast_dsp_silence(), ast_event_cb(), ast_format_str_reduce(), ast_frdup(), ast_getformatname_multiple(), ast_http_send(), ast_http_uri_link(), ast_mkdir(), ast_read_image(), ast_rtcp_write_rr(), ast_rtcp_write_sr(), ast_rtp_read(), ast_say_number_full_ka(), ast_smoother_read(), ast_str_buffer(), ast_str_substitute_variables_full(), ast_translate(), ast_udptl_write(), ast_xml_escape(), ast_xmldoc_printable(), auth_exec(), authenticate(), build_device(), build_facility(), build_route(), callerid_generate(), cleaned_basedn(), clearvar_prefix(), cli_console_sendtext(), complete_agent_logoff_cmd(), complete_confno(), complete_dialplan_add_extension(), complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_extension(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), complete_meetmecmd_list(), complete_meetmecmd_mute_kick(), complete_peer_helper(), complete_trans_path_choice(), complete_userno(), conf_play(), config_jitterbuffer(), cops_getmsg(), copy(), create_video_frame(), dahdi_sendtext(), dahdi_setoption(), devstate_write(), dialgroup_refreshdb(), dictate_exec(), do_pktccops(), dundi_encrypt(), dundi_parse_ies(), dundi_send(), enc_ie_facility(), evt_event_deliver_cb(), expand_gosub_args(), expr2_token_subst(), ext_cmp_exten_strlen(), ffmpeg_decode(), find_by_part(), get_body(), get_ip_and_port_from_sdp(), get_sdp(), get_sdp_iterate(), get_to_address(), gsm_write(), gsmtolin_framein(), h261_encap(), h263_encap(), h263_read(), h263_write(), h263p_encap(), h264_read(), h264_write(), handle_cli_core_show_translation(), handle_cli_devstate_change(), handle_commandmatchesarray(), handle_incoming(), handle_message(), handle_output(), handle_response(), handle_show_sysinfo(), help1(), iax_parse_ies(), iax_str2flags(), launch_monitor_thread(), listener(), load_file(), local_call(), lpc10tolin_framein(), lws2sws(), message_template_parse_emailbody(), method_match(), mgcp_ss(), mgcpsock_read(), misdn_read(), monmp3thread(), mpeg4_encap(), newpvt(), parse_ie(), ParseBookmark(), pbx_substitute_variables_helper_full(), phoneprov_callback(), process_sdp(), read_credentials(), readfile_exec(), red_t140_to_red(), reschedule_precache(), run_agi(), scan_thread(), schedule_delivery(), set(), set_egress_subscription(), sip_addheader(), sip_show_channel(), sip_show_history(), skinny_ss(), sms_messagetx(), socket_process_meta(), socket_read(), static_callback(), term_filter_escapes(), transfer_exec(), try_firmware(), udptl_build_packet(), unistim_sp(), unquote(), wav_write(), and xmldoc_get_syntax_fun().

01213 {
01214    int length = 0;
01215 
01216    if (data)
01217       length = strlen(data);
01218 
01219    snprintf(buf, buflen, "%d", length);
01220 
01221    return 0;
01222 }

static int listfilter ( struct ast_channel chan,
const char *  cmd,
char *  parse,
char *  buf,
struct ast_str **  bufstr,
ssize_t  len 
) [static]

Definition at line 566 of file func_strings.c.

References args, ast_alloca, AST_APP_ARG, ast_channel_lock, ast_channel_unlock, ast_copy_string(), AST_DECLARE_APP_ARGS, ast_get_encoded_str(), ast_log(), AST_STANDARD_APP_ARGS, ast_str_append(), ast_str_append_substr(), ast_str_buffer(), ast_str_make_space(), ast_str_reset(), ast_str_set(), ast_str_strlen(), ast_str_substitute_variables(), ast_str_thread_get(), first, LOG_ERROR, and result_buf.

Referenced by listfilter_read(), and listfilter_read2().

00567 {
00568    AST_DECLARE_APP_ARGS(args,
00569       AST_APP_ARG(listname);
00570       AST_APP_ARG(delimiter);
00571       AST_APP_ARG(fieldvalue);
00572    );
00573    struct ast_str *orig_list = ast_str_thread_get(&tmp_buf, 16);
00574    const char *begin, *cur, *next;
00575    int dlen, flen, first = 1;
00576    struct ast_str *result, **result_ptr = &result;
00577    char *delim, *varsubst;
00578 
00579    AST_STANDARD_APP_ARGS(args, parse);
00580 
00581    if (buf) {
00582       if (!(result = ast_str_thread_get(&result_buf, 16))) {
00583          return -1;
00584       }
00585    } else {
00586       /* Place the result directly into the output buffer */
00587       result_ptr = bufstr;
00588    }
00589 
00590    if (args.argc < 3) {
00591       ast_log(LOG_ERROR, "Usage: LISTFILTER(<listname>,<delimiter>,<fieldvalue>)\n");
00592       return -1;
00593    }
00594 
00595    varsubst = ast_alloca(strlen(args.listname) + 4);
00596    sprintf(varsubst, "${%s}", args.listname);
00597 
00598    /* If we don't lock the channel, the variable could disappear out from underneath us. */
00599    if (chan) {
00600       ast_channel_lock(chan);
00601    }
00602    ast_str_substitute_variables(&orig_list, 0, chan, varsubst);
00603    if (!ast_str_strlen(orig_list)) {
00604       ast_log(LOG_ERROR, "List variable '%s' not found\n", args.listname);
00605       if (chan) {
00606          ast_channel_unlock(chan);
00607       }
00608       return -1;
00609    }
00610 
00611    /* If the string isn't there, just copy out the string and be done with it. */
00612    if (!strstr(ast_str_buffer(orig_list), args.fieldvalue)) {
00613       if (buf) {
00614          ast_copy_string(buf, ast_str_buffer(orig_list), len);
00615       } else {
00616          ast_str_set(result_ptr, len, "%s", ast_str_buffer(orig_list));
00617       }
00618       if (chan) {
00619          ast_channel_unlock(chan);
00620       }
00621       return 0;
00622    }
00623 
00624    dlen = strlen(args.delimiter);
00625    delim = ast_alloca(dlen + 1);
00626    ast_get_encoded_str(args.delimiter, delim, dlen + 1);
00627 
00628    if ((dlen = strlen(delim)) == 0) {
00629       delim = ",";
00630       dlen = 1;
00631    }
00632 
00633    flen = strlen(args.fieldvalue);
00634 
00635    ast_str_reset(*result_ptr);
00636    /* Enough space for any result */
00637    if (len > -1) {
00638       ast_str_make_space(result_ptr, len ? len : ast_str_strlen(orig_list) + 1);
00639    }
00640 
00641    begin = ast_str_buffer(orig_list);
00642    next = strstr(begin, delim);
00643 
00644    do {
00645       /* Find next boundary */
00646       if (next) {
00647          cur = next;
00648          next = strstr(cur + dlen, delim);
00649       } else {
00650          cur = strchr(begin + dlen, '\0');
00651       }
00652 
00653       if (flen == cur - begin && !strncmp(begin, args.fieldvalue, flen)) {
00654          /* Skip field */
00655          begin += flen + dlen;
00656       } else {
00657          /* Copy field to output */
00658          if (!first) {
00659             ast_str_append(result_ptr, len, "%s", delim);
00660          }
00661 
00662          ast_str_append_substr(result_ptr, len, begin, cur - begin);
00663          first = 0;
00664          begin = cur + dlen;
00665       }
00666    } while (*cur != '\0');
00667    if (chan) {
00668       ast_channel_unlock(chan);
00669    }
00670 
00671    if (buf) {
00672       ast_copy_string(buf, ast_str_buffer(result), len);
00673    }
00674 
00675    return 0;
00676 }

static int listfilter_read ( struct ast_channel chan,
const char *  cmd,
char *  parse,
char *  buf,
size_t  len 
) [static]

Definition at line 678 of file func_strings.c.

References listfilter().

00679 {
00680    return listfilter(chan, cmd, parse, buf, NULL, len);
00681 }

static int listfilter_read2 ( struct ast_channel chan,
const char *  cmd,
char *  parse,
struct ast_str **  buf,
ssize_t  len 
) [static]

Definition at line 683 of file func_strings.c.

References listfilter().

00684 {
00685    return listfilter(chan, cmd, parse, NULL, buf, len);
00686 }

static int load_module ( void   )  [static]

Definition at line 1785 of file func_strings.c.

References ast_custom_function_register, ast_register_application_xml, AST_TEST_REGISTER, and exec_clearhash().

01786 {
01787    int res = 0;
01788 
01789    AST_TEST_REGISTER(test_FIELDNUM);
01790    AST_TEST_REGISTER(test_REPLACE);
01791    AST_TEST_REGISTER(test_FILTER);
01792    res |= ast_custom_function_register(&fieldqty_function);
01793    res |= ast_custom_function_register(&fieldnum_function);
01794    res |= ast_custom_function_register(&filter_function);
01795    res |= ast_custom_function_register(&replace_function);
01796    res |= ast_custom_function_register(&listfilter_function);
01797    res |= ast_custom_function_register(&regex_function);
01798    res |= ast_custom_function_register(&array_function);
01799    res |= ast_custom_function_register(&quote_function);
01800    res |= ast_custom_function_register(&csv_quote_function);
01801    res |= ast_custom_function_register(&len_function);
01802    res |= ast_custom_function_register(&strftime_function);
01803    res |= ast_custom_function_register(&strptime_function);
01804    res |= ast_custom_function_register(&eval_function);
01805    res |= ast_custom_function_register(&keypadhash_function);
01806    res |= ast_custom_function_register(&hashkeys_function);
01807    res |= ast_custom_function_register(&hash_function);
01808    res |= ast_register_application_xml(app_clearhash, exec_clearhash);
01809    res |= ast_custom_function_register(&toupper_function);
01810    res |= ast_custom_function_register(&tolower_function);
01811    res |= ast_custom_function_register(&shift_function);
01812    res |= ast_custom_function_register(&pop_function);
01813    res |= ast_custom_function_register(&push_function);
01814    res |= ast_custom_function_register(&unshift_function);
01815    res |= ast_custom_function_register(&passthru_function);
01816 
01817    return res;
01818 }

static int passthru ( struct ast_channel chan,
const char *  cmd,
char *  data,
struct ast_str **  buf,
ssize_t  len 
) [static]

Definition at line 1560 of file func_strings.c.

References ast_str_set().

01561 {
01562    ast_str_set(buf, len, "%s", data);
01563    return 0;
01564 }

static int quote ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
) [static]

Definition at line 1138 of file func_strings.c.

References ast_copy_string(), ast_log(), ast_strlen_zero(), LOG_ERROR, and LOG_WARNING.

Referenced by __ast_app_separate_args(), and parse_options().

01139 {
01140    char *bufptr = buf, *dataptr = data;
01141 
01142    if (len < 3){ /* at least two for quotes and one for binary zero */
01143       ast_log(LOG_ERROR, "Not enough buffer\n");
01144       return -1;
01145    }
01146 
01147    if (ast_strlen_zero(data)) {
01148       ast_log(LOG_WARNING, "No argument specified!\n");
01149       ast_copy_string(buf, "\"\"", len);
01150       return 0;
01151    }
01152 
01153    *bufptr++ = '"';
01154    for (; bufptr < buf + len - 3; dataptr++) {
01155       if (*dataptr == '\\') {
01156          *bufptr++ = '\\';
01157          *bufptr++ = '\\';
01158       } else if (*dataptr == '"') {
01159          *bufptr++ = '\\';
01160          *bufptr++ = '"';
01161       } else if (*dataptr == '\0') {
01162          break;
01163       } else {
01164          *bufptr++ = *dataptr;
01165       }
01166    }
01167    *bufptr++ = '"';
01168    *bufptr = '\0';
01169    return 0;
01170 }

static int regex ( struct ast_channel chan,
const char *  cmd,
char *  parse,
char *  buf,
size_t  len 
) [static]

Definition at line 844 of file func_strings.c.

References args, AST_APP_ARG, ast_debug, AST_DECLARE_APP_ARGS, ast_log(), AST_NONSTANDARD_APP_ARGS, LOG_ERROR, LOG_WARNING, and str.

00846 {
00847    AST_DECLARE_APP_ARGS(args,
00848               AST_APP_ARG(null);
00849               AST_APP_ARG(reg);
00850               AST_APP_ARG(str);
00851    );
00852    int errcode;
00853    regex_t regexbuf;
00854 
00855    buf[0] = '\0';
00856 
00857    AST_NONSTANDARD_APP_ARGS(args, parse, '"');
00858 
00859    if (args.argc != 3) {
00860       ast_log(LOG_ERROR, "Unexpected arguments: should have been in the form '\"<regex>\" <string>'\n");
00861       return -1;
00862    }
00863    if ((*args.str == ' ') || (*args.str == '\t'))
00864       args.str++;
00865 
00866    ast_debug(1, "FUNCTION REGEX (%s)(%s)\n", args.reg, args.str);
00867 
00868    if ((errcode = regcomp(&regexbuf, args.reg, REG_EXTENDED | REG_NOSUB))) {
00869       regerror(errcode, &regexbuf, buf, len);
00870       ast_log(LOG_WARNING, "Malformed input %s(%s): %s\n", cmd, parse, buf);
00871       return -1;
00872    }
00873    
00874    strcpy(buf, regexec(&regexbuf, args.str, 0, NULL, 0) ? "0" : "1");
00875 
00876    regfree(&regexbuf);
00877 
00878    return 0;
00879 }

static int replace ( struct ast_channel chan,
const char *  cmd,
char *  data,
struct ast_str **  buf,
ssize_t  len 
) [static]

Definition at line 775 of file func_strings.c.

References args, ast_alloca, AST_APP_ARG, ast_debug, AST_DECLARE_APP_ARGS, ast_free, ast_get_encoded_char(), ast_get_encoded_str(), ast_log(), AST_STANDARD_APP_ARGS, ast_str_buffer(), ast_str_create(), ast_str_set(), ast_str_strlen(), ast_str_substitute_variables(), ast_strlen_zero(), LOG_ERROR, RAII_VAR, and str.

Referenced by process_text_line().

00776 {
00777    AST_DECLARE_APP_ARGS(args,
00778       AST_APP_ARG(varname);
00779       AST_APP_ARG(find);
00780       AST_APP_ARG(replace);
00781    );
00782    char *strptr, *varsubst;
00783    RAII_VAR(struct ast_str *, str, ast_str_create(16), ast_free);
00784    char find[256]; /* Only 256 characters possible */
00785    char replace[2] = "";
00786    size_t unused;
00787 
00788    AST_STANDARD_APP_ARGS(args, data);
00789 
00790    if (!str) {
00791       return -1;
00792    }
00793 
00794    if (args.argc < 2) {
00795       ast_log(LOG_ERROR, "Usage: %s(<varname>,<search-chars>[,<replace-char>])\n", cmd);
00796       return -1;
00797    }
00798 
00799    /* Decode escapes */
00800    ast_get_encoded_str(args.find, find, sizeof(find));
00801    ast_get_encoded_char(args.replace, replace, &unused);
00802 
00803    if (ast_strlen_zero(find) || ast_strlen_zero(args.varname)) {
00804       ast_log(LOG_ERROR, "The characters to search for and the variable name must not be empty.\n");
00805       return -1;
00806    }
00807 
00808    varsubst = ast_alloca(strlen(args.varname) + 4);
00809    sprintf(varsubst, "${%s}", args.varname);
00810    ast_str_substitute_variables(&str, 0, chan, varsubst);
00811 
00812    if (!ast_str_strlen(str)) {
00813       /* Blank, nothing to replace */
00814       return -1;
00815    }
00816 
00817    ast_debug(3, "String to search: (%s)\n", ast_str_buffer(str));
00818    ast_debug(3, "Characters to find: (%s)\n", find);
00819    ast_debug(3, "Character to replace with: (%s)\n", replace);
00820 
00821    for (strptr = ast_str_buffer(str); *strptr; strptr++) {
00822       /* buf is already a mutable buffer, so we construct the result
00823        * directly there */
00824       if (strchr(find, *strptr)) {
00825          if (ast_strlen_zero(replace)) {
00826             memmove(strptr, strptr + 1, strlen(strptr + 1) + 1);
00827             strptr--;
00828          } else {
00829             /* Replace character */
00830             *strptr = *replace;
00831          }
00832       }
00833    }
00834 
00835    ast_str_set(buf, len, "%s", ast_str_buffer(str));
00836    return 0;
00837 }

static int shift_pop ( struct ast_channel chan,
const char *  cmd,
char *  data,
struct ast_str **  buf,
ssize_t  len 
) [static]

Definition at line 1436 of file func_strings.c.

References args, ast_alloca, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_get_encoded_char(), ast_log(), AST_STANDARD_APP_ARGS, ast_str_buffer(), ast_str_set(), ast_str_strlen(), ast_str_substitute_variables(), ast_str_thread_get(), ast_strlen_zero(), beginning, LOG_WARNING, pbx_builtin_setvar_helper(), result_buf, and var.

01437 {
01438 #define beginning (cmd[0] == 'S') /* SHIFT */
01439    char *after, delimiter[2] = ",", *varsubst;
01440    size_t unused;
01441    struct ast_str *before = ast_str_thread_get(&result_buf, 16);
01442    char *(*search_func)(const char *s, int c) = (beginning ? strchr : strrchr);
01443    AST_DECLARE_APP_ARGS(args,
01444       AST_APP_ARG(var);
01445       AST_APP_ARG(delimiter);
01446    );
01447 
01448    if (!before) {
01449       return -1;
01450    }
01451 
01452    AST_STANDARD_APP_ARGS(args, data);
01453 
01454    if (ast_strlen_zero(args.var)) {
01455       ast_log(LOG_WARNING, "%s requires a variable name\n", cmd);
01456       return -1;
01457    }
01458 
01459    varsubst = ast_alloca(strlen(args.var) + 4);
01460    sprintf(varsubst, "${%s}", args.var);
01461    ast_str_substitute_variables(&before, 0, chan, varsubst);
01462 
01463    if (args.argc > 1 && !ast_strlen_zero(args.delimiter)) {
01464       ast_get_encoded_char(args.delimiter, delimiter, &unused);
01465    }
01466 
01467    if (!ast_str_strlen(before)) {
01468       /* Nothing to pop */
01469       return -1;
01470    }
01471 
01472    if (!(after = search_func(ast_str_buffer(before), delimiter[0]))) {
01473       /* Only one entry in array */
01474       ast_str_set(buf, len, "%s", ast_str_buffer(before));
01475       pbx_builtin_setvar_helper(chan, args.var, "");
01476    } else {
01477       *after++ = '\0';
01478       ast_str_set(buf, len, "%s", beginning ? ast_str_buffer(before) : after);
01479       pbx_builtin_setvar_helper(chan, args.var, beginning ? after : ast_str_buffer(before));
01480    }
01481 
01482    return 0;
01483 #undef beginning
01484 }

static int string_tolower ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  buflen 
) [static]

Definition at line 1407 of file func_strings.c.

01408 {
01409    char *bufptr = buf, *dataptr = data;
01410 
01411    while ((bufptr < buf + buflen - 1) && (*bufptr++ = tolower(*dataptr++)));
01412 
01413    return 0;
01414 }

static int string_tolower2 ( struct ast_channel chan,
const char *  cmd,
char *  data,
struct ast_str **  buf,
ssize_t  buflen 
) [static]

Definition at line 1416 of file func_strings.c.

References ast_str_buffer(), ast_str_make_space(), ast_str_size(), and ast_str_update().

01417 {
01418    char *bufptr, *dataptr = data;
01419 
01420    if (buflen > -1) {
01421       ast_str_make_space(buf, buflen > 0 ? buflen : strlen(data) + 1);
01422    }
01423    bufptr = ast_str_buffer(*buf);
01424    while ((bufptr < ast_str_buffer(*buf) + ast_str_size(*buf) - 1) && (*bufptr++ = tolower(*dataptr++)));
01425    ast_str_update(*buf);
01426 
01427    return 0;
01428 }

static int string_toupper ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  buflen 
) [static]

Definition at line 1378 of file func_strings.c.

01379 {
01380    char *bufptr = buf, *dataptr = data;
01381 
01382    while ((bufptr < buf + buflen - 1) && (*bufptr++ = toupper(*dataptr++)));
01383 
01384    return 0;
01385 }

static int string_toupper2 ( struct ast_channel chan,
const char *  cmd,
char *  data,
struct ast_str **  buf,
ssize_t  buflen 
) [static]

Definition at line 1387 of file func_strings.c.

References ast_str_buffer(), ast_str_make_space(), ast_str_size(), and ast_str_update().

01388 {
01389    char *bufptr, *dataptr = data;
01390 
01391    if (buflen > -1) {
01392       ast_str_make_space(buf, buflen > 0 ? buflen : strlen(data) + 1);
01393    }
01394    bufptr = ast_str_buffer(*buf);
01395    while ((bufptr < ast_str_buffer(*buf) + ast_str_size(*buf) - 1) && (*bufptr++ = toupper(*dataptr++)));
01396    ast_str_update(*buf);
01397 
01398    return 0;
01399 }

static int unload_module ( void   )  [static]

Definition at line 1750 of file func_strings.c.

References ast_custom_function_unregister(), AST_TEST_UNREGISTER, and ast_unregister_application().

01751 {
01752    int res = 0;
01753 
01754    AST_TEST_UNREGISTER(test_FIELDNUM);
01755    AST_TEST_UNREGISTER(test_REPLACE);
01756    AST_TEST_UNREGISTER(test_FILTER);
01757    res |= ast_custom_function_unregister(&fieldqty_function);
01758    res |= ast_custom_function_unregister(&fieldnum_function);
01759    res |= ast_custom_function_unregister(&filter_function);
01760    res |= ast_custom_function_unregister(&replace_function);
01761    res |= ast_custom_function_unregister(&listfilter_function);
01762    res |= ast_custom_function_unregister(&regex_function);
01763    res |= ast_custom_function_unregister(&array_function);
01764    res |= ast_custom_function_unregister(&quote_function);
01765    res |= ast_custom_function_unregister(&csv_quote_function);
01766    res |= ast_custom_function_unregister(&len_function);
01767    res |= ast_custom_function_unregister(&strftime_function);
01768    res |= ast_custom_function_unregister(&strptime_function);
01769    res |= ast_custom_function_unregister(&eval_function);
01770    res |= ast_custom_function_unregister(&keypadhash_function);
01771    res |= ast_custom_function_unregister(&hashkeys_function);
01772    res |= ast_custom_function_unregister(&hash_function);
01773    res |= ast_unregister_application(app_clearhash);
01774    res |= ast_custom_function_unregister(&toupper_function);
01775    res |= ast_custom_function_unregister(&tolower_function);
01776    res |= ast_custom_function_unregister(&shift_function);
01777    res |= ast_custom_function_unregister(&pop_function);
01778    res |= ast_custom_function_unregister(&push_function);
01779    res |= ast_custom_function_unregister(&unshift_function);
01780    res |= ast_custom_function_unregister(&passthru_function);
01781 
01782    return res;
01783 }

static int unshift_push ( struct ast_channel chan,
const char *  cmd,
char *  data,
const char *  new_value 
) [static]

Definition at line 1496 of file func_strings.c.

References args, ast_alloca, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_get_encoded_char(), ast_log(), AST_STANDARD_APP_ARGS, ast_str_buffer(), ast_str_set(), ast_str_strlen(), ast_str_substitute_variables(), ast_str_thread_get(), ast_strlen_zero(), beginning, LOG_WARNING, MIN, pbx_builtin_setvar_helper(), result_buf, and var.

01497 {
01498 #define beginning (cmd[0] == 'U') /* UNSHIFT */
01499    char delimiter[2] = ",", *varsubst;
01500    size_t unused;
01501    struct ast_str *buf, *previous_value;
01502    AST_DECLARE_APP_ARGS(args,
01503       AST_APP_ARG(var);
01504       AST_APP_ARG(delimiter);
01505    );
01506    const char *stripped_var;
01507 
01508    if (!(buf = ast_str_thread_get(&result_buf, 16)) ||
01509       !(previous_value = ast_str_thread_get(&tmp_buf, 16))) {
01510       return -1;
01511    }
01512 
01513    AST_STANDARD_APP_ARGS(args, data);
01514 
01515    if (ast_strlen_zero(args.var)) {
01516       ast_log(LOG_WARNING, "%s requires a variable name\n", cmd);
01517       return -1;
01518    }
01519 
01520    if (args.argc > 1 && !ast_strlen_zero(args.delimiter)) {
01521       ast_get_encoded_char(args.delimiter, delimiter, &unused);
01522    }
01523 
01524    /* UNSHIFT and PUSH act as ways of setting a variable, so we need to be
01525     * sure to skip leading underscores if they appear. However, we only want
01526     * to skip up to two since that is the maximum number that can be used to
01527     * indicate variable inheritance. Any further underscores are part of the
01528     * variable name.
01529     */
01530    stripped_var = args.var + MIN(strspn(args.var, "_"), 2);
01531    varsubst = ast_alloca(strlen(stripped_var) + 4);
01532    sprintf(varsubst, "${%s}", stripped_var);
01533    ast_str_substitute_variables(&previous_value, 0, chan, varsubst);
01534 
01535    if (!ast_str_strlen(previous_value)) {
01536       ast_str_set(&buf, 0, "%s", new_value);
01537    } else {
01538       ast_str_set(&buf, 0, "%s%c%s",
01539          beginning ? new_value : ast_str_buffer(previous_value),
01540          delimiter[0],
01541          beginning ? ast_str_buffer(previous_value) : new_value);
01542    }
01543 
01544    pbx_builtin_setvar_helper(chan, args.var, ast_str_buffer(buf));
01545 
01546    return 0;
01547 #undef beginning
01548 }


Variable Documentation

char* app_clearhash = "ClearHash" [static]

Definition at line 889 of file func_strings.c.

Initial value:
 {
   .name = "ARRAY",
   .write = array,
}

Definition at line 1133 of file func_strings.c.

Initial value:
 {
   .name = "CSV_QUOTE",
   .read = csv_quote,
}

Definition at line 1207 of file func_strings.c.

Initial value:
 {
   .name = "EVAL",
   .read = function_eval,
   .read2 = function_eval2,
}

Definition at line 1332 of file func_strings.c.

Initial value:
 {
   .name = "FIELDNUM",
   .read = function_fieldnum,
   .read2 = function_fieldnum_str,
}

Definition at line 560 of file func_strings.c.

Initial value:
 {
   .name = "FIELDQTY",
   .read = function_fieldqty,
   .read2 = function_fieldqty_str,
}

Definition at line 481 of file func_strings.c.

Initial value:
 {
   .name = "FILTER",
   .read = filter,
}

Definition at line 770 of file func_strings.c.

Initial value:
 {
   .name = "HASH",
   .write = hash_write,
   .read = hash_read,
}

Definition at line 1121 of file func_strings.c.

Initial value:
 {
   .name = "HASHKEYS",
   .read = hashkeys_read,
   .read2 = hashkeys_read2,
}

Definition at line 1127 of file func_strings.c.

Initial value:
 {
   .name = "KEYPADHASH",
   .read = keypadhash,
}

Definition at line 1373 of file func_strings.c.

Initial value:
 {
   .name = "LEN",
   .read = len,
   .read_max = 12,
}

Definition at line 1224 of file func_strings.c.

Initial value:
 {
   .name = "LISTFILTER",
   .read = listfilter_read,
   .read2 = listfilter_read2,
}

Definition at line 688 of file func_strings.c.

Initial value:
 {
   .name = "PASSTHRU",
   .read2 = passthru,
}

Definition at line 1566 of file func_strings.c.

Initial value:
 {
   .name = "POP",
   .read2 = shift_pop,
}

Definition at line 1491 of file func_strings.c.

Initial value:
 {
   .name = "PUSH",
   .write = unshift_push,
}

Definition at line 1550 of file func_strings.c.

Initial value:
 {
   .name = "QUOTE",
   .read = quote,
}

Definition at line 1172 of file func_strings.c.

Initial value:
 {
   .name = "REGEX",
   .read = regex,
}

Definition at line 881 of file func_strings.c.

Initial value:
 {
   .name = "REPLACE",
   .read2 = replace,
}

Definition at line 839 of file func_strings.c.

Initial value:
 {
   .name = "SHIFT",
   .read2 = shift_pop,
}

Definition at line 1486 of file func_strings.c.

Initial value:
 {
   .name = "STRFTIME",
   .read = acf_strftime,
}

Definition at line 1259 of file func_strings.c.

Initial value:
 {
   .name = "STRPTIME",
   .read = acf_strptime,
}

Definition at line 1301 of file func_strings.c.

Initial value:
 {
   .name = "TOLOWER",
   .read = string_tolower,
   .read2 = string_tolower2,
}

Definition at line 1430 of file func_strings.c.

Initial value:
 {
   .name = "TOUPPER",
   .read = string_toupper,
   .read2 = string_toupper2,
}

Definition at line 1401 of file func_strings.c.

Initial value:
 {
   .name = "UNSHIFT",
   .write = unshift_push,
}

Definition at line 1555 of file func_strings.c.


Generated on 7 Aug 2019 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1