How to allow/escape special charaters in callfiles?

Hi,

I have a PHP script that generates a call file when an incoming SMS is received. All works well, with the exception if the SMS text includes special characters like new-line, line-feed or semicolon ‘;’.

My question is how do I “escape” such characters in the call file? (I have figured out that I can escape semicolon using ‘\;’)

The call file below will only pass the first line to the endpoint and then asterisk will complain:
pbx_spool.c:208 in parse_line: Syntax error at line 13

Channel: Local/12025550183@dp_entry_channel_open
CallerID: "" <12025550160>
WaitTime: 60
MaxRetries: 100
RetryTime: 300
Context: dp_entry_trunk_texting
Extension: 12025550183
Priority: 1
Archive: yes
setvar: MESSAGE(to)=12025550183
setvar: MESSAGE(from)=12025550160
setvar: MESSAGE(body)=This is the first line of the SMS
This is the second line of the SMS
This is the third line of the SMS

You can use PHP regular expresion to remove it or replace it

Hello ambiorixg12,

Yes, but with what? A simple but unsatisfactory solution is just to remove the new-lines. But what do I do if I want to keep the format of the original
message?

I’ve never heard of newlines being allowed in Asterisk dialplan variables.

I agree that, that is unlikely. So how can I escape/quote the newlines in the call file?

That will depend on how you intend to unescape them when you use them.

Yes, I suppose. In this situation Asterisk pick up the call file and sets the channel variables.

Are you suggesting that I can use a custom function (script) in the dial-plan to “unescape” the new-lines?

If, so then, yes, then I agree that that is a way to address this issue.

No. I’m suggesting that you use code in the application that you write that consumes the string, as anything done in dialplan will have the same problem, the inability to place newlines in variables.

Ok, I get your general point.

The relevant line in my dialplan is (I do not need to state MESSAGE(body) explicitly):

 same => n,MessageSend(pjsip:${contact},${MESSAGE(from)})

So the application that consumes the string is MessageSend. But I could call a custom function first and do the character remapping there.

You would need to rewrite MessaageSend itself, as MyMessageSend

Whilst is is possible that you could write a MySet that did the un-escaping, I think you would be in uncharted territory. There might even be code injection risks if you use a variable with actual newlines directly in the dialplan.

Many thanks for all the valuable insights.
I think I now have a new angle to attack this problem.
I will comeback here after i have done some experimentation.

Asterisk’s call file is not suport multi-line.

you need to multi-line to single-line for call file.
at this time, you can use a URLEncoder.
when you send a text at dial-plan, you can use URLDecoder.

how about this?

Yes, that seems to be a very good idea. I have tested that approach and it works great. I will post my solution here once I have cleaned up the code a little.

Many thanks for your very useful suggestion!

That’s good. congrats!!

Many thanks for the very useful suggestions.

Should anyone stumble on, and find interest in this topic, I post my solution to the problem with handling the linefeed character in call files below.

The solution is based on encoding the SMS string that is used in the call file. When Asterisk pick up that call file the string is decoded before the SMS is sent to the endpoint.

php code snippet

This piece of code encodes the string to be used in the call file.

/*--------------------------------------------------------------------------
The message cannot span multiple lines in an Asterisk call file. To work
around that we encode the message (RFC3986, which supersedes RFC2396).
@param string $string to escape
@return string escaped string
*/
private function gen_body($string) {
	if ($this->config['astqueue']['message_encode'] === 'rfc3986') {
		return rawurlencode($string);
	} else {
		return $string;
	}
}

call file

This is an example call file with encoded MESSAGE(body).

Channel: Local/+12025550160@dp_entry_channel_open
CallerID: "" <+15017122661>
WaitTime: 45
MaxRetries: 0
RetryTime: 300
Context: dp_entry_trunk_texting
Extension: +12025550160
Priority: 1
Archive: yes
setvar: MESSAGE(to)=+12025550160
setvar: MESSAGE(from)=+15017122661
setvar: MESSAGE(body)=This%20is%20a%20test%20message%2Csent%20Thu%2019%20Dec%202019%2010%3A29%3A56%20PM%20CET%2C%20with%20special%20chars%3A%20%E2%98%BA%
20%5B%24%22%5C%5D%3B%3B%20and%204%20additional%20lines%3A%0A1%0A2%0A3%0A4.
setvar: MESSAGE_ENCODE=rfc3986

dialplan snippet

This is the subroutine in the dialplan (extensions.conf) that decodes the string.

;-------------------------------- sub_decode_body
; URL decode the MESSAGE(body) subroutine
; Usage: Gosub(sub_decode_body,s,1)
;
; Implementation details
; If MESSAGE_ENCODE = rfc3986 then the MESSAGE(body) is URL encoded
; (using RFC3986 which supersedes RFC2396) in the callfile, so decode it here.
;
[sub_decode_body]
exten => s,1,GotoIf($[ ${MESSAGE_ENCODE} != rfc3986 ]?return)
 same => n,Verbose(3,"Original message body ${MESSAGE(body)}")
 same => n,Set(MESSAGE(body)=${URIDECODE(${MESSAGE(body)})})
 same => n,Verbose(3,"Updated message body ${MESSAGE(body)}")
 same => n(return),Return()
1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.