func_odbc: Add SQL_ESC_BACKSLASHES dialplan function.

Some databases depending on their configuration using backslashes
for escaping. When combined with the use of ' this can result in
a broken func_odbc query.

This change adds a SQL_ESC_BACKSLASHES dialplan function which can
be used to escape the backslashes.

This is done as a dialplan function instead of being always done
as some databases do not require this, and always doing it would
result in incorrect data being put into the database.

ASTERISK-29838

Change-Id: I152bf34899b96ddb09cca3e767254d8d78f0c83d
This commit is contained in:
Joshua C. Colp 2022-02-10 08:02:23 -04:00 committed by Joshua Colp
parent ca53a8a833
commit 1e3ffda3db
3 changed files with 46 additions and 4 deletions

View File

@ -36,6 +36,10 @@
; to use the dialplan function SQL_ESC() to escape the data prior to its
; inclusion in the SQL statement.
;
; If you have data which may potentially contain backslashes, you may wish to
; use the dialplan function SQL_ESC_BACKSLASHES() to escape the backslashes.
; Note that not all databases may require escaping of the backslashes.
;
;
; The following options are available in this configuration file:
;

View File

@ -0,0 +1,7 @@
Subject: func_odbc
A SQL_ESC_BACKSLASHES dialplan function has been added which
escapes backslashes. Usage of this is dependent on whether the
database in use can use backslashes to escape ticks or not. If
it can, then usage of this prevents a broken SQL query depending
on how the SQL query is constructed.

View File

@ -96,6 +96,19 @@
<para>Example: SELECT foo FROM bar WHERE baz='${SQL_ESC(${ARG1})}'</para>
</description>
</function>
<function name="SQL_ESC_BACKSLASHES" language="en_US">
<synopsis>
Escapes backslashes for use in SQL statements.
</synopsis>
<syntax>
<parameter name="string" required="true" />
</syntax>
<description>
<para>Used in SQL templates to escape data which may contain backslashes
<literal>\</literal> which are otherwise used to escape data.</para>
<para>Example: SELECT foo FROM bar WHERE baz='${SQL_ESC(${SQL_ESC_BACKSLASHES(${ARG1})})}'</para>
</description>
</function>
***/
static char *config = "func_odbc.conf";
@ -1102,13 +1115,13 @@ end_acf_read:
return 0;
}
static int acf_escape(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static int acf_escape(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len, char character)
{
char *out = buf;
for (; *data && out - buf < len; data++) {
if (*data == '\'') {
*out = '\'';
if (*data == character) {
*out = character;
out++;
}
*out++ = *data;
@ -1118,9 +1131,25 @@ static int acf_escape(struct ast_channel *chan, const char *cmd, char *data, cha
return 0;
}
static int acf_escape_ticks(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
{
return acf_escape(chan, cmd, data, buf, len, '\'');
}
static struct ast_custom_function escape_function = {
.name = "SQL_ESC",
.read = acf_escape,
.read = acf_escape_ticks,
.write = NULL,
};
static int acf_escape_backslashes(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
{
return acf_escape(chan, cmd, data, buf, len, '\\');
}
static struct ast_custom_function escape_backslashes_function = {
.name = "SQL_ESC_BACKSLASHES",
.read = acf_escape_backslashes,
.write = NULL,
};
@ -1858,6 +1887,7 @@ static int load_module(void)
ast_config_destroy(cfg);
res |= ast_custom_function_register(&escape_function);
res |= ast_custom_function_register(&escape_backslashes_function);
ast_cli_register_multiple(cli_func_odbc, ARRAY_LEN(cli_func_odbc));
AST_RWLIST_UNLOCK(&queries);
@ -1877,6 +1907,7 @@ static int unload_module(void)
}
res |= ast_custom_function_unregister(&escape_function);
res |= ast_custom_function_unregister(&escape_backslashes_function);
res |= ast_custom_function_unregister(&fetch_function);
res |= ast_unregister_application(app_odbcfinish);
ast_cli_unregister_multiple(cli_func_odbc, ARRAY_LEN(cli_func_odbc));