00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "asterisk.h"
00029
00030 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 122314 $")
00031
00032 #include <stdlib.h>
00033 #include <stdio.h>
00034 #include <string.h>
00035
00036 #include "asterisk/lock.h"
00037 #include "asterisk/file.h"
00038 #include "asterisk/logger.h"
00039 #include "asterisk/channel.h"
00040 #include "asterisk/pbx.h"
00041 #include "asterisk/app.h"
00042 #include "asterisk/module.h"
00043 #include "asterisk/translate.h"
00044 #include "asterisk/options.h"
00045 #include "asterisk/utils.h"
00046 #include "asterisk/indications.h"
00047
00048 enum {
00049 OPT_SKIP = (1 << 0),
00050 OPT_INDICATION = (1 << 1),
00051 OPT_NOANSWER = (1 << 2),
00052 } read_option_flags;
00053
00054 AST_APP_OPTIONS(read_app_options, {
00055 AST_APP_OPTION('s', OPT_SKIP),
00056 AST_APP_OPTION('i', OPT_INDICATION),
00057 AST_APP_OPTION('n', OPT_NOANSWER),
00058 });
00059
00060 static char *app = "Read";
00061
00062 static char *synopsis = "Read a variable";
00063
00064 static char *descrip =
00065 " Read(variable[|filename][|maxdigits][|option][|attempts][|timeout])\n\n"
00066 "Reads a #-terminated string of digits a certain number of times from the\n"
00067 "user in to the given variable.\n"
00068 " filename -- file to play before reading digits or tone with option i\n"
00069 " maxdigits -- maximum acceptable number of digits. Stops reading after\n"
00070 " maxdigits have been entered (without requiring the user to\n"
00071 " press the '#' key).\n"
00072 " Defaults to 0 - no limit - wait for the user press the '#' key.\n"
00073 " Any value below 0 means the same. Max accepted value is 255.\n"
00074 " option -- options are 's' , 'i', 'n'\n"
00075 " 's' to return immediately if the line is not up,\n"
00076 " 'i' to play filename as an indication tone from your indications.conf\n"
00077 " 'n' to read digits even if the line is not up.\n"
00078 " attempts -- if greater than 1, that many attempts will be made in the \n"
00079 " event no data is entered.\n"
00080 " timeout -- An integer number of seconds to wait for a digit response. If greater\n"
00081 " than 0, that value will override the default timeout.\n\n"
00082 "Read should disconnect if the function fails or errors out.\n";
00083
00084
00085 #define ast_next_data(instr,ptr,delim) if((ptr=strchr(instr,delim))) { *(ptr) = '\0' ; ptr++;}
00086
00087 static int read_exec(struct ast_channel *chan, void *data)
00088 {
00089 int res = 0;
00090 struct ast_module_user *u;
00091 char tmp[256] = "";
00092 int maxdigits = 255;
00093 int tries = 1, to = 0, x = 0;
00094 char *argcopy = NULL;
00095 struct ind_tone_zone_sound *ts;
00096 struct ast_flags flags = {0};
00097
00098 AST_DECLARE_APP_ARGS(arglist,
00099 AST_APP_ARG(variable);
00100 AST_APP_ARG(filename);
00101 AST_APP_ARG(maxdigits);
00102 AST_APP_ARG(options);
00103 AST_APP_ARG(attempts);
00104 AST_APP_ARG(timeout);
00105 );
00106
00107 if (ast_strlen_zero(data)) {
00108 ast_log(LOG_WARNING, "Read requires an argument (variable)\n");
00109 return -1;
00110 }
00111
00112 u = ast_module_user_add(chan);
00113
00114 argcopy = ast_strdupa(data);
00115
00116 AST_STANDARD_APP_ARGS(arglist, argcopy);
00117
00118 if (!ast_strlen_zero(arglist.options)) {
00119 ast_app_parse_options(read_app_options, &flags, NULL, arglist.options);
00120 }
00121
00122 if (!ast_strlen_zero(arglist.attempts)) {
00123 tries = atoi(arglist.attempts);
00124 if (tries <= 0)
00125 tries = 1;
00126 }
00127
00128 if (!ast_strlen_zero(arglist.timeout)) {
00129 to = atoi(arglist.timeout);
00130 if (to <= 0)
00131 to = 0;
00132 else
00133 to *= 1000;
00134 }
00135
00136 if (ast_strlen_zero(arglist.filename)) {
00137 arglist.filename = NULL;
00138 }
00139 if (!ast_strlen_zero(arglist.maxdigits)) {
00140 maxdigits = atoi(arglist.maxdigits);
00141 if ((maxdigits<1) || (maxdigits>255)) {
00142 maxdigits = 255;
00143 } else if (option_verbose > 2)
00144 ast_verbose(VERBOSE_PREFIX_3 "Accepting a maximum of %d digits.\n", maxdigits);
00145 }
00146 if (ast_strlen_zero(arglist.variable)) {
00147 ast_log(LOG_WARNING, "Invalid! Usage: Read(variable[|filename][|maxdigits][|option][|attempts][|timeout])\n\n");
00148 ast_module_user_remove(u);
00149 return -1;
00150 }
00151 ts=NULL;
00152 if (ast_test_flag(&flags,OPT_INDICATION)) {
00153 if (!ast_strlen_zero(arglist.filename)) {
00154 ts = ast_get_indication_tone(chan->zone,arglist.filename);
00155 }
00156 }
00157 if (chan->_state != AST_STATE_UP) {
00158 if (ast_test_flag(&flags,OPT_SKIP)) {
00159
00160 pbx_builtin_setvar_helper(chan, arglist.variable, "\0");
00161 ast_module_user_remove(u);
00162 return 0;
00163 } else if (!ast_test_flag(&flags,OPT_NOANSWER)) {
00164
00165 res = ast_answer(chan);
00166 }
00167 }
00168 if (!res) {
00169 while (tries && !res) {
00170 ast_stopstream(chan);
00171 if (ts && ts->data[0]) {
00172 if (!to)
00173 to = chan->pbx ? chan->pbx->rtimeout * 1000 : 6000;
00174 res = ast_playtones_start(chan, 0, ts->data, 0);
00175 for (x = 0; x < maxdigits; ) {
00176 res = ast_waitfordigit(chan, to);
00177 ast_playtones_stop(chan);
00178 if (res < 1) {
00179 tmp[x]='\0';
00180 break;
00181 }
00182 tmp[x++] = res;
00183 if (tmp[x-1] == '#') {
00184 tmp[x-1] = '\0';
00185 break;
00186 }
00187 }
00188 } else {
00189 res = ast_app_getdata(chan, arglist.filename, tmp, maxdigits, to);
00190 }
00191 if (res > -1) {
00192 pbx_builtin_setvar_helper(chan, arglist.variable, tmp);
00193 if (!ast_strlen_zero(tmp)) {
00194 if (option_verbose > 2)
00195 ast_verbose(VERBOSE_PREFIX_3 "User entered '%s'\n", tmp);
00196 tries = 0;
00197 } else {
00198 tries--;
00199 if (option_verbose > 2) {
00200 if (tries)
00201 ast_verbose(VERBOSE_PREFIX_3 "User entered nothing, %d chance%s left\n", tries, (tries != 1) ? "s" : "");
00202 else
00203 ast_verbose(VERBOSE_PREFIX_3 "User entered nothing.\n");
00204 }
00205 }
00206 res = 0;
00207 } else {
00208 pbx_builtin_setvar_helper(chan, arglist.variable, tmp);
00209 if (option_verbose > 2)
00210 ast_verbose(VERBOSE_PREFIX_3 "User disconnected\n");
00211 }
00212 }
00213 }
00214 ast_module_user_remove(u);
00215 return res;
00216 }
00217
00218 static int unload_module(void)
00219 {
00220 int res;
00221
00222 res = ast_unregister_application(app);
00223
00224 ast_module_user_hangup_all();
00225
00226 return res;
00227 }
00228
00229 static int load_module(void)
00230 {
00231 return ast_register_application(app, read_exec, synopsis, descrip);
00232 }
00233
00234 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Read Variable Application");