<p>Friendly Automation has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/18377">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">func_odbc: Add SQL_ESC_BACKSLASHES dialplan function.<br><br>Some databases depending on their configuration using backslashes<br>for escaping. When combined with the use of ' this can result in<br>a broken func_odbc query.<br><br>This change adds a SQL_ESC_BACKSLASHES dialplan function which can<br>be used to escape the backslashes.<br><br>This is done as a dialplan function instead of being always done<br>as some databases do not require this, and always doing it would<br>result in incorrect data being put into the database.<br><br>ASTERISK-29838<br><br>Change-Id: I152bf34899b96ddb09cca3e767254d8d78f0c83d<br>---<br>M configs/samples/func_odbc.conf.sample<br>A doc/CHANGES-staging/func_odbc_esc_backslashes.txt<br>M funcs/func_odbc.c<br>3 files changed, 46 insertions(+), 4 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/77/18377/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/configs/samples/func_odbc.conf.sample b/configs/samples/func_odbc.conf.sample</span><br><span>index b825974..fce8a92 100644</span><br><span>--- a/configs/samples/func_odbc.conf.sample</span><br><span>+++ b/configs/samples/func_odbc.conf.sample</span><br><span>@@ -36,6 +36,10 @@</span><br><span> ; to use the dialplan function SQL_ESC() to escape the data prior to its</span><br><span> ; inclusion in the SQL statement.</span><br><span> ;</span><br><span style="color: hsl(120, 100%, 40%);">+; If you have data which may potentially contain backslashes, you may wish to</span><br><span style="color: hsl(120, 100%, 40%);">+; use the dialplan function SQL_ESC_BACKSLASHES() to escape the backslashes.</span><br><span style="color: hsl(120, 100%, 40%);">+; Note that not all databases may require escaping of the backslashes.</span><br><span style="color: hsl(120, 100%, 40%);">+;</span><br><span> ;</span><br><span> ; The following options are available in this configuration file:</span><br><span> ;</span><br><span>diff --git a/doc/CHANGES-staging/func_odbc_esc_backslashes.txt b/doc/CHANGES-staging/func_odbc_esc_backslashes.txt</span><br><span>new file mode 100644</span><br><span>index 0000000..087bb42</span><br><span>--- /dev/null</span><br><span>+++ b/doc/CHANGES-staging/func_odbc_esc_backslashes.txt</span><br><span>@@ -0,0 +1,7 @@</span><br><span style="color: hsl(120, 100%, 40%);">+Subject: func_odbc</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+A SQL_ESC_BACKSLASHES dialplan function has been added which</span><br><span style="color: hsl(120, 100%, 40%);">+escapes backslashes. Usage of this is dependent on whether the</span><br><span style="color: hsl(120, 100%, 40%);">+database in use can use backslashes to escape ticks or not. If</span><br><span style="color: hsl(120, 100%, 40%);">+it can, then usage of this prevents a broken SQL query depending</span><br><span style="color: hsl(120, 100%, 40%);">+on how the SQL query is constructed.</span><br><span>diff --git a/funcs/func_odbc.c b/funcs/func_odbc.c</span><br><span>index 48619b1..7e4e6a3 100644</span><br><span>--- a/funcs/func_odbc.c</span><br><span>+++ b/funcs/func_odbc.c</span><br><span>@@ -96,6 +96,19 @@</span><br><span>                       <para>Example: SELECT foo FROM bar WHERE baz='${SQL_ESC(${ARG1})}'</para></span><br><span>                </description></span><br><span>         </function></span><br><span style="color: hsl(120, 100%, 40%);">+     <function name="SQL_ESC_BACKSLASHES" language="en_US"></span><br><span style="color: hsl(120, 100%, 40%);">+              <synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+                      Escapes backslashes for use in SQL statements.</span><br><span style="color: hsl(120, 100%, 40%);">+                </synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+             <syntax></span><br><span style="color: hsl(120, 100%, 40%);">+                        <parameter name="string" required="true" /></span><br><span style="color: hsl(120, 100%, 40%);">+         </syntax></span><br><span style="color: hsl(120, 100%, 40%);">+               <description></span><br><span style="color: hsl(120, 100%, 40%);">+                   <para>Used in SQL templates to escape data which may contain backslashes</span><br><span style="color: hsl(120, 100%, 40%);">+                        <literal>\</literal> which are otherwise used to escape data.</para></span><br><span style="color: hsl(120, 100%, 40%);">+                        <para>Example: SELECT foo FROM bar WHERE baz='${SQL_ESC(${SQL_ESC_BACKSLASHES(${ARG1})})}'</para></span><br><span style="color: hsl(120, 100%, 40%);">+         </description></span><br><span style="color: hsl(120, 100%, 40%);">+  </function></span><br><span>  ***/</span><br><span> </span><br><span> static char *config = "func_odbc.conf";</span><br><span>@@ -1102,13 +1115,13 @@</span><br><span>        return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static int acf_escape(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)</span><br><span style="color: hsl(120, 100%, 40%);">+static int acf_escape(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len, char character)</span><br><span> {</span><br><span>      char *out = buf;</span><br><span> </span><br><span>         for (; *data && out - buf < len; data++) {</span><br><span style="color: hsl(0, 100%, 40%);">-           if (*data == '\'') {</span><br><span style="color: hsl(0, 100%, 40%);">-                        *out = '\'';</span><br><span style="color: hsl(120, 100%, 40%);">+              if (*data == character) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     *out = character;</span><br><span>                    out++;</span><br><span>               }</span><br><span>            *out++ = *data;</span><br><span>@@ -1118,9 +1131,25 @@</span><br><span>     return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static int acf_escape_ticks(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      return acf_escape(chan, cmd, data, buf, len, '\'');</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static struct ast_custom_function escape_function = {</span><br><span>        .name = "SQL_ESC",</span><br><span style="color: hsl(0, 100%, 40%);">-    .read = acf_escape,</span><br><span style="color: hsl(120, 100%, 40%);">+   .read = acf_escape_ticks,</span><br><span style="color: hsl(120, 100%, 40%);">+     .write = NULL,</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int acf_escape_backslashes(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      return acf_escape(chan, cmd, data, buf, len, '\\');</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct ast_custom_function escape_backslashes_function = {</span><br><span style="color: hsl(120, 100%, 40%);">+   .name = "SQL_ESC_BACKSLASHES",</span><br><span style="color: hsl(120, 100%, 40%);">+      .read = acf_escape_backslashes,</span><br><span>      .write = NULL,</span><br><span> };</span><br><span> </span><br><span>@@ -1858,6 +1887,7 @@</span><br><span> </span><br><span>         ast_config_destroy(cfg);</span><br><span>     res |= ast_custom_function_register(&escape_function);</span><br><span style="color: hsl(120, 100%, 40%);">+    res |= ast_custom_function_register(&escape_backslashes_function);</span><br><span>       ast_cli_register_multiple(cli_func_odbc, ARRAY_LEN(cli_func_odbc));</span><br><span> </span><br><span>      AST_RWLIST_UNLOCK(&queries);</span><br><span>@@ -1877,6 +1907,7 @@</span><br><span>     }</span><br><span> </span><br><span>        res |= ast_custom_function_unregister(&escape_function);</span><br><span style="color: hsl(120, 100%, 40%);">+  res |= ast_custom_function_unregister(&escape_backslashes_function);</span><br><span>     res |= ast_custom_function_unregister(&fetch_function);</span><br><span>  res |= ast_unregister_application(app_odbcfinish);</span><br><span>   ast_cli_unregister_multiple(cli_func_odbc, ARRAY_LEN(cli_func_odbc));</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/18377">change 18377</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/c/asterisk/+/18377"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I152bf34899b96ddb09cca3e767254d8d78f0c83d </div>
<div style="display:none"> Gerrit-Change-Number: 18377 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Friendly Automation </div>
<div style="display:none"> Gerrit-CC: Joshua Colp <jcolp@sangoma.com> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>