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 #include "asterisk.h"
00032
00033 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 328209 $")
00034
00035 #include "asterisk/file.h"
00036 #include "asterisk/pbx.h"
00037 #include "asterisk/app.h"
00038 #include "asterisk/module.h"
00039 #include "asterisk/indications.h"
00040 #include "asterisk/channel.h"
00041
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
00116
00117
00118
00119 enum readexten_option_flags {
00120 OPT_SKIP = (1 << 0),
00121 OPT_INDICATION = (1 << 1),
00122 OPT_NOANSWER = (1 << 2),
00123 };
00124
00125 AST_APP_OPTIONS(readexten_app_options, {
00126 AST_APP_OPTION('s', OPT_SKIP),
00127 AST_APP_OPTION('i', OPT_INDICATION),
00128 AST_APP_OPTION('n', OPT_NOANSWER),
00129 });
00130
00131 static char *app = "ReadExten";
00132
00133 static int readexten_exec(struct ast_channel *chan, const char *data)
00134 {
00135 int res = 0;
00136 char exten[256] = "";
00137 int maxdigits = sizeof(exten) - 1;
00138 int timeout = 0, digit_timeout = 0, x = 0;
00139 char *argcopy = NULL, *status = "";
00140 struct ast_tone_zone_sound *ts = NULL;
00141 struct ast_flags flags = {0};
00142
00143 AST_DECLARE_APP_ARGS(arglist,
00144 AST_APP_ARG(variable);
00145 AST_APP_ARG(filename);
00146 AST_APP_ARG(context);
00147 AST_APP_ARG(options);
00148 AST_APP_ARG(timeout);
00149 );
00150
00151 if (ast_strlen_zero(data)) {
00152 ast_log(LOG_WARNING, "ReadExten requires at least one argument\n");
00153 pbx_builtin_setvar_helper(chan, "READEXTENSTATUS", "ERROR");
00154 return 0;
00155 }
00156
00157 argcopy = ast_strdupa(data);
00158 AST_STANDARD_APP_ARGS(arglist, argcopy);
00159
00160 if (ast_strlen_zero(arglist.variable)) {
00161 ast_log(LOG_WARNING, "Usage: ReadExten(variable[,filename[,context[,options[,timeout]]]])\n");
00162 pbx_builtin_setvar_helper(chan, "READEXTENSTATUS", "ERROR");
00163 return 0;
00164 }
00165
00166 if (ast_strlen_zero(arglist.filename))
00167 arglist.filename = NULL;
00168
00169 if (ast_strlen_zero(arglist.context))
00170 arglist.context = chan->context;
00171
00172 if (!ast_strlen_zero(arglist.options))
00173 ast_app_parse_options(readexten_app_options, &flags, NULL, arglist.options);
00174
00175 if (!ast_strlen_zero(arglist.timeout)) {
00176 timeout = atoi(arglist.timeout);
00177 if (timeout > 0)
00178 timeout *= 1000;
00179 }
00180
00181 if (timeout <= 0)
00182 timeout = chan->pbx ? chan->pbx->rtimeoutms : 10000;
00183
00184 if (digit_timeout <= 0)
00185 digit_timeout = chan->pbx ? chan->pbx->dtimeoutms : 5000;
00186
00187 if (ast_test_flag(&flags, OPT_INDICATION) && !ast_strlen_zero(arglist.filename)) {
00188 ts = ast_get_indication_tone(chan->zone, arglist.filename);
00189 }
00190
00191 do {
00192 if (chan->_state != AST_STATE_UP) {
00193 if (ast_test_flag(&flags, OPT_SKIP)) {
00194
00195 pbx_builtin_setvar_helper(chan, arglist.variable, "");
00196 status = "SKIP";
00197 break;
00198 } else if (!ast_test_flag(&flags, OPT_NOANSWER)) {
00199
00200 res = ast_answer(chan);
00201 }
00202 }
00203
00204 if (res < 0) {
00205 status = "HANGUP";
00206 break;
00207 }
00208
00209 ast_playtones_stop(chan);
00210 ast_stopstream(chan);
00211
00212 if (ts && ts->data[0]) {
00213 res = ast_playtones_start(chan, 0, ts->data, 0);
00214 } else if (arglist.filename) {
00215 if (ast_test_flag(&flags, OPT_INDICATION) && ast_fileexists(arglist.filename, NULL, chan->language) <= 0) {
00216
00217
00218
00219
00220
00221
00222 res = ast_playtones_start(chan, 0, arglist.filename, 0);
00223 } else {
00224 res = ast_streamfile(chan, arglist.filename, chan->language);
00225 }
00226 }
00227
00228 for (x = 0; x < maxdigits; x++) {
00229 ast_debug(3, "extension so far: '%s', timeout: %d\n", exten, timeout);
00230 res = ast_waitfordigit(chan, timeout);
00231
00232 ast_playtones_stop(chan);
00233 ast_stopstream(chan);
00234 timeout = digit_timeout;
00235
00236 if (res < 1) {
00237 if (ast_check_hangup(chan)) {
00238 status = "HANGUP";
00239 } else if (x == 0) {
00240 pbx_builtin_setvar_helper(chan, arglist.variable, "t");
00241 status = "TIMEOUT";
00242 }
00243 break;
00244 }
00245
00246 exten[x] = res;
00247 if (!ast_matchmore_extension(chan, arglist.context, exten, 1 ,
00248 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
00249 if (!ast_exists_extension(chan, arglist.context, exten, 1,
00250 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))
00251 && res == '#') {
00252 exten[x] = '\0';
00253 }
00254 break;
00255 }
00256 }
00257
00258 if (!ast_strlen_zero(status))
00259 break;
00260
00261 if (ast_exists_extension(chan, arglist.context, exten, 1,
00262 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
00263 ast_debug(3, "User entered valid extension '%s'\n", exten);
00264 pbx_builtin_setvar_helper(chan, arglist.variable, exten);
00265 status = "OK";
00266 } else {
00267 ast_debug(3, "User dialed invalid extension '%s' in context '%s' on %s\n", exten, arglist.context, chan->name);
00268 pbx_builtin_setvar_helper(chan, arglist.variable, "i");
00269 pbx_builtin_setvar_helper(chan, "INVALID_EXTEN", exten);
00270 status = "INVALID";
00271 }
00272 } while (0);
00273
00274 if (ts) {
00275 ts = ast_tone_zone_sound_unref(ts);
00276 }
00277
00278 pbx_builtin_setvar_helper(chan, "READEXTENSTATUS", status);
00279
00280 return status[0] == 'H' ? -1 : 0;
00281 }
00282
00283 static int acf_isexten_exec(struct ast_channel *chan, const char *cmd, char *parse, char *buffer, size_t buflen)
00284 {
00285 int priority_int;
00286 AST_DECLARE_APP_ARGS(args,
00287 AST_APP_ARG(context);
00288 AST_APP_ARG(extension);
00289 AST_APP_ARG(priority);
00290 );
00291
00292 AST_STANDARD_APP_ARGS(args, parse);
00293
00294 if (ast_strlen_zero(args.context))
00295 args.context = chan->context;
00296
00297 if (ast_strlen_zero(args.extension)) {
00298 ast_log(LOG_WARNING, "Syntax: VALID_EXTEN([<context>],<extension>[,<priority>]) - missing argument <extension>!\n");
00299 return -1;
00300 }
00301
00302 if (ast_strlen_zero(args.priority))
00303 priority_int = 1;
00304 else
00305 priority_int = atoi(args.priority);
00306
00307 if (ast_exists_extension(chan, args.context, args.extension, priority_int,
00308 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
00309 ast_copy_string(buffer, "1", buflen);
00310 } else {
00311 ast_copy_string(buffer, "0", buflen);
00312 }
00313
00314 return 0;
00315 }
00316
00317 static struct ast_custom_function acf_isexten = {
00318 .name = "VALID_EXTEN",
00319 .read = acf_isexten_exec,
00320 };
00321
00322 static int unload_module(void)
00323 {
00324 int res = ast_unregister_application(app);
00325 res |= ast_custom_function_unregister(&acf_isexten);
00326
00327 return res;
00328 }
00329
00330 static int load_module(void)
00331 {
00332 int res = ast_register_application_xml(app, readexten_exec);
00333 res |= ast_custom_function_register(&acf_isexten);
00334 return res;
00335 }
00336
00337 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Read and evaluate extension validity");