Here’s a strange problem I’ve been trying to figure out for the past hour:
I would like to be able to set a variable equal to a channel name in a variable. Doing this for the extension works, no problem. I need to be able to set multiple variables for different channels, however.
Using ${CHANNEL} literally fails, because channel names contain semicolons so the System() eats the ; up. Thus, the ; needs to be escaped. So, naturally, replace ; with ;, right?
Except that \ itself is a special character, and needs to be escaped. Better make that \;, to prevent the escaper from getting escaped.
There seem to be 3 levels of escaping in play. The ; needs to be escaped in the dialplan, or the ; is interpreted as a dialplan comment (this only applies to literal channel names, not those in a variable like ${CHANNEL}). Once the ; makes it into the System() call, it needs to be escaped again or it will throw an error about invalid call file contents. But, after all that, the variable seems to get truncated, rather than set properly.
As an example:
same => n,System(echo Setvar: chan1=${STRREPLACE(ARG1,\;,\\\\\;)} >> /tmp/${UNIQUEID}.call)
same => n,System(echo Setvar: chan2=${STRREPLACE(ARG1,\;,\\\\\\\;)} >> /tmp/${UNIQUEID}.call)
;same => n,System(echo Setvar: chan3=${STRREPLACE(ARG1,\;,\\\\\\\\\;)} >> /tmp/${UNIQUEID}.call)
;same => n,System(echo Setvar: chan4=${STRREPLACE(ARG1,\;,\\\;)} >> /tmp/${UNIQUEID}.call)
chan3 and chan4 are commented out, because they are invalid call file contents and will cause the call to crash. Too few or too many backslashes and it fails, so the correct number seems to be either 4 or 6 backslashes.
Here’s what that looks like in the CLI:
[Apr 20 19:49:52] -- Executing [s@blind-transfer-recall-monitor-schedule:7] System("Local/1A12128@extensions-0000001d;2", "echo Setvar: chan1=Local/SIPATAxLB1@outgoing-00000021\\;2 >> /tmp/1618962580.78.call") in new stack
[Apr 20 19:49:52] -- Executing [s@blind-transfer-recall-monitor-schedule:8] System("Local/1A12128@extensions-0000001d;2", "echo Setvar: chan2=Local/SIPATAxLB1@outgoing-00000021\\\;2 >> /tmp/1618962580.78.call") in new stack
So then I NoOp() them out on the other end, and what do I get?
Executing [s@blind-transfer-recall:4] NoOp("Local/35@wait-00000025;1", "Local/SIPATAxLB1@outgoing-00000021 / Local/SIPATAxLB1@outgoing-00000021 / / ") in new stack
The ;2 is cut off from the variables - meaning that somewhere between putting the channel name in a call file and the channel getting created, everything after the semicolon, including the semicolon, got truncated. Consequently, subsequent dialplan execution fails because no such channels exist.
If you take a look at the source code, this is exactly how semicolons in call files should be escaped: asterisk/pbx_spool.c at fd0ca1c3f9b972a52d48a82b492fd6bac772dc78 · asterisk/asterisk · GitHub
So, this seems to be the right approach, but everything I try either ends up with the call file failing → call crashing or a truncated variable name.
Has anyone figured out the proper way to escape the semicolon in channel names for usage in creating a call file?