Summary:ASTERISK-05141: [patch] Cannot do substrings with functions
Reporter:Tilghman Lesher (tilghman)Labels:
Date Opened:2005-09-24 11:30:36Date Closed:2008-01-15 15:49:46.000-0600
Versions:Frequency of
Environment:Attachments:( 0) 20050928__func_substring.diff.txt
Description:In 1.0, people frequently checked portions of CALLERIDNUM and set things according to that:

GotoIf($[${CALLERIDNUM:0:3} = 615]?...)

However, in 1.2, we have a new way of doing CALLERID with functions:


but there's no way to do substrings on that, i.e. THIS DOESN'T WORK:



For the time being, there's a simple workaround:  use the deprecated builtin variables.  However, since these will eventually be going away, we need a more
appropriate solution.

This bug is open for the discussion of the proper solution for this, before coding it.  I'll volunteer to code it, but we need a definitive syntax for it, first (definitive, as in, agreed to by either Mark or Kevin).
Comments:By: Brian West (bkw918) 2005-09-24 11:57:54

try this from and call it from a sip phone. ${EVAL(${CALLERID(num)})}

I get a nicely formated output like this... is this what it should do?  And no sip debug is not on.

-- Executing Answer("SIP/1000-8c8e", "") in new stack    
-- Executing NoOp("SIP/1000-8c8e", "1000From: "Brian West" <sip:1000@>;tag=54badc3675b36424o0To: <sip:664@>;tag=as699a52e3Call-ID: 3d7ae31e-fd04ca5c@ 102 INVITEUser-Agent: bkw.org/1.2Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFYContact: <sip:664@>Content-Type: application/sdpContent-Length: 321v=0o=root 6003 6003 IN IP4 IP4 0m=audio 16532 RTP/AVP 0 8 111 18 4 101a=rtpmap:0 PCMU/8000a=rtpmap:8 PCMA/8000a=rtpmap:111 G726-32/8000a=rtpmap:18 G729/8000a=rtpmap:4 G723/8000a=rtpmap:101 telephone-event/8000a=fmtp:101 0-16a=silenceSupp:off - - - -") in new stack    
-- Executing Hangup("SIP/1000-8c8e", "") in new stack

By: Tilghman Lesher (tilghman) 2005-09-24 13:12:25

No, that's a different problem.  Looks like we have a one-off in the conversion of EVAL from an application to a function.

By: Brian West (bkw918) 2005-09-24 15:58:48

Ok just wanted to point that out while trying a few things ;)


By: Kevin P. Fleming (kpfleming) 2005-09-25 16:58:20

Mark and I agree that this syntax is acceptable, as long as you can check for the colon characters 'cheaply' (i.e. by just looking at the character after the ')', rather than having to search for it).

By: Tilghman Lesher (tilghman) 2005-09-25 22:39:51

Unfortunately, we're going to have to search for it.  We already made the compromise that it's only seen as a function if there's a ')' immediately before the '}'.  We could probably check for a ':' 2, 3, and 4 characters before the '}', but that's as close as we can make it.

By: Kevin P. Fleming (kpfleming) 2005-09-25 23:04:38

Ugh... I forgot about that. It's even worse than that, since the numeric offsets could be longer, and negative, so the last colon could even be 6 characters away from the }.

I can only think of potentially ugly solutions right now... maybe my brain is too tired :-)

1) ${CALLERID(num):0:3:}

2) ${CALLERID:0:3(num)}

Can you think of any other syntax that would be easy to parse? I don't really want to make it ugly in trade-off for efficiency, but Mark may not give us any other options...

By: Tilghman Lesher (tilghman) 2005-09-25 23:33:23

The other thing we could do is to simplify the code a bit.  We already scan variable names in pbx_retrieve_variable to check to see if there's a ':' in the name, to do the substring.  If we did that scan in pbx_substitute_variables_helper, instead, and only then did the separation between variables and functions, we'd save ourselves a bit of hassle, while not making the code any less efficient.

By: Kevin P. Fleming (kpfleming) 2005-09-26 13:13:08

OK, after reviewing the code (and making some optimizations in the existing stuff), I agree that would be a good plan of attack.

However, we can't change the API of pbx_retrieve_variable, so these changes will have to happen at a lower layer. I think that means three new functions:

1) One to parse a variable name/function string and split off any offset/length, returning them already converted to ints if found.

2) One to handle retrieval of already-parsed variable names from a varshead (and the magic channel variables).

3) One to take a string and the offset/length values and return the substring.

With these components, we can provide the existing pbx_retrieve_variable API call, and also provide the same behavior in pbx_substitue_variables_helper_full for both variables and functions without additional searching.

However, searching for the offset/length will be a bit tricky in the case of a function string if we use the original syntax, since any ':' inside the '()' will have to be ignored. I still think that syntax is the best for the end user, though, so it would worth some code complexity to make it work :-)

By: Tilghman Lesher (tilghman) 2005-09-28 12:12:46

Found another bug while I was doing this:

Asterisk currently does no downward bounds checking on the second parameter.

So you could do ${EXTEN:0:-5000} and get a NULL plopped somewhere in memory, way out of bounds.

By: Tilghman Lesher (tilghman) 2005-09-28 12:30:37

Patch uploaded.  Much testing already done; let me know if you find any edge cases that I missed.

By: Kevin P. Fleming (kpfleming) 2005-09-29 00:43:08

Very nice work! Committed to CVS HEAD, although we'll need to update doc/README.variables so that people know about this substring support for function results.

By: Digium Subversion (svnbot) 2008-01-15 15:49:46.000-0600

Repository: asterisk
Revision: 6695

U   trunk/pbx.c

r6695 | kpfleming | 2008-01-15 15:49:46 -0600 (Tue, 15 Jan 2008) | 2 lines

re-factor variable/function name parsing, and add substring support to function results (issue ASTERISK-5141)