<p>Leandro Dardini has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/15331">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">main/pbx_variables.c: Better parsing of variable name and value<br>                      separator for Set command<br>main/utils.c: Added a subroutine to return name and value from<br>              Set command argument<br><br>The variable name and value of a Set command are separated by a<br>=, but the = character may appear in the variable name portion as<br>a parameter for a function, like any ODBC_* func_odbc.conf<br>function, so better handling of quotes, parenthesis, and brackets<br>was needed.<br><br>ASTERISK-29239 #close<br><br>Change-Id: I7cd3bc6118033530ad00ae4b6bdad97b6b349b6f<br>---<br>M include/asterisk/utils.h<br>M main/pbx_variables.c<br>M main/utils.c<br>3 files changed, 69 insertions(+), 9 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/31/15331/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/asterisk/utils.h b/include/asterisk/utils.h</span><br><span>index 0ee11ee..54da45d 100644</span><br><span>--- a/include/asterisk/utils.h</span><br><span>+++ b/include/asterisk/utils.h</span><br><span>@@ -928,6 +928,12 @@</span><br><span>  */</span><br><span> int ast_check_ipv6(void);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ *\brief Parse a name = value assignment pair.</span><br><span style="color: hsl(120, 100%, 40%);">+ *\return Returns -1 if there is no valid assignment in the string.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int ast_parse_name_value(const char *input, char **name, char **value);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> enum ast_fd_flag_operation {</span><br><span>       AST_FD_FLAG_SET,</span><br><span>     AST_FD_FLAG_CLEAR,</span><br><span>diff --git a/main/pbx_variables.c b/main/pbx_variables.c</span><br><span>index 91b5bbb..22d14b2 100644</span><br><span>--- a/main/pbx_variables.c</span><br><span>+++ b/main/pbx_variables.c</span><br><span>@@ -1128,23 +1128,22 @@</span><br><span> </span><br><span> int pbx_builtin_setvar(struct ast_channel *chan, const char *data)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-        char *name, *value, *mydata;</span><br><span style="color: hsl(120, 100%, 40%);">+        char *name = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+        char *value = NULL;</span><br><span> </span><br><span>    if (ast_strlen_zero(data)) {</span><br><span>                 ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n");</span><br><span>              return 0;</span><br><span>    }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   mydata = ast_strdupa(data);</span><br><span style="color: hsl(0, 100%, 40%);">-     name = strsep(&mydata, "=");</span><br><span style="color: hsl(0, 100%, 40%);">-      value = mydata;</span><br><span style="color: hsl(0, 100%, 40%);">- if (!value) {</span><br><span style="color: hsl(0, 100%, 40%);">-           ast_log(LOG_WARNING, "Set requires an '=' to be a valid assignment.\n");</span><br><span style="color: hsl(0, 100%, 40%);">-              return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-       }</span><br><span style="color: hsl(120, 100%, 40%);">+     /* We don't know how much of "data" is the name and how much is the value so we'll use the worst case */</span><br><span style="color: hsl(120, 100%, 40%);">+    name = ast_alloca(strlen(data) + 1);</span><br><span style="color: hsl(120, 100%, 40%);">+  value = ast_alloca(strlen(data) + 1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       ast_parse_name_value(data,&name,&value);</span><br><span> </span><br><span>         if (strchr(name, ' ')) {</span><br><span style="color: hsl(0, 100%, 40%);">-                ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata);</span><br><span style="color: hsl(120, 100%, 40%);">+              ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, value);</span><br><span>      }</span><br><span> </span><br><span>        pbx_builtin_setvar_helper(chan, name, value);</span><br><span>diff --git a/main/utils.c b/main/utils.c</span><br><span>index 827ee2e..aa44cd5 100644</span><br><span>--- a/main/utils.c</span><br><span>+++ b/main/utils.c</span><br><span>@@ -2372,6 +2372,61 @@</span><br><span>  return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ *\brief Parse a name = value assignment pair.</span><br><span style="color: hsl(120, 100%, 40%);">+ *\return Returns -1 if there is no valid assignment in the string.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int ast_parse_name_value(const char *input, char **name, char **value)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        char *mydata = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+        char *scan = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+        int paren = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+        int quote = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+        int bracket = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+      int ret = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if (ast_strlen_zero(input)) {</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_log(LOG_ERROR, "Input must be not NULL");</span><br><span style="color: hsl(120, 100%, 40%);">+       ret = -1;</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%);">+   mydata = ast_strdupa(input);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        scan = mydata;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      for (; *scan; scan++) {</span><br><span style="color: hsl(120, 100%, 40%);">+          if (*scan == '(') {</span><br><span style="color: hsl(120, 100%, 40%);">+            paren++;</span><br><span style="color: hsl(120, 100%, 40%);">+          } else if (*scan == ')') {</span><br><span style="color: hsl(120, 100%, 40%);">+            if (paren) {</span><br><span style="color: hsl(120, 100%, 40%);">+              paren--;</span><br><span style="color: hsl(120, 100%, 40%);">+            }</span><br><span style="color: hsl(120, 100%, 40%);">+          } else if (*scan == '[') {</span><br><span style="color: hsl(120, 100%, 40%);">+            bracket++;</span><br><span style="color: hsl(120, 100%, 40%);">+          } else if (*scan == ']') {</span><br><span style="color: hsl(120, 100%, 40%);">+            if (bracket) {</span><br><span style="color: hsl(120, 100%, 40%);">+              bracket--;</span><br><span style="color: hsl(120, 100%, 40%);">+            }</span><br><span style="color: hsl(120, 100%, 40%);">+          } else if (*scan == '"') {</span><br><span style="color: hsl(120, 100%, 40%);">+            quote = quote ? 0 : 1;</span><br><span style="color: hsl(120, 100%, 40%);">+          } else if (*scan == '\\') {</span><br><span style="color: hsl(120, 100%, 40%);">+            scan++;</span><br><span style="color: hsl(120, 100%, 40%);">+          } else if ((*scan == '=') && !paren && !quote && !bracket) {</span><br><span style="color: hsl(120, 100%, 40%);">+            *scan++ = '\0';</span><br><span style="color: hsl(120, 100%, 40%);">+            strcpy(*value, scan);</span><br><span style="color: hsl(120, 100%, 40%);">+            strcpy(*name, mydata);</span><br><span style="color: hsl(120, 100%, 40%);">+            break;</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!*value) {</span><br><span style="color: hsl(120, 100%, 40%);">+                ast_log(LOG_WARNING, "Set requires an '=' to be a valid assignment.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+            ret = -1;</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%);">+   return ret;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> int ast_get_tid(void)</span><br><span> {</span><br><span>       int ret = -1;</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/15331">change 15331</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/+/15331"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 16 </div>
<div style="display:none"> Gerrit-Change-Id: I7cd3bc6118033530ad00ae4b6bdad97b6b349b6f </div>
<div style="display:none"> Gerrit-Change-Number: 15331 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Leandro Dardini <ldardini@gmail.com> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>