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
00029
00030
00031
00032 #include "asterisk.h"
00033
00034 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 328209 $")
00035
00036 #include "asterisk/file.h"
00037 #include "asterisk/pbx.h"
00038 #include "asterisk/channel.h"
00039 #include "asterisk/app.h"
00040 #include "asterisk/module.h"
00041 #include "asterisk/indications.h"
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115 enum read_option_flags {
00116 OPT_SKIP = (1 << 0),
00117 OPT_INDICATION = (1 << 1),
00118 OPT_NOANSWER = (1 << 2),
00119 };
00120
00121 AST_APP_OPTIONS(read_app_options, {
00122 AST_APP_OPTION('s', OPT_SKIP),
00123 AST_APP_OPTION('i', OPT_INDICATION),
00124 AST_APP_OPTION('n', OPT_NOANSWER),
00125 });
00126
00127 static char *app = "Read";
00128
00129 extern AST_LIST_HEAD(readmaskvars, ast_variable_list) readmaskvars;
00130
00131 static int read_exec(struct ast_channel *chan, const char *data)
00132 {
00133 int res = 0;
00134 char tmp[256] = "";
00135 char *digits;
00136 int maxdigits = 255;
00137 int tries = 1, to = 0, x = 0;
00138 double tosec;
00139 char *argcopy = NULL;
00140 struct ast_tone_zone_sound *ts = NULL;
00141 struct ast_flags flags = {0};
00142 const char *status = "ERROR";
00143 struct ast_variable_list *cur;
00144
00145 AST_DECLARE_APP_ARGS(arglist,
00146 AST_APP_ARG(variable);
00147 AST_APP_ARG(filename);
00148 AST_APP_ARG(maxdigits);
00149 AST_APP_ARG(options);
00150 AST_APP_ARG(attempts);
00151 AST_APP_ARG(timeout);
00152 );
00153
00154 pbx_builtin_setvar_helper(chan, "READSTATUS", status);
00155 if (ast_strlen_zero(data)) {
00156 ast_log(LOG_WARNING, "Read requires an argument (variable)\n");
00157 return 0;
00158 }
00159
00160 argcopy = ast_strdupa(data);
00161
00162 AST_STANDARD_APP_ARGS(arglist, argcopy);
00163
00164 if (!ast_strlen_zero(arglist.options)) {
00165 ast_app_parse_options(read_app_options, &flags, NULL, arglist.options);
00166 }
00167
00168 if (!ast_strlen_zero(arglist.attempts)) {
00169 tries = atoi(arglist.attempts);
00170 if (tries <= 0)
00171 tries = 1;
00172 }
00173
00174 if (!ast_strlen_zero(arglist.timeout)) {
00175 tosec = atof(arglist.timeout);
00176 if (tosec <= 0)
00177 to = 0;
00178 else
00179 to = tosec * 1000.0;
00180 }
00181
00182 if (ast_strlen_zero(arglist.filename)) {
00183 arglist.filename = NULL;
00184 }
00185 if (!ast_strlen_zero(arglist.maxdigits)) {
00186 maxdigits = atoi(arglist.maxdigits);
00187 if ((maxdigits < 1) || (maxdigits > 255)) {
00188 maxdigits = 255;
00189 } else
00190 ast_verb(3, "Accepting a maximum of %d digits.\n", maxdigits);
00191 }
00192 if (ast_strlen_zero(arglist.variable)) {
00193 ast_log(LOG_WARNING, "Invalid! Usage: Read(variable[,filename][,maxdigits][,option][,attempts][,timeout])\n\n");
00194 return 0;
00195 }
00196 if (ast_test_flag(&flags, OPT_INDICATION)) {
00197 if (!ast_strlen_zero(arglist.filename)) {
00198 ts = ast_get_indication_tone(chan->zone, arglist.filename);
00199 }
00200 }
00201 if (chan->_state != AST_STATE_UP) {
00202 if (ast_test_flag(&flags, OPT_SKIP)) {
00203
00204 pbx_builtin_setvar_helper(chan, arglist.variable, "");
00205 pbx_builtin_setvar_helper(chan, "READSTATUS", "SKIPPED");
00206 return 0;
00207 } else if (!ast_test_flag(&flags, OPT_NOANSWER)) {
00208
00209 res = ast_answer(chan);
00210 }
00211 }
00212 if (!res) {
00213 while (tries && !res) {
00214 ast_stopstream(chan);
00215 if (ts && ts->data[0]) {
00216 if (!to)
00217 to = chan->pbx ? chan->pbx->rtimeoutms : 6000;
00218 res = ast_playtones_start(chan, 0, ts->data, 0);
00219 for (x = 0; x < maxdigits; ) {
00220 res = ast_waitfordigit(chan, to);
00221 ast_playtones_stop(chan);
00222 if (res < 1) {
00223 if (res == 0)
00224 status = "TIMEOUT";
00225 tmp[x]='\0';
00226 break;
00227 }
00228 tmp[x++] = res;
00229 if (tmp[x-1] == '#') {
00230 tmp[x-1] = '\0';
00231 status = "OK";
00232 break;
00233 }
00234 if (x >= maxdigits) {
00235 status = "OK";
00236 }
00237 }
00238 } else {
00239 res = ast_app_getdata(chan, arglist.filename, tmp, maxdigits, to);
00240 if (res == AST_GETDATA_COMPLETE || res == AST_GETDATA_EMPTY_END_TERMINATED)
00241 status = "OK";
00242 else if (res == AST_GETDATA_TIMEOUT)
00243 status = "TIMEOUT";
00244 else if (res == AST_GETDATA_INTERRUPTED)
00245 status = "INTERRUPTED";
00246 }
00247 if (res > -1) {
00248 pbx_builtin_setvar_helper(chan, arglist.variable, tmp);
00249 if (!ast_strlen_zero(tmp)) {
00250 if (VERBOSITY_ATLEAST(3)) {
00251 digits = ast_strdupa(tmp);
00252 AST_LIST_TRAVERSE(&readmaskvars, cur, list) {
00253 if (!strncmp(arglist.variable, cur->variable, sizeof(cur->variable))) {
00254 mask_string(digits, readmaskvarini, readmaskvarend, 0);
00255 break;
00256 }
00257 }
00258 ast_verb(3, "User entered '%s'\n", digits);
00259 }
00260 tries = 0;
00261 } else {
00262 tries--;
00263 if (tries)
00264 ast_verb(3, "User entered nothing, %d chance%s left\n", tries, (tries != 1) ? "s" : "");
00265 else
00266 ast_verb(3, "User entered nothing.\n");
00267 }
00268 res = 0;
00269 } else {
00270 pbx_builtin_setvar_helper(chan, arglist.variable, tmp);
00271 ast_verb(3, "User disconnected\n");
00272 }
00273 }
00274 }
00275
00276 if (ts) {
00277 ts = ast_tone_zone_sound_unref(ts);
00278 }
00279
00280 if (ast_check_hangup(chan))
00281 status = "HANGUP";
00282 pbx_builtin_setvar_helper(chan, "READSTATUS", status);
00283 return 0;
00284 }
00285
00286 static int unload_module(void)
00287 {
00288 return ast_unregister_application(app);
00289 }
00290
00291 static int load_module(void)
00292 {
00293 return ast_register_application_xml(app, read_exec);
00294 }
00295
00296 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Read Variable Application");