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`.

(cherry picked from commit f8212d4594)
This commit is contained in:
Sean Bright
2023-11-07 15:03:53 -05:00
committed by Asterisk Development Team
parent 989e61890a
commit f19b74ad31
9 changed files with 69 additions and 19 deletions

View File

@@ -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)

View File

@@ -77,6 +77,13 @@
</synopsis>
<syntax>
<parameter name="filenames" required="true" argsep="&amp;">
<para>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 <literal>&amp;</literal> in the URL you can enclose
the URL in single quotes.</para>
<argument name="filename1" required="true" />
<argument name="filename2" multiple="true" />
</parameter>
@@ -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;