Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:47:54 2009

## Asterisk developer's documentation

# func_strings.c

Go to the documentation of this file.

    00001 /*
    00002  * Asterisk -- An open source telephony toolkit.
    00003  *
    00004  * Copyright (C) 2005, Digium, Inc.
    00005  * Portions Copyright (C) 2005, Tilghman Lesher.  All rights reserved.
    00006  * Portions Copyright (C) 2005, Anthony Minessale II
    00007  *
    00008  * See http://www.asterisk.org for more information about
    00009  * the Asterisk project. Please do not directly contact
    00010  * any of the maintainers of this project for assistance;
    00011  * the project provides a web site, mailing lists and IRC
    00012  * channels for your use.
    00013  *
    00014  * This program is free software, distributed under the terms of
    00015  * the GNU General Public License Version 2. See the LICENSE file
    00016  * at the top of the source tree.
    00017  */
    00018
    00019 /*! \file
    00020  *
    00021  * \brief String manipulation dialplan functions
    00022  *
    00023  */
    00024
    00025 #include <stdlib.h>
    00026 #include <stdio.h>
    00027 #include <string.h>
    00028 #include <sys/types.h>
    00029 #include <regex.h>
    00030
    00031 #include "asterisk.h"
    00032
    00033 /* ASTERISK_FILE_VERSION(__FILE__, "$Revision: 211526 $") */
    00034
    00035 #include "asterisk/channel.h"
    00036 #include "asterisk/pbx.h"
    00037 #include "asterisk/logger.h"
    00038 #include "asterisk/utils.h"
    00039 #include "asterisk/app.h"
    00040 #include "asterisk/localtime.h"
    00041
    00042 static char *function_fieldqty(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
    00043 {
    00044    char *varname, *varsubst, varval[8192] = "", *varval2 = varval;
    00045    char *delim = ast_strdupa(data);
    00046    int fieldcount = 0;
    00047
    00048    if (delim) {
    00049       varname = strsep(&delim, "|");
    00050       varsubst = alloca(strlen(varname) + 4);
    00051
    00052       sprintf(varsubst, "${%s}", varname);
    00053       pbx_substitute_variables_helper(chan, varsubst, varval, sizeof(varval) - 1);
    00054       if (ast_strlen_zero(varval))
    00055          fieldcount = 0;
    00056       else if (delim) {
    00057          while (strsep(&varval2, delim))
    00058             fieldcount++;
    00059       } else if (!ast_strlen_zero(varval)) {
    00060          fieldcount = 1;
    00061       }
    00062       snprintf(buf, len, "%d", fieldcount);
    00063    } else {
    00064       ast_log(LOG_ERROR, "Out of memory\n");
    00065       ast_copy_string(buf, "1", len);
    00066    }
    00067    return buf;
    00068 }
    00069
    00070 #ifndef BUILTIN_FUNC
    00071 static
    00072 #endif
    00073 struct ast_custom_function fieldqty_function = {
    00074    .name = "FIELDQTY",
    00075    .synopsis = "Count the fields, with an arbitrary delimiter",
    00076    .syntax = "FIELDQTY(<varname>,<delim>)",
    00077    .read = function_fieldqty,
    00078 };
    00079
    00080 static char *builtin_function_regex(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
    00081 {
    00082    char *arg, *earg = NULL, *tmp, errstr[256] = "";
    00083    int errcode;
    00084    regex_t regexbuf;
    00085
    00086    ast_copy_string(buf, "0", len);
    00087
    00088    tmp = ast_strdupa(data);
    00089    if (!tmp) {
    00090       ast_log(LOG_ERROR, "Out of memory in %s(%s)\n", cmd, data);
    00091       return buf;
    00092    }
    00093
    00094    /* Regex in quotes */
    00095    arg = strchr(tmp, '"');
    00096    if (arg) {
    00097       earg = ++arg;
    00098       strsep(&earg, "\"");
    00099       if (earg) {
    00100          /* Skip over any spaces before the data we are checking */
    00101          while (*earg == ' ')
    00102             earg++;
    00103       }
    00104    } else {
    00105       arg = tmp;
    00106    }
    00107
    00108    if ((errcode = regcomp(&regexbuf, arg, REG_EXTENDED | REG_NOSUB))) {
    00109       regerror(errcode, &regexbuf, errstr, sizeof(errstr));
    00110       ast_log(LOG_WARNING, "Malformed input %s(%s): %s\n", cmd, data, errstr);
    00111    } else {
    00112       if (!regexec(&regexbuf, earg ? earg : "", 0, NULL, 0))
    00113          ast_copy_string(buf, "1", len);
    00114    }
    00115    regfree(&regexbuf);
    00116
    00117    return buf;
    00118 }
    00119
    00120 #ifndef BUILTIN_FUNC
    00121 static
    00122 #endif
    00123 struct ast_custom_function regex_function = {
    00124    .name = "REGEX",
    00125    .synopsis = "Regular Expression: Returns 1 if data matches regular expression.",
    00126    .syntax = "REGEX(\"<regular expression>\" <data>)",
    00127    .read = builtin_function_regex,
    00128 };
    00129
    00130 static char *builtin_function_len(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
    00131 {
    00132    int length = 0;
    00133    if (data) {
    00134       length = strlen(data);
    00135    }
    00136    snprintf(buf, len, "%d", length);
    00137    return buf;
    00138 }
    00139
    00140 #ifndef BUILTIN_FUNC
    00141 static
    00142 #endif
    00143 struct ast_custom_function len_function = {
    00144    .name = "LEN",
    00145    .synopsis = "Returns the length of the argument given",
    00146    .syntax = "LEN(<string>)",
    00147    .read = builtin_function_len,
    00148 };
    00149
    00150 static char *acf_strftime(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
    00151 {
    00152    char *format, *epoch, *timezone = NULL;
    00153    long epochi;
    00154    struct tm time;
    00155
    00156    buf[0] = '\0';
    00157
    00158    if (!data) {
    00159       ast_log(LOG_ERROR, "Asterisk function STRFTIME() requires an argument.\n");
    00160       return buf;
    00161    }
    00162
    00163    format = ast_strdupa(data);
    00164    if (!format) {
    00165       ast_log(LOG_ERROR, "Out of memory\n");
    00166       return buf;
    00167    }
    00168
    00169    epoch = strsep(&format, "|");
    00170    timezone = strsep(&format, "|");
    00171
    00172    if (ast_strlen_zero(epoch) || !sscanf(epoch, "%30ld", &epochi)) {
    00173       struct timeval tv = ast_tvnow();
    00174       epochi = tv.tv_sec;
    00175    }
    00176
    00177    ast_localtime(&epochi, &time, timezone);
    00178
    00179    if (!format) {
    00180       format = "%c";
    00181    }
    00182
    00183    if (!strftime(buf, len, format, &time)) {
    00184       ast_log(LOG_WARNING, "C function strftime() output nothing?!!\n");
    00185    }
    00186    buf[len - 1] = '\0';
    00187
    00188    return buf;
    00189 }
    00190
    00191 #ifndef BUILTIN_FUNC
    00192 static
    00193 #endif
    00194 struct ast_custom_function strftime_function = {
    00195    .name = "STRFTIME",
    00196    .synopsis = "Returns the current date/time in a specified format.",
    00197    .syntax = "STRFTIME([<epoch>][,[timezone][,format]])",
    00198    .read = acf_strftime,
    00199 };
    00200
    00201 static char *function_eval(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
    00202 {
    00203    memset(buf, 0, len);
    00204
    00205    if (ast_strlen_zero(data)) {
    00206       ast_log(LOG_WARNING, "EVAL requires an argument: EVAL(<string>)\n");
    00207       return buf;
    00208    }
    00209
    00210    pbx_substitute_variables_helper(chan, data, buf, len - 1);
    00211
    00212    return buf;
    00213 }
    00214
    00215 #ifndef BUILTIN_FUNC
    00216 static
    00217 #endif
    00218 struct ast_custom_function eval_function = {
    00219    .name = "EVAL",
    00220    .synopsis = "Evaluate stored variables.",
    00221    .syntax = "EVAL(<variable>)",
    00222    .desc = "Using EVAL basically causes a string to be evaluated twice.\n"
    00223       "When a variable or expression is in the dialplan, it will be\n"
    00224       "evaluated at runtime. However, if the result of the evaluation\n"
    00225       "is in fact a variable or expression, using EVAL will have it\n"
    00226       "evaluated a second time. For example, if the variable ${MYVAR}\n"
    00227       "contains \"${OTHERVAR}\", then the result of putting ${EVAL(${MYVAR})}\n"
    00228       "in the dialplan will be the contents of the variable, OTHERVAR.\n"
    00229       "Normally, by just putting ${MYVAR} in the dialplan, you would be\n"
    00230       "left with \"${OTHERVAR}\".\n",
    00231    .read = function_eval,
    00232 };
    00233