From 4aedaaadebb8ea31f39a95f26781d181fb83344a Mon Sep 17 00:00:00 2001 From: "Joshua C. Colp" <jcolp@sangoma.com> Date: Thu, 10 Feb 2022 08:02:23 -0400 Subject: [PATCH] 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 --- configs/samples/func_odbc.conf.sample | 4 ++ .../func_odbc_esc_backslashes.txt | 7 ++++ funcs/func_odbc.c | 39 +++++++++++++++++-- 3 files changed, 46 insertions(+), 4 deletions(-) create mode 100644 doc/CHANGES-staging/func_odbc_esc_backslashes.txt diff --git a/configs/samples/func_odbc.conf.sample b/configs/samples/func_odbc.conf.sample index b825974ea7..fce8a92612 100644 --- a/configs/samples/func_odbc.conf.sample +++ b/configs/samples/func_odbc.conf.sample @@ -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: ; diff --git a/doc/CHANGES-staging/func_odbc_esc_backslashes.txt b/doc/CHANGES-staging/func_odbc_esc_backslashes.txt new file mode 100644 index 0000000000..087bb42141 --- /dev/null +++ b/doc/CHANGES-staging/func_odbc_esc_backslashes.txt @@ -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. diff --git a/funcs/func_odbc.c b/funcs/func_odbc.c index 48619b1354..7e4e6a3bb7 100644 --- a/funcs/func_odbc.c +++ b/funcs/func_odbc.c @@ -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)); -- GitLab