From f8212d4594b8af24db896d8988f734e2c51694f6 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Tue, 7 Nov 2023 15:03:53 -0500 Subject: [PATCH] app.c: Allow ampersands in playback lists to be escaped. Any function or application that accepts a `&`-separated list of filenames can now include a literal `&` in a filename by wrapping the entire filename in single quotes, e.g.: ``` exten = _X.,n,Playback('https://example.com/sound.cgi?a=b&c=d'&hello-world) ``` Fixes #172 UpgradeNote: Ampersands in URLs passed to the `Playback()`, `Background()`, `SpeechBackground()`, `Read()`, `Authenticate()`, or `Queue()` applications as filename arguments can now be escaped by single quoting the filename. Additionally, this is also possible when using the `CONFBRIDGE` dialplan function, or configuring various features in `confbridge.conf` and `queues.conf`. --- apps/app_authenticate.c | 13 +++++++++++-- apps/app_confbridge.c | 4 ++-- apps/app_playback.c | 9 ++++++++- apps/app_queue.c | 19 +++++++++++++------ apps/app_read.c | 12 +++++++++--- apps/app_skel.c | 3 ++- apps/app_speech_utils.c | 17 +++++++++++++++-- main/app.c | 2 +- main/pbx_builtins.c | 9 ++++++++- 9 files changed, 69 insertions(+), 19 deletions(-) diff --git a/apps/app_authenticate.c b/apps/app_authenticate.c index 3ec04b72f9..ef63b9e50c 100644 --- a/apps/app_authenticate.c +++ b/apps/app_authenticate.c @@ -95,8 +95,17 @@ static const char app[] = "Authenticate"; maxdigits have been entered (without requiring the user to press the # key). Defaults to 0 - no limit - wait for the user press the # key. - - Override the agent-pass prompt file. + + Override the "agent-pass" sound file. Can be + an ampersand separated list of filenames. If the filename + is a relative filename (it does not begin with a slash), it + will be searched for in the Asterisk sounds directory. If the + filename is able to be parsed as a URL, Asterisk will + download the file and then begin playback on it. To include a + literal & in the URL you can enclose + the URL in single quotes. + + diff --git a/apps/app_confbridge.c b/apps/app_confbridge.c index dd683d35c6..046cd42b29 100644 --- a/apps/app_confbridge.c +++ b/apps/app_confbridge.c @@ -3035,7 +3035,7 @@ static int action_playback(struct ast_bridge_channel *bridge_channel, const char char *file_copy = ast_strdupa(playback_file); char *file = NULL; - while ((file = strsep(&file_copy, "&"))) { + while ((file = ast_strsep(&file_copy, '&', AST_STRSEP_STRIP | AST_STRSEP_TRIM))) { if (ast_stream_and_wait(bridge_channel->chan, file, "")) { ast_log(LOG_WARNING, "Failed to playback file %s to channel\n", file); return -1; @@ -3059,7 +3059,7 @@ static int action_playback_and_continue(struct confbridge_conference *conference char *file_copy = ast_strdupa(playback_file); char *file = NULL; - while ((file = strsep(&file_copy, "&"))) { + while ((file = ast_strsep(&file_copy, '&', AST_STRSEP_STRIP | AST_STRSEP_TRIM))) { if (ast_streamfile(bridge_channel->chan, file, ast_channel_language(bridge_channel->chan))) { ast_log(LOG_WARNING, "Failed to playback file %s to channel\n", file); return -1; diff --git a/apps/app_playback.c b/apps/app_playback.c index afa959be00..8b83f53a04 100644 --- a/apps/app_playback.c +++ b/apps/app_playback.c @@ -48,6 +48,13 @@ + Ampersand separated list of filenames. If the filename + is a relative filename (it does not begin with a slash), it + will be searched for in the Asterisk sounds directory. If the + filename is able to be parsed as a URL, Asterisk will + download the file and then begin playback on it. To include a + literal & in the URL you can enclose + the URL in single quotes. @@ -492,7 +499,7 @@ static int playback_exec(struct ast_channel *chan, const char *data) char *front; ast_stopstream(chan); - while (!res && (front = strsep(&back, "&"))) { + while (!res && (front = ast_strsep(&back, '&', AST_STRSEP_STRIP | AST_STRSEP_TRIM))) { if (option_say) res = say_full(chan, front, "", ast_channel_language(chan), NULL, -1, -1); else if (option_mix){ diff --git a/apps/app_queue.c b/apps/app_queue.c index 2684a40271..295e655ac3 100644 --- a/apps/app_queue.c +++ b/apps/app_queue.c @@ -241,11 +241,18 @@ URL will be sent to the called party if the channel supports it. - - Announcement file(s) to play to agent before bridging call, overriding the announcement(s) - configured in queues.conf, if any. - - + Announcement file(s) to play to agent before bridging + call, overriding the announcement(s) configured in + queues.conf, if any. + Ampersand separated list of filenames. If the filename + is a relative filename (it does not begin with a slash), it + will be searched for in the Asterisk sounds directory. If the + filename is able to be parsed as a URL, Asterisk will + download the file and then begin playback on it. To include a + literal & in the URL you can enclose + the URL in single quotes. + + Will cause the queue to fail out after a specified number of @@ -7244,7 +7251,7 @@ static int try_calling(struct queue_ent *qe, struct ast_flags opts, char **opt_a if (!res2 && announce) { char *front; char *announcefiles = ast_strdupa(announce); - while ((front = strsep(&announcefiles, "&"))) { + while ((front = ast_strsep(&announcefiles, '&', AST_STRSEP_STRIP | AST_STRSEP_TRIM))) { if (play_file(peer, front) < 0) { ast_log(LOG_ERROR, "play_file failed for '%s' on %s\n", front, ast_channel_name(peer)); } diff --git a/apps/app_read.c b/apps/app_read.c index e2ac60cc96..9a64941d52 100644 --- a/apps/app_read.c +++ b/apps/app_read.c @@ -49,9 +49,15 @@ name. - - file(s) to play before reading digits or tone with option i - + Ampersand separated list of filenames to play before + reading digits or tone with option i. If + the filename is a relative filename (it does not begin with a + slash), it will be searched for in the Asterisk sounds + directory. If the filename is able to be parsed as a URL, + Asterisk will download the file and then begin playback on + it. To include a literal & in the URL + you can enclose the URL in single quotes. + diff --git a/apps/app_skel.c b/apps/app_skel.c index e0b8bca7bc..b59ebe56bd 100644 --- a/apps/app_skel.c +++ b/apps/app_skel.c @@ -371,7 +371,8 @@ static void play_files_helper(struct ast_channel *chan, const char *prompts) char *prompt, *rest = ast_strdupa(prompts); ast_stopstream(chan); - while ((prompt = strsep(&rest, "&")) && !ast_stream_and_wait(chan, prompt, "")) { + while ((prompt = ast_strsep(&rest, '&', AST_STRSEP_STRIP | AST_STRSEP_TRIM)) + && !ast_stream_and_wait(chan, prompt, "")) { ast_stopstream(chan); } } diff --git a/apps/app_speech_utils.c b/apps/app_speech_utils.c index 9af8d2aee2..fa4a75a148 100644 --- a/apps/app_speech_utils.c +++ b/apps/app_speech_utils.c @@ -85,7 +85,17 @@ Play a sound file and wait for speech to be recognized. - + + Ampersand separated list of filenames. If the filename + is a relative filename (it does not begin with a slash), it + will be searched for in the Asterisk sounds directory. If the + filename is able to be parsed as a URL, Asterisk will + download the file and then begin playback on it. To include a + literal & in the URL you can enclose + the URL in single quotes. + + + Timeout integer in seconds. Note the timeout will only start once the sound file has stopped playing. @@ -776,7 +786,10 @@ static int speech_background(struct ast_channel *chan, const char *data) /* Okay it's streaming so go into a loop grabbing frames! */ while (done == 0) { /* If the filename is null and stream is not running, start up a new sound file */ - if (!quieted && (ast_channel_streamid(chan) == -1 && ast_channel_timingfunc(chan) == NULL) && (filename = strsep(&filename_tmp, "&"))) { + if (!quieted + && ast_channel_streamid(chan) == -1 + && ast_channel_timingfunc(chan) == NULL + && (filename = ast_strsep(&filename_tmp, '&', AST_STRSEP_STRIP | AST_STRSEP_TRIM))) { /* Discard old stream information */ ast_stopstream(chan); /* Start new stream */ diff --git a/main/app.c b/main/app.c index a99157b18e..5d3d78867b 100644 --- a/main/app.c +++ b/main/app.c @@ -205,7 +205,7 @@ enum ast_getdata_result ast_app_getdata_terminator(struct ast_channel *c, const prompt = ""; filename = ast_strdupa(prompt); - while ((front = strsep(&filename, "&"))) { + while ((front = ast_strsep(&filename, '&', AST_STRSEP_STRIP | AST_STRSEP_TRIM))) { if (!ast_strlen_zero(front)) { res = ast_streamfile(c, front, ast_channel_language(c)); if (res) diff --git a/main/pbx_builtins.c b/main/pbx_builtins.c index fa6e63d184..6fc0aa6860 100644 --- a/main/pbx_builtins.c +++ b/main/pbx_builtins.c @@ -77,6 +77,13 @@ + Ampersand separated list of filenames. If the filename + is a relative filename (it does not begin with a slash), it + will be searched for in the Asterisk sounds directory. If the + filename is able to be parsed as a URL, Asterisk will + download the file and then begin playback on it. To include a + literal & in the URL you can enclose + the URL in single quotes. @@ -1251,7 +1258,7 @@ static int pbx_builtin_background(struct ast_channel *chan, const char *data) ast_stopstream(chan); /* Stop anything playing */ /* Stream the list of files */ - while (!res && (front = strsep(&back, "&")) ) { + while (!res && (front = ast_strsep(&back, '&', AST_STRSEP_STRIP | AST_STRSEP_TRIM))) { if ( (res = ast_streamfile(chan, front, args.lang)) ) { ast_log(LOG_WARNING, "ast_streamfile failed on %s for %s\n", ast_channel_name(chan), (char*)data); res = 0;