Newer
Older
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
cmd = 0;
}
break;
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '*':
case '#':
cmd = ast_play_and_wait(chan, "vm-sorry");
break;
default:
if (message_exists) {
cmd = ast_play_and_wait(chan, "vm-review");
}
else {
cmd = ast_play_and_wait(chan, "vm-torerecord");
if (!cmd)
cmd = ast_waitfordigit(chan, 600);
}
if (!cmd)
cmd = ast_waitfordigit(chan, 6000);
if (!cmd) {
attempts++;
}
if (attempts > max_attempts) {
cmd = 't';
}
}
}
if (cmd == 't')
cmd = 0;
return cmd;
}
#define RES_UPONE (1 << 16)
#define RES_EXIT (1 << 17)
#define RES_REPEAT (1 << 18)
#define RES_RESTART ((1 << 19) | RES_REPEAT)
static int ast_ivr_menu_run_internal(struct ast_channel *chan, struct ast_ivr_menu *menu, void *cbdata);
static int ivr_dispatch(struct ast_channel *chan, struct ast_ivr_option *option, char *exten, void *cbdata)
{
int res;
int (*ivr_func)(struct ast_channel *, void *);
char *c;
char *n;
switch(option->action) {
case AST_ACTION_UPONE:
return RES_UPONE;
case AST_ACTION_EXIT:
return RES_EXIT | (((unsigned long)(option->adata)) & 0xffff);
case AST_ACTION_REPEAT:
return RES_REPEAT | (((unsigned long)(option->adata)) & 0xffff);
case AST_ACTION_RESTART:
return RES_RESTART ;
case AST_ACTION_NOOP:
return 0;
case AST_ACTION_BACKGROUND:
res = ast_stream_and_wait(chan, (char *)option->adata, chan->language, AST_DIGIT_ANY);
if (res < 0) {
ast_log(LOG_NOTICE, "Unable to find file '%s'!\n", (char *)option->adata);
res = 0;
}
return res;
case AST_ACTION_PLAYBACK:
res = ast_stream_and_wait(chan, (char *)option->adata, chan->language, "");
if (res < 0) {
ast_log(LOG_NOTICE, "Unable to find file '%s'!\n", (char *)option->adata);
res = 0;
}
return res;
case AST_ACTION_MENU:
res = ast_ivr_menu_run_internal(chan, (struct ast_ivr_menu *)option->adata, cbdata);
/* Do not pass entry errors back up, treaat ast though ti was an "UPONE" */
if (res == -2)
res = 0;
return res;
case AST_ACTION_WAITOPTION:
res = ast_waitfordigit(chan, 1000 * (chan->pbx ? chan->pbx->rtimeout : 10));
if (!res)
return 't';
return res;
case AST_ACTION_CALLBACK:
ivr_func = option->adata;
res = ivr_func(chan, cbdata);
return res;
case AST_ACTION_TRANSFER:
res = ast_parseable_goto(chan, option->adata);
case AST_ACTION_PLAYLIST:
case AST_ACTION_BACKLIST:
res = 0;
c = ast_strdupa(option->adata);
Russell Bryant
committed
while ((n = strsep(&c, ";"))) {
if ((res = ast_stream_and_wait(chan, n, chan->language,
(option->action == AST_ACTION_BACKLIST) ? AST_DIGIT_ANY : "")))
break;
Russell Bryant
committed
ast_stopstream(chan);
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
default:
ast_log(LOG_NOTICE, "Unknown dispatch function %d, ignoring!\n", option->action);
return 0;
};
return -1;
}
static int option_exists(struct ast_ivr_menu *menu, char *option)
{
int x;
for (x=0;menu->options[x].option;x++)
if (!strcasecmp(menu->options[x].option, option))
return x;
return -1;
}
static int option_matchmore(struct ast_ivr_menu *menu, char *option)
{
int x;
for (x=0;menu->options[x].option;x++)
if ((!strncasecmp(menu->options[x].option, option, strlen(option))) &&
(menu->options[x].option[strlen(option)]))
return x;
return -1;
}
static int read_newoption(struct ast_channel *chan, struct ast_ivr_menu *menu, char *exten, int maxexten)
{
int res=0;
int ms;
while(option_matchmore(menu, exten)) {
ms = chan->pbx ? chan->pbx->dtimeout : 5000;
if (strlen(exten) >= maxexten - 1)
break;
res = ast_waitfordigit(chan, ms);
if (res < 1)
break;
exten[strlen(exten) + 1] = '\0';
exten[strlen(exten)] = res;
}
return res > 0 ? 0 : res;
}
static int ast_ivr_menu_run_internal(struct ast_channel *chan, struct ast_ivr_menu *menu, void *cbdata)
{
/* Execute an IVR menu structure */
int res=0;
int pos = 0;
int retries = 0;
char exten[AST_MAX_EXTENSION] = "s";
if (option_exists(menu, "s") < 0) {
strcpy(exten, "g");
if (option_exists(menu, "g") < 0) {
ast_log(LOG_WARNING, "No 's' nor 'g' extension in menu '%s'!\n", menu->title);
return -1;
}
}
while(!res) {
while(menu->options[pos].option) {
if (!strcasecmp(menu->options[pos].option, exten)) {
res = ivr_dispatch(chan, menu->options + pos, exten, cbdata);
ast_log(LOG_DEBUG, "IVR Dispatch of '%s' (pos %d) yields %d\n", exten, pos, res);
if (res < 0)
break;
else if (res & RES_UPONE)
return 0;
else if (res & RES_EXIT)
return res;
else if (res & RES_REPEAT) {
int maxretries = res & 0xffff;
if ((res & RES_RESTART) == RES_RESTART) {
retries++;
if (!maxretries)
maxretries = 3;
if ((maxretries > 0) && (retries >= maxretries)) {
ast_log(LOG_DEBUG, "Max retries %d exceeded\n", maxretries);
if (option_exists(menu, "g") > -1)
strcpy(exten, "g");
else if (option_exists(menu, "s") > -1)
strcpy(exten, "s");
}
pos=0;
} else if (res && strchr(AST_DIGIT_ANY, res)) {
ast_log(LOG_DEBUG, "Got start of extension, %c\n", res);
exten[1] = '\0';
exten[0] = res;
if ((res = read_newoption(chan, menu, exten, sizeof(exten))))
break;
if (option_exists(menu, exten) < 0) {
if (option_exists(menu, "i")) {
ast_log(LOG_DEBUG, "Invalid extension entered, going to 'i'!\n");
strcpy(exten, "i");
pos = 0;
continue;
} else {
ast_log(LOG_DEBUG, "Aborting on invalid entry, with no 'i' option!\n");
res = -2;
break;
}
} else {
ast_log(LOG_DEBUG, "New existing extension: %s\n", exten);
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
pos = 0;
continue;
}
}
}
pos++;
}
ast_log(LOG_DEBUG, "Stopping option '%s', res is %d\n", exten, res);
pos = 0;
if (!strcasecmp(exten, "s"))
strcpy(exten, "g");
else
break;
}
return res;
}
int ast_ivr_menu_run(struct ast_channel *chan, struct ast_ivr_menu *menu, void *cbdata)
{
int res;
res = ast_ivr_menu_run_internal(chan, menu, cbdata);
/* Hide internal coding */
if (res > 0)
res = 0;
return res;
}
char *ast_read_textfile(const char *filename)
{
int fd;
char *output=NULL;
struct stat filesize;
int count=0;
int res;
if(stat(filename,&filesize)== -1){
ast_log(LOG_WARNING,"Error can't stat %s\n", filename);
return NULL;
}
count=filesize.st_size + 1;
fd = open(filename, O_RDONLY);
if (fd < 0) {
ast_log(LOG_WARNING, "Cannot open file '%s' for reading: %s\n", filename, strerror(errno));
return NULL;
if ((output = ast_malloc(count))) {
res = read(fd, output, count - 1);
if (res == count - 1) {
output[res] = '\0';
} else {
ast_log(LOG_WARNING, "Short read of %s (%d of %d): %s\n", filename, res, count - 1, strerror(errno));
free(output);
output = NULL;
}
close(fd);
return output;
}
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
{
char *s;
int curarg;
unsigned int argloc;
char *arg;
int res = 0;
ast_clear_flag(flags, AST_FLAGS_ALL);
if (!optstr)
return 0;
while (*s) {
curarg = *s++ & 0x7f; /* the array (in app.h) has 128 entries */
ast_set_flag(flags, options[curarg].flag);
argloc = options[curarg].arg_index;
if (*s == '(') {
/* Has argument */
s = strchr(s, ')');
if (*s) {
if (argloc)
args[argloc - 1] = arg;
*s++ = '\0';
ast_log(LOG_WARNING, "Missing closing parenthesis for argument '%c' in string '%s'\n", curarg, arg);
} else if (argloc) {
args[argloc - 1] = NULL;
return res;
}