From 979eb709ae4b597ca85115f2597969355f962e52 Mon Sep 17 00:00:00 2001 From: David Vossel Date: Tue, 3 Mar 2009 23:21:18 +0000 Subject: [PATCH] app_read does not break from prompt loop with user terminated empty string In app.c, ast_app_getdata is called to stream the prompts and receive DTMF input. If ast_app_getdata() receives an empty string caused by the user inputing the end of string character, in this case '#', it should break from the prompt loop and return to app_read, but instead it cycles through all the prompts. I've added a return value for this special case in ast_readstring() which uses an enum I've delcared in apps.h. This enum is now used as a return value for ast_app_getdata(). (closes issue #14279) Reported by: Marquis Patches: fix_app_read.patch uploaded by Marquis (license 32) read-ampersanmd.patch2 uploaded by dvossel (license 671) Tested by: Marquis, dvossel Review: http://reviewboard.digium.com/r/177/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@180032 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- apps/app_read.c | 6 +++--- include/asterisk/app.h | 10 ++++++++++ main/app.c | 10 +++++++--- main/channel.c | 21 +++++++++++++-------- 4 files changed, 33 insertions(+), 14 deletions(-) diff --git a/apps/app_read.c b/apps/app_read.c index 6b4088cb78..d845c59007 100644 --- a/apps/app_read.c +++ b/apps/app_read.c @@ -231,11 +231,11 @@ static int read_exec(struct ast_channel *chan, void *data) } } else { res = ast_app_getdata(chan, arglist.filename, tmp, maxdigits, to); - if (res == 0) + if (res == AST_GETDATA_COMPLETE || res == AST_GETDATA_EMPTY_END_TERMINATED) status = "OK"; - else if (res == 1) + else if (res == AST_GETDATA_TIMEOUT) status = "TIMEOUT"; - else if (res == 2) + else if (res == AST_GETDATA_INTERRUPTED) status = "INTERRUPTED"; } if (res > -1) { diff --git a/include/asterisk/app.h b/include/asterisk/app.h index 0e8e0c9107..2731be032a 100644 --- a/include/asterisk/app.h +++ b/include/asterisk/app.h @@ -209,6 +209,16 @@ int ast_play_and_record(struct ast_channel *chan, const char *playfile, const ch 'silencethreshold' or use '-1' for either or both parameters for defaults. */ int ast_play_and_prepend(struct ast_channel *chan, char *playfile, char *recordfile, int maxtime_sec, char *fmt, int *duration, int beep, int silencethreshold, int maxsilence_ms); +enum ast_getdata_result { + AST_GETDATA_FAILED = -1, + AST_GETDATA_COMPLETE = 0, + AST_GETDATA_TIMEOUT = 1, + AST_GETDATA_INTERRUPTED = 2, + /*! indicates a user terminated empty string rather than an empty string resulting + * from a timeout or other factors */ + AST_GETDATA_EMPTY_END_TERMINATED = 3, +}; + enum AST_LOCK_RESULT { AST_LOCK_SUCCESS = 0, AST_LOCK_TIMEOUT = -1, diff --git a/main/app.c b/main/app.c index 8204344358..af20839d1c 100644 --- a/main/app.c +++ b/main/app.c @@ -121,7 +121,7 @@ int ast_app_dtget(struct ast_channel *chan, const char *context, char *collect, * \param maxlen How many digits to read (maximum) * \param timeout set timeout to 0 for "standard" timeouts. Set timeout to -1 for * "ludicrous time" (essentially never times out) */ -int ast_app_getdata(struct ast_channel *c, const char *prompt, char *s, int maxlen, int timeout) +enum ast_getdata_result ast_app_getdata(struct ast_channel *c, const char *prompt, char *s, int maxlen, int timeout) { int res = 0, to, fto; char *front, *filename; @@ -158,10 +158,14 @@ int ast_app_getdata(struct ast_channel *c, const char *prompt, char *s, int maxl to = c->pbx ? c->pbx->dtimeoutms : 2000; } res = ast_readstring(c, s, maxlen, to, fto, "#"); - if (!ast_strlen_zero(s)) + if (res == AST_GETDATA_EMPTY_END_TERMINATED) { return res; + } + if (!ast_strlen_zero(s)) { + return res; + } } - + return res; } diff --git a/main/channel.c b/main/channel.c index a39dfb906f..c457e28a75 100644 --- a/main/channel.c +++ b/main/channel.c @@ -3709,20 +3709,25 @@ int ast_readstring_full(struct ast_channel *c, char *s, int len, int timeout, in d = ast_waitfordigit_full(c, to, audiofd, ctrlfd); } if (d < 0) - return -1; + return AST_GETDATA_FAILED; if (d == 0) { - s[pos]='\0'; - return 1; + s[pos] = '\0'; + return AST_GETDATA_TIMEOUT; } if (d == 1) { - s[pos]='\0'; - return 2; + s[pos] = '\0'; + return AST_GETDATA_INTERRUPTED; } - if (!strchr(enders, d)) + if (strchr(enders, d) && (pos == 0)) { + s[pos] = '\0'; + return AST_GETDATA_EMPTY_END_TERMINATED; + } + if (!strchr(enders, d)) { s[pos++] = d; + } if (strchr(enders, d) || (pos >= len)) { - s[pos]='\0'; - return 0; + s[pos] = '\0'; + return AST_GETDATA_COMPLETE; } to = timeout; }