config: Allow ConfBridge DTMF menus to have '#' as the first digit.

ConfBridge allows custom DTMF menus to be created in the confbridge.conf
file by assigning a DTMF key sequence to a sequence of actions as follows:

DTMF-sequence = action,action...

Unfortunately, the normal config file processing code interprets an
initial '#' character as starting a directive such as #include.

* Add the ability to escape the first non-blank character in a config line
so the '#' character can be used without triggering the directive
processing code.

(closes issue AFS-2)
(closes issue ASTERISK-22478)
Reported by: Nicolas Tanski
Patches:
      jira_asterisk_22478_v11.patch (license #5621) patch uploaded by rmudgett (modified)

Review: https://reviewboard.asterisk.org/r/2969/
........

Merged revisions 402407 from http://svn.asterisk.org/svn/asterisk/branches/11
........

Merged revisions 402416 from http://svn.asterisk.org/svn/asterisk/branches/12


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@402417 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Richard Mudgett
2013-11-02 01:15:11 +00:00
parent 5401b2bfbf
commit 0721b1de83
3 changed files with 33 additions and 6 deletions

View File

@@ -429,6 +429,13 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
each channel using the application. Like the User and Bridge profiles a menu
is passed in to ConfBridge as an argument in the dialplan.</para>
<para>Below is a list of menu actions that can be assigned to a DTMF sequence.</para>
<note><para>
To have the first DTMF digit in a sequence be the '#' character, you need to
escape it. If it is not escaped then normal config file processing will
think it is a directive like #include. For example: The mute setting is
toggled when <literal>#1</literal> is pressed.</para>
<para><literal>\#1=toggle_mute</literal></para>
</note>
<note><para>
A single DTMF sequence can have multiple actions associated with it. This is
accomplished by stringing the actions together and using a <literal>,</literal> as the
@@ -453,7 +460,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
<enum name="toggle_mute"><para>
Toggle turning on and off mute. Mute will make the user silent
to everyone else, but the user will still be able to listen in.
continue to collect the dtmf sequence.</para></enum>
</para></enum>
<enum name="no_op"><para>
This action does nothing (No Operation). Its only real purpose exists for
being able to reserve a sequence in the config as a menu exit sequence.</para></enum>

View File

@@ -248,6 +248,11 @@ type=bridge
; Below is a list of menu actions that can be assigned
; to a DTMF sequence.
;
; To have the first DTMF digit in a sequence be the '#' character, you need to
; escape it. If it is not escaped then normal config file processing will
; think it is a directive like #include. For example:
; \#1=toggle_mute ; Pressing #1 will toggle the mute setting.
;
; A single DTMF sequence can have multiple actions associated with it. This is
; accomplished by stringing the actions together and using a ',' as the delimiter.
; Example: Both listening and talking volume is reset when '5' is pressed.
@@ -270,7 +275,7 @@ type=bridge
; using the '&' character as a delimiter.
; toggle_mute ; Toggle turning on and off mute. Mute will make the user silent
; to everyone else, but the user will still be able to listen in.
; continue to collect the dtmf sequence.
; no_op ; This action does nothing (No Operation). Its only real purpose exists for
; being able to reserve a sequence in the config as a menu exit sequence.
; decrease_listening_volume ; Decreases the channel's listening volume.

View File

@@ -1419,14 +1419,26 @@ static int process_text_line(struct ast_config *cfg, struct ast_category **cat,
} else {
/* Just a line (variable = value) */
int object = 0;
int is_escaped;
if (!(*cat)) {
ast_log(LOG_WARNING,
"parse error: No category context for line %d of %s\n", lineno, configfile);
return -1;
}
c = strchr(cur, '=');
if (c && c > cur && (*(c - 1) == '+')) {
is_escaped = cur[0] == '\\';
if (is_escaped) {
/* First character is escaped. */
++cur;
if (cur[0] < 33) {
ast_log(LOG_ERROR, "Invalid escape in line %d of %s\n", lineno, configfile);
return -1;
}
}
c = strchr(cur + is_escaped, '=');
if (c && c > cur + is_escaped && (*(c - 1) == '+')) {
struct ast_variable *var, *replace = NULL;
struct ast_str **str = ast_threadstorage_get(&appendbuf, sizeof(*str));
@@ -1462,8 +1474,11 @@ static int process_text_line(struct ast_config *cfg, struct ast_category **cat,
object = 1;
c++;
}
cur = ast_strip(cur);
set_new_variable:
if ((v = ast_variable_new(ast_strip(cur), ast_strip(c), S_OR(suggested_include_file, cfg->include_level == 1 ? "" : configfile)))) {
if (ast_strlen_zero(cur)) {
ast_log(LOG_WARNING, "No variable name in line %d of %s\n", lineno, configfile);
} else if ((v = ast_variable_new(cur, ast_strip(c), S_OR(suggested_include_file, cfg->include_level == 1 ? "" : configfile)))) {
v->lineno = lineno;
v->object = object;
*last_cat = 0;